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
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 }