Package org.jdesktop.wonderland.modules.sasxremwin.provider

Source Code of org.jdesktop.wonderland.modules.sasxremwin.provider.SasXrwProviderMain

/**
* Project Wonderland
*
* Copyright (c) 2004-2009, Sun Microsystems, Inc., All Rights Reserved
*
* Redistributions in source code form must reproduce the above
* copyright and this condition.
*
* The contents of this file are subject to the GNU General Public
* License, Version 2 (the "License"); you may not use this file
* except in compliance with the License. A copy of the License is
* available at http://www.opensource.org/licenses/gpl-license.php.
*
* Sun designates this particular file as subject to the "Classpath"
* exception as provided by Sun in the License file that accompanied
* this code.
*/
package org.jdesktop.wonderland.modules.sasxremwin.provider;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;
import org.jdesktop.wonderland.common.ExperimentalAPI;
import org.jdesktop.wonderland.modules.appbase.client.ProcessReporterFactory;
import org.jdesktop.wonderland.modules.sas.provider.SasProvider;
import org.jdesktop.wonderland.modules.sas.provider.SasProviderConnection;
import org.jdesktop.wonderland.modules.sas.provider.SasProviderConnectionListener;
import org.jdesktop.wonderland.modules.sas.provider.SasProviderSession;
import org.jdesktop.wonderland.modules.xremwin.client.AppXrwMaster;
import org.jdesktop.wonderland.common.messages.MessageID;
import java.util.logging.Logger;
import java.util.HashMap;
import java.util.logging.Level;
import org.jdesktop.wonderland.common.cell.CellID;
import org.jdesktop.wonderland.modules.appbase.client.App2D;
import org.jdesktop.wonderland.common.login.CredentialManager;

