KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > osgi > framework > launcher > Launcher


1 /*******************************************************************************
2  * Copyright (c) 2003, 2006 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11
12 package org.eclipse.osgi.framework.launcher;
13
14 import java.lang.reflect.Constructor JavaDoc;
15 import java.util.*;
16 import org.eclipse.osgi.framework.adaptor.FrameworkAdaptor;
17 import org.eclipse.osgi.framework.internal.core.*;
18 import org.eclipse.osgi.util.NLS;
19
20 /**
21  * <p>This class provides an entry point for launching the OSGi framework.
22  * It configures the OSGi framework according to the command line arguments:
23  * <ul>
24  * <li><b>-con[sole][:<i>port</i>]</b><br>
25  * Starts the OSGi framework with a console window. Any command line arguments not recognized are passed
26  * to the console for it to execute. If a port is specified the console will listen on that
27  * port for commands. If no port is specified, the console will use System.in and System.out.
28  * </li>
29  * <li><b>-adaptor[:adaptor-name][adaptor-args]</b>
30  * <pre>
31  * [adaptor-name] := "" | fully qualified class name of the FrameworkAdapter
32  * [adaptor-args] := *( ":" [value])
33  * [value] := [token] | [quoted-string]
34  *
35  * This allows
36  *
37  * -adaptor::"bundledir=c:\jarbundles":reset DefaultAdaptor is chosen with args[] {"bundledir=c:\jarbundles", "reset"}
38  * -adaptor:com.foo.MyAdaptor com.foo.MyAdaptor chosen with args[] {}
39  * </pre>
40  * <p>-adaptor specifies the implementation class for the FrameworkAdapter to be used.
41  * args contains a list of FrameworkAdaptor arguments, separated by ":". FrameworkAdaptor arguments
42  * format is defined by the adaptor implementation class. They
43  * are passed to the adaptor class as an array of Strings.
44  * Example arguments used by the DefaultAdaptor are:
45  * <ul>
46  * <li>"bundledir=<i>directory"</i>. The directory to be used by the adaptor to store data.
47  * <li>reset</i>. Perform the reset action to clear the bundledir.
48  * <p>Actions can be defined by an adaptor. Multiple actions can be specified,
49  * separated by ":".
50  * </ul>
51  * <p>It is up to the adaptor implementation to define reasonable defaults if it's required
52  * arguments are not specified.
53  * <p>If -adaptor is not specified, or if no adaptor classname is specified, DefaultAdaptor will be
54  * used, which is file based and stores the files in the \bundles directory
55  * relative to the current directory.
56  * </ul>
57  * <li>-app[lication]:application-args
58  * <pre>
59  * [application-args] := *( ":" [value])
60  * [value] := [token] | [quoted-string]
61  * </pre>
62  * <p>This argument allows arguments to be passed to specific applications at launch time. This is for eclipse
63  * plugins installed as applications. The arguments are as Eclipse currently needs them - one list of key=value pairs
64  * which are parsed by the applications. The application peels off only the args that apply to it. Others are ignored.
65  * </li>
66  * <p>
67  * Any other command line arguments are passed on to the console window
68  * of the framework if started with the -console option. If the console is not started,
69  * any unrecognized arguments will be ignored and a message displayed.
70  * <p>
71  * If none of the options above are specified, the OSGi framework is started:
72  * <ul>
73  * <li>with the Default FrameworkAdaptor
74  * <li>without a console window
75  * <li>without the remote agent
76  * </ul>
77  * @since 3.1
78  */

