All Downloads are FREE. Search and download functionalities are using the official Maven repository.

at.spardat.xma.boot.Launcher Maven / Gradle / Ivy

There is a newer version: 1.16.0
Show newest version
/*******************************************************************************
 * Copyright (c) 2003, 2007 s IT Solutions AT Spardat GmbH .
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     s IT Solutions AT Spardat GmbH - initial API and implementation
 *******************************************************************************/

package at.spardat.xma.boot;

import java.awt.Window;
import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Properties;

import javax.swing.UIManager;

import at.spardat.xma.boot.comp.AppManager;
import at.spardat.xma.boot.component.IComponentHelper;
import at.spardat.xma.boot.exc.BRTCodes;
import at.spardat.xma.boot.exc.BootRuntimeException;
import at.spardat.xma.boot.logger.LogLevel;
import at.spardat.xma.boot.logger.Logger;
import at.spardat.xma.boot.transport.XMA_URI;

/**
 * Entry class for xma component calls. This class starts an XMA client by its main() method.
 * Possible are also calls to Launcher.lauch() (e.g. from JNI).
 *
 * This class is works directly from a commandline (java) as well as  by a browser call via the .xma
 * mime type linking. Typically a script or some java launch programm attached to the .xma mime type
 * would start the XMA client with a call to this classes main method.
 *
 * When an XMA client is started by some link inside a browser then first the XMA server is connected.
 * In this case the XmaLauncherServlet sends back some response attached to the .xma mime type which
 * so will activate the XMA client launcher. Unfortunatly the XmaLauncherServlet response differs
 * in its format from the arguments of a command line call.
 * As this class cannot know per se how it was started some preprocessing has to be done before
 * the XMA client is launched.
 * If this classes main was started by commandline the first argument must be a valid URL of an
 * XMA component (without .xma!).  In the case of activation by a browser the first argument to main()
 * is a path of a temporary file holding the XmaLauncherServlet response.
 *
 * Before starting Launcher.main this class checks the first argument.
 * If this is a valid URL then an commandline start is assumed,
 * if it is not a valid URL than a path to an XmaLauncherServlet response is assumed.
 *
 * Example Commandline
 * java at.spardat.xma.Launcher  [key value]
 * java at.spardat.xma.boot.Launcher http://localhost:8080/jndiTest/Test param1 value1
 *
 * Example Browsercall
 * The XmaLauncherServlet creates a response from which the Browser creates a temp file. In this
 * case the launcher is started by the browser with the path to this file as argument
 * java at.spardat.xma.boot.Launcher 
 * java at.spardat.xma.boot.Launcher "C:\Documents and Settings\s3460\Local Settings\Temporary Internet Files\Content.IE5\0P2F4PYN\Test[1].xma"
 *
 * The response from the XmaLauncherServlet has the form of an ini file:
   -----------------------------------------------
   [Component]
   name=http://localhost:8080/localtest/Test

   [Params]
   showPopUp=true
   reuseWin=testappl
   -----------------------------------------------
 *
 *(Note: In former XMA versions only a C-programm "xmalaunchw.exe" dealt with the maLauncherServlet response
 * and called at.spardat.xma.boot.Launcher by JNI)
 *
 *
 * @author s2877, s3595
 * @version $Id: Launcher.java 10005 2012-11-06 11:56:58Z dschwarz $
 */
public class Launcher {

    private static final String SELFTEST = "selftest";

    /** Singleton BootRuntime */
    private static BootRuntime br_ = null;

    /** logger */
    private static Logger log_;


    /**
     * common launch method
     */
    public static KeyValue[] launch( String component, KeyValue[] parameters) {
       return launchImpl(component,parameters,true);
    }

    public static KeyValue[] launchGUILess(String component, KeyValue[] parameters) {
        return launchImpl(component,parameters,false);
    }