/**
* The main logic for the SAS Xremwin provider client.
*
* @author deronj
*/
@ExperimentalAPI
public class SasXrwProviderMain
    implements SasProviderConnectionListener, AppXrwMaster.ExitListener {

    static final Logger logger = Logger.getLogger(SasXrwProviderMain.class.getName());

    /** The property for enabling user-specified app commands */
    private static final String ENABLE_USER_COMMANDS_PROP =
            SasXrwProviderMain.class.getSimpleName() + ".enable.user.commands";
    /** The URL to map app names to user commands */
    private static final String COMMAND_URL_PROP =
            SasXrwProviderMain.class.getSimpleName() + ".command.url";
    /** The default URL for user commands */
    private static final String COMMAND_URL_DEFAULT =
            "/xapps-config/wonderland-xapps-config/browse?action=check&app=";

    /** The property to set with the username */
    private static final String USERNAME_PROP = "sas.user";
    /** The default username */
    private static final String USERNAME_DEFAULT = "sasxprovider";
    /** The property to set with the password file location */
    private static final String PASSWORD_FILE_PROP = "sas.password.file";

    /** The URL of the Wonderland server */
    private final String serverUrl;

    /** Whether user commands are allowed */
    private final boolean userCommands;

    /** The command URL to query */
    private final String commandURL;

    /** The session associated with this provider. */
    private SasProviderSession session;

    /** An entry which holds information needed to notify the SasServer of app exit. */
    private class AppInfo {
        private SasProviderConnection connection;
        private MessageID launchMessageID;
        private AppInfo (SasProviderConnection connection, MessageID launchMessageID) {
            this.connection = connection;
            this.launchMessageID = launchMessageID;
        }
    }

    /** Information about the apps which are running in this provider. */
    private final HashMap<AppXrwMaster,AppInfo> runningAppInfos = new HashMap<AppXrwMaster,AppInfo>();

    /** The xremwin-specific provider object. */
    private static SasXrwProvider provider;

    // Register the sas provider shutdown hook
    static {
        Runtime.getRuntime().addShutdownHook(new Thread("SasXrw Shutdown Hook") {
            @Override
            public void run() {
                if (provider != null) {
                    provider.cleanup();
                }
            }
        });
    }

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        SasXrwProviderMain providerMain = new SasXrwProviderMain();
    }

    private SasXrwProviderMain () {

        checkPlatform();

        // parse username from the system property
        String username = System.getProperty(USERNAME_PROP, USERNAME_DEFAULT);

        // parse the password file from the system property.  This may be
        // null if no password file is specified (for insecure deployments)
        String passwordFileName = System.getProperty(PASSWORD_FILE_PROP);
        File passwordFile = null;
        if (passwordFileName != null && passwordFileName.trim().length() > 0) {
            passwordFile = new File(passwordFileName);
        }

        // read the server URL property
        serverUrl = System.getProperty("wonderland.web.server.url", "http://localhost:8080");
        logger.warning("Connecting to server " + serverUrl);

        // Read the userCommands property.  The default is false unless the
        // property is specified and is equal to "true"
        userCommands = Boolean.parseBoolean(System.getProperty(ENABLE_USER_COMMANDS_PROP));

        // Read the commandURL property
        commandURL = System.getProperty(COMMAND_URL_PROP, COMMAND_URL_DEFAULT);

        try {
            provider = new SasXrwProvider(username, passwordFile, serverUrl, this, this);
        } catch (Exception ex) {
            logger.severe("Exception " + ex);
            logger.severe("Cannot connect to server " + serverUrl);
            System.exit(1);
        }       
    }

    /**
     * SAS can only run on a Unix platform. Exit if this is not the case.
     */
    private void checkPlatform() {
        String osName = System.getProperty("os.name");
        if (!"Linux".equals(osName) &&
            !"SunOS".equals(osName)) {
            logger.severe("SasXrwProviderMain cannot run on platform " + osName);
            logger.severe("Program terminated.");
            System.exit(1);
        }
    }

    /**
     * {@inheritDoc}
     */
    public void setSession (SasProviderSession session) {
        this.session = session;
    }

    /**
     * {@inheritDoc}
     */
    public String launch (String appName, String command, SasProviderConnection connection,
                          MessageID launchMessageID, CellID cellID) {
        AppXrwMaster app = null;
       
        // resolve the command based on the app name. A command value of null
        // indicates that the given appName could not be resolved
        command = resolveCommand(appName, command);
        if (command == null) {
            return null;
        }
        logger.warning("Resolved command = " + command);

        try {
            app = new AppXrwMaster(appName, command, cellID, null,
                                   ProcessReporterFactory.getFactory().create(appName), session, true);
        } catch (InstantiationException ex) {
            return null;
        }

        app.setExitListener(this);

        synchronized (runningAppInfos) {
            runningAppInfos.put(app, new AppInfo(connection, launchMessageID));
        }

        // Now it is time to enable the master client loop
        app.getClient().enable();

        return app.getConnectionInfo().toString();
    }


    /**
     * Called when an app exits.
     */
    public void appExitted (AppXrwMaster app) {
        logger.warning("App Exitted: " + app.getName());
        synchronized (runningAppInfos) {
            AppInfo appInfo = runningAppInfos.get(app);
            if (appInfo != null) {
                runningAppInfos.remove(app);

                // Don't send the app exitted message if the app base is no longer running.
                // This happens when a SAS Provider JVM shutdown hook has been called. If
                // a shutdown of the SAS provider has occurred it will be restarted by the
                // web server. But if we treat this as an app exit condition then the server
                // cells for the apps will be deleted and their apps won't get restarted on
                // the new SAS provider.
                if (App2D.isAppBaseRunning()) {
                    appInfo.connection.appExitted(appInfo.launchMessageID, app.getExitValue());
                }
            }
        }
    }

    /**
     * {@inheritDoc}
     */
    public void appStop (SasProviderConnection connection, MessageID launchMessageID) {
        synchronized (runningAppInfos) {
            for (AppXrwMaster app : runningAppInfos.keySet()) {
                AppInfo appInfo = runningAppInfos.get(app);
                if (appInfo.connection == connection && appInfo.launchMessageID.equals(launchMessageID)) {
                    runningAppInfos.remove(app);
                    app.stop();
                }
            }
        }
    }

    /**
     * Resolve an app name into a command using a web service.
     * @param appName the app name to resolve
     * @param command the command the user specified (may be null)
     * @return the command to execute for the given app, or null
     * to return an error
     */
    protected String resolveCommand(String appName, String command) {
        // if the user specified a command, check if that command is
        // allowed
        if (command != null) {
            if (userCommands) {
                return command;
            } else {
                logger.warning("User-specified command " + command + " for " +
                               appName + " when user commands are disabled. " +
                               "Set " + ENABLE_USER_COMMANDS_PROP + " to " +
                               "enable user commands.");
                return null;
            }
        }

        // if we get here, it means the user did not specify a command.  In
        // that case, use the web service to try to find the command
        try {
            // construct the service request URL by adding the server
            // URL, the command URL and the app name (URL encoded) together.
            URL url = new URL(new URL(serverUrl), commandURL +
                              URLEncoder.encode(appName, "UTF-8"));
            URLConnection uc = url.openConnection();

            // if this was an HTTP URL connection, check the return value
            if (uc instanceof HttpURLConnection) {
                HttpURLConnection huc = (HttpURLConnection) uc;

                // don't redirect to the login page if there is a login failure
                huc.setRequestProperty("Redirect", "false");

                // secure the connection with the credentials for our session
                // (we can only do this for an http connection)
                CredentialManager cm = session.getSessionManager().getCredentialManager();
                cm.secureURLConnection(huc);

                if (huc.getResponseCode() != HttpURLConnection.HTTP_OK) {
                    logger.warning("Connection to " + url + " returns " +
                            huc.getResponseCode() + " : " +
                            huc.getResponseMessage());
                    return null;
                }
            }

            // read the command name from the web service
            BufferedReader br = new BufferedReader(
                                    new InputStreamReader(uc.getInputStream()));
            return br.readLine();
        } catch (IOException ioe) {
            logger.log(Level.WARNING, "Error resolving command for " + appName,
                       ioe);
            return null;
        }
    }
}
TOP

Related Classes of org.jdesktop.wonderland.modules.sasxremwin.provider.SasXrwProviderMain

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.