/*************************************************************************
*
* $RCSfile: AppStarter.java,v $
*
* $Revision: 1.1.1.1 $
*
* last change: $Author: hr $ $Date: 2000/09/18 16:54:03 $
*
* The Contents of this file are made available subject to the terms of
* either of the following licenses
*
* - GNU Lesser General Public License Version 2.1
* - Sun Industry Standards Source License Version 1.1
*
* Sun Microsystems Inc., October, 2000
*
* GNU Lesser General Public License Version 2.1
* =============================================
* Copyright 2000 by Sun Microsystems, Inc.
* 901 San Antonio Road, Palo Alto, CA 94303, USA
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License version 2.1, as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*
*
* Sun Industry Standards Source License Version 1.1
* =================================================
* The contents of this file are subject to the Sun Industry Standards
* Source License Version 1.1 (the "License"); You may not use this file
* except in compliance with the License. You may obtain a copy of the
* License at http://www.openoffice.org/license.html.
*
* Software provided under this License is provided on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
* WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
* MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
* See the License for the specific provisions governing your rights and
* obligations concerning the Software.
*
* The Initial Developer of the Original Code is: Sun Microsystems, Inc.
*
* Copyright: 2000 by Sun Microsystems, Inc.
*
* All Rights Reserved.
*
* Contributor(s): _______________________________________
*
*
************************************************************************/
package stardiv.controller;
import java.lang.reflect.Method;
import java.lang.reflect.Array;
import java.util.Vector;
import java.util.Hashtable;
import java.util.Properties;
import java.util.StringTokenizer;
import java.net.URL;
import java.net.MalformedURLException;
import java.beans.Beans;
import com.sun.star.lib.sandbox.ClassContext;
import com.sun.star.lib.sandbox.ClassContextProxy;
import com.sun.star.lib.sandbox.ResourceProxy;
/**
* This class load java classes and call asynchronously the main method or
* instantiate the class through java.beans.Bean.instantiate(...).
* If the class has no default constructor or some arguments are provided
* than the main function is called.
*
* @version $Version: 1.0 $
* @author Markus Meyer
*
*/
public class AppStarter implements Runnable {
private String className;
private Hashtable atts;
private String[] args;
private Object createdObject;
private Thread starterThread;
AppStarterStatus pStatusCallback;
/**
* The constructor with the arguments to load and start the JavaClass.
*
* @param className The full qualified name of the class (eg: "stardiv.app.TestApp").
* @param args The argument passed to the program.
*
*/
public AppStarter( String className, Vector args ) {
this( null, className, null, args );
}
/**
* The constructor with the arguments to load and start the JavaClass.
*
* @param status The status callback of the loading process.
* @param className The full qualified name of the class (eg: "stardiv.app.TestApp").
* @param atts a hash table of additional parameters:<BR>
* "codeBase": the origin of the source code.
* "archive": the jar-files.
* @param args The argument passed to the program.
*
*/
public AppStarter( AppStarterStatus status, String className, Hashtable atts, Vector args ) {
pStatusCallback = status;
this.className = className;
this.atts = atts;
int nSize = args.size();
boolean stringStarts = false;
Vector vec = new Vector();
String str = "";
for( int i = 0; i < nSize; i++ ) {
String entry = (String) args.elementAt( i );
if (stringStarts) {
if (entry.endsWith('"'+"") && !entry.endsWith("\\\"")) {//Test auf String-Ende
str += " "+ entry.substring(0, entry.length()-1);
stringStarts = false;
StringTokenizer stringTokenizer = new StringTokenizer(str, "\\", false);
String s = new String(stringTokenizer.nextToken());
while (stringTokenizer.hasMoreTokens()) {
String toc = stringTokenizer.nextToken();
if (toc.startsWith("\"")) {
s += toc;
} else {
s += '\\'+toc;
}
}
vec.addElement(s);
System.err.println("VecAdd1:" + s);
} else {
str += " "+ entry;
}
} else {
if (entry.trim().startsWith('"'+"")) {
stringStarts = true;
entry = entry.trim();
str = entry.substring(1, entry.length());
} else {
vec.addElement(entry);
System.err.println("VecAdd2:" + entry);
}
}
}
this.args = new String[ vec.size() ];
for (int i=0; i< vec.size(); i++) {
this.args[i] = (String) vec.elementAt(i);
}
starterThread = new Thread( this, "AppStarter" );
starterThread.start();
}
public void run() {
try {
ClassContext pLoader = null;
boolean bDoMain = false;
String workDir = null;;
/*
** Der ResourceProxy muss innerhalb des Scopes des ClassLoaders sein,
** da anderfalls der Proxy vom GC eventuell schon freigegeben wurde und
** die aus dem Archive gezogenen Resourcen schon weg sind.
*/
ResourceProxy resourceProxy = null;
if ( atts != null ) {
String jarFiles = (String) atts.get( "archive" );
String codeBase = (String) atts.get( "codeBase" );
String useMain = (String) atts.get( "useMain" );
workDir = (String) atts.get( "workDir" );
if ( codeBase != null ) {
URL url = new URL( codeBase );
if (url.getProtocol().equals("file")) {
pLoader = ClassContextProxy.create(url, null, null); // Security ausschalten
}
else {
pLoader = ClassContextProxy.create(url, null, null);
}
}
else if ( jarFiles != null ) {
try {
pLoader = ClassContextProxy.create(new URL("http://"), null, null);
}
catch(MalformedURLException e) {}
}
if (useMain != null) {
bDoMain = true;
}
if( jarFiles != null ) {
StringTokenizer st = new StringTokenizer(jarFiles, ",", false);
while (st.hasMoreTokens()) {
String tok = st.nextToken().trim();
try {
resourceProxy = ResourceProxy.load(new URL(pLoader.getBase(), tok), null);
resourceProxy.loadJar(pLoader.getBase());
}
catch(java.io.IOException iOException) {
System.err.println("Archive not found:" + iOException);
}
}
}
}
if (!bDoMain) {
try {
if ( args.length == 0 ) {
createdObject = Beans.instantiate( (pLoader == null)
? null
: pLoader.getClassLoader(), className );
if ( pStatusCallback != null ) {
pStatusCallback.started( createdObject );
}
} else {
bDoMain = true;
}
}
/*
** Die Beans fangen alle Exceptions und
** werfen stattdessen eine ClassNotFoundException.
*/
catch ( ClassNotFoundException classNotFoundException ) {
// catch ( NoSuchMethodError e ) {
bDoMain = true;
}
}
if ( bDoMain ) {
Class c;
if ( pLoader == null ) {
c = Class.forName( className );
} else {
c = pLoader.loadClass( className );
}
if (workDir != null) {
int error = setCurWorkDir(workDir);
if (error != 0)
throw new java.io.IOException("can't set working directory to " + workDir);
}
// try main
// first argument of main is a String[]
Class parameters[] = new Class[] {args.getClass()};
Method pMain = c.getMethod( "main", parameters );
if( pMain != null ) {
Object margs[] = new Object[] {args};
pMain.invoke(c, margs);
if ( pStatusCallback != null ) {
pStatusCallback.started( null );
}
}
}
}
catch(Exception e) {
if( pStatusCallback != null )
pStatusCallback.abort( e );
if (e instanceof java.lang.reflect.InvocationTargetException) {
((java.lang.reflect.InvocationTargetException) e).getTargetException().printStackTrace();
} else {
e.printStackTrace();
}
}
}
/**
* Es wird der LoaderThread beendet. Ist die Java Applikation schon gestartet,
* so kann diese auf diesem Weg nicht beendet werden.
*/
public void cancel() {
if (starterThread != null) {
try {
starterThread.stop();
} catch (SecurityException e) {
System.err.println("can`t stop thread "+
starterThread.toString() + " for reason: "+ e.toString() );
}
starterThread = null;
}
}
native static int setCurWorkDir(String directory);
public static void main( String [] args ) {
Properties props = new Properties();
props.put( "stardiv.security.defaultSecurityManager", "true" );
// Install a property list.
SjSettings.changeProperties(props);
Vector aArgs = new Vector( args.length );
for ( int i = 0; i < args.length; i++ ) {
aArgs.addElement( args[i] );
}
Hashtable atts = new Hashtable();
atts.put( "codeBase", "file:///f:/test/" );
// atts.put( "archive", "file:///f:/test/test.jar" );
atts.put( "archive", "test.jar" );
class Callback implements AppStarterStatus {
public void started( Object createdObject ) {
System.out.println( "started: " + createdObject );
}
public void abort( Throwable Excp ) {
System.out.println( "abort: " + Excp );
}
public void setCurrentWorkDir(String directory) {
System.out.println( "set current working directory to " + directory );
}
}
new AppStarter( new Callback(), "Application" , atts, aArgs );
}
}