    private static KeyValue[] launchImpl( String component, KeyValue[] parameters, boolean showErrors) {

        KeyValue[] out = new KeyValue[0];
        
        try {

            /*
             * initialize boot runtime
             */
            Launcher.init();
            
            if (SELFTEST.equalsIgnoreCase(component)) {
                BRNotificationBox.showDetailsDialog("Bootruntime", (Throwable) null);
            } else {
                out = launchComponent(component, parameters);
            }

        } catch( Exception ex ){
            if(log_ != null){
                log_.log(LogLevel.SEVERE, ex.getLocalizedMessage(), ex );
            }
            else{
                ex.printStackTrace();
            }

            if(showErrors) {
                BRNotificationBox.show(ex);
            }
            else{
                throw new RuntimeException(ex);
            }

        } catch( Error err ){
            if(log_ != null){
                log_.log(LogLevel.SEVERE, err.getLocalizedMessage(), err );
            }
            else{
                err.printStackTrace();
            }

            if(showErrors){
                BRNotificationBox.show(err);
            }

            throw err;
        }
        finally {
            if(br_!=null) {
                AppManager appM = br_.getAppManager();
                if(appM!=null) {
                    IComponentHelper compHelp = appM.getCompHelper();
                    if(compHelp!=null) compHelp.cleanupSWTDisplay();
                }
            }
        }
        
        for (Window window : Window.getWindows()) {
            if(log_!=null) log_.log(LogLevel.FINE, "Disposing window " + window);
            window.dispose();
        }
        
        // Stop all threads brute force except daemons and main
        // Mantis 0049971: Previous solution cleaning up frames using 'javax.swing.SwingUtilities.invokeLater(...'
        // isn't sufficient on some workstations any more
        
        Thread[] threads = new Thread[Thread.activeCount()+10];
        int threadCount = Thread.enumerate(threads);
        for (int i = 0; i < threadCount; i++) {
            Thread thread = threads[i];
            if (thread != null) {
                if(log_!=null) log_.log(LogLevel.FINE,"Thread " + thread.getName() +
                        ", isAlive:" + thread.isAlive() + " isDaemon:" + thread.isDaemon());
                if (thread.isAlive()
                    && ! thread.isDaemon()
                    && thread != Thread.currentThread()) {
                    
                    if(log_!=null) log_.log(LogLevel.FINE,"Stopping thread " + thread.getName());
                    thread.stop();
                }
            }
        }
        return out;
    }


    private static KeyValue[] launchComponent(String component, KeyValue[] parameters) throws BootRuntimeException, Exception {
        
        Properties input = new Properties();
        log_.log(LogLevel.ALL, parameters.length == 0 ? "No Input Data": "Input Data: " ); //$NON-NLS-1$ //$NON-NLS-2$

        for (int i = 0; i < parameters.length; i++) {
            input.setProperty(parameters[i].getKey(), parameters[i].getValue());
            log_.log(LogLevel.ALL, "key: {0} value: {1}", new Object[] { parameters[i].getKey(), parameters[i].getValue() } ); //$NON-NLS-1$
        }
        try {
            new XMA_URI(component);
        } catch( MalformedURLException ex) {
            BootRuntimeException brtExc = new BootRuntimeException(ex,"").setCode(BRTCodes.INVALID_CALL_XMA_URI).setShowToEndUser(true);
            String strMessage = BRTCodes.getText(BRTCodes.INVALID_CALL_XMA_URI);
            brtExc.setMessage(strMessage + " \"" + component +"\"");
            throw brtExc;
        }

        /*
         * launch component
         */
        Properties output = br_.getAppManager().launch(component,input);

        /*
         * prepare output list
         */
        log_.log(LogLevel.ALL, "Output Data: " ); //$NON-NLS-1$

        KeyValue[] out = new KeyValue[output.size()];
        Enumeration enumer = output.keys();
        for (int i = 0; enumer.hasMoreElements(); i++) {
            String key = (String) enumer.nextElement();
            out[i] = new KeyValue(key, output.getProperty(key));
            log_.log(LogLevel.ALL, "key: {0} value: {1}", new Object[] {key, out[i].getValue() } ); //$NON-NLS-1$

        }
        return out;
    }


