1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.eclipse.jetty.xml;
20
21 import java.io.IOException;
22 import java.io.InputStream;
23 import java.io.StringReader;
24 import java.lang.reflect.Array;
25 import java.lang.reflect.Constructor;
26 import java.lang.reflect.Field;
27 import java.lang.reflect.InvocationTargetException;
28 import java.lang.reflect.Method;
29 import java.lang.reflect.Modifier;
30 import java.net.InetAddress;
31 import java.net.MalformedURLException;
32 import java.net.URL;
33 import java.net.UnknownHostException;
34 import java.security.AccessController;
35 import java.security.PrivilegedAction;
36 import java.util.ArrayList;
37 import java.util.Collection;
38 import java.util.Enumeration;
39 import java.util.HashMap;
40 import java.util.HashSet;
41 import java.util.LinkedList;
42 import java.util.List;
43 import java.util.Locale;
44 import java.util.Map;
45 import java.util.Properties;
46 import java.util.Queue;
47 import java.util.ServiceLoader;
48 import java.util.Set;
49 import java.util.concurrent.atomic.AtomicReference;
50
51 import org.eclipse.jetty.util.ArrayQueue;
52 import org.eclipse.jetty.util.LazyList;
53 import org.eclipse.jetty.util.Loader;
54 import org.eclipse.jetty.util.TypeUtil;
55 import org.eclipse.jetty.util.component.LifeCycle;
56 import org.eclipse.jetty.util.log.Log;
57 import org.eclipse.jetty.util.log.Logger;
58 import org.eclipse.jetty.util.resource.Resource;
59 import org.eclipse.jetty.xml.XmlParser.Node;
60 import org.xml.sax.InputSource;
61 import org.xml.sax.SAXException;
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80 public class XmlConfiguration
81 {
82 private static final Logger LOG = Log.getLogger(XmlConfiguration.class);
83
84 private static final Class<?>[] __primitives =
85 {Boolean.TYPE, Character.TYPE, Byte.TYPE, Short.TYPE, Integer.TYPE, Long.TYPE, Float.TYPE, Double.TYPE, Void.TYPE};
86
87 private static final Class<?>[] __boxedPrimitives =
88 {Boolean.class, Character.class, Byte.class, Short.class, Integer.class, Long.class, Float.class, Double.class, Void.class};
89
90 private static final Class<?>[] __supportedCollections =
91 {ArrayList.class, ArrayQueue.class, HashSet.class, Queue.class, List.class, Set.class, Collection.class,};
92
93 private static final Iterable<ConfigurationProcessorFactory> __factoryLoader = ServiceLoader.load(ConfigurationProcessorFactory.class);
94 private static final XmlParser __parser = initParser();
95 private synchronized static XmlParser initParser()
96 {
97 XmlParser parser = new XmlParser();
98 URL config60 = Loader.getResource(XmlConfiguration.class,"org/eclipse/jetty/xml/configure_6_0.dtd",true);
99 URL config76 = Loader.getResource(XmlConfiguration.class,"org/eclipse/jetty/xml/configure_7_6.dtd",true);
100 URL config90 = Loader.getResource(XmlConfiguration.class,"org/eclipse/jetty/xml/configure_9_0.dtd",true);
101 parser.redirectEntity("configure.dtd",config90);
102 parser.redirectEntity("configure_1_0.dtd",config60);
103 parser.redirectEntity("configure_1_1.dtd",config60);
104 parser.redirectEntity("configure_1_2.dtd",config60);
105 parser.redirectEntity("configure_1_3.dtd",config60);
106 parser.redirectEntity("configure_6_0.dtd",config60);
107 parser.redirectEntity("configure_7_6.dtd",config76);
108 parser.redirectEntity("configure_9_0.dtd",config90);
109
110 parser.redirectEntity("http://jetty.mortbay.org/configure.dtd",config90);
111 parser.redirectEntity("http://jetty.eclipse.org/configure.dtd",config90);
112 parser.redirectEntity("http://www.eclipse.org/jetty/configure.dtd",config90);
113
114 parser.redirectEntity("-//Mort Bay Consulting//DTD Configure//EN",config90);
115 parser.redirectEntity("-//Jetty//Configure//EN",config90);
116
117 return parser;
118 }
119
120 private final Map<String, Object> _idMap = new HashMap<>();
121 private final Map<String, String> _propertyMap = new HashMap<>();
122 private final URL _url;
123 private final String _dtd;
124 private ConfigurationProcessor _processor;
125
126
127
128
129
130
131
132
133 public XmlConfiguration(URL configuration) throws SAXException, IOException
134 {
135 synchronized (__parser)
136 {
137 _url=configuration;
138 setConfig(__parser.parse(configuration.toString()));
139 _dtd=__parser.getDTD();
140 }
141 }
142
143
144
145
146
147
148
149
150
151 public XmlConfiguration(String configuration) throws SAXException, IOException
152 {
153 configuration = "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\n<!DOCTYPE Configure PUBLIC \"-//Jetty//Configure//EN\" \"http://eclipse.org/jetty/configure.dtd\">"
154 + configuration;
155 InputSource source = new InputSource(new StringReader(configuration));
156 synchronized (__parser)
157 {
158 _url=null;
159 setConfig( __parser.parse(source));
160 _dtd=__parser.getDTD();
161 }
162 }
163
164
165
166
167
168
169
170
171 public XmlConfiguration(InputStream configuration) throws SAXException, IOException
172 {
173 InputSource source = new InputSource(configuration);
174 synchronized (__parser)
175 {
176 _url=null;
177 setConfig(__parser.parse(source));
178 _dtd=__parser.getDTD();
179 }
180 }
181
182 private void setConfig(XmlParser.Node config)
183 {
184 if ("Configure".equals(config.getTag()))
185 {
186 _processor=new JettyXmlConfiguration();
187 }
188 else if (__factoryLoader!=null)
189 {
190 for (ConfigurationProcessorFactory factory : __factoryLoader)
191 {
192 _processor = factory.getConfigurationProcessor(_dtd, config.getTag());
193 if (_processor!=null)
194 break;
195 }
196
197 if (_processor==null)
198 throw new IllegalStateException("Unknown configuration type: "+config.getTag()+" in "+this);
199 }
200 else
201 {
202 throw new IllegalArgumentException("Unknown XML tag:"+config.getTag());
203 }
204 _processor.init(_url,config,this);
205 }
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222 public Map<String, Object> getIdMap()
223 {
224 return _idMap;
225 }
226
227
228
229
230
231
232
233 public Map<String, String> getProperties()
234 {
235 return _propertyMap;
236 }
237
238
239
240
241
242
243
244
245
246 public Object configure(Object obj) throws Exception
247 {
248 return _processor.configure(obj);
249 }
250
251
252
253
254
255
256
257
258
259
260 public Object configure() throws Exception
261 {
262 return _processor.configure();
263 }
264
265
266
267
268
269
270
271
272 public void initializeDefaults(Object object)
273 {
274 }
275
276 private static class JettyXmlConfiguration implements ConfigurationProcessor
277 {
278 private String _url;
279 XmlParser.Node _root;
280 XmlConfiguration _configuration;
281
282 public void init(URL url, XmlParser.Node root, XmlConfiguration configuration)
283 {
284 _url=url==null?null:url.toString();
285 _root=root;
286 _configuration=configuration;
287 }
288
289 public Object configure(Object obj) throws Exception
290 {
291
292 Class<?> oClass = nodeClass(_root);
293 if (oClass != null && !oClass.isInstance(obj))
294 {
295 String loaders = (oClass.getClassLoader()==obj.getClass().getClassLoader())?"":"Object Class and type Class are from different loaders.";
296 throw new IllegalArgumentException("Object of class '"+obj.getClass().getCanonicalName()+"' is not of type '" + oClass.getCanonicalName()+"'. "+loaders+" in "+_url);
297 }
298 configure(obj,_root,0);
299 return obj;
300 }
301
302 public Object configure() throws Exception
303 {
304 Class<?> oClass = nodeClass(_root);
305
306 String id = _root.getAttribute("id");
307 Object obj = id == null?null:_configuration.getIdMap().get(id);
308
309 int index = 0;
310 if (obj == null && oClass != null)
311 {
312 index = _root.size();
313 Map<String, Object> namedArgMap = new HashMap<>();
314
315 List<Object> arguments = new LinkedList<>();
316 for (int i = 0; i < _root.size(); i++)
317 {
318 Object o = _root.get(i);
319 if (o instanceof String)
320 {
321 continue;
322 }
323 XmlParser.Node node = (XmlParser.Node)o;
324
325 if (!(node.getTag().equals("Arg")))
326 {
327 index = i;
328 break;
329 }
330 else
331 {
332 String namedAttribute = node.getAttribute("name");
333 Object value=value(obj,(XmlParser.Node)o);
334 if (namedAttribute != null)
335 namedArgMap.put(namedAttribute,value);
336 arguments.add(value);
337 }
338 }
339
340 try
341 {
342 if (namedArgMap.size() > 0)
343 obj = TypeUtil.construct(oClass, arguments.toArray(), namedArgMap);
344 else
345 obj = TypeUtil.construct(oClass, arguments.toArray());
346 }
347 catch (NoSuchMethodException x)
348 {
349 throw new IllegalStateException("No suitable constructor on " + oClass, x);
350 }
351 }
352 _configuration.initializeDefaults(obj);
353
354 configure(obj, _root, index);
355 return obj;
356 }
357
358 private static Class<?> nodeClass(XmlParser.Node node) throws ClassNotFoundException
359 {
360 String className = node.getAttribute("class");
361 if (className == null)
362 return null;
363
364 return Loader.loadClass(XmlConfiguration.class,className,true);
365 }
366
367
368
369
370
371
372
373
374
375
376 public void configure(Object obj, XmlParser.Node cfg, int i) throws Exception
377 {
378 String id = cfg.getAttribute("id");
379 if (id != null)
380 _configuration.getIdMap().put(id,obj);
381
382
383 for (; i < cfg.size(); i++)
384 {
385 Object o = cfg.get(i);
386 if (o instanceof String)
387 continue;
388 XmlParser.Node node = (XmlParser.Node)o;
389 if ("Arg".equals(node.getTag()))
390 {
391 LOG.warn("Ignored arg: "+node);
392 continue;
393 }
394 break;
395 }
396
397
398 for (; i < cfg.size(); i++)
399 {
400 Object o = cfg.get(i);
401 if (o instanceof String)
402 continue;
403 XmlParser.Node node = (XmlParser.Node)o;
404
405 try
406 {
407 String tag = node.getTag();
408 switch (tag)
409 {
410 case "Set":
411 set(obj, node);
412 break;
413 case "Put":
414 put(obj, node);
415 break;
416 case "Call":
417 call(obj, node);
418 break;
419 case "Get":
420 get(obj, node);
421 break;
422 case "New":
423 newObj(obj, node);
424 break;
425 case "Array":
426 newArray(obj, node);
427 break;
428 case "Ref":
429 refObj(obj, node);
430 break;
431 case "Property":
432 propertyObj(node);
433 break;
434 default:
435 throw new IllegalStateException("Unknown tag: " + tag + " in " + _url);
436 }
437 }
438 catch (Exception e)
439 {
440 LOG.warn("Config error at " + node,e.toString()+" in "+_url);
441 throw e;
442 }
443 }
444 }
445
446
447
448
449
450
451
452
453 private void set(Object obj, XmlParser.Node node) throws Exception
454 {
455 String attr = node.getAttribute("name");
456 String name = "set" + attr.substring(0,1).toUpperCase(Locale.ENGLISH) + attr.substring(1);
457 Object value = value(obj,node);
458 Object[] arg =
459 { value };
460
461 Class<?> oClass = nodeClass(node);
462 if (oClass != null)
463 obj = null;
464 else
465 oClass = obj.getClass();
466
467 Class<?>[] vClass =
468 { Object.class };
469 if (value != null)
470 vClass[0] = value.getClass();
471
472 if (LOG.isDebugEnabled())
473 LOG.debug("XML " + (obj != null?obj.toString():oClass.getName()) + "." + name + "(" + value + ")");
474
475
476 try
477 {
478 Method set = oClass.getMethod(name,vClass);
479 set.invoke(obj,arg);
480 return;
481 }
482 catch (IllegalArgumentException | IllegalAccessException | NoSuchMethodException e)
483 {
484 LOG.ignore(e);
485 }
486
487
488 try
489 {
490 Field type = vClass[0].getField("TYPE");
491 vClass[0] = (Class<?>)type.get(null);
492 Method set = oClass.getMethod(name,vClass);
493 set.invoke(obj,arg);
494 return;
495 }
496 catch (NoSuchFieldException | IllegalArgumentException | IllegalAccessException | NoSuchMethodException e)
497 {
498 LOG.ignore(e);
499 }
500
501
502 try
503 {
504 Field field = oClass.getField(attr);
505 if (Modifier.isPublic(field.getModifiers()))
506 {
507 field.set(obj,value);
508 return;
509 }
510 }
511 catch (NoSuchFieldException e)
512 {
513 LOG.ignore(e);
514 }
515
516
517 Method[] sets = oClass.getMethods();
518 Method set = null;
519 for (int s = 0; sets != null && s < sets.length; s++)
520 {
521 Class<?>[] paramTypes = sets[s].getParameterTypes();
522 if (name.equals(sets[s].getName()) && paramTypes.length == 1)
523 {
524
525 try
526 {
527 set = sets[s];
528 sets[s].invoke(obj,arg);
529 return;
530 }
531 catch (IllegalArgumentException | IllegalAccessException e)
532 {
533 LOG.ignore(e);
534 }
535
536 try
537 {
538 for (Class<?> c : __supportedCollections)
539 if (paramTypes[0].isAssignableFrom(c))
540 {
541 sets[s].invoke(obj,convertArrayToCollection(value,c));
542 return;
543 }
544 }
545 catch (IllegalAccessException e)
546 {
547 LOG.ignore(e);
548 }
549 }
550 }
551
552
553 if (set != null)
554 {
555 try
556 {
557 Class<?> sClass = set.getParameterTypes()[0];
558 if (sClass.isPrimitive())
559 {
560 for (int t = 0; t < __primitives.length; t++)
561 {
562 if (sClass.equals(__primitives[t]))
563 {
564 sClass = __boxedPrimitives[t];
565 break;
566 }
567 }
568 }
569 Constructor<?> cons = sClass.getConstructor(vClass);
570 arg[0] = cons.newInstance(arg);
571 _configuration.initializeDefaults(arg[0]);
572 set.invoke(obj,arg);
573 return;
574 }
575 catch (NoSuchMethodException | IllegalAccessException | InstantiationException e)
576 {
577 LOG.ignore(e);
578 }
579 }
580
581
582 throw new NoSuchMethodException(oClass + "." + name + "(" + vClass[0] + ")");
583 }
584
585
586
587
588
589
590 private static Collection<?> convertArrayToCollection(Object array, Class<?> collectionType)
591 {
592 Collection<?> collection = null;
593 if (array.getClass().isArray())
594 {
595 if (collectionType.isAssignableFrom(ArrayList.class))
596 collection = convertArrayToArrayList(array);
597 else if (collectionType.isAssignableFrom(HashSet.class))
598 collection = new HashSet<>(convertArrayToArrayList(array));
599 else if (collectionType.isAssignableFrom(ArrayQueue.class))
600 {
601 ArrayQueue<Object> q= new ArrayQueue<>();
602 q.addAll(convertArrayToArrayList(array));
603 collection=q;
604 }
605 }
606 if (collection==null)
607 throw new IllegalArgumentException("Can't convert \"" + array.getClass() + "\" to " + collectionType);
608 return collection;
609 }
610
611 private static ArrayList<Object> convertArrayToArrayList(Object array)
612 {
613 int length = Array.getLength(array);
614 ArrayList<Object> list = new ArrayList<>(length);
615 for (int i = 0; i < length; i++)
616 list.add(Array.get(array,i));
617 return list;
618 }
619
620
621
622
623
624
625 private void put(Object obj, XmlParser.Node node) throws Exception
626 {
627 if (!(obj instanceof Map))
628 throw new IllegalArgumentException("Object for put is not a Map: " + obj);
629 @SuppressWarnings("unchecked")
630 Map<Object, Object> map = (Map<Object, Object>)obj;
631
632 String name = node.getAttribute("name");
633 Object value = value(obj,node);
634 map.put(name,value);
635 if (LOG.isDebugEnabled())
636 LOG.debug("XML " + obj + ".put(" + name + "," + value + ")");
637 }
638
639
640
641
642
643
644 private Object get(Object obj, XmlParser.Node node) throws Exception
645 {
646 Class<?> oClass = nodeClass(node);
647 if (oClass != null)
648 obj = null;
649 else
650 oClass = obj.getClass();
651
652 String name = node.getAttribute("name");
653 String id = node.getAttribute("id");
654 if (LOG.isDebugEnabled())
655 LOG.debug("XML get " + name);
656
657 try
658 {
659
660 Method method = oClass.getMethod("get" + name.substring(0,1).toUpperCase(Locale.ENGLISH) + name.substring(1),(java.lang.Class[])null);
661 obj = method.invoke(obj,(java.lang.Object[])null);
662 configure(obj,node,0);
663 }
664 catch (NoSuchMethodException nsme)
665 {
666 try
667 {
668 Field field = oClass.getField(name);
669 obj = field.get(obj);
670 configure(obj,node,0);
671 }
672 catch (NoSuchFieldException nsfe)
673 {
674 throw nsme;
675 }
676 }
677 if (id != null)
678 _configuration.getIdMap().put(id,obj);
679 return obj;
680 }
681
682
683
684
685
686
687
688
689 private Object call(Object obj, XmlParser.Node node) throws Exception
690 {
691 String id = node.getAttribute("id");
692 Class<?> oClass = nodeClass(node);
693 if (oClass != null)
694 obj = null;
695 else if (obj != null)
696 oClass = obj.getClass();
697 if (oClass == null)
698 throw new IllegalArgumentException(node.toString());
699
700 int size = 0;
701 int argIndex = node.size();
702 for (int i = 0; i < node.size(); i++)
703 {
704 Object o = node.get(i);
705 if (o instanceof String)
706 continue;
707 if (!((XmlParser.Node)o).getTag().equals("Arg"))
708 {
709 argIndex = i;
710 break;
711 }
712 size++;
713 }
714
715 Object[] arg = new Object[size];
716 for (int i = 0, j = 0; j < size; i++)
717 {
718 Object o = node.get(i);
719 if (o instanceof String)
720 continue;
721 arg[j++] = value(obj,(XmlParser.Node)o);
722 }
723
724 String method = node.getAttribute("name");
725 if (LOG.isDebugEnabled())
726 LOG.debug("XML call " + method);
727
728 try
729 {
730 Object n= TypeUtil.call(oClass,method,obj,arg);
731 if (id != null)
732 _configuration.getIdMap().put(id,n);
733 configure(n,node,argIndex);
734 return n;
735 }
736 catch (NoSuchMethodException e)
737 {
738 IllegalStateException ise = new IllegalStateException("No Method: " + node + " on " + oClass);
739 ise.initCause(e);
740 throw ise;
741 }
742 }
743
744
745
746
747
748
749
750
751
752 private Object newObj(Object obj, XmlParser.Node node) throws Exception
753 {
754 Class<?> oClass = nodeClass(node);
755 int argIndex = node.size();
756
757 Map<String, Object> namedArgMap = new HashMap<>();
758 List<Object> arguments = new LinkedList<>();
759 XmlParser.Node child;
760
761
762 for (int i = 0; i < node.size(); i++)
763 {
764 Object o = node.get(i);
765 if (o instanceof String)
766 {
767
768 continue;
769 }
770
771 child = (XmlParser.Node)o;
772 if(child.getTag().equals("Arg"))
773 {
774 String namedAttribute = child.getAttribute("name");
775 Object value=value(obj,child);
776 if (namedAttribute != null)
777 {
778
779 namedArgMap.put(namedAttribute,value);
780 }
781
782 arguments.add(value);
783 } else {
784
785
786
787 argIndex = i;
788 break;
789 }
790 }
791
792 if (LOG.isDebugEnabled())
793 LOG.debug("XML new " + oClass);
794
795 Object n;
796 try
797 {
798 if (namedArgMap.size() > 0)
799 {
800 LOG.debug("using named mapping");
801 n = TypeUtil.construct(oClass, arguments.toArray(), namedArgMap);
802 }
803 else
804 {
805 LOG.debug("using normal mapping");
806 n = TypeUtil.construct(oClass, arguments.toArray());
807 }
808 }
809 catch (NoSuchMethodException e)
810 {
811 throw new IllegalStateException("No suitable constructor: " + node + " on " + obj);
812 }
813
814 _configuration.initializeDefaults(n);
815 configure(n,node,argIndex);
816 return n;
817 }
818
819
820
821
822
823
824 private Object refObj(Object obj, XmlParser.Node node) throws Exception
825 {
826 String refid = node.getAttribute("refid");
827 if (refid==null)
828 refid = node.getAttribute("id");
829 obj = _configuration.getIdMap().get(refid);
830 if (obj == null && node.size()>0)
831 throw new IllegalStateException("No object for refid=" + refid);
832 configure(obj,node,0);
833 return obj;
834 }
835
836
837
838
839 private Object newArray(Object obj, XmlParser.Node node) throws Exception
840 {
841
842 Class<?> aClass = java.lang.Object.class;
843 String type = node.getAttribute("type");
844 final String id = node.getAttribute("id");
845 if (type != null)
846 {
847 aClass = TypeUtil.fromName(type);
848 if (aClass == null)
849 {
850 switch (type)
851 {
852 case "String":
853 aClass = String.class;
854 break;
855 case "URL":
856 aClass = URL.class;
857 break;
858 case "InetAddress":
859 aClass = InetAddress.class;
860 break;
861 default:
862 aClass = Loader.loadClass(XmlConfiguration.class, type, true);
863 break;
864 }
865 }
866 }
867
868 Object al = null;
869
870 for (Object nodeObject : node)
871 {
872 XmlParser.Node item = (Node)nodeObject;
873 String nid = item.getAttribute("id");
874 Object v = value(obj,item);
875 al = LazyList.add(al,(v == null && aClass.isPrimitive())?0:v);
876 if (nid != null)
877 _configuration.getIdMap().put(nid,v);
878 }
879
880 Object array = LazyList.toArray(al,aClass);
881 if (id != null)
882 _configuration.getIdMap().put(id,array);
883 return array;
884 }
885
886
887
888
889 private Object newMap(Object obj, XmlParser.Node node) throws Exception
890 {
891 String id = node.getAttribute("id");
892
893 Map<Object, Object> map = new HashMap<>();
894 if (id != null)
895 _configuration.getIdMap().put(id,map);
896
897 for (Object o : node)
898 {
899 if (o instanceof String)
900 continue;
901 XmlParser.Node entry = (XmlParser.Node)o;
902 if (!entry.getTag().equals("Entry"))
903 throw new IllegalStateException("Not an Entry");
904
905 XmlParser.Node key = null;
906 XmlParser.Node value = null;
907
908 for (Object object : entry)
909 {
910 if (object instanceof String)
911 continue;
912 XmlParser.Node item = (XmlParser.Node)object;
913 if (!item.getTag().equals("Item"))
914 throw new IllegalStateException("Not an Item");
915 if (key == null)
916 key = item;
917 else
918 value = item;
919 }
920
921 if (key == null || value == null)
922 throw new IllegalStateException("Missing Item in Entry");
923 String kid = key.getAttribute("id");
924 String vid = value.getAttribute("id");
925
926 Object k = value(obj,key);
927 Object v = value(obj,value);
928 map.put(k,v);
929
930 if (kid != null)
931 _configuration.getIdMap().put(kid,k);
932 if (vid != null)
933 _configuration.getIdMap().put(vid,v);
934 }
935
936 return map;
937 }
938
939
940
941
942
943
944
945
946 private Object propertyObj(XmlParser.Node node) throws Exception
947 {
948 String id = node.getAttribute("id");
949 String name = node.getAttribute("name");
950 String defaultValue = node.getAttribute("default");
951 Object prop;
952 Map<String,String> property_map=_configuration.getProperties();
953 if (property_map != null && property_map.containsKey(name))
954 prop = property_map.get(name);
955 else
956 prop = defaultValue;
957 if (id != null)
958 _configuration.getIdMap().put(id,prop);
959 if (prop != null)
960 configure(prop,node,0);
961 return prop;
962 }
963
964
965
966
967
968 private Object value(Object obj, XmlParser.Node node) throws Exception
969 {
970 Object value;
971
972
973 String type = node.getAttribute("type");
974
975
976 String ref = node.getAttribute("ref");
977 if (ref != null)
978 {
979 value = _configuration.getIdMap().get(ref);
980 }
981 else
982 {
983
984 if (node.size() == 0)
985 {
986 if ("String".equals(type))
987 return "";
988 return null;
989 }
990
991
992 int first = 0;
993 int last = node.size() - 1;
994
995
996 if (type == null || !"String".equals(type))
997 {
998
999 Object item;
1000 while (first <= last)
1001 {
1002 item = node.get(first);
1003 if (!(item instanceof String))
1004 break;
1005 item = ((String)item).trim();
1006 if (((String)item).length() > 0)
1007 break;
1008 first++;
1009 }
1010
1011
1012 while (first < last)
1013 {
1014 item = node.get(last);
1015 if (!(item instanceof String))
1016 break;
1017 item = ((String)item).trim();
1018 if (((String)item).length() > 0)
1019 break;
1020 last--;
1021 }
1022
1023
1024 if (first > last)
1025 return null;
1026 }
1027
1028 if (first == last)
1029
1030 value = itemValue(obj,node.get(first));
1031 else
1032 {
1033
1034 StringBuilder buf = new StringBuilder();
1035 for (int i = first; i <= last; i++)
1036 {
1037 Object item = node.get(i);
1038 buf.append(itemValue(obj,item));
1039 }
1040 value = buf.toString();
1041 }
1042 }
1043
1044
1045 if (value == null)
1046 {
1047 if ("String".equals(type))
1048 return "";
1049 return null;
1050 }
1051
1052
1053 if (type == null)
1054 {
1055 if (value instanceof String)
1056 return ((String)value).trim();
1057 return value;
1058 }
1059
1060 if (isTypeMatchingClass(type,String.class))
1061 return value.toString();
1062
1063 Class<?> pClass = TypeUtil.fromName(type);
1064 if (pClass != null)
1065 return TypeUtil.valueOf(pClass,value.toString());
1066
1067 if (isTypeMatchingClass(type,URL.class))
1068 {
1069 if (value instanceof URL)
1070 return value;
1071 try
1072 {
1073 return new URL(value.toString());
1074 }
1075 catch (MalformedURLException e)
1076 {
1077 throw new InvocationTargetException(e);
1078 }
1079 }
1080
1081 if (isTypeMatchingClass(type,InetAddress.class))
1082 {
1083 if (value instanceof InetAddress)
1084 return value;
1085 try
1086 {
1087 return InetAddress.getByName(value.toString());
1088 }
1089 catch (UnknownHostException e)
1090 {
1091 throw new InvocationTargetException(e);
1092 }
1093 }
1094
1095 for (Class<?> collectionClass : __supportedCollections)
1096 {
1097 if (isTypeMatchingClass(type,collectionClass))
1098 return convertArrayToCollection(value,collectionClass);
1099 }
1100
1101 throw new IllegalStateException("Unknown type " + type);
1102 }
1103
1104 private static boolean isTypeMatchingClass(String type, Class<?> classToMatch)
1105 {
1106 return classToMatch.getSimpleName().equalsIgnoreCase(type) || classToMatch.getName().equals(type);
1107 }
1108
1109
1110
1111
1112 private Object itemValue(Object obj, Object item) throws Exception
1113 {
1114
1115 if (item instanceof String)
1116 return item;
1117
1118 XmlParser.Node node = (XmlParser.Node)item;
1119 String tag = node.getTag();
1120 if ("Call".equals(tag))
1121 return call(obj,node);
1122 if ("Get".equals(tag))
1123 return get(obj,node);
1124 if ("New".equals(tag))
1125 return newObj(obj,node);
1126 if ("Ref".equals(tag))
1127 return refObj(obj,node);
1128 if ("Array".equals(tag))
1129 return newArray(obj,node);
1130 if ("Map".equals(tag))
1131 return newMap(obj,node);
1132 if ("Property".equals(tag))
1133 return propertyObj(node);
1134 if ("SystemProperty".equals(tag))
1135 {
1136 String name = node.getAttribute("name");
1137 String defaultValue = node.getAttribute("default");
1138 return System.getProperty(name,defaultValue);
1139 }
1140 if ("Env".equals(tag))
1141 {
1142 String name = node.getAttribute("name");
1143 String defaultValue = node.getAttribute("default");
1144 String value=System.getenv(name);
1145 return value==null?defaultValue:value;
1146 }
1147
1148 LOG.warn("Unknown value tag: " + node,new Throwable());
1149 return null;
1150 }
1151 }
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170 public static void main(final String... args) throws Exception
1171 {
1172 final AtomicReference<Throwable> exception = new AtomicReference<>();
1173
1174 AccessController.doPrivileged(new PrivilegedAction<Object>()
1175 {
1176 public Object run()
1177 {
1178 try
1179 {
1180
1181 Properties properties = null;
1182
1183
1184 try
1185 {
1186 Class<?> config = XmlConfiguration.class.getClassLoader().loadClass("org.eclipse.jetty.start.Config");
1187 properties = (Properties)config.getMethod("getProperties").invoke(null);
1188 LOG.debug("org.eclipse.jetty.start.Config properties = {}",properties);
1189 }
1190 catch (NoClassDefFoundError | ClassNotFoundException e)
1191 {
1192 LOG.ignore(e);
1193 }
1194 catch (Exception e)
1195 {
1196 LOG.warn(e);
1197 }
1198
1199
1200 if (properties == null)
1201 {
1202 properties = new Properties();
1203
1204 Enumeration<?> ensysprop = System.getProperties().propertyNames();
1205 while (ensysprop.hasMoreElements())
1206 {
1207 String name = (String)ensysprop.nextElement();
1208 properties.put(name,System.getProperty(name));
1209 }
1210 }
1211
1212
1213 for (String arg : args)
1214 {
1215 if (arg.toLowerCase(Locale.ENGLISH).endsWith(".properties"))
1216 properties.load(Resource.newResource(arg).getInputStream());
1217 }
1218
1219
1220 XmlConfiguration last = null;
1221 Object[] obj = new Object[args.length];
1222 for (int i = 0; i < args.length; i++)
1223 {
1224 if (!args[i].toLowerCase(Locale.ENGLISH).endsWith(".properties"))
1225 {
1226 XmlConfiguration configuration = new XmlConfiguration(Resource.newResource(args[i]).getURL());
1227 if (last != null)
1228 configuration.getIdMap().putAll(last.getIdMap());
1229 if (properties.size() > 0)
1230 {
1231 Map<String, String> props = new HashMap<>();
1232 for (Object key : properties.keySet())
1233 {
1234 props.put(key.toString(),String.valueOf(properties.get(key)));
1235 }
1236 configuration.getProperties().putAll(props);
1237 }
1238 obj[i] = configuration.configure();
1239 last = configuration;
1240 }
1241 }
1242
1243
1244 for (int i = 0; i < args.length; i++)
1245 {
1246 if (obj[i] instanceof LifeCycle)
1247 {
1248 LifeCycle lc = (LifeCycle)obj[i];
1249 if (!lc.isRunning())
1250 lc.start();
1251 }
1252 }
1253 }
1254 catch (Exception e)
1255 {
1256 LOG.debug(Log.EXCEPTION,e);
1257 exception.set(e);
1258 }
1259 return null;
1260 }
1261 });
1262
1263 Throwable th = exception.get();
1264 if (th != null)
1265 {
1266 if (th instanceof RuntimeException)
1267 throw (RuntimeException)th;
1268 else if (th instanceof Exception)
1269 throw (Exception)th;
1270 else if (th instanceof Error)
1271 throw (Error)th;
1272 throw new Error(th);
1273 }
1274 }
1275 }