001: /**
002: *
003: * JOnAS: Java(TM) Open Application Server
004: * Copyright (C) 1999-2005 Bull S.A.
005: * Contact: jonas-team@objectweb.org
006: *
007: * This library is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU Lesser General Public
009: * License as published by the Free Software Foundation; either
010: * version 2.1 of the License, or any later version.
011: *
012: * This library is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015: * Lesser General Public License for more details.
016: *
017: * You should have received a copy of the GNU Lesser General Public
018: * License along with this library; if not, write to the Free Software
019: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
020: * USA
021: *
022: * --------------------------------------------------------------------------
023: * $Id: NamingManager.java 6893 2005-06-06 11:20:35Z benoitf $
024: * --------------------------------------------------------------------------
025: */package org.objectweb.jonas.naming;
026:
027: import java.util.Hashtable;
028:
029: import javax.ejb.spi.HandleDelegate;
030: import javax.naming.Context;
031: import javax.naming.InitialContext;
032: import javax.naming.NamingException;
033:
034: import org.omg.CORBA.ORB;
035:
036: import org.objectweb.carol.jndi.ns.JacORBCosNaming;
037:
038: import org.objectweb.jonas_ejb.container.JHandleDelegate;
039:
040: import org.objectweb.jonas_lib.naming.ContainerNaming;
041:
042: import org.objectweb.jonas.common.Log;
043:
044: import org.objectweb.util.monolog.api.BasicLevel;
045: import org.objectweb.util.monolog.api.Logger;
046:
047: /**
048: * Naming Manager for an EJB Server. this singleton class must exist in each
049: * jonas server.
050: * @author Philippe Durieux
051: * @author Philippe Coq : Monolog
052: * @author Florent Benoit & Ludovic Bert : Context for web container
053: */
054: public class NamingManager implements ContainerNaming {
055:
056: /**
057: * Logger used for traces
058: */
059: private static Logger logger = Log
060: .getLogger(Log.JONAS_NAMING_PREFIX);
061:
062: /**
063: * Naming Context associated with the thread
064: */
065: private ThreadLocal threadContext = new ThreadLocal();
066:
067: /**
068: * Initial Context
069: */
070: private InitialContext ictx = null;
071:
072: /**
073: * Context of the server
074: */
075: private static Context serverContext = null;
076:
077: /**
078: * Environment
079: */
080: private Hashtable myEnv = null;
081:
082: /**
083: * Associate a context to a class loader
084: */
085: private Hashtable clBindings = null;
086:
087: /**
088: * Static context used by client container. One context for all the JVM.
089: */
090: private static Context clientCtx = null;
091:
092: /**
093: * Singleton management: - the constructor is private. - use static method
094: * getInstance to retrieve/create the instance.
095: */
096: private static NamingManager unique = null;
097:
098: /**
099: * UserTransaction object, to be shared by all components.
100: */
101: private Object userTransaction = null;
102:
103: /**
104: * HandleDelegate implementation is shared by all component contexts
105: */
106: private HandleDelegate handleDelegate = null;
107:
108: /**
109: * Create the naming manager.
110: * @throws NamingException if no initial context is built
111: */
112: private NamingManager() throws NamingException {
113: try {
114: ictx = new InitialContext();
115: // there is a bug in carol that makes this not work.
116: //myEnv = ictx.getEnvironment();
117: clBindings = new Hashtable();
118:
119: } catch (NamingException n) {
120: logger.log(BasicLevel.ERROR, "NamingManager: "
121: + n.getExplanation());
122: Throwable t = n.getRootCause();
123: if (t != null) {
124: if (t.getMessage().startsWith(
125: "Connection refused to host:")) {
126: logger
127: .log(BasicLevel.ERROR,
128: "NamingManager: rmi registry not started ?");
129: } else if (t.getMessage().startsWith(
130: "error during remote invocation")) {
131: logger
132: .log(BasicLevel.ERROR,
133: "NamingManager: jrmi registry not started ?");
134: } else {
135: logger.log(BasicLevel.ERROR, "NamingManager: "
136: + t.getMessage());
137: }
138: }
139: throw n;
140: }
141:
142: }
143:
144: /**
145: * Return the unique instance of a NamingManager.
146: * @return NamingManager the unique instance.
147: * @throws NamingException if it failed.
148: */
149: public static NamingManager getInstance() throws NamingException {
150: if (unique == null) {
151: unique = new NamingManager();
152: }
153: return unique;
154: }
155:
156: // ------------------------------------------------------------------
157: // ContainerNaming implementation
158: // ------------------------------------------------------------------
159:
160: /**
161: * Get the initialContext used in this jonas server.
162: * @return InitialContext the initial context.
163: */
164: public InitialContext getInitialContext() {
165: return ictx;
166: }
167:
168: /**
169: * @return The HandleDelegate implementation for this server
170: */
171: public HandleDelegate getHandleDelegate() {
172: if (handleDelegate == null) {
173: handleDelegate = new JHandleDelegate();
174: }
175: return handleDelegate;
176: }
177:
178: /**
179: * Create Context for application and component environments. (formally
180: * known as createComponentContext)
181: * @param namespace namespace to used for the Context
182: * @return a java: context with comp/ subcontext
183: * @throws NamingException if the creation of the java: context failed.
184: */
185: public Context createEnvironmentContext(String namespace)
186: throws NamingException {
187:
188: if (Log.isDebugNaming()) {
189: logger.log(BasicLevel.DEBUG, namespace);
190: }
191:
192: // Create a new environment
193: CompNamingContext ctx = new CompNamingContext(namespace);
194:
195: // Create subContext
196: Context compCtx = ctx.createSubcontext("comp");
197:
198: // Bind java:comp/UserTransaction
199: if (userTransaction == null) {
200: try {
201: userTransaction = ictx
202: .lookup("javax.transaction.UserTransaction");
203: } catch (NamingException ne) {
204: if (Log.isDebugNaming()) {
205: logger.log(BasicLevel.DEBUG,
206: "Cannot lookup UserTransaction.");
207: }
208: }
209: }
210: if (userTransaction != null) {
211: compCtx.rebind("UserTransaction", userTransaction);
212: }
213:
214: ORB orb = JacORBCosNaming.getOrb();
215: if (orb != null) {
216: try {
217: // Bind the java:comp/ORB object instance
218: compCtx.rebind("ORB", orb);
219: } catch (NamingException e) {
220: String err = "Cannot create URL for java:comp/ORB object : "
221: + e;
222: logger.log(BasicLevel.ERROR, err);
223: throw new NamingException(err);
224: }
225: }
226:
227: // Bind java:comp/HandleDelegate
228: compCtx.rebind("HandleDelegate", getHandleDelegate());
229:
230: return ctx;
231: }
232:
233: /**
234: * Get the Context associated with the current thread or to a class loader
235: * @return Context the component context.
236: * @throws NamingException When operation is not allowed
237: */
238: public Context getComponentContext() throws NamingException {
239:
240: Context ctx = null;
241:
242: // Check if there is a context to the local thread
243: // For ejbs
244: ctx = (Context) threadContext.get();
245: if (ctx != null) {
246: if (Log.isDebugNaming()) {
247: logger.log(BasicLevel.DEBUG, "return Context for ejb");
248: }
249: return ctx;
250: }
251:
252: // Check if there is a context which match the currentThread
253: // classLoader
254: // For webapps
255: ClassLoader cl = Thread.currentThread().getContextClassLoader();
256: if ((cl != null) && (cl.getParent() != null)) {
257: ctx = (Context) clBindings.get(cl.getParent());
258: if (ctx != null) {
259: if (Log.isDebugNaming()) {
260: logger.log(BasicLevel.DEBUG,
261: "return Context for webapp");
262: }
263: return ctx;
264: }
265: }
266:
267: // Check static context. use in client. One context per JVM.
268: if (clientCtx != null) {
269: ctx = clientCtx;
270: if (ctx != null) {
271: if (Log.isDebugNaming()) {
272: logger.log(BasicLevel.DEBUG,
273: "return Context for client");
274: }
275: return ctx;
276: }
277: }
278:
279: // No context found. This is outside of a j2ee component or server
280: // component.
281: if (ctx == null) {
282: ctx = getServerContext();
283: if (Log.isDebugNaming()) {
284: logger.log(BasicLevel.DEBUG,
285: "return default server Context");
286: }
287: }
288: return ctx;
289: }
290:
291: /**
292: * Associate this CompNamingContext with the current thread. This method
293: * should be called in preinvoke/postinvoke and when we build the bean
294: * environment or web environment.
295: * @param ctx the context to associate to the current thread.
296: * @return Context the context of the thread
297: */
298: public Context setComponentContext(Context ctx) {
299: Context ret = (Context) threadContext.get();
300: threadContext.set(ctx);
301: return ret;
302: }
303:
304: /**
305: * Set back the context with the given value.
306: * Don't return the previous context, use setComponentContext() method for this.
307: * @param ctx the context to associate to the current thread.
308: */
309: public void resetComponentContext(Context ctx) {
310: threadContext.set(ctx);
311: }
312:
313: /**
314: * Associate the specified CompNamingContext with the given classloader.
315: * @param ctx the context to associate to the classloader.
316: * @param cl the classloader which is bind to the context.
317: */
318: public void setComponentContext(Context ctx, ClassLoader cl) {
319: if (Log.isDebugNaming()) {
320: logger.log(BasicLevel.DEBUG, "class loader = " + cl);
321: }
322: clBindings.put(cl, ctx);
323: }
324:
325: /**
326: * Set the context used by client container (per JVM instead of per thread)
327: * @param ctx the context to set
328: */
329: public void setClientContainerComponentContext(Context ctx) {
330: if (Log.isDebugNaming()) {
331: logger.log(BasicLevel.DEBUG, "");
332: }
333: clientCtx = ctx;
334: }
335:
336: /**
337: * Return the CompNamingContext associated with the given classloader.
338: * @param cl the classloader which is bind to the context.
339: * @return the CompNamingContext associated with the given classloader.
340: */
341: public Context getComponentContext(ClassLoader cl) {
342: if (Log.isDebugNaming()) {
343: logger.log(BasicLevel.DEBUG, "class loader = " + cl);
344: }
345: return (Context) clBindings.get(cl);
346: }
347:
348: /**
349: * Remove the CompNamingContext associated with the given classloader.
350: * @param cl the classloader which is bind to the context.
351: */
352: public void unSetComponentContext(ClassLoader cl) {
353: if (Log.isDebugNaming()) {
354: logger.log(BasicLevel.DEBUG, "class loader = " + cl);
355: }
356: clBindings.remove(cl);
357: }
358:
359: /**
360: * Return the environment for JNDI This is used only for handles today.
361: * @return Hashtable the environment.
362: */
363: public Hashtable getEnv() {
364: return myEnv;
365: }
366:
367: /**
368: * Create Immutable Context. Not implemented !
369: * @param namespace namespace to used for the Context
370: * @return Context an immutable context
371: * @throws NamingException if the creation of the java: context failed.
372: */
373: public Context createImmutableEnvironmentContext(String namespace)
374: throws NamingException {
375: logger.log(BasicLevel.ERROR, "Not Implemented");
376: return null;
377: }
378:
379: // ------------------------------------------------------------------
380: // other proprietary methods
381: // ------------------------------------------------------------------
382:
383: /**
384: * Get the server component context. This is used only internally in the
385: * jonas NamingManager.
386: * @return Context the server component context.
387: */
388: public Context getServerContext() {
389: if (serverContext == null) {
390: try {
391: serverContext = createEnvironmentContext("server");
392: } catch (NamingException e) {
393: logger.log(BasicLevel.ERROR,
394: "cannot create serverContext:" + e);
395: }
396: }
397: return serverContext;
398: }
399:
400: }
|