    /**
     * main
     */
    public static void main(String[] args) {
        try {
        if (args.length < 1 || args.length % 2 != 1) {
            Launcher.usage();
           return;
        }

        String component = null;
        KeyValue[] input = null;

        if(isUrl(args[0])){ //started by commandline
            component = args[0];
            int keyValues = (args.length - 1)/2;

            input = new KeyValue[ keyValues ];
            int j=1;
            for (int i=0; i < keyValues; i++ ) {
              input[i] = new KeyValue( args[j], args[j+1] );
              j+=2;
            }
        }else{ //started by browser -> path to XmaLauncherServlet response file
            IniFileReader reader = new IniFileReader(args[0]);
            component = reader.getProperty("Component", "name");

            Map params = reader.getSection("Params");
            if(params != null){
                input = new KeyValue[params.size()];
                int i = 0;
                for (Iterator iter = params.keySet().iterator(); iter.hasNext(); i++) {
                    String  key =  (String) iter.next();
                    String  value = (String) params.get(key);
                    input[i] = new KeyValue(key, value);
                }
            } else{
                input = new KeyValue[0];
            }
        }

        //actual launch of XMA client
        KeyValue[] output = launch( component, input );

        //print out return values
        for(int i = 0; i < output.length ; i++) {
          System.out.println("key: " + output[i].getKey() + " value: " + output[i].getValue());       //$NON-NLS-1$ //$NON-NLS-2$
        }
        } finally {
            System.exit(0); // for Webstart/Applet and such
        }
    }

    /**
     * Tests if the argument is a valid URL
     * @param url
     * @return
     * @since version_number
     * @author s3460
     */
    private static boolean isUrl(String url) {
        boolean isUrl;
        try {
            new URL(url);
            isUrl = true;
        } catch (MalformedURLException e) {
            isUrl = false;
        }

        return isUrl;
    }

    /**
     * Reads a XmaLauncherServlet response file and transforms in an String[] array filled
     * like XMA commandline arguments:  [key value]
     *
     * @param filePath
     * @return
     * @since version_number
     * @author s3460
     */
    private static String[] argsFromXMAFile(String filePath){
        List list = new ArrayList();
        IniFileReader reader = new IniFileReader(filePath);
        String comp = reader.getProperty("Component", "name");
        list.add(comp);
        Map params = reader.getSection("Params");
        for (Iterator iter = params.keySet().iterator(); iter.hasNext();) {
            Object key =  iter.next();
            Object value = params.get(key);
            list.add(key);
            list.add(value);
        }

        return (String[]) list.toArray(new String[list.size()]);

    }

    /** usage */
    private static void usage() {
       System.out.println("usage:\n java at.spardat.xma.Launcher  [key value]..."); //$NON-NLS-1$
    }


    /**
     * initialize the runtime if necessary
     * @throws IOException
     */
    public static synchronized void init () throws IOException {

        if( br_ == null ) {
            log_ = Logger.getLogger("bootrt.launcher"); //$NON-NLS-1$
            SimpleDateFormat sdf = new SimpleDateFormat( "EEE, dd MMM yyyy hh:mm:ss zzz", Locale.getDefault() );            //$NON-NLS-1$
            log_.log( LogLevel.INFO, "initializing xma runtime: {0} ", sdf.format(new Date() )); //$NON-NLS-1$

            // initialize Swing
            // There is a bug in the Linux JVM and SWT: if the Swing System look and feel is set by the UIManager.setLookAndFeel() then SWT works not properly.
            // So in Linux start XMA with the VM argument: -Dxma.boot.skipSetSwingSystemLookAndFeel=true.
            // For details about the bug see: https://bugs.eclipse.org/bugs/show_bug.cgi?id=320524
            String skip = System.getProperty("xma.boot.skipSetSwingSystemLookAndFeel"); //$NON-NLS-1$
            if (skip == null || "true".equalsIgnoreCase(skip) == false) {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (Exception e) {
                    log_.log(LogLevel.WARNING, "error setting swing look and feel: ", e);
                }
            }

            String strHome = System.getProperty("xma.boot.homedir"); //$NON-NLS-1$
            if( strHome == null) {
                strHome = System.getProperty( "user.dir");
                log_.log( LogLevel.INFO, "fallback::boot runtime installation directory defaults to: {0} ", strHome ); //$NON-NLS-1$
            }
            log_.log( LogLevel.INFO, "boot runtime installation directory is: {0} ", strHome ); //$NON-NLS-1$

            File f = new File( strHome );

            br_ = BootRuntime.initialize(f, log_ );
        } // if br
    }// init

    /**
     * Get the properties loaded by the BootRuntime from bootcfg.properties.
     * @return the properties or null if the BootRuntime is not initialized yet.
     * @since 1.7.0
     */
    public static Properties getBootRuntimeProperties() {
        if(br_==null) {
            return null;
        } else {
            return br_.getConfigProperties();
        }
    }

}






© 2015 - 2024 Weber Informatics LLC | Privacy Policy