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 :System.getProperty("jetty.version", "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);
486
487 if (DEBUG)
488 System.err.println((expression?"T ":"F ")+line);
489 if (!expression)
490 {
491 done.add(file);
492 continue;
493 }
494
495
496 if (subject.indexOf("~=")>0)
497 {
498 int i=file.indexOf("~=");
499 String property=file.substring(0,i);
500 String value=fixPath(file.substring(i+2));
501 if (DEBUG)
502 System.err.println(" "+property+"~="+value);
503 setProperty(property,value);
504 }
505 else
506
507 if (subject.indexOf("/=")>0)
508 {
509 int i=file.indexOf("/=");
510 String property=file.substring(0,i);
511 String value=fixPath(file.substring(i+2));
512 String canonical=new File(value).getCanonicalPath();
513 if (DEBUG)
514 System.err.println(" "+property+"/="+value+"=="+canonical);
515 setProperty(property,canonical);
516 }
517 else
518
519 if (subject.indexOf("=")>0)
520 {
521 int i=file.indexOf("=");
522 String property=file.substring(0,i);
523 String value=fixPath(file.substring(i+1));
524 if (DEBUG)
525 System.err.println(" "+property+"="+value);
526 System.setProperty(property,value);
527 }
528 else
529
530 if (subject.endsWith("/*"))
531 {
532
533
534 File dir=new File(fixPath(file.substring(0,file.length()-1)));
535 addJars(dir,done,false);
536 }
537 else
538
539 if (subject.endsWith("/**"))
540 {
541
542
543 File dir=new File(fixPath(file.substring(0,file.length()-2)));
544 addJars(dir,done,true);
545 }
546 else
547
548 if (subject.endsWith("/"))
549 {
550
551 File cd=new File(fixPath(file));
552 String d=cd.getCanonicalPath();
553 if (!done.contains(d))
554 {
555 done.add(d);
556 boolean added=_classpath.addComponent(d);
557 if (DEBUG)
558 System.err.println((added?" CLASSPATH+=":" !")+d);
559 }
560 }
561 else
562
563 if (subject.toLowerCase().endsWith(".xml"))
564 {
565
566 File f=new File(fixPath(file));
567 if (f.exists())
568 _xml.add(f.getCanonicalPath());
569 if (DEBUG)
570 System.err.println(" ARGS+="+f);
571 }
572 else
573
574 if (subject.toLowerCase().endsWith(".class"))
575 {
576
577 String cn=expand(subject.substring(0,subject.length()-6));
578 if (cn!=null&&cn.length()>0)
579 {
580 if (DEBUG)
581 System.err.println(" CLASS="+cn);
582 _classname=cn;
583 }
584 }
585 else
586
587 if (subject.toLowerCase().endsWith(".path"))
588 {
589
590 String cn=expand(subject.substring(0,subject.length()-5));
591 if (cn!=null&&cn.length()>0)
592 {
593 if (DEBUG)
594 System.err.println(" PATH="+cn);
595 _classpath.addClasspath(cn);
596 }
597 }
598 else
599
600 if (subject.toLowerCase().endsWith(".policy"))
601 {
602
603 String cn=expand(subject.substring(0,subject.length()));
604 if (cn!=null&&cn.length()>0)
605 {
606 if (DEBUG)
607 System.err.println(" POLICY="+cn);
608 _policies.add(fixPath(cn));
609 }
610 }
611 else
612 {
613
614 File f=new File(fixPath(file));
615 if(f.exists())
616 {
617 String d=f.getCanonicalPath();
618 if (!done.contains(d))
619 {
620 done.add(d);
621 boolean added=_classpath.addComponent(d);
622 if (!added)
623 {
624 added=_classpath.addClasspath(expand(subject));
625 if (DEBUG)
626 System.err.println((added?" CLASSPATH+=":" !")+d);
627 }
628 else if (DEBUG)
629 System.err.println((added?" CLASSPATH+=":" !")+d);
630 }
631 }
632 }
633 }
634 catch (Exception e)
635 {
636 System.err.println("on line: '"+line+"'");
637 e.printStackTrace();
638 }
639 }
640
641 if (unsatisfied_options!=null && unsatisfied_options.size()>0)
642 {
643 System.err.println("Unresolved options: "+unsatisfied_options);
644 }
645 }
646
647 private String fixPath(String path)
648 {
649 return path.replace('/',File.separatorChar);
650 }
651
652
653 public void start(String[] args)
654 {
655
656 InputStream cpcfg=null;
657 try
658 {
659 int port = Integer.parseInt(getProperty("STOP.PORT","-1"));
660 String key = getProperty("STOP.KEY", null);
661
662 Monitor.monitor(port,key);
663
664 String config=getProperty("START","org/eclipse/jetty/start/start.config");
665 if (DEBUG)
666 {
667 System.err.println("config="+config);
668 System.err.println("properties="+_properties);
669 }
670 cpcfg=getClass().getClassLoader().getResourceAsStream(config);
671 if (cpcfg==null)
672 cpcfg=new FileInputStream(config);
673
674 configure(cpcfg,args.length);
675
676 String jetty_home=System.getProperty("jetty.home");
677 if (jetty_home!=null)
678 {
679 File file=new File(jetty_home);
680 String canonical=file.getCanonicalPath();
681 System.setProperty("jetty.home",canonical);
682 }
683
684 }
685 catch (Exception e)
686 {
687 e.printStackTrace();
688 System.exit(1);
689 }
690 finally
691 {
692 try
693 {
694 cpcfg.close();
695 }
696 catch (Exception e)
697 {
698 e.printStackTrace();
699 }
700 }
701
702 System.setProperty("java.class.path",_classpath.toString());
703 ClassLoader cl=_classpath.getClassLoader();
704 if (DEBUG)
705 {
706 System.err.println("java.class.path="+System.getProperty("java.class.path"));
707 System.err.println("jetty.home="+System.getProperty("jetty.home"));
708 System.err.println("java.io.tmpdir="+System.getProperty("java.io.tmpdir"));
709 System.err.println("java.class.path="+_classpath);
710 System.err.println("classloader="+cl);
711 System.err.println("classloader.parent="+cl.getParent());
712 }
713
714 Thread.currentThread().setContextClassLoader(cl);
715
716 try
717 {
718 if ( _activeOptions.contains("secure") )
719 {
720 Class jettyPolicy = cl.loadClass( "org.eclipse.jetty.policy.JettyPolicy" );
721 Constructor c = jettyPolicy.getConstructor( new Class[] { Set.class, Map.class } );
722 Object policyClass = c.newInstance( _policies, _properties );
723
724 Policy.setPolicy( (Policy)policyClass );
725 System.setSecurityManager( new SecurityManager() );
726 }
727 else
728 {
729 Policy policy=Policy.getPolicy();
730 if (policy!=null)
731 policy.refresh();
732 }
733 }
734 catch (Exception e)
735 {
736 e.printStackTrace();
737 }
738 try
739 {
740 for (int i=0; i<args.length; i++)
741 {
742 if (args[i]==null)
743 continue;
744 _xml.add(args[i]);
745 }
746 args=(String[])_xml.toArray(args);
747
748 String mainClass=System.getProperty("jetty.server");
749 if (mainClass!=null)
750 _classname=mainClass;
751 mainClass=System.getProperty("main.class");
752 if (mainClass!=null)
753 _classname=mainClass;
754 if (DEBUG)
755 System.err.println("main.class="+_classname);
756 invokeMain(cl,_classname,args);
757 }
758 catch (Exception e)
759 {
760 e.printStackTrace();
761 }
762 }
763
764
765
766
767 public void stop(int port,String key)
768 {
769 int _port=port;
770 String _key=key;
771
772 try
773 {
774 if (_port<=0)
775 System.err.println("STOP.PORT system property must be specified");
776 if (_key==null)
777 {
778 _key="";
779 System.err.println("STOP.KEY system property must be specified");
780 System.err.println("Using empty key");
781 }
782
783 Socket s=new Socket(InetAddress.getByName("127.0.0.1"),_port);
784 OutputStream out=s.getOutputStream();
785 out.write((_key+"\r\nstop\r\n").getBytes());
786 out.flush();
787 s.close();
788 }
789 catch (ConnectException e)
790 {
791 System.err.println("ERROR: Not running!");
792 }
793 catch (Exception e)
794 {
795 e.printStackTrace();
796 }
797 }
798
799 private void addJars(File dir, Set<String> table, boolean recurse) throws IOException
800 {
801 File[] entries=dir.listFiles();
802
803 for (int i=0; entries!=null&&i<entries.length; i++)
804 {
805 File entry=entries[i];
806
807 if (entry.isDirectory()&&recurse)
808 addJars(entry,table,recurse);
809 else
810 {
811 String name=entry.getName().toLowerCase();
812 if (name.endsWith(".jar")||name.endsWith(".zip"))
813 {
814 String jar=entry.getCanonicalPath();
815 if (!table.contains(jar))
816 {
817 table.add(jar);
818 boolean added=_classpath.addComponent(jar);
819 if (DEBUG)
820 System.err.println((added?" CLASSPATH+=":" !")+jar);
821 }
822 }
823 }
824 }
825 }
826 }