1
2
3
4
5
6
7
8
9
10
11
12
13 package org.eclipse.jetty.start;
14
15 import java.io.BufferedReader;
16 import java.io.File;
17 import java.io.FileInputStream;
18 import java.io.IOException;
19 import java.io.InputStream;
20 import java.io.InputStreamReader;
21 import java.io.OutputStream;
22 import java.lang.reflect.Constructor;
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.HashMap;
33 import java.util.HashSet;
34 import java.util.Hashtable;
35 import java.util.Iterator;
36 import java.util.List;
37 import java.util.Map;
38 import java.util.Set;
39 import java.util.StringTokenizer;
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 private static final String _version = (Main.class.getPackage()!=null && Main.class.getPackage().getImplementationVersion()!=null)
108 ?Main.class.getPackage().getImplementationVersion()
109 :"Unknown";
110
111 public static boolean DEBUG=false;
112
113 private Map<String,String> _properties = new HashMap<String,String>();
114
115
116 private String _classname=null;
117 private Classpath _classpath=new Classpath();
118
119 private boolean _showVersions=false;
120 private List<String> _xml=new ArrayList<String>();
121 private Set<String> _activeOptions = new HashSet<String>();
122 private Set<String> _options = new HashSet<String>();
123 private Set<String> _policies = new HashSet<String>();
124
125
126
127
128
129 public static void main(String[] args)
130 {
131 try
132 {
133 Main main=new Main();
134 List<String> arguments = new ArrayList<String>(Arrays.asList(args));
135
136 for (int i=0; i<arguments.size(); i++)
137 {
138 String arg=arguments.get(i);
139 if (arg.equalsIgnoreCase("--help"))
140 {
141 usage();
142 }
143
144 if (arg.equalsIgnoreCase("--stop"))
145 {
146 int port = Integer.parseInt(main.getProperty("STOP.PORT","-1"));
147 String key = main.getProperty("STOP.KEY", null);
148 main.stop(port,key);
149 return;
150 }
151
152 if (arg.equalsIgnoreCase("--version")||arg.equalsIgnoreCase("-v")||arg.equalsIgnoreCase("-info"))
153 {
154 arguments.remove(i--);
155 main._showVersions=true;
156 }
157
158 if (arg.indexOf('=')>=0)
159 {
160 arguments.remove(i--);
161 String[] assign=arg.split("=",2);
162
163 if (assign.length==2)
164 main.setProperty(assign[0],assign[1]);
165 else
166 main.setProperty(assign[0],null);
167 }
168 }
169
170 DEBUG=Boolean.parseBoolean(main.getProperty("DEBUG","false"));
171 main.start(arguments.toArray(new String[arguments.size()]));
172
173 }
174 catch (Exception e)
175 {
176 e.printStackTrace();
177 usage();
178 }
179 }
180
181 private String getSystemProperty(String name)
182 {
183 if ("version".equalsIgnoreCase(name))
184 return _version;
185 if (_properties.containsKey(name))
186 return _properties.get(name);
187 return System.getProperty(name);
188 }
189
190 private String getProperty(String name)
191 {
192 if ("version".equalsIgnoreCase(name))
193 return _version;
194
195 return _properties.get(name);
196 }
197
198 private String getProperty(String name, String dftValue)
199 {
200 if (_properties.containsKey(name))
201 return _properties.get(name);
202 return dftValue;
203 }
204
205 private void setProperty(String name, String value)
206 {
207 _properties.put(name,value);
208 }
209
210 private static void usage()
211 {
212 System.err.println("Usage: java -jar start.jar [--help|--stop|--version] [OPTIONS=option,...] [name=value ...] [config ...]");
213 System.exit(1);
214 }
215
216 static File getDirectory(String name)
217 {
218 try
219 {
220 if (name!=null)
221 {
222 File dir=new File(name).getCanonicalFile();
223 if (dir.isDirectory())
224 {
225 return dir;
226 }
227 }
228 }
229 catch (IOException e)
230 {
231 }
232 return null;
233 }
234
235 boolean isAvailable(String classname)
236 {
237 try
238 {
239 Class.forName(classname);
240 return true;
241 }
242 catch (NoClassDefFoundError e)
243 {
244 if (DEBUG)
245 System.err.println(e);
246 }
247 catch (ClassNotFoundException e)
248 {
249 if (DEBUG)
250 System.err.println(e);
251 }
252 ClassLoader loader=_classpath.getClassLoader();
253 try
254 {
255 loader.loadClass(classname);
256 return true;
257 }
258 catch (NoClassDefFoundError e)
259 {
260 if (DEBUG)
261 System.err.println(e);
262 }
263 catch (ClassNotFoundException e)
264 {
265 if (DEBUG)
266 System.err.println(e);
267 }
268 return false;
269 }
270
271 public void invokeMain(ClassLoader classloader, String classname, String[] args) throws IllegalAccessException, InvocationTargetException,
272 NoSuchMethodException, ClassNotFoundException
273 {
274 Class invoked_class=null;
275
276 try
277 {
278 invoked_class=classloader.loadClass(classname);
279 }
280 catch(ClassNotFoundException e)
281 {
282
283 }
284
285 if (DEBUG || _showVersions || invoked_class==null)
286 {
287 if (invoked_class==null)
288 System.err.println("ClassNotFound: "+classname);
289 else
290 System.err.println(classname+" "+invoked_class.getPackage().getImplementationVersion());
291 File[] elements = _classpath.getElements();
292 for (int i=0;i<elements.length;i++)
293 System.err.println(" "+elements[i].getAbsolutePath());
294 if (_showVersions || invoked_class==null)
295 {
296 System.err.println("OPTIONS: "+_options);
297 usage();
298 }
299 }
300
301 Class[] method_param_types=new Class[1];
302 method_param_types[0]=args.getClass();
303 Method main=null;
304 main=invoked_class.getDeclaredMethod("main",method_param_types);
305 Object[] method_params=new Object[1];
306 method_params[0]=args;
307
308 main.invoke(null,method_params);
309 }
310
311
312 String expand(String s)
313 {
314 int i1=0;
315 int i2=0;
316 while (s!=null)
317 {
318 i1=s.indexOf("$(");
319 if (i1<0)
320 break;
321 i2=s.indexOf(")",i1+2);
322 if (i2<0)
323 break;
324 String name=s.substring(i1+2,i2);
325 String property=getSystemProperty(name);
326 s=s.substring(0,i1)+property+s.substring(i2+1);
327 }
328
329 i1=0;
330 i2=0;
331 while (s!=null)
332 {
333 i1=s.indexOf("${");
334 if (i1<0)
335 break;
336 i2=s.indexOf("}",i1+2);
337 if (i2<0)
338 break;
339 String name=s.substring(i1+2,i2);
340 String property=getProperty(name);
341 s=s.substring(0,i1)+property+s.substring(i2+1);
342 }
343
344 return s;
345 }
346
347
348 void configure(InputStream config, int nargs) throws Exception
349 {
350 BufferedReader cfg=new BufferedReader(new InputStreamReader(config,"ISO-8859-1"));
351 Version java_version=new Version(System.getProperty("java.version"));
352 Version ver=new Version();
353
354 Set<String> done=new HashSet<String>();
355
356
357 String classpath=System.getProperty("CLASSPATH");
358 if (classpath!=null)
359 {
360 StringTokenizer tok=new StringTokenizer(classpath,File.pathSeparator);
361 while (tok.hasMoreTokens())
362 _classpath.addComponent(tok.nextToken());
363 }
364
365 List<String> section=null;
366 String o=getProperty("OPTIONS","default");
367 _activeOptions.addAll(Arrays.asList((o.toString()+",*").split("[ ,]")));
368 List<String> unsatisfied_options = new ArrayList<String>( _activeOptions );
369
370
371 String line=null;
372 while (true)
373 {
374 line=cfg.readLine();
375 if (line==null)
376 break;
377 String trim=line.trim();
378 if (trim.length()==0||trim.startsWith("#"))
379 continue;
380
381
382 if (trim.startsWith("[") && trim.endsWith("]"))
383 {
384 section = Arrays.asList(trim.substring(1,trim.length()-1).split("[ ,]"));
385 _options.addAll(section);
386 }
387
388 if (section!=null && Collections.disjoint(section,_activeOptions))
389 continue;
390 if (section!=null)
391 unsatisfied_options.removeAll(section);
392 try
393 {
394 StringTokenizer st=new StringTokenizer(line);
395 String subject=st.nextToken();
396 boolean expression=true;
397 boolean not=false;
398 String condition=null;
399
400 while (st.hasMoreTokens())
401 {
402 condition=st.nextToken();
403 if (condition.equalsIgnoreCase("!"))
404 {
405 not=true;
406 continue;
407 }
408 if (condition.equalsIgnoreCase("OR"))
409 {
410 if (expression)
411 break;
412 expression=true;
413 continue;
414 }
415 if (condition.equalsIgnoreCase("AND"))
416 {
417 if (!expression)
418 break;
419 continue;
420 }
421 boolean eval=true;
422 if (condition.equals("true")||condition.equals("always"))
423 {
424 eval=true;
425 }
426 else if (condition.equals("false")||condition.equals("never"))
427 {
428 eval=false;
429 }
430 else if (condition.equals("available"))
431 {
432 String class_to_check=st.nextToken();
433 eval=isAvailable(class_to_check);
434 }
435 else if (condition.equals("exists"))
436 {
437 try
438 {
439 eval=false;
440 File file=new File(expand(st.nextToken()));
441 eval=file.exists();
442 }
443 catch (Exception e)
444 {
445 if (DEBUG)
446 e.printStackTrace();
447 }
448 }
449 else if (condition.equals("property"))
450 {
451 String property=getProperty(st.nextToken());
452 eval=property!=null&&property.length()>0;
453 }
454 else if (condition.equals("system"))
455 {
456 String property=System.getProperty(st.nextToken());
457 eval=property!=null&&property.length()>0;
458 }
459 else if (condition.equals("java"))
460 {
461 String operator=st.nextToken();
462 String version=st.nextToken();
463 ver.parse(version);
464 eval=(operator.equals("<")&&java_version.compare(ver)<0)||(operator.equals(">")&&java_version.compare(ver)>0)
465 ||(operator.equals("<=")&&java_version.compare(ver)<=0)||(operator.equals("=<")&&java_version.compare(ver)<=0)
466 ||(operator.equals("=>")&&java_version.compare(ver)>=0)||(operator.equals(">=")&&java_version.compare(ver)>=0)
467 ||(operator.equals("==")&&java_version.compare(ver)==0)||(operator.equals("!=")&&java_version.compare(ver)!=0);
468 }
469 else if (condition.equals("nargs"))
470 {
471 String operator=st.nextToken();
472 int number=Integer.parseInt(st.nextToken());
473 eval=(operator.equals("<")&&nargs<number)||(operator.equals(">")&&nargs>number)||(operator.equals("<=")&&nargs<=number)
474 ||(operator.equals("=<")&&nargs<=number)||(operator.equals("=>")&&nargs>=number)||(operator.equals(">=")&&nargs>=number)
475 ||(operator.equals("==")&&nargs==number)||(operator.equals("!=")&&nargs!=number);
476 }
477 else
478 {
479 System.err.println("ERROR: Unknown condition: "+condition);
480 eval=false;
481 }
482 expression&=not?!eval:eval;
483 not=false;
484 }
485 String file=expand(subject).replace('/',File.separatorChar);
486 if (DEBUG)
487 System.err.println((expression?"T ":"F ")+line);
488 if (!expression)
489 {
490 done.add(file);
491 continue;
492 }
493
494
495
496 if (subject.indexOf("~=")>0)
497 {
498 int i=file.indexOf("~=");
499 String property=file.substring(0,i);
500 String value=file.substring(i+2);
501 if (DEBUG)
502 System.err.println(" "+property+"~="+value);
503 setProperty(property,value);
504 }
505 if (subject.indexOf("/=")>0)
506 {
507 int i=file.indexOf("/=");
508 String property=file.substring(0,i);
509 String value=file.substring(i+2);
510 String canonical=new File(value).getCanonicalPath();
511 if (DEBUG)
512 System.err.println(" "+property+"/="+value+"=="+canonical);
513 setProperty(property,canonical);
514 }
515 else if (subject.indexOf("=")>0)
516 {
517 int i=file.indexOf("=");
518 String property=file.substring(0,i);
519 String value=file.substring(i+1);
520 if (DEBUG)
521 System.err.println(" "+property+"="+value);
522 System.setProperty(property,value);
523 }
524 else if (subject.endsWith("/*"))
525 {
526
527
528 File dir=new File(file.substring(0,file.length()-1));
529 addJars(dir,done,false);
530 }
531 else if (subject.endsWith("/**"))
532 {
533
534
535 File dir=new File(file.substring(0,file.length()-2));
536 addJars(dir,done,true);
537 }
538 else if (subject.endsWith("/"))
539 {
540
541 File cd=new File(file);
542 String d=cd.getCanonicalPath();
543 if (!done.contains(d))
544 {
545 done.add(d);
546 boolean added=_classpath.addComponent(d);
547 if (DEBUG)
548 System.err.println((added?" CLASSPATH+=":" !")+d);
549 }
550 }
551 else if (subject.toLowerCase().endsWith(".xml"))
552 {
553
554 File f=new File(file);
555 if (f.exists())
556 _xml.add(f.getCanonicalPath());
557 if (DEBUG)
558 System.err.println(" ARGS+="+f);
559 }
560 else if (subject.toLowerCase().endsWith(".class"))
561 {
562
563 String cn=expand(subject.substring(0,subject.length()-6));
564 if (cn!=null&&cn.length()>0)
565 {
566 if (DEBUG)
567 System.err.println(" CLASS="+cn);
568 _classname=cn;
569 }
570 }
571 else if (subject.toLowerCase().endsWith(".path"))
572 {
573
574 String cn=expand(subject.substring(0,subject.length()-5));
575 if (cn!=null&&cn.length()>0)
576 {
577 if (DEBUG)
578 System.err.println(" PATH="+cn);
579 _classpath.addClasspath(cn);
580 }
581 }
582 else if (subject.toLowerCase().endsWith(".policy"))
583 {
584
585 String cn=expand(subject.substring(0,subject.length()));
586 if (cn!=null&&cn.length()>0)
587 {
588 if (DEBUG)
589 System.err.println(" POLICY="+cn);
590 _policies.add(cn);
591 }
592 }
593 else
594 {
595
596 File f=new File(file);
597 if(f.exists())
598 {
599 String d=f.getCanonicalPath();
600 if (!done.contains(d))
601 {
602 done.add(d);
603 boolean added=_classpath.addComponent(d);
604 if (!added)
605 {
606 added=_classpath.addClasspath(expand(subject));
607 if (DEBUG)
608 System.err.println((added?" CLASSPATH+=":" !")+d);
609 }
610 else if (DEBUG)
611 System.err.println((added?" CLASSPATH+=":" !")+d);
612 }
613 }
614 }
615 }
616 catch (Exception e)
617 {
618 System.err.println("on line: '"+line+"'");
619 e.printStackTrace();
620 }
621 }
622
623 if (unsatisfied_options!=null && unsatisfied_options.size()>0)
624 {
625 System.err.println("Unresolved options: "+unsatisfied_options);
626 }
627 }
628
629
630 public void start(String[] args)
631 {
632
633 InputStream cpcfg=null;
634 try
635 {
636 int port = Integer.parseInt(getProperty("STOP.PORT","-1"));
637 String key = getProperty("STOP.KEY", null);
638
639 Monitor.monitor(port,key);
640
641 String config=getProperty("START","org/eclipse/jetty/start/start.config");
642 if (DEBUG)
643 {
644 System.err.println("config="+config);
645 System.err.println("properties="+_properties);
646 }
647 cpcfg=getClass().getClassLoader().getResourceAsStream(config);
648 if (cpcfg==null)
649 cpcfg=new FileInputStream(config);
650
651 configure(cpcfg,args.length);
652
653 String jetty_home=System.getProperty("jetty.home");
654 if (jetty_home!=null)
655 {
656 File file=new File(jetty_home);
657 String canonical=file.getCanonicalPath();
658 System.setProperty("jetty.home",canonical);
659 }
660
661 }
662 catch (Exception e)
663 {
664 e.printStackTrace();
665 System.exit(1);
666 }
667 finally
668 {
669 try
670 {
671 cpcfg.close();
672 }
673 catch (Exception e)
674 {
675 e.printStackTrace();
676 }
677 }
678
679 System.setProperty("java.class.path",_classpath.toString());
680 ClassLoader cl=_classpath.getClassLoader();
681 if (DEBUG)
682 {
683 System.err.println("java.class.path="+System.getProperty("java.class.path"));
684 System.err.println("jetty.home="+System.getProperty("jetty.home"));
685 System.err.println("java.io.tmpdir="+System.getProperty("java.io.tmpdir"));
686 System.err.println("java.class.path="+_classpath);
687 System.err.println("classloader="+cl);
688 System.err.println("classloader.parent="+cl.getParent());
689 }
690
691 Thread.currentThread().setContextClassLoader(cl);
692
693 try
694 {
695 if ( _activeOptions.contains("secure") )
696 {
697 Class jettyPolicy = cl.loadClass( "org.eclipse.jetty.policy.JettyPolicy" );
698 Constructor c = jettyPolicy.getConstructor( new Class[] { Set.class, Map.class } );
699 Object policyClass = c.newInstance( _policies, _properties );
700
701 Policy.setPolicy( (Policy)policyClass );
702 System.setSecurityManager( new SecurityManager() );
703 }
704 else
705 {
706 Policy policy=Policy.getPolicy();
707 if (policy!=null)
708 policy.refresh();
709 }
710 }
711 catch (Exception e)
712 {
713 e.printStackTrace();
714 }
715 try
716 {
717 for (int i=0; i<args.length; i++)
718 {
719 if (args[i]==null)
720 continue;
721 _xml.add(args[i]);
722 }
723 args=(String[])_xml.toArray(args);
724
725 String mainClass=System.getProperty("jetty.server");
726 if (mainClass!=null)
727 _classname=mainClass;
728 mainClass=System.getProperty("main.class");
729 if (mainClass!=null)
730 _classname=mainClass;
731 if (DEBUG)
732 System.err.println("main.class="+_classname);
733 invokeMain(cl,_classname,args);
734 }
735 catch (Exception e)
736 {
737 e.printStackTrace();
738 }
739 }
740
741
742
743
744 public void stop(int port,String key)
745 {
746 int _port=port;
747 String _key=key;
748
749 try
750 {
751 if (_port<=0)
752 System.err.println("STOP.PORT system property must be specified");
753 if (_key==null)
754 {
755 _key="";
756 System.err.println("STOP.KEY system property must be specified");
757 System.err.println("Using empty key");
758 }
759
760 Socket s=new Socket(InetAddress.getByName("127.0.0.1"),_port);
761 OutputStream out=s.getOutputStream();
762 out.write((_key+"\r\nstop\r\n").getBytes());
763 out.flush();
764 s.close();
765 }
766 catch (ConnectException e)
767 {
768 System.err.println("ERROR: Not running!");
769 }
770 catch (Exception e)
771 {
772 e.printStackTrace();
773 }
774 }
775
776 private void addJars(File dir, Set<String> table, boolean recurse) throws IOException
777 {
778 File[] entries=dir.listFiles();
779
780 for (int i=0; entries!=null&&i<entries.length; i++)
781 {
782 File entry=entries[i];
783
784 if (entry.isDirectory()&&recurse)
785 addJars(entry,table,recurse);
786 else
787 {
788 String name=entry.getName().toLowerCase();
789 if (name.endsWith(".jar")||name.endsWith(".zip"))
790 {
791 String jar=entry.getCanonicalPath();
792 if (!table.contains(jar))
793 {
794 table.add(jar);
795 boolean added=_classpath.addComponent(jar);
796 if (DEBUG)
797 System.err.println((added?" CLASSPATH+=":" !")+jar);
798 }
799 }
800 }
801 }
802 }
803 }