79 public class Launcher {
80
81     /** default console port */
82     protected String JavaDoc consolePort = ""; //$NON-NLS-1$
83

84     /** flag to indicate whether or not to start the console */
85     protected boolean console = false;
86
87     /** string containing the classname of the adaptor to be used in this framework instance */
88     protected String JavaDoc adaptorClassName = "org.eclipse.osgi.baseadaptor.BaseAdaptor"; //$NON-NLS-1$
89

90     protected final String JavaDoc osgiConsoleClazz = "org.eclipse.osgi.framework.internal.core.FrameworkConsole"; //$NON-NLS-1$
91

92     /** array of adaptor arguments to be passed to FrameworkAdaptor.initialize() */
93     protected String JavaDoc[] adaptorArgs = null;
94
95     /* Components that can be installed and activated optionally. */
96     private static final String JavaDoc OSGI_CONSOLE_COMPONENT_NAME = "OSGi Console"; //$NON-NLS-1$
97
private static final String JavaDoc OSGI_CONSOLE_COMPONENT = "console.jar"; //$NON-NLS-1$
98

99     /**
100      * main method for Launcher. This method creates an Launcher object
101      * and kicks off the actual launch of a Framework instance.
102      *
103      * @param args The command line arguments
104      */

105     public static void main(String JavaDoc args[]) {
106
107         new Launcher().doIt(args);
108
109     }
110
111     /**
112      * Default constructor. Nothing at all to do here.
113      */

114     public Launcher() {
115         // do nothing;
116
}
117
118     /**
119      * Performs the actual launch based on the command line arguments
120      *
121      * @param args The command line arguments
122      */

123     protected void doIt(String JavaDoc[] args) {
124         // set the compatibility boot delegation flag to false to get "standard" OSGi behavior WRT boot delegation (bug 178477)
125
if (FrameworkProperties.getProperty(Constants.OSGI_COMPATIBILITY_BOOTDELEGATION) == null)
126             FrameworkProperties.setProperty(Constants.OSGI_COMPATIBILITY_BOOTDELEGATION, "false"); //$NON-NLS-1$
127
String JavaDoc[] consoleArgs = parseArgs(args);
128
129         FrameworkAdaptor adaptor = null;
130         try {
131             adaptor = doAdaptor();
132         } catch (Exception JavaDoc e) {
133             System.out.println(Msg.LAUNCHER_ADAPTOR_ERROR);
134             e.printStackTrace();
135             return;
136         }
137
138         OSGi osgi = doOSGi(adaptor);
139         if (osgi != null) {
140             if (console) {
141                 doConsole(osgi, consoleArgs);
142             } else {
143                 osgi.launch();
144             }
145         }
146     }
147
148     /**
149      * Parses the command line arguments and remembers them so they can be processed later.
150      *
151      * @param args The command line arguments
152      * @return String [] Any arguments that should be passed to the console
153      */

154     protected String JavaDoc[] parseArgs(String JavaDoc[] args) {
155         Vector consoleArgsVector = new Vector();
156         for (int i = 0; i < args.length; i++) {
157             boolean match = false;
158
159             // Have to check for args that may be contained in double quotes but broken up by spaces - for example
160
// -adaptor::"bundledir=c:/my bundle dir":reset should all be one arg, but java breaks it into 3 args,
161
// ignoring the quotes. Must put it back together into one arg.
162
String JavaDoc fullarg = args[i];
163             int quoteidx = fullarg.indexOf("\""); //$NON-NLS-1$
164
if (quoteidx > 0) {
165                 if (quoteidx == fullarg.lastIndexOf("\"")) { //$NON-NLS-1$
166
boolean stillparsing = true;
167                     i++;
168                     while (i < args.length && stillparsing) {
169                         fullarg = fullarg + " " + args[i]; //$NON-NLS-1$
170
i++;
171                         if (quoteidx < fullarg.lastIndexOf("\"")) { //$NON-NLS-1$
172
stillparsing = false;
173                         }
174                     }
175                 }
176             } else {
177                 // IDE can't pass double quotes due to known eclipse bug (see Bugzilla 93201). Allowing for use of single quotes.
178
quoteidx = fullarg.indexOf("'"); //$NON-NLS-1$
179
if (quoteidx > 0) {
180                     if (quoteidx == fullarg.lastIndexOf("'")) { //$NON-NLS-1$
181
boolean stillparsing = true;
182                         i++;
183                         while (i < args.length && stillparsing) {
184                             fullarg = fullarg + " " + args[i]; //$NON-NLS-1$
185
i++;
186                             if (quoteidx < fullarg.lastIndexOf("'")) { //$NON-NLS-1$
187
stillparsing = false;
188                             }
189                         }
190                     }
191                     fullarg = fullarg.replace('\'', '\"');
192                 }
193             }
194
195             Tokenizer tok = new Tokenizer(fullarg);
196             if (tok.hasMoreTokens()) {
197                 String JavaDoc command = tok.getString(" "); //$NON-NLS-1$
198
StringTokenizer subtok = new StringTokenizer(command, ":"); //$NON-NLS-1$
199
String JavaDoc subcommand = subtok.nextToken().toLowerCase();
200
201                 if (matchCommand("-console", subcommand, 4)) { //$NON-NLS-1$
202
_console(command);
203                     match = true;
204                 }
205                 if (matchCommand("-adaptor", subcommand, 2)) { //$NON-NLS-1$
206
_adaptor(command);
207                     match = true;
208                 }
209                 if (match == false) {
210                     // if the command doesn't match any of the known commands, save it to pass
211
// to the console
212
consoleArgsVector.addElement(fullarg);
213                 }
214             }
215         }
216         // convert arguments to be passed to console into a string array for the Console
217
String JavaDoc[] consoleArgsArray = new String JavaDoc[consoleArgsVector.size()];
218         Enumeration e = consoleArgsVector.elements();
219         for (int i = 0; i < consoleArgsArray.length; i++) {
220             consoleArgsArray[i] = (String JavaDoc) e.nextElement();
221         }
222         return consoleArgsArray;
223     }
224
225     public static boolean matchCommand(String JavaDoc command, String JavaDoc input, int minLength) {
226         if (minLength <= 0) {
227             minLength = command.length();
228         }
229
230         int length = input.length();
231
232         if (minLength > length) {
233             length = minLength;
234         }
235
236         return (command.regionMatches(0, input, 0, length));
237     }
238
239     /**
240      * Remembers that the -console option has been requested.
241      */

242     protected void _console(String JavaDoc command) {
243         console = true;
244         StringTokenizer tok = new StringTokenizer(command, ":"); //$NON-NLS-1$
245
// first token is always "-console"
246
tok.nextToken();
247         if (tok.hasMoreTokens()) {
248             consolePort = tok.nextToken();
249         }
250     }
251
252     /**
253      * Remembers that the -adaptor option has been requested. Parses off the adaptor class
254      * file name, the adaptor file name, and the size if they are there.
255      *
256      * @param command The rest of the -adaptor parameter string that contains the class file name,
257      * and possibly the adaptor file and file size.
258      */

259     protected void _adaptor(String JavaDoc command) {
260         Tokenizer tok = new Tokenizer(command);
261         // first token is always "-adaptor"
262
tok.getToken(":"); //$NON-NLS-1$
263
tok.getChar(); // advance to next token
264
// and next token is either adaptor class name or ":" if we should use the default adaptor
265
String JavaDoc adp = tok.getToken(":"); //$NON-NLS-1$
266
if (adp != null && adp.length() > 0) {
267             adaptorClassName = adp;
268         }
269
270         // The following tokens are arguments to be processed by the adaptor implementation class.
271
// They may be enclosed in quotes.
272
// Store them in a vector until we know how many there are.
273
Vector v = new Vector();
274         parseloop: while (true) {
275             tok.getChar(); // advance to next token
276
String JavaDoc arg = tok.getString(":"); //$NON-NLS-1$
277
if (arg == null)
278                 break parseloop;
279             v.addElement(arg);
280         }
281         // now that we know how many args there are, move args from vector to String[]
282
if (v != null) {
283             int numArgs = v.size();
284             adaptorArgs = new String JavaDoc[numArgs];
285             Enumeration e = v.elements();
286             for (int i = 0; i < numArgs; i++) {
287                 adaptorArgs[i] = (String JavaDoc) e.nextElement();
288             }
289         }
290     }
291
292     /**
293      * Processes the -adaptor command line argument.
294      *
295      * Parses the arguments to get the adaptor class name, the adaptor dir or filename,
296      * and the adaptor file size.
297      *
298      * @return a FrameworkAdaptor object
299      */

300     protected FrameworkAdaptor doAdaptor() throws Exception JavaDoc {
301
302         Class JavaDoc adaptorClass = Class.forName(adaptorClassName);
303         Class JavaDoc[] constructorArgs = new Class JavaDoc[] {String JavaDoc[].class};
304         Constructor JavaDoc constructor = adaptorClass.getConstructor(constructorArgs);
305         return (FrameworkAdaptor) constructor.newInstance(new Object JavaDoc[] {adaptorArgs});
306     }
307
308     /**
309      * Creates the OSGi framework object.
310      *
311      * @param adaptor The FrameworkAdaptor object
312      */

313     private OSGi doOSGi(FrameworkAdaptor adaptor) {
314         return new OSGi(adaptor);
315     }
316
317     /**
318      * Invokes the OSGi Console on another thread
319      *
320      * @param osgi The current OSGi instance for the console to attach to
321      * @param consoleArgs An String array containing commands from the command line
322      * for the console to execute
323      */

324     private void doConsole(OSGi osgi, String JavaDoc[] consoleArgs) {
325
326         Constructor JavaDoc consoleConstructor;
327         Object JavaDoc osgiconsole;
328         Class JavaDoc[] parameterTypes;
329         Object JavaDoc[] parameters;
330
331         try {
332             Class JavaDoc osgiconsoleClass = Class.forName(osgiConsoleClazz);
333             if (consolePort.length() == 0) {
334                 parameterTypes = new Class JavaDoc[] {OSGi.class, String JavaDoc[].class};
335                 parameters = new Object JavaDoc[] {osgi, consoleArgs};
336             } else {
337                 parameterTypes = new Class JavaDoc[] {OSGi.class, int.class, String JavaDoc[].class};
338                 parameters = new Object JavaDoc[] {osgi, new Integer JavaDoc(consolePort), consoleArgs};
339             }
340             consoleConstructor = osgiconsoleClass.getConstructor(parameterTypes);
341             osgiconsole = consoleConstructor.newInstance(parameters);
342
343             Thread JavaDoc t = new Thread JavaDoc(((Runnable JavaDoc) osgiconsole), OSGI_CONSOLE_COMPONENT_NAME);
344             t.start();
345         } catch (NumberFormatException JavaDoc nfe) {
346             System.err.println(NLS.bind(Msg.LAUNCHER_INVALID_PORT, consolePort));
347         } catch (Exception JavaDoc ex) {
348             informAboutMissingComponent(OSGI_CONSOLE_COMPONENT_NAME, OSGI_CONSOLE_COMPONENT);
349         }
350
351     }
352
353     /**
354      * Informs the user about a missing component.
355      *
356      * @param component The name of the component
357      * @param jar The jar file that contains the component
358      */

359     void informAboutMissingComponent(String JavaDoc component, String JavaDoc jar) {
360         System.out.println();
361         System.out.print(NLS.bind(Msg.LAUNCHER_COMPONENT_MISSING, component));
362         System.out.println(NLS.bind(Msg.LAUNCHER_COMPONENT_JAR, jar));
363         System.out.println();
364     }
365 }
366
Popular Tags