1 package jfun.yan.xml; 2 3 import java.beans.IntrospectionException ; 4 import java.beans.PropertyEditor ; 5 import java.beans.PropertyEditorManager ; 6 import java.io.File ; 7 import java.io.IOException ; 8 import java.io.InputStream ; 9 import java.net.URL ; 10 import java.util.ArrayList ; 11 import java.util.Arrays ; 12 import java.util.Comparator ; 13 import java.util.HashMap ; 14 import java.util.Hashtable ; 15 import java.util.Iterator ; 16 import java.util.List ; 17 import java.util.Map ; 18 import java.util.Set ; 19 20 21 22 import jfun.util.Misc; 23 import jfun.util.dict.Dict; 24 import jfun.util.dict.DictFactory; 25 import jfun.yan.Component; 26 import jfun.yan.Components; 27 import jfun.yan.Container; 28 import jfun.yan.Creator; 29 import jfun.yan.ParameterBinder; 30 import jfun.yan.PropertyBinder; 31 import jfun.yan.Registrar; 32 import jfun.yan.containers.ManualContainer; 33 import jfun.yan.factory.Factory; 34 import jfun.yan.lifecycle.DefaultLifecycleManager; 35 import jfun.yan.util.deserializer.Deserializer; 36 import jfun.yan.util.resource.ClassLoader2ResourceLoader; 37 import jfun.yan.util.resource.ResourceLoader; 38 import jfun.yan.xml.nut.Nut; 39 import jfun.yan.xml.nut.NutDescriptor; 40 import jfun.yan.xml.nut.NutIntrospector; 41 42 43 import org.xml.sax.InputSource ; 44 45 46 54 public class NutsProcessor implements java.io.Serializable { 55 private Map getDeserializers(){ 56 final Map deserializers = NutsUtils.getDeserializers(); 57 deserializers.put(File .class, new Deserializer(){ 58 public Object deserialize(String str) throws Exception { 59 return NutsUtils.toFile(getBaseDir(), str); 60 } 61 }); 62 deserializers.put(Class .class, new Deserializer(){ 63 public Object deserialize(String str) throws Exception { 64 return MyUtil.getClass(getClassLoader(), str); 65 } 66 }); 67 deserializers.put(URL .class, new Deserializer(){ 68 public Object deserialize(String str) throws Exception { 69 return NutsUtils.toUrl(getBaseDir(), str); 70 } 71 }); 72 deserializers.put(SingletonMode.class, new SingletonModeEditor()); 73 return deserializers; 74 } 75 private final DefaultLifecycleManager manager; 76 private final Container yan; 77 private final ClassLoader cloader; 78 private final ResourceLoader rloader; 79 private final File basedir; 80 private final Map deserializers = getDeserializers(); 81 private final Map services = new Hashtable (); 82 private final Map external_nuts = new Hashtable (); 83 private final Map eager_instantiations = new Hashtable (); 84 private final Map variables = new Hashtable (); 85 private ParameterBinder param_wiring = null; 86 private PropertyBinder prop_wiring = null; 87 private SingletonMode singleton_mode = Modes.simple_singleton; 88 private static final NutIntrospector introspector = new NutIntrospector(); 89 private static final class CustomWiringModes implements AutoWiringMap{ 90 private final Map prop_wiring_modes = new Hashtable (); 91 private final Map param_wiring_modes = new Hashtable (); 92 void addWiringMode(String name, ParameterBinder pmode){ 93 param_wiring_modes.put(canonicalize(name), 94 pmode); 95 } 96 void addWiringMode(String name, PropertyBinder pmode){ 97 prop_wiring_modes.put(canonicalize(name), pmode); 98 } 99 private static String canonicalize(String name){ 100 return NutsUtils.canonicalizeAttributeName(name); 101 } 102 public ParameterBinder getParameterWiringMode(String mode_name) { 103 return (ParameterBinder)param_wiring_modes.get(canonicalize(mode_name)); 104 } 105 public PropertyBinder getPropertyWiringMode(String mode_name) { 106 return (PropertyBinder)prop_wiring_modes.get(canonicalize(mode_name)); 107 } 108 } 109 private final CustomWiringModes custom_wiring_modes = new CustomWiringModes(); 110 private Interpreter createInterpreter(){ 111 return new Interpreter(this, getInitialFrame(), this.getInitialCompileContext()); 112 } 113 private Dict bindVariables(Dict ctxt){ 114 synchronized(variables){ 115 final Object [] keys = variables.keySet().toArray(); 116 final Object [] vals = new Object [keys.length]; 117 for(int i=0; i<keys.length; i++){ 118 vals[i] = variables.get(keys[i]); 119 } 120 return ctxt.puts(keys, vals); 121 } 123 } 124 private Dict getInitialFrame(){ 125 return bindVariables(DictFactory.safeInstance().put(Constants.NULL, null)); 126 } 127 private Dict getInitialCompileContext(){ 128 return bindVariables(DictFactory.instance() 129 .put(Constants.NULL, MyUtil.value(null, new Location("SYSTEM", 0, 0))) 130 ); 131 } 132 private String [] processModule(Module module){ 133 module.register(toRegistry(yan)); 134 registerDynamics(this.yan); 135 return (String [])module.getDependencies().clone(); 136 } 137 144 public NutsProcessor(){ 145 this(NutsProcessor.class.getClassLoader()); 146 } 147 151 public NutsProcessor(ClassLoader classloader){ 152 this(classloader, new ClassLoader2ResourceLoader(classloader)); 153 } 154 159 public NutsProcessor(ClassLoader classloader, ResourceLoader rloader){ 160 this(classloader, rloader, new ManualContainer()); 161 } 162 170 public NutsProcessor(ClassLoader cloader, Container yan, 171 DefaultLifecycleManager manager, 172 File basedir) { 173 this(cloader, new ClassLoader2ResourceLoader(cloader), yan, manager, basedir); 174 } 175 184 public NutsProcessor(ClassLoader cloader, ResourceLoader rloader, 185 Container yan, 186 DefaultLifecycleManager manager, 187 File basedir) { 188 this.basedir = basedir; 189 this.cloader = cloader; 190 this.rloader = rloader; 191 this.manager = manager; 192 this.yan = yan; 193 this.variables.put(Constants.THIS_CONTAINER, Components.thisContainer()); 194 this.variables.put(Constants.RESOURCE_LOADER, rloader); 195 } 196 201 public NutsProcessor(ClassLoader cloader, Container yan){ 202 this(cloader, new ClassLoader2ResourceLoader(cloader), yan); 203 } 204 210 public NutsProcessor(ClassLoader cloader, ResourceLoader rloader, 211 Container yan){ 212 this(cloader, rloader, yan, 213 new DefaultLifecycleManager(), new File (".").getAbsoluteFile()); 214 } 215 224 public Object deserialize(Class type, String v) 225 throws Throwable { 226 final Deserializer des = (Deserializer)deserializers.get(type); 227 if(des != null) return des.deserialize(v); 228 else{ 229 final PropertyEditor editor = PropertyEditorManager.findEditor(type); 230 if(editor==null){ 231 throw new IllegalArgumentException ("cannot convert to "+ 232 Misc.getTypeName(type)); 233 } 234 else{ 235 editor.setAsText(v); 236 return editor.getValue(); 237 } 238 } 239 } 240 247 public boolean isDeserializable(Class type){ 248 return type.isAssignableFrom(String .class) 249 || deserializers.get(type)!=null 250 || PropertyEditorManager.findEditor(type)!=null; 251 } 252 private synchronized String [] process(Object id, final InputSource in) 253 throws IOException { 254 return processModule(createInterpreter() 255 .interpret(id, in)); 256 } 257 266 public synchronized String [] processResource(final String resourcename) 267 throws IOException { 268 return processModule(createInterpreter() 269 .interpretResource(resourcename)); 270 } 271 280 public synchronized String [] processFile(String filename) 281 throws IOException { 282 return processFile(new File (filename)); 283 } 285 294 public synchronized String [] processFile(File file) 295 throws IOException { 296 return processModule(createInterpreter() 297 .interpretFile(file)); 298 } 299 309 public synchronized String [] process(Object id, InputStream in) 310 throws IOException { 311 return processModule(createInterpreter().interpret(id, in)); 312 } 313 320 public Map preInstantiate(Container container, Map store){ 321 final UID[] keys = getOrderedUIDs(); 322 for(int i=0; i<keys.length; i++){ 323 final UID key = keys[i]; 324 final Creator c = (Creator)eager_instantiations.get(key); 325 store.put(key, container.instantiateComponent(key, c)); 326 } 327 return store; 328 } 329 335 public Map preInstantiate(Container container){ 336 return preInstantiate(container, new HashMap ()); 337 } 338 344 public Map preInstantiate(Map store){ 345 return preInstantiate(yan, store); 346 } 347 352 public Map preInstantiate(){ 353 return preInstantiate(yan); 354 } 355 358 public DefaultLifecycleManager getLifecycleManager() { 359 return manager; 360 } 361 364 public Container getContainer() { 365 return yan; 366 } 367 370 public File getBaseDir() { 371 return basedir; 372 } 373 374 377 public ClassLoader getClassLoader() { 378 return cloader; 379 } 380 383 public ResourceLoader getResourceLoader(){ 384 return rloader; 385 } 386 392 public void registerAutoWiring(String mode_name, PropertyBinder mode){ 393 custom_wiring_modes.addWiringMode(mode_name, mode); 394 } 395 401 public void registerAutoWiring(String mode_name, ParameterBinder mode){ 402 custom_wiring_modes.addWiringMode(mode_name, mode); 403 } 404 414 public void registerDeserializer(Class type, Deserializer deserializer, 415 boolean overriding, boolean mandatory) 416 throws IllegalArgumentException { 417 if(!overriding){ 418 if(deserializers.containsKey(type)){ 419 if(mandatory){ 420 throw new IllegalArgumentException ("Deserializer for " 421 + type + " already exists"); 422 } 423 else return; 424 } 425 } 426 deserializers.put(type, deserializer); 427 } 428 435 public Object findService(Object key){ 436 return services.get(key); 437 } 438 447 public void registerService(Object key, Object service){ 448 services.put(key, service); 449 } 450 454 public void unregisterService(Object key){ 455 services.remove(key); 456 } 457 460 public Set getServiceKeys(){ 461 return services.keySet(); 462 } 463 464 469 public void registerNut(String key, NutDescriptor desc){ 470 external_nuts.put(key, desc); 471 } 472 478 public NutDescriptor findNut(String key){ 479 return (NutDescriptor)external_nuts.get(key); 480 } 481 485 public void removeNut(String key){ 486 external_nuts.remove(key); 487 } 488 494 public void registerVariable(String key, Object val){ 495 variables.put(key, val); 496 } 497 502 public Object getVariable(String key){ 503 return variables.get(key); 504 } 505 509 public boolean hasVariable(String key){ 510 return variables.containsKey(key); 511 } 512 516 public void removeVariable(String key){ 517 variables.remove(key); 518 } 519 522 public Set getNutKeys(){ 523 return external_nuts.keySet(); 524 } 525 528 public synchronized ParameterBinder getParameterWiring() { 529 return param_wiring; 530 } 531 535 public synchronized void setParameterWiring(ParameterBinder param_wiring) { 536 this.param_wiring = param_wiring; 537 } 538 541 public synchronized PropertyBinder getPropertyWiring() { 542 return prop_wiring; 543 } 544 549 public synchronized void setPropertyWiring(PropertyBinder prop_wiring) { 550 this.prop_wiring = prop_wiring; 551 } 552 555 public synchronized SingletonMode getSingletonMode() { 556 return singleton_mode; 557 } 558 563 public synchronized void setSingletonMode(SingletonMode singleton_mode) { 564 this.singleton_mode = singleton_mode; 565 } 566 567 592 public synchronized NutsProcessor createMetaProcessor(ClassLoader loader, 593 ResourceLoader rloader){ 594 final NutsProcessor aux = new NutsProcessor(loader, rloader, new ManualContainer(), 595 manager, basedir); 596 aux.setSingletonMode(null); 597 aux.setParameterWiring(Modes.params_bytype); 598 aux.services.putAll(services); 599 aux.external_nuts.putAll(external_nuts); 600 return aux; 601 } 602 626 public NutsProcessor createMetaProcessor(ClassLoader loader){ 627 return createMetaProcessor(loader, new ClassLoader2ResourceLoader(loader)); 628 } 629 655 public NutsProcessor createMetaInterpreter(){ 656 return createMetaProcessor(cloader, rloader); 657 } 658 662 public synchronized void loadNutsFromContainer(Container nuts){ 663 final HashMap descs = new HashMap (); 664 populateNuts(nuts, descs); 665 addNuts(nuts, descs); 666 } 667 private static void populateNuts(Container nuts, Map descs){ 668 final Set nutkeys = nuts.keys(); 669 for(Iterator it=nutkeys.iterator(); it.hasNext();){ 670 final Object key = it.next(); 671 if(!(key instanceof String )){ 672 continue; 674 } 675 final Component c = nuts.getComponent(key); 676 final Class type = c.getType(); 677 if(type==null){ 678 throw new IllegalArgumentException ("unknown type for nut component "+key 679 + ", consider using 'type' attribute to explicitly specify the type for it"); 680 } 681 if(!Nut.class.isAssignableFrom(type)){ 682 continue; 684 695 } 696 try{ 697 final NutDescriptor desc = introspector.getNutDescriptor(type); 698 descs.put(key, desc); 699 } 700 catch(IntrospectionException e){ 701 throw new IllegalArgumentException ("failed to introspect type "+Misc.getTypeName(type)); 702 } 703 } 705 } 706 private synchronized void addNuts(Container nuts, Map descs){ 707 for(Iterator it=descs.keySet().iterator();it.hasNext();){ 708 final Object key = it.next(); 709 final NutDescriptor desc = (NutDescriptor)descs.get(key); 710 final Factory factory = nuts.getFactory(key); 711 desc.setFactory(factory); 712 registerNut(key.toString(), desc); 713 } 714 } 715 private void prewireNuts(Object id, ClassLoader loader, ResourceLoader rloader, InputSource in) 716 throws IOException { 717 final NutsProcessor aux = createMetaProcessor(loader, rloader); 718 final Container nuts = aux.getContainer(); 719 aux.process(id, in); 720 loadNutsFromContainer(nuts); 721 } 722 734 public void loadNutsMetaFile(ClassLoader loader, ResourceLoader rloader, 735 String filename) 736 throws IOException { 737 final File file = Misc.getAbsolutePath(basedir, new File (filename)); 738 prewireNuts(file, loader, rloader, new InputSource (filename)); 739 } 740 752 public void loadNutsMetaData(Object id, ClassLoader loader, 753 ResourceLoader rloader, InputStream in) 754 throws IOException { 755 prewireNuts(id, loader, rloader, new InputSource (in)); 756 } 757 758 759 772 public void loadNutsMetaFile(String filename) 773 throws IOException { 774 loadNutsMetaFile(filename); 775 } 776 789 public void loadNutsMetaData(Object id, InputStream in) 790 throws IOException { 791 loadNutsMetaData(id, cloader, rloader, in); 792 } 793 811 public void loadNutsMetaResource(String resourcename) 812 throws IOException { 813 final URL url = rloader.getResource(resourcename); 814 final InputStream in = MyUtil.readResource(this.rloader, resourcename); 815 try{ 816 loadNutsMetaData(url, this.cloader, rloader, in); 817 } 818 finally{ 819 in.close(); 820 } 821 } 822 private static Registry toRegistry(final Registrar reg){ 823 return new Registry(){ 824 public void put(String key, Object v, Location loc){ 825 reg.registerComponent(key, NutsUtils.asComponent(v)); 826 } 827 public String toString(){ 828 return reg.toString(); 829 } 830 }; 831 } 832 private final List modules_involved = new ArrayList (); 833 void registerModuleImport(Object module_id){ 834 modules_involved.add(module_id); 835 } 836 void registerEagerInstantiation(UID key, Component c){ 837 this.eager_instantiations.put(key, c); 838 } 839 Map getExternalNuts(){ 840 return external_nuts; 841 } 842 AutoWiringMap getCustomWiringModes(){ 843 return custom_wiring_modes; 844 } 845 Map getServices(){ 846 return this.services; 847 } 848 private UID[] getOrderedUIDs(){ 849 final Set uids = this.eager_instantiations.keySet(); 850 final UID[] result = new UID[uids.size()]; 851 uids.toArray(result); 852 Arrays.sort(result, getUIDComparator()); 853 return result; 854 } 855 private Comparator getUIDComparator(){ 856 final HashMap module_sequence = new HashMap (); 857 final int sz = modules_involved.size(); 858 for(int i=0; i<sz; i++){ 859 module_sequence.put(modules_involved.get(i), new Integer (i)); 860 } 861 return new Comparator (){ 862 public int compare(Object arg0, Object arg1) { 863 final UID id1 = (UID)arg0; 864 final UID id2 = (UID)arg1; 865 final Integer module_seq1 = (Integer )module_sequence.get(id1.getModuleId()); 866 final Integer module_seq2 = (Integer )module_sequence.get(id2.getModuleId()); 867 int result = module_seq1.intValue() - module_seq2.intValue(); 868 if(result==0){ 869 result = id1.getDeclarationSequence() - id2.getDeclarationSequence(); 870 if(result == 0){ 871 result = id1.getEvaluationSequence()-id2.getEvaluationSequence(); 872 } 873 } 874 return result; 875 } 876 public String toString(){ 877 return "UID comparator"; 878 } 879 }; 880 } 881 private final NutsRegistrar dynamic_registered = new NutsRegistrar(); 882 void register(Object key, Object val, boolean overridable, 883 boolean overriding, Location loc){ 884 dynamic_registered.register(key, val, overridable, overriding, loc); 885 } 886 887 private void registerDynamics(Registrar reg){ 888 for(Iterator it=dynamic_registered.keySet().iterator(); it.hasNext();){ 889 final Object key = it.next(); 890 final NutsRegistrar.Entry entry = dynamic_registered.getEntry(key); 891 if(reg.containsKey(key)){ 892 throw new ConfigurationException("component "+key+" already registered.", 893 entry.getLocation()); 894 } 895 reg.registerComponent(key, NutsUtils.asComponent(entry.getValue())); 896 } 897 } 898 } 899 | Popular Tags |