Package jfun.yan.xml

Source Code of jfun.yan.xml.NutsProcessor$CustomWiringModes

package jfun.yan.xml;

import java.beans.IntrospectionException;
import java.beans.PropertyEditor;
import java.beans.PropertyEditorManager;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;



import jfun.util.Misc;
import jfun.util.dict.Dict;
import jfun.util.dict.DictFactory;
import jfun.yan.Component;
import jfun.yan.Components;
import jfun.yan.Container;
import jfun.yan.Creator;
import jfun.yan.ParameterBinder;
import jfun.yan.PropertyBinder;
import jfun.yan.Registrar;
import jfun.yan.containers.ManualContainer;
import jfun.yan.factory.Factory;
import jfun.yan.lifecycle.DefaultLifecycleManager;
import jfun.yan.util.deserializer.Deserializer;
import jfun.yan.util.resource.ClassLoader2ResourceLoader;
import jfun.yan.util.resource.ResourceLoader;
import jfun.yan.xml.nut.Nut;
import jfun.yan.xml.nut.NutDescriptor;
import jfun.yan.xml.nut.NutIntrospector;


import org.xml.sax.InputSource;


/**
* The main class that parses an xml config file and populates
* container and lifecycle manager with the information stored
* in the config file.
* <p>
* @author Ben Yu
*
*/
public class NutsProcessor implements java.io.Serializable{
  private Map getDeserializers(){
    final Map deserializers = NutsUtils.getDeserializers();
    deserializers.put(File.class, new Deserializer(){
      public Object deserialize(String str) throws Exception {
        return NutsUtils.toFile(getBaseDir(), str);
      }
    });
    deserializers.put(Class.class, new Deserializer(){
      public Object deserialize(String str) throws Exception {
        return MyUtil.getClass(getClassLoader(), str);
      }     
    });
    deserializers.put(URL.class, new Deserializer(){
      public Object deserialize(String str) throws Exception {
        return NutsUtils.toUrl(getBaseDir(), str);
      }
    });
    deserializers.put(SingletonMode.class, new SingletonModeEditor());   
    return deserializers;
  }
  private final DefaultLifecycleManager manager;
  private final Container yan;
  private final ClassLoader cloader;
  private final ResourceLoader rloader;
  private final File basedir;
  private final Map deserializers = getDeserializers();
  private final Map services = new Hashtable();
  private final Map external_nuts = new Hashtable();
  private final Map eager_instantiations = new Hashtable();
  private final Map variables = new Hashtable();
  private ParameterBinder param_wiring = null;
  private PropertyBinder prop_wiring = null;
  private SingletonMode singleton_mode = Modes.simple_singleton;
  private static final NutIntrospector introspector = new NutIntrospector();
  private static final class CustomWiringModes implements AutoWiringMap{
    private final Map prop_wiring_modes = new Hashtable();
    private final Map param_wiring_modes = new Hashtable();
    void addWiringMode(String name, ParameterBinder pmode){
      param_wiring_modes.put(canonicalize(name),
          pmode);
    }
    void addWiringMode(String name, PropertyBinder pmode){
      prop_wiring_modes.put(canonicalize(name), pmode);
    }
    private static String canonicalize(String name){
      return NutsUtils.canonicalizeAttributeName(name);
    }
    public ParameterBinder getParameterWiringMode(String mode_name) {
      return (ParameterBinder)param_wiring_modes.get(canonicalize(mode_name));
    }
    public PropertyBinder getPropertyWiringMode(String mode_name) {
      return (PropertyBinder)prop_wiring_modes.get(canonicalize(mode_name));
    }
  }
  private final CustomWiringModes custom_wiring_modes = new CustomWiringModes();
  private Interpreter createInterpreter(){
    return new Interpreter(this, getInitialFrame(), this.getInitialCompileContext());
  }
  private Dict bindVariables(Dict ctxt){
    synchronized(variables){
      final Object[] keys = variables.keySet().toArray();
      final Object[] vals = new Object[keys.length];
      for(int i=0; i<keys.length; i++){
        vals[i] = variables.get(keys[i]);
      }
      return ctxt.puts(keys, vals);
      //.put(Constants.THIS_CONTAINER, Components.thisContainer());
    }
  }
  private Dict getInitialFrame(){
    return bindVariables(DictFactory.safeInstance().put(Constants.NULL, null));
  }
  private Dict getInitialCompileContext(){
    return bindVariables(DictFactory.instance()
      .put(Constants.NULL, MyUtil.value(null, new Location("SYSTEM", 0, 0)))
    );
  }
  private String[] processModule(Module module){
    module.register(toRegistry(yan));
    registerDynamics(this.yan);
    return (String[])module.getDependencies().clone();
  }
  /**
   * Create a NutsProcessor object.
   * <p>
   * The ClassLoader object that loads this class
   * is used to load the nut classes and the component classes.
   * </p>
   */
  public NutsProcessor(){
    this(NutsProcessor.class.getClassLoader());
  }
  /**
   * Create an NutsProcessor object.
   * @param classloader the ClassLoader object to load component classes and resources.
   */
  public NutsProcessor(ClassLoader classloader){
    this(classloader, new ClassLoader2ResourceLoader(classloader));
  }
  /**
   * Create an NutsProcessor object.
   * @param classloader the ClassLoader object to load component classes.
   * @param rloader the ResourceLoader object to load resources.
   */
  public NutsProcessor(ClassLoader classloader, ResourceLoader rloader){
    this(classloader, rloader, new ManualContainer());
  }
  /**
   * Create an NutsProcessor object.
   * @param cloader the ClassLoader object to load component classes and resources.
   * @param yan the container that registers the components.
   * @param manager the life cycle manager.
   * @param basedir the base directory against which relative paths
   * found in the config file can be resolved.
   */
  public NutsProcessor(ClassLoader cloader, Container yan,
      DefaultLifecycleManager manager,
      File basedir) {
    this(cloader, new ClassLoader2ResourceLoader(cloader), yan, manager, basedir);
  }
  /**
   * Create an NutsProcessor object.
   * @param cloader the ClassLoader object to load component classes.
   * @param rloader the ResourceLoader object to load resources.
   * @param yan the container that registers the components.
   * @param manager the life cycle manager.
   * @param basedir the base directory against which relative paths
   * found in the config file can be resolved.
   */
  public NutsProcessor(ClassLoader cloader, ResourceLoader rloader,
      Container yan,
      DefaultLifecycleManager manager,
      File basedir) {
    this.basedir = basedir;
    this.cloader = cloader;
    this.rloader = rloader;
    this.manager = manager;
    this.yan = yan;
    this.variables.put(Constants.THIS_CONTAINER, Components.thisContainer());
    this.variables.put(Constants.RESOURCE_LOADER, rloader);
  }
  /**
   * Create an NutsProcessor object.
   * @param cloader the ClassLoader to load the component classes and resources.
   * @param yan the container that registeres the components.
   */
  public NutsProcessor(ClassLoader cloader, Container yan){
    this(cloader, new ClassLoader2ResourceLoader(cloader), yan);
  }
  /**
   * Create an NutsProcessor object.
   * @param cloader the ClassLoader to load the component classes.
   * @param rloader the ResourceLoader to load resources.
   * @param yan the container that registeres the components.
   */
  public NutsProcessor(ClassLoader cloader, ResourceLoader rloader,
      Container yan){
    this(cloader, rloader, yan,
        new DefaultLifecycleManager(), new File(".").getAbsoluteFile());
  }
  /**
   * Convert a string literal to an object of a certain type.
   * A PropertyEditor is searched if the deserialization of the target type
   * is not supported by the framework by default.
   * @param type the target type.
   * @param v the string literal.
   * @return the object of the target type.
   * @throws Throwable when any error happens.
   */
  public Object deserialize(Class type, String v)
  throws Throwable{
    final Deserializer des = (Deserializer)deserializers.get(type);
    if(des != null) return des.deserialize(v);
    else{
      final PropertyEditor editor = PropertyEditorManager.findEditor(type);
      if(editor==null){
        throw new IllegalArgumentException("cannot convert to "+
          Misc.getTypeName(type));
      }
      else{
        editor.setAsText(v);
        return editor.getValue();
      }
    }
  }
  /**
   * To determine if string literal can be converted to the target type.
   * PropertyEditor is also searched if the type is not by default
   * deserializable by the framework
   * @param type the target type.
   * @return true if convertible.
   */
  public boolean isDeserializable(Class type){
    return type.isAssignableFrom(String.class)
      || deserializers.get(type)!=null
      || PropertyEditorManager.findEditor(type)!=null;
  }
  private synchronized String[] process(Object id, final InputSource in)
  throws IOException{
    return processModule(createInterpreter()
        .interpret(id, in));
  }
  /**
   * Process a resource from the component class loader as an xml configuration.
   * @param resourcename the resource name.
   * @return an array of dependency names that the module requires
   * to be present in the container in order for the module to
   * wire up properly.
   * An empty array is returned if there's no dependency required.
   * @throws IOException when resource reading fails.
   */
  public synchronized String[] processResource(final String resourcename)
  throws IOException{
    return processModule(createInterpreter()
        .interpretResource(resourcename));
  }
  /**
   * Process a config file.
   * @param filename the configuration file name.
   * @return an array of dependency names that the module requires
   * to be present in the container in order for the module to
   * wire up properly.
   * An empty array is returned if there's no dependency required.
   * @throws IOException if file reading fails.
   */
  public synchronized String[] processFile(String filename)
  throws IOException{
    return processFile(new File(filename));
    //processModule(createInterpreter().interpretFile(filename));
  }
  /**
   * Process a config file.
   * @param file the configuration file.
   * @return an array of dependency names that the module requires
   * to be present in the container in order for the module to
   * wire up properly.
   * An empty array is returned if there's no dependency required. An empty array is returned if there's no dependency required.
   * @throws IOException if file reading fails.
   */
  public synchronized String[] processFile(File file)
  throws IOException{
    return processModule(createInterpreter()
        .interpretFile(file));
  }
  /**
   * Process bytes read from an InputStream.
   * @param id the module id.
   * @param in the InputStream object.
   * @return an array of dependency names that the module requires
   * to be present in the container in order for the module to
   * wire up properly.
   * An empty array is returned if there's no dependency required.
   * @throws IOException any io error.
   */
  public synchronized String[] process(Object id, InputStream in)
  throws IOException{
    return processModule(createInterpreter().interpret(id, in));
  }
  /**
   * Pre-initialize eagerly instantiated components.
   * @param container the container to resolve dependency for these components.
   * @param store the Map object to collect the instantiated results.
   * The map key is {@link UID}, which is a combination of the module id and the component id.
   * @return reference to the Map object.
   */
  public Map preInstantiate(Container container, Map store){
    final UID[] keys = getOrderedUIDs();
    for(int i=0; i<keys.length; i++){
      final UID key = keys[i];
      final Creator c = (Creator)eager_instantiations.get(key);
      store.put(key, container.instantiateComponent(key, c));
    }
    return store;
  }
  /**
   * Pre-initialize eagerly instantiated components.
   * @param container the container to resolve dependency for these components.
   * @return the Map object to collect the instantiated results.
   * The map key is {@link UID}, which is a combination of the module id and the component id.
   */
  public Map preInstantiate(Container container){
    return preInstantiate(container, new HashMap());   
  }
  /**
   * Pre-initialize eagerly instantiated components.
   * @param store the Map object to collect the instantiated results.
   * The map key is {@link UID}, which is a combination of the module id and the component id.
   * @return reference to the Map object.
   */
  public Map preInstantiate(Map store){
    return preInstantiate(yan, store);
  }
  /**
   * Pre-initialize eagerly instantiated components.
   * @return the Map object to collect the instantiated results.
   * The map key is {@link UID}, which is a combination of the module id and the component id.
   */
  public Map preInstantiate(){
    return preInstantiate(yan);
 
  /**
   * To get the lifecycle manager used by this processor.
   */
  public DefaultLifecycleManager getLifecycleManager() {
    return manager;
  }
  /**
   * To get the container used by this processor.
   */
  public Container getContainer() {
    return yan;
  }
  /**
   * To get the base directory used by the processor.
   */
  public File getBaseDir() {
    return basedir;
  }

  /**
   * To get the ClassLoader used to load component classes.
   */
  public ClassLoader getClassLoader() {
    return cloader;
  }
  /**
   * To get the ResourceLoader used to load resources.
   */
  public ResourceLoader getResourceLoader(){
    return rloader;
  }
  /**
   * Register a property autowiring mode. Any existent mode or predefined mode
   * with the same name will be overriden.
   * @param mode_name the mode name.
   * @param mode the PropertyBinder object encapsulating the autowiring logic.
   */
  public void registerAutoWiring(String mode_name, PropertyBinder mode){
    custom_wiring_modes.addWiringMode(mode_name, mode);
  }
  /**
   * Register a parameter autowiring mode. Any existent mode or predefined mode
   * with the same name will be overriden.
   * @param mode_name the mode name.
   * @param mode the ParameterBinder object encapsulating the autowiring logic.
   */
  public void registerAutoWiring(String mode_name, ParameterBinder mode){
    custom_wiring_modes.addWiringMode(mode_name, mode);
  }
  /**
   * To register a Deserializer.
   * @param type the type that uses the Deserializer to convert
   * literal string to objects of this type.
   * @param deserializer the Deserializer object.
   * @param overriding whether override the existent Deserializer if any.
   * @param mandatory true if this registration has to go through.
   * @exception IllegalArgumentException if the registration is mandatory but not overriding
   * and an Deserializer object is already registered for the target type.
   */
  public void registerDeserializer(Class type, Deserializer deserializer,
      boolean overriding, boolean mandatory)
  throws IllegalArgumentException{
    if(!overriding){
      if(deserializers.containsKey(type)){
        if(mandatory){
          throw new IllegalArgumentException("Deserializer for "
              + type + " already exists");
        }
        else return;
      }
    }
    deserializers.put(type, deserializer);
  }
  /**
   * To find the service object registered using
   * {@link #registerService(Object, Object)}.
   * @param key the key to the service object.
   * @return the service object.
   * null is returned if no object is registered under this key.
   */
  public Object findService(Object key){
    return services.get(key);
  }
  /**
   * To register a service object that can be read by customized Nuts classes
   * through the call of {@link NutEnvironment#findService(Object)}.
   * <p>
   * register and unregister are thread safe.
   * </p>
   * @param key the service key.
   * @param service the service object.
   */
  public void registerService(Object key, Object service){
    services.put(key, service);
  }
  /**
   * To unregister a service object. No-op if the key is not found.
   * @param key the key of the service object.
   */
  public void unregisterService(Object key){
    services.remove(key);
  }
  /**
   * Get the set of the keys of the service objects.
   */
  public Set getServiceKeys(){
    return services.keySet();
  }
 
  /**
   * Add an external nut descriptor for the processor to use.
   * @param key the key of the nut.
   * @param desc the descriptor.
   */
  public void registerNut(String key, NutDescriptor desc){
    external_nuts.put(key, desc);
  }
  /**
   * Get a NutDescriptor registered by putNut().
   * @param key the key of the NutDescriptor.
   * @return the NutDescriptor object.
   * Null is returned if the key is not found.
   */
  public NutDescriptor findNut(String key){
    return (NutDescriptor)external_nuts.get(key);
  }
  /**
   * Unregister a NutDescriptor.
   * @param key the key of the NutDescriptor.
   */
  public void removeNut(String key){
    external_nuts.remove(key);
  }
  /**
   * Register a variable that can be referenced in the xml file
   * using "$varname" syntax.
   * @param key the variable name.
   * @param val the variable value.
   */
  public void registerVariable(String key, Object val){
    variables.put(key, val);
  }
  /**
   * To get a variable value.
   * @param key the variable name.
   * @return the variable value. Or null if not found.
   */
  public Object getVariable(String key){
    return variables.get(key);
  }
  /**
   * Checks whether a variable name exists.
   * @param key the variable name.
   */
  public boolean hasVariable(String key){
    return variables.containsKey(key);
  }
  /**
   * To remove a registration of a variable.
   * @param key the variable name.
   */
  public void removeVariable(String key){
    variables.remove(key);
  }
  /**
   * Get the set of keys of Nut descriptors.
   */
  public Set getNutKeys(){
    return external_nuts.keySet();
  }
  /**
   * Get the default parameter auto wiring mode.
   */
  public synchronized ParameterBinder getParameterWiring() {
    return param_wiring;
  }
  /**
   * Set the default parameter auto-wiring mode.
   * @param param_wiring the wiring mode. Null if auto-wiring is disabled.
   */
  public synchronized void setParameterWiring(ParameterBinder param_wiring) {
    this.param_wiring = param_wiring;
  }
  /**
   * Get the default property auto-wiring mode.
   */
  public synchronized PropertyBinder getPropertyWiring() {
    return prop_wiring;
  }
  /**
   * Set the default property auto-wiring mode.
   * @param prop_wiring the wiring mode.
   * Null if auto-wiring is disabled.
   */
  public synchronized void setPropertyWiring(PropertyBinder prop_wiring) {
    this.prop_wiring = prop_wiring;
  }
  /**
   * Get the default singleton mode.
   */
  public synchronized SingletonMode getSingletonMode() {
    return singleton_mode;
  }
  /**
   * Set the default singleton mode.
   * @param singleton_mode the singleton mode.
   * Null if prototype is used.
   */
  public synchronized void setSingletonMode(SingletonMode singleton_mode) {
    this.singleton_mode = singleton_mode;
  }
 
  /**
   * Create an NutsProcessor object that's gonna be used to
   * load meta configuration of Nut classes.
   * <p>
   * The default singleton mode is "off" and the default parameter auto-wiring
   * mode is "bytype".
   * </p>
   * <p>
   * All the service objects and externally registered nuts descriptors
   * will be copied to this new NutsProcessor object.
   * </p>
   * <p>
   * It is fine to create an NutsProcessor object by calling
   * the constructor directly.
   * Any NutsProcessor object can be used to interpret meta configuration.
   * </p>
   * <p>
   * This method just makes it more convenient
   * to set the default settings and copy the existing service objects
   * and externally registered nut descriptors.
   * </p>
   * @param loader The class loader to load classes.
   * @param rloader the ResourceLoader to load resources.
   * @return the new NutsProcessor object.
   */
  public synchronized NutsProcessor createMetaProcessor(ClassLoader loader,
      ResourceLoader rloader){
    final NutsProcessor aux = new NutsProcessor(loader, rloader, new ManualContainer(),
        manager, basedir);
    aux.setSingletonMode(null);
    aux.setParameterWiring(Modes.params_bytype);
    aux.services.putAll(services);
    aux.external_nuts.putAll(external_nuts);
    return aux;
  }
  /**
   * Create an NutsProcessor object that's gonna be used to
   * load meta configuration of Nut classes.
   * <p>
   * The default singleton mode is "off" and the default parameter auto-wiring
   * mode is "bytype".
   * </p>
   * <p>
   * All the service objects and externally registered nuts descriptors
   * will be copied to this new NutsProcessor object.
   * </p>
   * <p>
   * It is fine to create an NutsProcessor object by calling
   * the constructor directly.
   * Any NutsProcessor object can be used to interpret meta configuration.
   * </p>
   * <p>
   * This method just makes it more convenient
   * to set the default settings and copy the existing service objects
   * and externally registered nut descriptors.
   * </p>
   * @param loader The class loader to load classes and resources.
   * @return the new NutsProcessor object.
   */
  public NutsProcessor createMetaProcessor(ClassLoader loader){
    return createMetaProcessor(loader, new ClassLoader2ResourceLoader(loader));
  }
  /**
   * Create an NutsProcessor object that's gonna be used to
   * load meta configuration of Nut classes.
   * <p>
   * The component classloader is used to load classes.
   * </p>
   * <p>
   * The default singleton mode is "off" and the default parameter auto-wiring
   * mode is "bytype".
   * </p>
   * <p>
   * All the service objects and externally registered nuts descriptors
   * will be copied to this new NutsProcessor object.
   * </p>
   * <p>
   * It is fine to create an NutsProcessor object by calling
   * the constructor directly.
   * Any NutsProcessor object can be used to interpret meta configuration.
   * </p>
   * <p>
   * This method just makes it more convenient
   * to set the default settings and copy the existing service objects
   * and externally registered nut descriptors.
   * </p>
   * @return the new NutsProcessor object.
   */
  public NutsProcessor createMetaInterpreter(){
    return createMetaProcessor(cloader, rloader);
  }
  /**
   * Load descriptors of the nut classes registered in a Container.
   * @param nuts the container containing nut components.
   */
  public synchronized void loadNutsFromContainer(Container nuts){
    final HashMap descs = new HashMap();
    populateNuts(nuts, descs);
    addNuts(nuts, descs);
  }
  private static void populateNuts(Container nuts, Map descs){
    final Set nutkeys = nuts.keys();
    for(Iterator it=nutkeys.iterator(); it.hasNext();){
      final Object key = it.next();
      if(!(key instanceof String)){
        //non-configured component, skip.
        continue;
      }
      final Component c = nuts.getComponent(key);
      final Class type = c.getType();
      if(type==null){
        throw new IllegalArgumentException("unknown type for nut component "+key
            + ", consider using 'type' attribute to explicitly specify the type for it");
      }
      if(!Nut.class.isAssignableFrom(type)){
        //not nut class, helper type.
        continue;
        /*
        if(type.isAssignableFrom(Nut.class)){
          throw new IllegalArgumentException("nut component "+key
              + " is of type " + Misc.getTypeName(type)
              + ", not a subtype of Nut.\nconsider using 'type' attribute to explicitly specify the type.");
        }
        else{
          throw new IllegalArgumentException("nut component "+key
              + " is of type "+Misc.getTypeName(type)
              +", not a subtype of Nut.");
        }*/
      }
      try{
        final NutDescriptor desc = introspector.getNutDescriptor(type);
        descs.put(key, desc);
      }
      catch(IntrospectionException e){
        throw new IllegalArgumentException("failed to introspect type "+Misc.getTypeName(type));
      }
      //nuts.registerComponent(key, c.factory());
    }
  }
  private synchronized void addNuts(Container nuts, Map descs){
    for(Iterator it=descs.keySet().iterator();it.hasNext();){
      final Object key = it.next();
      final NutDescriptor desc = (NutDescriptor)descs.get(key);
      final Factory factory = nuts.getFactory(key);
      desc.setFactory(factory);
      registerNut(key.toString(), desc);
    }
  }
  private void prewireNuts(Object id, ClassLoader loader, ResourceLoader rloader, InputSource in)
  throws IOException{
    final NutsProcessor aux = createMetaProcessor(loader, rloader);
    final Container nuts = aux.getContainer();
    aux.process(id, in);
    loadNutsFromContainer(nuts);
  }
  /**
   * Load a configuration file that wires Nut classes.
   * The Nut descriptors and their ids loaded from this file will be used
   * during interpretation of regular configuration files for components.
   * <p>
   * By default, singleton mode in a nuts meta file is disabled.
   * </p>
   * @param loader the class loader to load classes during interpretation.
   * @param rloader the
   * @param filename the config file containing the nuts class wiring.
   * @throws IOException when file reading fails.
   */
  public void loadNutsMetaFile(ClassLoader loader, ResourceLoader rloader,
      String filename)
  throws IOException{
    final File file = Misc.getAbsolutePath(basedir, new File(filename));
    prewireNuts(file, loader, rloader, new InputSource(filename));
  }
  /**
   * Load configuration information from an InputStream and wires Nut classes.
   * The Nut descriptors and their ids loaded from this InputStream will be used
   * during interpretation of regular configuration files for components.
   * <p>
   * By default, singleton mode is disabled.
   * </p>
   * @param loader the class loader to load classes during interpretation.
   * @param rloader the ResourceLoader to load resources during interpretation.
   * @param in the stream containing meta configuration information.
   * @throws IOException when file reading fails.
   */
  public void loadNutsMetaData(Object id, ClassLoader loader,
      ResourceLoader rloader, InputStream in)
  throws IOException{
    prewireNuts(id, loader, rloader, new InputSource(in));
  }
 
 
  /**
   * Load a configuration file that wires Nut classes.
   * The Nut descriptors and their ids loaded from this file will be used
   * during interpretation of regular configuration files for components.
   * <p>
   * By default, singleton mode in a nuts meta file is disabled.
   * </p>
   * <p>
   * The component classloader is used to load these nuts classes.
   * </p>
   * @param filename the config file containing the nuts class wiring.
   * @throws IOException when file reading fails.
   */
  public void loadNutsMetaFile(String filename)
  throws IOException{
    loadNutsMetaFile(filename);
  }
  /**
   * Load configuration information from an InputStream and wires Nut classes.
   * The Nut descriptors and their ids loaded from this InputStream will be used
   * during interpretation of regular configuration files for components.
   * <p>
   * By default, singleton mode is disabled.
   * </p>
   * <p>
   * The component classloader is used to load these nuts classes.
   * </p>
   * @param in the stream containing meta configuration information.
   * @throws IOException when file reading fails.
   */
  public void loadNutsMetaData(Object id, InputStream in)
  throws IOException{
    loadNutsMetaData(id, cloader, rloader, in);
  }
  /**
   * Load configuration information from a resource loaded
   * by the component class loader.
   * Nuts classes are wired using this configuration information.
   * <p>
   * The Nut descriptors and their ids loaded from this InputStream will be used
   * during interpretation of regular configuration files for components.
   * </p>
   * <p>
   * By default, singleton mode is disabled.
   * </p>
   * <p>
   * The component classloader is used to load these nuts classes.
   * </p>
   * @param resourcename the name of the resource containing meta configuration
   * information.
   * @throws IOException when file reading fails.
   */
  public void loadNutsMetaResource(String resourcename)
  throws IOException{
    final URL url = rloader.getResource(resourcename);
    final InputStream in = MyUtil.readResource(this.rloader, resourcename);
    try{
      loadNutsMetaData(url, this.cloader, rloader, in);
    }
    finally{
      in.close();
    }
  }
  private static Registry toRegistry(final Registrar reg){
    return new Registry(){
      public void put(String key, Object v, Location loc){
        reg.registerComponent(key, NutsUtils.asComponent(v));
      }
      public String toString(){
        return reg.toString();
      }
    };
  }
  private final List modules_involved = new ArrayList();
  void registerModuleImport(Object module_id){
    modules_involved.add(module_id);
  }
  void registerEagerInstantiation(UID key, Component c){
    this.eager_instantiations.put(key, c);
  }
  Map getExternalNuts(){
    return external_nuts;
  }
  AutoWiringMap getCustomWiringModes(){
    return custom_wiring_modes;
  }
  Map getServices(){
    return this.services;
  }
  private UID[] getOrderedUIDs(){
    final Set uids = this.eager_instantiations.keySet();
    final UID[] result = new UID[uids.size()];
    uids.toArray(result);
    Arrays.sort(result, getUIDComparator());
    return result;
  }
  private Comparator getUIDComparator(){
    final HashMap module_sequence = new HashMap();
    final int sz = modules_involved.size();
    for(int i=0; i<sz; i++){
      module_sequence.put(modules_involved.get(i), new Integer(i));
    }
    return new Comparator(){
      public int compare(Object arg0, Object arg1) {
        final UID id1 = (UID)arg0;
        final UID id2 = (UID)arg1;
        final Integer module_seq1 = (Integer)module_sequence.get(id1.getModuleId());
        final Integer module_seq2 = (Integer)module_sequence.get(id2.getModuleId());
        int result = module_seq1.intValue() - module_seq2.intValue();
        if(result==0){
          result = id1.getDeclarationSequence() - id2.getDeclarationSequence();
          if(result == 0){
            result = id1.getEvaluationSequence()-id2.getEvaluationSequence();
          }
        }
        return result;
      }
      public String toString(){
        return "UID comparator";
      }
    };
  }
  private final NutsRegistrar dynamic_registered = new NutsRegistrar();
  void register(Object key, Object val, boolean overridable,
      boolean overriding, Location loc){
    dynamic_registered.register(key, val, overridable, overriding, loc);
  }
 
  private void registerDynamics(Registrar reg){
    for(Iterator it=dynamic_registered.keySet().iterator(); it.hasNext();){
      final Object key = it.next();
      final NutsRegistrar.Entry entry = dynamic_registered.getEntry(key);
      if(reg.containsKey(key)){
        throw new ConfigurationException("component "+key+" already registered.",
            entry.getLocation());
      }
      reg.registerComponent(key, NutsUtils.asComponent(entry.getValue()));
    }
  }
}
TOP

Related Classes of jfun.yan.xml.NutsProcessor$CustomWiringModes

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.