1
2
3
4
5
6
7
8
9
10
11
12
13
14 package org.mortbay.start;
15
16 import java.io.BufferedReader;
17 import java.io.File;
18 import java.io.FileInputStream;
19 import java.io.IOException;
20 import java.io.InputStream;
21 import java.io.InputStreamReader;
22 import java.io.OutputStream;
23 import java.lang.reflect.InvocationTargetException;
24 import java.lang.reflect.Method;
25 import java.net.ConnectException;
26 import java.net.InetAddress;
27 import java.net.Socket;
28 import java.security.Policy;
29 import java.util.ArrayList;
30 import java.util.Arrays;
31 import java.util.Collections;
32 import java.util.HashSet;
33 import java.util.Hashtable;
34 import java.util.List;
35 import java.util.Set;
36 import java.util.StringTokenizer;
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105 public class Main
106 {
107 static boolean _debug=System.getProperty("DEBUG",null)!=null;
108 private String _classname=null;
109 private Classpath _classpath=new Classpath();
110 private String _config=System.getProperty("START","org/mortbay/start/start.config");
111 private ArrayList _xml=new ArrayList();
112 private boolean _version=false;
113
114 public static void main(String[] args)
115 {
116 try
117 {
118 if (args.length>0&&args[0].equalsIgnoreCase("--help"))
119 {
120 usage();
121 }
122 else if (args.length>0&&args[0].equalsIgnoreCase("--stop"))
123 {
124 new Main().stop();
125 }
126 else if (args.length>0&&args[0].equalsIgnoreCase("--version"))
127 {
128 String[] nargs=new String[args.length-1];
129 System.arraycopy(args,1,nargs,0,nargs.length);
130 Main main=new Main();
131 main._version=true;
132 main.start(nargs);
133 }
134 else
135 {
136 new Main().start(args);
137 }
138 }
139 catch (Exception e)
140 {
141 e.printStackTrace();
142 usage();
143 }
144 }
145
146 private static void usage()
147 {
148 System.err.println("Usage: java [-DDEBUG] [-DSTART=start.config] [-DOPTIONS=opts] [-Dmain.class=org.MyMain] -jar start.jar [--help|--stop|--version] [config ...]");
149 System.exit(1);
150 }
151
152 static File getDirectory(String name)
153 {
154 try
155 {
156 if (name!=null)
157 {
158 File dir=new File(name).getCanonicalFile();
159 if (dir.isDirectory())
160 {
161 return dir;
162 }
163 }
164 }
165 catch (IOException e)
166 {
167 }
168 return null;
169 }
170
171 boolean isAvailable(String classname)
172 {
173 try
174 {
175 Class.forName(classname);
176 return true;
177 }
178 catch (NoClassDefFoundError e)
179 {
180 }
181 catch (ClassNotFoundException e)
182 {
183 }
184 ClassLoader loader=_classpath.getClassLoader();
185 try
186 {
187 loader.loadClass(classname);
188 return true;
189 }
190 catch (NoClassDefFoundError e)
191 {
192 }
193 catch (ClassNotFoundException e)
194 {
195 }
196 return false;
197 }
198
199 public void invokeMain(ClassLoader classloader, String classname, String[] args) throws IllegalAccessException, InvocationTargetException,
200 NoSuchMethodException, ClassNotFoundException
201 {
202 Class invoked_class=null;
203 invoked_class=classloader.loadClass(classname);
204
205 if (_version)
206 {
207 System.err.println(invoked_class.getPackage().getImplementationTitle()+" "+invoked_class.getPackage().getImplementationVersion());
208 System.exit(0);
209 }
210
211 Class[] method_param_types=new Class[1];
212 method_param_types[0]=args.getClass();
213 Method main=null;
214 main=invoked_class.getDeclaredMethod("main",method_param_types);
215 Object[] method_params=new Object[1];
216 method_params[0]=args;
217
218 main.invoke(null,method_params);
219 }
220
221
222 String expand(String s)
223 {
224 int i1=0;
225 int i2=0;
226 while (s!=null)
227 {
228 i1=s.indexOf("$(",i2);
229 if (i1<0)
230 break;
231 i2=s.indexOf(")",i1+2);
232 if (i2<0)
233 break;
234 String property=System.getProperty(s.substring(i1+2,i2),"");
235 s=s.substring(0,i1)+property+s.substring(i2+1);
236 }
237 return s;
238 }
239
240
241 void configure(InputStream config, int nargs) throws Exception
242 {
243 BufferedReader cfg=new BufferedReader(new InputStreamReader(config,"ISO-8859-1"));
244 Version java_version=new Version(System.getProperty("java.version"));
245 Version ver=new Version();
246
247 Hashtable done=new Hashtable();
248
249 String classpath=System.getProperty("CLASSPATH");
250 if (classpath!=null)
251 {
252 StringTokenizer tok=new StringTokenizer(classpath,File.pathSeparator);
253 while (tok.hasMoreTokens())
254 _classpath.addComponent(tok.nextToken());
255 }
256
257 List section=null;
258 List options=null;
259 String o=System.getProperty("OPTIONS");
260 if (o==null)
261 o="default";
262 options=Arrays.asList((o.toString()+",*").split("[ ,]"));
263
264
265 String line=null;
266 while (true)
267 {
268 line=cfg.readLine();
269 if (line==null)
270 break;
271 String trim=line.trim();
272 if (trim.length()==0||trim.startsWith("#"))
273 continue;
274
275
276 if (trim.startsWith("[") && trim.endsWith("]"))
277 section = Arrays.asList(trim.substring(1,trim.length()-1).split("[ ,]"));
278
279 if (section!=null && Collections.disjoint(section,options))
280 continue;
281
282 try
283 {
284 StringTokenizer st=new StringTokenizer(line);
285 String subject=st.nextToken();
286 boolean expression=true;
287 boolean not=false;
288 String condition=null;
289
290 while (st.hasMoreTokens())
291 {
292 condition=st.nextToken();
293 if (condition.equalsIgnoreCase("!"))
294 {
295 not=true;
296 continue;
297 }
298 if (condition.equalsIgnoreCase("OR"))
299 {
300 if (expression)
301 break;
302 expression=true;
303 continue;
304 }
305 if (condition.equalsIgnoreCase("AND"))
306 {
307 if (!expression)
308 break;
309 continue;
310 }
311 boolean eval=true;
312 if (condition.equals("true")||condition.equals("always"))
313 {
314 eval=true;
315 }
316 else if (condition.equals("false")||condition.equals("never"))
317 {
318 eval=false;
319 }
320 else if (condition.equals("available"))
321 {
322 String class_to_check=st.nextToken();
323 eval=isAvailable(class_to_check);
324 }
325 else if (condition.equals("exists"))
326 {
327 try
328 {
329 eval=false;
330 File file=new File(expand(st.nextToken()));
331 eval=file.exists();
332 }
333 catch (Exception e)
334 {
335 if (_debug)
336 e.printStackTrace();
337 }
338 }
339 else if (condition.equals("property"))
340 {
341 String property=System.getProperty(st.nextToken());
342 eval=property!=null&&property.length()>0;
343 }
344 else if (condition.equals("java"))
345 {
346 String operator=st.nextToken();
347 String version=st.nextToken();
348 ver.parse(version);
349 eval=(operator.equals("<")&&java_version.compare(ver)<0)||(operator.equals(">")&&java_version.compare(ver)>0)
350 ||(operator.equals("<=")&&java_version.compare(ver)<=0)||(operator.equals("=<")&&java_version.compare(ver)<=0)
351 ||(operator.equals("=>")&&java_version.compare(ver)>=0)||(operator.equals(">=")&&java_version.compare(ver)>=0)
352 ||(operator.equals("==")&&java_version.compare(ver)==0)||(operator.equals("!=")&&java_version.compare(ver)!=0);
353 }
354 else if (condition.equals("nargs"))
355 {
356 String operator=st.nextToken();
357 int number=Integer.parseInt(st.nextToken());
358 eval=(operator.equals("<")&&nargs<number)||(operator.equals(">")&&nargs>number)||(operator.equals("<=")&&nargs<=number)
359 ||(operator.equals("=<")&&nargs<=number)||(operator.equals("=>")&&nargs>=number)||(operator.equals(">=")&&nargs>=number)
360 ||(operator.equals("==")&&nargs==number)||(operator.equals("!=")&&nargs!=number);
361 }
362 else
363 {
364 System.err.println("ERROR: Unknown condition: "+condition);
365 eval=false;
366 }
367 expression&=not?!eval:eval;
368 not=false;
369 }
370 String file=expand(subject).replace('/',File.separatorChar);
371 if (_debug)
372 System.err.println((expression?"T ":"F ")+line);
373 if (!expression)
374 {
375 done.put(file,file);
376 continue;
377 }
378
379 if (subject.indexOf("=")>0)
380 {
381 int i=file.indexOf("=");
382 String property=file.substring(0,i);
383 String value=file.substring(i+1);
384 if (_debug)
385 System.err.println(" "+property+"="+value);
386 System.setProperty(property,value);
387 }
388 else if (subject.endsWith("/*"))
389 {
390
391
392 File dir=new File(file.substring(0,file.length()-1));
393 addJars(dir,done,false);
394 }
395 else if (subject.endsWith("/**"))
396 {
397
398
399 File dir=new File(file.substring(0,file.length()-2));
400 addJars(dir,done,true);
401 }
402 else if (subject.endsWith("/"))
403 {
404
405 File cd=new File(file);
406 String d=cd.getCanonicalPath();
407 if (!done.containsKey(d))
408 {
409 done.put(d,d);
410 boolean added=_classpath.addComponent(d);
411 if (_debug)
412 System.err.println((added?" CLASSPATH+=":" !")+d);
413 }
414 }
415 else if (subject.toLowerCase().endsWith(".xml"))
416 {
417
418 File f=new File(file);
419 if (f.exists())
420 _xml.add(f.getCanonicalPath());
421 if (_debug)
422 System.err.println(" ARGS+="+f);
423 }
424 else if (subject.toLowerCase().endsWith(".class"))
425 {
426
427 String cn=expand(subject.substring(0,subject.length()-6));
428 if (cn!=null&&cn.length()>0)
429 {
430 if (_debug)
431 System.err.println(" CLASS="+cn);
432 _classname=cn;
433 }
434 }
435 else if (subject.toLowerCase().endsWith(".path"))
436 {
437
438 String cn=expand(subject.substring(0,subject.length()-5));
439 if (cn!=null&&cn.length()>0)
440 {
441 if (_debug)
442 System.err.println(" PATH="+cn);
443 _classpath.addClasspath(cn);
444 }
445 }
446 else
447 {
448
449 File f=new File(file);
450 if(f.exists())
451 {
452 String d=f.getCanonicalPath();
453 if (!done.containsKey(d))
454 {
455 done.put(d,d);
456 boolean added=_classpath.addComponent(d);
457 if (!added)
458 {
459 added=_classpath.addClasspath(expand(subject));
460 if (_debug)
461 System.err.println((added?" CLASSPATH+=":" !")+d);
462 }
463 else if (_debug)
464 System.err.println((added?" CLASSPATH+=":" !")+d);
465 }
466 }
467 }
468 }
469 catch (Exception e)
470 {
471 System.err.println("on line: '"+line+"'");
472 e.printStackTrace();
473 }
474 }
475 }
476
477
478 public void start(String[] args)
479 {
480 ArrayList al=new ArrayList();
481 for (int i=0; i<args.length; i++)
482 {
483 if (args[i]==null)
484 continue;
485 else
486 al.add(args[i]);
487 }
488 args=(String[])al.toArray(new String[al.size()]);
489
490 InputStream cpcfg=null;
491 try
492 {
493 Monitor.monitor();
494
495 cpcfg=getClass().getClassLoader().getResourceAsStream(_config);
496 if (_debug)
497 System.err.println("config="+_config);
498 if (cpcfg==null)
499 cpcfg=new FileInputStream(_config);
500 configure(cpcfg,args.length);
501 File file=new File(System.getProperty("jetty.home"));
502 String canonical=file.getCanonicalPath();
503 System.setProperty("jetty.home",canonical);
504 }
505 catch (Exception e)
506 {
507 e.printStackTrace();
508 System.exit(1);
509 }
510 finally
511 {
512 try
513 {
514 cpcfg.close();
515 }
516 catch (Exception e)
517 {
518 e.printStackTrace();
519 }
520 }
521
522 System.setProperty("java.class.path",_classpath.toString());
523 ClassLoader cl=_classpath.getClassLoader();
524 if (_debug)
525 {
526 System.err.println("java.class.path="+System.getProperty("java.class.path"));
527 System.err.println("jetty.home="+System.getProperty("jetty.home"));
528 System.err.println("java.io.tmpdir="+System.getProperty("java.io.tmpdir"));
529 System.err.println("java.class.path="+_classpath);
530 System.err.println("classloader="+cl);
531 System.err.println("classloader.parent="+cl.getParent());
532 }
533
534 Thread.currentThread().setContextClassLoader(cl);
535
536 try
537 {
538 Policy policy=Policy.getPolicy();
539 if (policy!=null)
540 policy.refresh();
541 }
542 catch (Exception e)
543 {
544 e.printStackTrace();
545 }
546 try
547 {
548 for (int i=0; i<args.length; i++)
549 {
550 if (args[i]==null)
551 continue;
552 _xml.add(args[i]);
553 }
554 args=(String[])_xml.toArray(args);
555
556 String mainClass=System.getProperty("jetty.server");
557 if (mainClass!=null)
558 _classname=mainClass;
559 mainClass=System.getProperty("main.class");
560 if (mainClass!=null)
561 _classname=mainClass;
562 if (_debug)
563 System.err.println("main.class="+_classname);
564 invokeMain(cl,_classname,args);
565 }
566 catch (Exception e)
567 {
568 e.printStackTrace();
569 }
570 }
571
572
573
574
575 public void stop()
576 {
577 int _port=Integer.getInteger("STOP.PORT",-1).intValue();
578 String _key=System.getProperty("STOP.KEY",null);
579
580 try
581 {
582 if (_port<=0)
583 System.err.println("STOP.PORT system property must be specified");
584 if (_key==null)
585 {
586 _key="";
587 System.err.println("STOP.KEY system property must be specified");
588 System.err.println("Using empty key");
589 }
590
591 Socket s=new Socket(InetAddress.getByName("127.0.0.1"),_port);
592 OutputStream out=s.getOutputStream();
593 out.write((_key+"\r\nstop\r\n").getBytes());
594 out.flush();
595 s.close();
596 }
597 catch (ConnectException e)
598 {
599 System.err.println("ERROR: Not running!");
600 }
601 catch (Exception e)
602 {
603 e.printStackTrace();
604 }
605 }
606
607 private void addJars(File dir, Hashtable table, boolean recurse) throws IOException
608 {
609 File[] entries=dir.listFiles();
610
611 for (int i=0; entries!=null&&i<entries.length; i++)
612 {
613 File entry=entries[i];
614
615 if (entry.isDirectory()&&recurse)
616 addJars(entry,table,recurse);
617 else
618 {
619 String name=entry.getName().toLowerCase();
620 if (name.endsWith(".jar")||name.endsWith(".zip"))
621 {
622 String jar=entry.getCanonicalPath();
623 if (!table.containsKey(jar))
624 {
625 table.put(jar,jar);
626 boolean added=_classpath.addComponent(jar);
627 if (_debug)
628 System.err.println((added?" CLASSPATH+=":" !")+jar);
629 }
630 }
631 }
632 }
633 }
634 }