components/visual-panels/core/src/java/vpanels/client/com/oracle/solaris/vp/client/swing/App.java
changeset 3553 f1d133b09a8c
parent 3552 077ebe3d0d24
child 3554 ef58713bafc4
--- a/components/visual-panels/core/src/java/vpanels/client/com/oracle/solaris/vp/client/swing/App.java	Tue Dec 16 05:53:51 2014 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,744 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-
-/*
- * Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved.
- */
-
-package com.oracle.solaris.vp.client.swing;
-
-import java.io.*;
-import java.net.*;
-import java.util.*;
-import java.util.logging.*;
-import com.oracle.solaris.rad.transports.*;
-import com.oracle.solaris.vp.client.common.*;
-import com.oracle.solaris.vp.panel.common.*;
-import com.oracle.solaris.vp.panel.common.action.*;
-import com.oracle.solaris.vp.panel.common.control.*;
-import com.oracle.solaris.vp.util.cli.*;
-import com.oracle.solaris.vp.util.misc.*;
-import com.oracle.solaris.vp.util.misc.finder.Finder;
-
-/**
- * The {@code App} class is a thread that listens for AF_UNIX
- * connections from other processes.  Multiple addresses of panels to
- * display, one per newline-terminated lines, may be sent through these
- * connections.
- */
-public class App extends Thread implements AppConstants {
-    //
-    // Inner classes
-    //
-
-    public static class CommandLineOptionsBean {
-	//
-	// Instance data
-	//
-
-	private String host = RadLoginManager.LOCAL_HOST;
-	private String user = RadLoginManager.LOCAL_USER;
-	private String role;
-	private String zone;
-	private String zoneUser;
-	private String zoneRole;
-	private String address = null;
-	private boolean noRemote;
-	private HelpFormatter help;
-	private Properties properties = new Properties();
-	private boolean inParam = false;
-
-	//
-	// Constructors
-	//
-
-	public CommandLineOptionsBean(HelpFormatter help) {
-	    this.help = help;
-	}
-
-	//
-	// CommandLineOptionsBean methods
-	//
-
-	public String getAddress() {
-	    return address;
-	}
-
-	public String getHost() {
-	    return host;
-	}
-
-	public boolean getNoremote() {
-	    return noRemote;
-	}
-
-	public Properties getProperties() {
-	    return properties;
-	}
-
-	public String getRole() {
-	    return role;
-	}
-
-	public String getUser() {
-	    return user;
-	}
-
-	public String getZone() {
-	    return zone;
-	}
-
-	public String getZonerole() {
-	    return zoneRole;
-	}
-
-	public String getZoneuser() {
-	    return zoneUser;
-	}
-
-	public void setAddress(String address) {
-	    boolean absolute = address.startsWith("/");
-	    if (this.address == null) {
-		if (!absolute) {
-		    // Assume non-relative path is a standalone shortcut
-		    address = String.format("/%s/%s",
-			Control.encode(AppRootControl.ID, null), address);
-		}
-		this.address = address;
-	    } else {
-		/*
-		 * If the address has already been set, we accumulate
-		 * additional operands as query parameters or subsequent
-		 * path elements.
-		 */
-		if (absolute) {
-		    this.address = this.address + address;
-		    inParam = false;
-		} else {
-		    try {
-			/*
-			 * Ideally we'd use Control.encode, but mapping
-			 * from our input to what it requires would be
-			 * much less straightforward than what follows.
-			 */
-			String[] parts = address.split("=", 2);
-			StringBuilder b = new StringBuilder(this.address);
-			b.append(inParam ? "&" : "?");
-			b.append(URLEncoder.encode(parts[0], Control.ENCODING));
-			b.append('=');
-			if (parts.length > 1)
-			    b.append(URLEncoder.encode(parts[1],
-				Control.ENCODING));
-			this.address = b.toString();
-			inParam = true;
-		    } catch (UnsupportedEncodingException ex) {
-		    }
-		}
-	    }
-	}
-
-	public void setHelp() {
-	    System.out.println(help.getHelp());
-	    System.exit(0);
-	}
-
-	public void setHost(String host) {
-	    this.host = host;
-	}
-
-	public void setNoremote() {
-	    noRemote = true;
-	}
-
-	public void setProperty(String property) {
-	    String value;
-	    int index = property.indexOf("=");
-	    if (index == -1) {
-		value = "";
-	    } else {
-		value = property.substring(index + 1);
-		property = property.substring(0, index - 1);
-	    }
-
-	    properties.setProperty(property, value);
-	}
-
-	public void setRole(String role) {
-	    this.role = role;
-	}
-
-	public void setUser(String user) {
-	    this.user = user;
-	}
-
-	public void setVersion() {
-	    showVersion();
-	    System.exit(0);
-	}
-
-	public void setZone(String zone) {
-	    this.zone = zone;
-	}
-
-	public void setZonerole(String zoneRole) {
-	    this.zoneRole = zoneRole;
-	}
-
-	public void setZoneuser(String zoneUser) {
-	    this.zoneUser = zoneUser;
-	}
-    }
-
-    private static class InstanceInfo implements Serializable {
-	//
-	// Instance data
-	//
-
-	public String address;
-	public Properties properties;
-	public String host;
-	public String user;
-	public String role;
-	public String zone;
-	public String zoneUser;
-	public String zoneRole;
-
-	//
-	// Constructors
-	//
-
-        public InstanceInfo(String address, Properties properties, String host,
-            String user, String role, String zone, String zoneUser,
-	    String zoneRole) {
-
-	    this.address = address;
-	    this.properties = properties;
-	    this.host = host;
-	    this.user = user;
-	    this.role = role;
-	    this.zone = zone;
-	    this.zoneUser = zoneUser;
-	    this.zoneRole = zoneRole;
-	}
-
-	//
-	// Object methods
-	//
-
-	@Override
-	public String toString() {
-	    return "address = " + quote(address) +
-		", host = " + quote(host) +
-		", user = " + quote(user) +
-		", role = " + quote(role) +
-		", zone = " + quote(zone) +
-		", zoneUser = " + quote(zoneUser) +
-		", zoneRole = " + quote(zoneRole);
-	}
-
-	//
-	// Static methods
-	//
-
-	private static String quote(String str) {
-	    if (str == null) {
-		return "(null)";
-	    }
-	    return "\"" + str + "\"";
-	}
-    }
-
-    //
-    // Static data
-    //
-
-    private static final String ARG_NONOPT_ADDRESS = "address";
-    private static final String ARG_SHORT_HOST = "h";
-    private static final String ARG_LONG_HOST = "host";
-    private static final String ARG_SHORT_NOREMOTE = "n";
-    private static final String ARG_LONG_NOREMOTE = "no-remote";
-    private static final String ARG_SHORT_ROLE = "r";
-    private static final String ARG_LONG_ROLE = "role";
-    private static final String ARG_SHORT_USER = "u";
-    private static final String ARG_LONG_USER = "user";
-    private static final String ARG_SHORT_VERSION = "v";
-    private static final String ARG_LONG_VERSION = "version";
-    private static final String ARG_SHORT_ZONE = "z";
-    private static final String ARG_LONG_ZONE = "zone";
-    private static final String ARG_SHORT_ZONEUSER = "U";
-    private static final String ARG_LONG_ZONEUSER = "zoneuser";
-    private static final String ARG_SHORT_ZONEROLE = "R";
-    private static final String ARG_LONG_ZONEROLE = "zonerole";
-    private static final String ARG_SHORT_HELP = "?";
-    private static final String ARG_LONG_HELP = "help";
-    private static final String ARG_SHORT_PROPERTY = "D";
-    private static final String ARG_LONG_PROPERTY = "property";
-
-    private static final String COMMAND_NAME = "vp";
-    private static final String COMMAND_DESC =
-	Finder.getString("cli.description");
-
-    private static OptionChoiceGroup options;
-    static {
-	OptionElement addressOption = new NoOptOptionElement(
-	    true, ARG_NONOPT_ADDRESS, Finder.getString("cli.arg.address"), -1);
-
-	OptionElement propOption = new OptionElement(ARG_SHORT_PROPERTY,
-	    ARG_LONG_PROPERTY, false, "property", "");
-	propOption.setDocumented(false);
-	propOption.setUseLimit(-1);
-
-	OptionElement hostOption = new OptionElement(ARG_SHORT_HOST,
-	    ARG_LONG_HOST, false, "host", Finder.getString("cli.arg.host"));
-
-	OptionElement noRemoteOption = new OptionElement(ARG_SHORT_NOREMOTE,
-	    ARG_LONG_NOREMOTE, false, Finder.getString("cli.arg.noremote"));
-
-	OptionElement userOption = new OptionElement(ARG_SHORT_USER,
-	    ARG_LONG_USER, false, "user", Finder.getString("cli.arg.user"));
-
-	OptionElement roleOption = new OptionElement(ARG_SHORT_ROLE,
-	    ARG_LONG_ROLE, false, "role", Finder.getString("cli.arg.role"));
-
-	OptionElement zoneOption = new OptionElement(ARG_SHORT_ZONE,
-	    ARG_LONG_ZONE, false, "zone", Finder.getString("cli.arg.zone"));
-
-	OptionElement zoneUserOption = new OptionElement(ARG_SHORT_ZONEUSER,
-	    ARG_LONG_ZONEUSER, false, "zoneuser",
-	    Finder.getString("cli.arg.zoneuser"));
-
-	OptionElement zoneRoleOption = new OptionElement(ARG_SHORT_ZONEROLE,
-	    ARG_LONG_ZONEROLE, false, "zonerole",
-	    Finder.getString("cli.arg.zonerole"));
-
-	OptionElement versionOption = new OptionElement(ARG_SHORT_VERSION,
-	    ARG_LONG_VERSION, false, Finder.getString("cli.arg.version"));
-
-	OptionElement helpOption = new OptionElement(ARG_SHORT_HELP,
-	    ARG_LONG_HELP, false, Finder.getString("cli.arg.help"));
-
-	OptionListGroup mainGroup = new OptionListGroup(false,
-	    propOption, hostOption, userOption, roleOption, zoneOption,
-	    zoneUserOption, zoneRoleOption, noRemoteOption, addressOption);
-
-	options = new OptionChoiceGroup(true, mainGroup, versionOption,
-	    helpOption);
-    }
-
-    public static final String VP_USER_DIR =
-	System.getProperty("user.home") + File.separator + ".vp";
-
-    static {
-	// Set up client logging
-	String fileName = VP_USER_DIR + File.separator + "log";
-
-	// Root Logger
-	Logger log = Logger.getLogger("");
-
-	try {
-	    File parent = new File(fileName).getParentFile();
-	    if (!parent.exists()) {
-		if (!parent.mkdirs()) {
-		    throw new IOException(
-			"could not create directory: " +
-			parent.getAbsolutePath());
-		}
-	    }
-
-	    Handler fHandler = new FileHandler(fileName);
-	    fHandler.setFormatter(new SimpleFormatter());
-	    log.addHandler(fHandler);
-
-	    // Don't output to the console by default
-	    for (Handler cHandler : log.getHandlers()) {
-		if (cHandler instanceof ConsoleHandler) {
-		    log.removeHandler(cHandler);
-		}
-	    }
-	} catch (IOException e) {
-	    Logger.getLogger(App.class.getName()).log(Level.WARNING,
-		"unable to create log file: " + fileName);
-	}
-    }
-
-    public static final File TRUSTSTORE_FILE =
-	new File(VP_USER_DIR, "truststore");
-
-    public static final File VP_UNIX;
-    static {
-	String hostName = NetUtil.getHostName();
-	if (hostName == null) {
-	    hostName = "localhost";
-	}
-
-	// May be null or malformed if not an X client
-	String display = System.getenv("DISPLAY");
-
-	if (display != null && !display.matches(".*:\\d+(\\.\\d)?$")) {
-	    String error = "invalid DISPLAY environment variable: " + display;
-	    Logger.getLogger(App.class.getName()).log(Level.WARNING, error);
-	    display = null;
-	}
-
-	if (display == null) {
-	    display = ":0.0";
-	} else {
-	    if (display.matches(".*:\\d+$")) {
-		display += ".0";
-	    }
-
-	    if (display.startsWith(hostName)) {
-		display = display.substring(hostName.length());
-	    }
-	}
-
-	String name = String.format(".unix-%s-%s", hostName, display);
-
-	VP_UNIX = new File(VP_USER_DIR, name);
-    }
-
-    public static final String VP_USER_PREFS =
-	VP_USER_DIR + File.separator + "vp.init";
-
-    private static final Preferences prefs = new Preferences(VP_USER_PREFS);
-
-    //
-    // Instance data
-    //
-
-    private UnixSocketServer server;
-    private boolean closing;
-    private final List<AppInstance> instances = new ArrayList<AppInstance>();
-    private ConnectionManager connManager = new ConnectionManager();
-    private LoginHistoryManager loginHistoryManager =
-	new LoginHistoryManager(connManager, new File(VP_USER_DIR, "history"));
-
-    //
-    // Constructors
-    //
-
-    public App() {
-	addVersionToThreadName(this);
-    }
-
-    //
-    // Runnable methods
-    //
-
-    @Override
-    public void run() {
-        Logger log = Logger.getLogger(getClass().getName());
-
-	// Start singleton application instance...
-	try {
-	    server = UnixDomainSocket.bind(VP_UNIX, 0600);
-
-	    while (true) {
-		final UnixSocket socket = server.accept();
-		String peerUser = socket.getPeerUser();
-
-		if (!RadLoginManager.LOCAL_USER.equals(peerUser)) {
-		    String error = String.format(
-			"user %s attempted to connect as %s", peerUser,
-			RadLoginManager.LOCAL_USER);
-		    log.log(Level.WARNING, error);
-		} else {
-		    // Spawn on a separate thread so as not to block other
-		    // incoming to conections -- not so much because we
-		    // anticipate a lot of traffic, but because we can't
-		    // guarantee that some poorly-behaved client won't keep its
-		    // connection open indefinitely.
-		    new Thread() {
-			@Override
-			public void run() {
-			    readFully(socket);
-			}
-		    }.start();
-		}
-	    }
-	} catch (AFUNIXNotSupportedException e) {
-	    // Bummer
-	    return;
-	} catch (IOException e) {
-	    if (!closing) {
-		// Major bummer
-		log.log(Level.SEVERE,
-		    "error communicating via incoming AF_UNIX connection", e);
-	    }
-	    return;
-	}
-    }
-
-    //
-    // App methods
-    //
-
-    public void abortableExit() throws ActionAbortedException {
-	synchronized (instances) {
-	    for (int i = instances.size() - 1; i >= 0; i--) {
-		// Throws ActionAbortedException
-		instances.get(i).closeInstance(false);
-	    }
-	}
-	exit();
-    }
-
-    public void exit(int exitCode) {
-	try {
-	    if (server != null) {
-		closing = true;
-		server.close();
-	    }
-	} catch (IOException ignore) {
-	}
-
-	try {
-	    prefs.store();
-	} catch (IOException e) {
-	    Logger.getLogger(getClass().getName()).log(Level.WARNING,
-		"could not write preferences", e);
-	}
-
-	System.exit(exitCode);
-    }
-
-    public void exit() {
-	exit(0);
-    }
-
-    private void exitIfNoIntances(int exitCode) {
-	if (instances.isEmpty()) {
-	    exit(exitCode);
-	}
-    }
-
-    public ConnectionManager getConnectionManager() {
-	return connManager;
-    }
-
-    public LoginHistoryManager getLoginHistoryManager() {
-	return loginHistoryManager;
-    }
-
-    protected Preferences getPreferences() {
-	return prefs;
-    }
-
-    protected void instanceClosed(AppInstance instance) {
-	synchronized (instances) {
-	    if (instances.remove(instance)) {
-		exitIfNoIntances(0);
-	    }
-	}
-    }
-
-    protected void instanceCreated(AppInstance instance) {
-	synchronized (instances) {
-	    instances.add(instance);
-	}
-    }
-
-    public void newInstance(InstanceInfo info) {
-	AppInstance instance = null;
-	boolean success = false;
-
-	try {
-	    LoginProperty<String> host =
-		new LoginProperty<String>(info.host, false);
-	    host.setEditableOnError(true);
-
-	    LoginProperty<String> user =
-		new LoginProperty<String>(info.user, false);
-	    user.setEditableOnError(true);
-
-	    LoginProperty<String> role =
-		new LoginProperty<String>(info.role, false);
-	    role.setEditableOnError(true);
-
-	    LoginProperty<String> zone =
-		new LoginProperty<String>(info.zone, false);
-	    zone.setEditableOnError(true);
-
-	    LoginProperty<String> zoneUser =
-		new LoginProperty<String>(info.zoneUser, false);
-	    zoneUser.setEditableOnError(true);
-
-	    LoginProperty<String> zoneRole =
-		new LoginProperty<String>(info.zoneRole, false);
-	    zoneRole.setEditableOnError(true);
-
-            boolean zonePromptVal = zone.getValue() != null ||
-		zoneUser.getValue() != null || zoneRole.getValue() != null;
-	    LoginProperty<Boolean> zonePrompt =
-		new LoginProperty<Boolean>(zonePromptVal, false);
-
-            LoginRequest request = new LoginRequest(host, user, role,
-		zonePrompt, zone, zoneUser, zoneRole);
-
-	    instance = new AppInstance(this, info.properties, request);
-
-	    SimpleNavigable[] path = Navigator.toArray(info.address);
-	    instance.getNavigator().goToAsyncAndWait(true, null, path);
-	    success = true;
-
-	// User is aware of this because he explicitly caused it
-	} catch (ActionAbortedException e) {
-
-	// User has been advised of this by RadLoginManager
-	} catch (ActionFailedException e) {
-
-	// User has been advised of this by SwingNavigator
-	} catch (NavigationException e) {
-
-	// Unexpected error - write to log
-	} catch (RuntimeException e) {
-	    Logger log = Logger.getLogger(getClass().getName());
-	    log.log(Level.SEVERE, "could not launch: " + info, e);
-
-	// Unexpected error - write to log
-	} catch (Error e) {
-	    Logger log = Logger.getLogger(getClass().getName());
-	    log.log(Level.SEVERE, "could not launch: " + info, e);
-
-	} finally {
-	    if (!success && instance != null &&
-		// Partial navigation failures aren't deal-breakers
-		!NavigationUtil.isPanelStarted(instance.getNavigator())) {
-
-		instance.close();
-	    }
-	}
-    }
-
-    public void readFully(UnixSocket socket) {
-	ObjectInputStream in = null;
-        Logger log = Logger.getLogger(getClass().getName());
-
-	try {
-	    in = new ObjectInputStream(socket.getInputStream());
-	    InstanceInfo info = (InstanceInfo)in.readObject();
-	    newInstance(info);
-	} catch (ClassNotFoundException e) {
-            log.log(Level.SEVERE,
-		"unexpected or invalid object read from AF_UNIX connection", e);
-
-	} catch (IOException e) {
-	    log.log(Level.SEVERE, "I/O error", e);
-
-	} finally {
-	    IOUtil.closeIgnore(in);
-	}
-    }
-
-    //
-    // Static methods
-    //
-
-    private static void addVersionToThreadName(Thread thread) {
-	// Add useful information to a thread dump
-	String name = String.format(
-	    "%s (app version %s)", thread.getName(), VERSION);
-
-	thread.setName(name);
-    }
-
-    public static void showVersion() {
-	System.out.println(Finder.getString("cli.error.version", VERSION));
-    }
-
-    public static void main(String args[]) {
-	addVersionToThreadName(Thread.currentThread());
-
-	CommandLineParser parser = new PosixCommandLineParser();
-	UsageFormatter usage = new UsageFormatter(
-	    COMMAND_NAME, options, parser.getOptionFormatter());
-	HelpFormatter help = new HelpFormatter(COMMAND_DESC, usage);
-	CommandLineOptionsBean bean = new CommandLineOptionsBean(help);
-
-	if (System.getProperty("vpanels.debug.version") != null) {
-	    showVersion();
-	}
-
-	try {
-	    // Populate bean
-	    CommandLineProcessor.process(args, options, parser, bean);
-	}
-
-	catch (Exception e) {
-	    CommandUtil.exit(e, usage);
-	}
-
-        InstanceInfo info = new InstanceInfo(bean.getAddress(),
-            bean.getProperties(), bean.getHost(), bean.getUser(),
-            bean.getRole(), bean.getZone(), bean.getZoneuser(),
-            bean.getZonerole());
-
-	if (!bean.getNoremote()) {
-	    // Check for running instance
-	    try {
-		UnixSocket socket = UnixDomainSocket.connect(VP_UNIX);
-
-		// Send arguments to running instance...
-		ObjectOutputStream out = new ObjectOutputStream(
-		    socket.getOutputStream());
-
-		out.writeObject(info);
-		out.close();
-		System.exit(0);
-	    } catch (AFUNIXNotSupportedException e) {
-		// AF_UNIX sockets are not supported on this platform
-	    } catch (IOException e) {
-		// We are the only running instance
-	    }
-	}
-
-	try {
-	    URL policy = Finder.getResource("panel.policy");
-	    if (policy == null) {
-		throw new IOException("panel.policy not found");
-	    }
-	    PanelClassLoader.loadPermissions(policy);
-	} catch (IOException e) {
-	    Logger.getLogger(App.class.getName()).log(Level.SEVERE,
-		"unable to read panel.policy", e);
-	    String message = Finder.getString("init.error.security.io");
-	    System.err.println(message);
-	    System.exit(1);
-	} catch (PermissionParseException e) {
-	    Logger.getLogger(App.class.getName()).log(Level.SEVERE,
-		"unable to parse panel.policy", e);
-	    String message = Finder.getString("init.error.security.parse");
-	    System.err.println(message);
-	    System.exit(1);
-	}
-
-	System.setSecurityManager(new SecurityManager());
-
-	App app = new App();
-	app.newInstance(info);
-	app.exitIfNoIntances(1);
-
-	if (!bean.getNoremote()) {
-	    // Start daemon thread listening for connections
-	    app.start();
-	}
-    }
-}