View Javadoc

1   package org.objectledge.naming;
2   
3   import java.util.HashMap;
4   import java.util.Hashtable;
5   import java.util.Map;
6   
7   import javax.naming.Context;
8   import javax.naming.InitialContext;
9   import javax.naming.NamingException;
10  import javax.naming.directory.DirContext;
11  import javax.naming.directory.InitialDirContext;
12  
13  import org.jcontainer.dna.Configuration;
14  import org.jcontainer.dna.ConfigurationException;
15  import org.jcontainer.dna.Logger;
16  import org.objectledge.ComponentInitializationError;
17  import org.picocontainer.PicoContainer;
18  
19  /***
20   * Naming context factory component.
21   *
22   * @author <a href="mail:rkrzewsk@caltha.pl">Rafal Krzewski</a>
23   * @author <a href="mail:pablo@caltha.pl">Pawel Potempski</a>
24   * @version $Id: ContextFactory.java,v 1.6 2004/12/23 07:16:43 rafal Exp $
25   */
26  public class ContextFactory
27  {
28  	/*** the logger */
29  	private Logger logger;
30  	
31      /*** Initial environments. */
32      private Map initial = new HashMap();
33  
34      /*** Context aliases. */
35      private Map alias = new HashMap();
36  
37      /*** Cached contexts. */
38      private Map context = new HashMap();
39  
40  	/***
41  	 * Component constructor.
42  	 * 
43       * @param container the container to resolve component properties from.
44  	 * @param config the configuration.
45  	 * @param logger the logger.
46       * @throws ConfigurationException if the component's configuration is invalid.
47  	 */  
48    	public ContextFactory(PicoContainer container, Configuration config, Logger logger)
49          throws ConfigurationException
50    	{
51    		this.logger = logger;
52          Configuration[] contexts = config.getChildren("context");
53          for (int i = 0; i < contexts.length; i++)
54          {
55              Hashtable env = new Hashtable();
56              String name = contexts[i].getAttribute("name");
57              // initial factory is required.
58              String initialFactory = contexts[i].getAttribute("initial_factory");
59              env.put("java.naming.factory.initial", initialFactory);
60              Configuration[] properties = contexts[i].getChildren("property");
61              for (int j = 0; j < properties.length; j++)
62              {
63                  String propertyName = properties[j].getAttribute("name");
64                  String propertyValue = properties[j].getAttribute("value", null);
65                  if (propertyValue == null)
66                  {
67                      propertyValue = properties[j].getValue();
68                  }
69                  env.put(propertyName, propertyValue);
70              }
71              Configuration[] componentProperties = contexts[i].getChildren("component-property");
72              for (int j = 0; j < componentProperties.length; j++)
73              {
74                  String propertyName = componentProperties[j].getAttribute("name");
75                  Object key = componentProperties[j].getAttribute("key", null);
76                  if(key == null)
77                  {
78                      String cn = componentProperties[j].getAttribute("class-key", null);
79                      if(cn != null)
80                      {
81                          try
82                          {
83                              key = Class.forName(cn);
84                          }
85                          catch(ClassNotFoundException e)
86                          {
87                              throw new ConfigurationException("non-existent class "+cn, 
88                                  componentProperties[j].getPath(), 
89                                  componentProperties[j].getLocation());
90                          }
91                      }
92                  }
93                  Object component = null;
94                  if(key != null)
95                  {
96                      component = container.getComponentInstance(key);
97                  }
98                  else
99                  {
100                     String cn = componentProperties[j].getAttribute("class");
101                     if(cn != null)
102                     {
103                         try
104                         {
105                             key = Class.forName(cn);
106                         }
107                         catch(ClassNotFoundException e)
108                         {
109                             throw new ConfigurationException("non-existent class "+cn, 
110                                 componentProperties[j].getPath(), 
111                                 componentProperties[j].getLocation());
112                         }
113                         component = container.getComponentInstanceOfType((Class)key);
114                     }
115                 }
116                 if(component == null)
117                 {
118                     throw new ConfigurationException("missing component "+key, 
119                         componentProperties[j].getPath(), 
120                         componentProperties[j].getLocation());
121                 }
122                 env.put(propertyName, component);
123             }
124             initial.put(name, env);
125             Configuration[] aliases = contexts[i].getChildren("alias");
126             for (int j = 0; j < aliases.length; j++)
127             {
128                 String aliasName = aliases[j].getAttribute("name");
129                 String prevContext = (String)alias.get(aliasName);
130                 if(prevContext != null)
131                 {
132                     throw new ComponentInitializationError("alias used" +
133                         " in more than one context: '"+prevContext+"','"+name+"...");
134                 }
135                 alias.put(aliasName, name);
136             }
137         }
138   	}
139 
140     /***
141      * Returns the specified naming context.
142      *
143      * @param name the context identifier used in the configuration file.
144      * @return thread-safe view of the context.
145      * @throws NamingException if identifier cannot be resolved.
146      */
147     public Context getContext(String name)
148         throws NamingException
149     {
150         if(alias.containsKey(name))
151         {
152             name = (String)alias.get(name);
153         }
154         Context ctx = (Context)context.get(name);
155         if(ctx == null)
156         {
157             Hashtable props = (Hashtable)initial.get(name);
158             if(props == null || props.isEmpty())
159             {
160                 throw new NamingException("context "+name+" was not found");
161             }
162             ctx = new InitialContext(props);
163             context.put(name, ctx);
164         }
165         return (Context)ctx.lookup("");
166     }
167     
168     /***
169      * Returns the specified directory context.
170      *
171      * @param name the directory context identifier used in the configuration file
172      * @return thread-safe view of the context.
173      * * @throws NamingException if identifier cannot be resolved.
174      */
175     public DirContext getDirContext(String name)
176         throws NamingException
177     {
178         if(alias.containsKey(name))
179         {
180             name = (String)alias.get(name);
181         }
182         DirContext ctx = (DirContext)context.get(name);
183         if(ctx == null)
184         {
185             Hashtable props = (Hashtable)initial.get(name);
186             if(props == null || props.isEmpty())
187             {
188                 throw new NamingException("context "+name+" was not found");
189             }
190             ctx = new InitialDirContext(props);
191             context.put(name, ctx);
192         }
193         return (DirContext)ctx.lookup("");
194     }
195 
196     /***
197      * Requests that the cached context object be discarded and created anew. 
198      *
199      * <p>This method is helpful for recovering from teporary failures of
200      * external naming/directory services.</p>
201      *
202      * @param name the name of the context.
203      */
204     public void reconnect(String name)
205     {
206         if(alias.containsKey(name))
207         {
208             name = (String)alias.get(name);
209         }
210         context.remove(name);
211     }
212 }