~ubuntu-branches/ubuntu/utopic/jetty/utopic-proposed

« back to all changes in this revision

Viewing changes to modules/naming/src/main/java/org/mortbay/naming/ContextFactory.java

  • Committer: Bazaar Package Importer
  • Author(s): Torsten Werner
  • Date: 2009-08-09 08:48:10 UTC
  • Revision ID: james.westby@ubuntu.com-20090809084810-k522b97ind2robyd
ImportĀ upstreamĀ versionĀ 6.1.19

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// ========================================================================
 
2
// $Id: ContextFactory.java 1327 2006-11-27 18:40:14Z janb $
 
3
// Copyright 1999-2006 Mort Bay Consulting Pty. Ltd.
 
4
// ------------------------------------------------------------------------
 
5
// Licensed under the Apache License, Version 2.0 (the "License");
 
6
// you may not use this file except in compliance with the License.
 
7
// You may obtain a copy of the License at 
 
8
// http://www.apache.org/licenses/LICENSE-2.0
 
9
// Unless required by applicable law or agreed to in writing, software
 
10
// distributed under the License is distributed on an "AS IS" BASIS,
 
11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 
12
// See the License for the specific language governing permissions and
 
13
// limitations under the License.
 
14
// ========================================================================
 
15
 
 
16
package org.mortbay.naming;
 
17
 
 
18
 
 
19
import java.util.Hashtable;
 
20
import java.util.WeakHashMap;
 
21
 
 
22
import javax.naming.Context;
 
23
import javax.naming.Name;
 
24
import javax.naming.NameParser;
 
25
import javax.naming.Reference;
 
26
import javax.naming.StringRefAddr;
 
27
import javax.naming.spi.ObjectFactory;
 
28
 
 
29
import org.mortbay.jetty.handler.ContextHandler;
 
30
import org.mortbay.log.Log;
 
31
 
 
32
 
 
33
 
 
34
/**
 
35
 * ContextFactory.java
 
36
 *
 
37
 * This is an object factory that produces a jndi naming
 
38
 * context based on a classloader. 
 
39
 * 
 
40
 *  It is used for the java:comp context.
 
41
 *  
 
42
 *  This object factory is bound at java:comp. When a
 
43
 *  lookup arrives for java:comp,  this object factory
 
44
 *  is invoked and will return a context specific to
 
45
 *  the caller's environment (so producing the java:comp/env
 
46
 *  specific to a webapp).
 
47
 *  
 
48
 *  The context selected is based on classloaders. First
 
49
 *  we try looking in at the classloader that is associated
 
50
 *  with the current webapp context (if there is one). If
 
51
 *  not, we use the thread context classloader.
 
52
 * 
 
53
 * Created: Fri Jun 27 09:26:40 2003
 
54
 *
 
55
 * @author <a href="mailto:janb@mortbay.com">Jan Bartel</a>
 
56
 * 
 
57
 */
 
58
public class ContextFactory implements ObjectFactory
 
59
{
 
60
    /**
 
61
     * Map of classloaders to contexts.
 
62
     */
 
63
    private static WeakHashMap _contextMap;
 
64
    
 
65
    /**
 
66
     * Threadlocal for injecting a context to use
 
67
     * instead of looking up the map.
 
68
     */
 
69
    private static ThreadLocal _threadContext;
 
70
 
 
71
    static
 
72
    {
 
73
        _contextMap = new WeakHashMap();
 
74
        _threadContext = new ThreadLocal();
 
75
    }
 
76
    
 
77
  
 
78
 
 
79
    /** 
 
80
     * Find or create a context which pertains to a classloader.
 
81
     * 
 
82
     * We use either the classloader for the current ContextHandler if
 
83
     * we are handling a request, OR we use the thread context classloader
 
84
     * if we are not processing a request.
 
85
     * @see javax.naming.spi.ObjectFactory#getObjectInstance(java.lang.Object, javax.naming.Name, javax.naming.Context, java.util.Hashtable)
 
86
     */
 
87
    public Object getObjectInstance (Object obj,
 
88
                                     Name name,
 
89
                                     Context nameCtx,
 
90
                                     Hashtable env)
 
91
        throws Exception
 
92
    {
 
93
        //First, see if we have had a context injected into us to use.
 
94
        Context ctx = (Context)_threadContext.get();
 
95
        if (ctx != null) 
 
96
        {
 
97
            if(Log.isDebugEnabled()) Log.debug("Using the Context that is bound on the thread");
 
98
            return ctx;
 
99
        }
 
100
        
 
101
        // Next, see if we are in a webapp context, if we are, use
 
102
        // the classloader of the webapp to find the right jndi comp context
 
103
        ClassLoader loader = null;
 
104
        if (ContextHandler.getCurrentContext() != null)
 
105
        {
 
106
            loader = ContextHandler.getCurrentContext().getContextHandler().getClassLoader();
 
107
        }
 
108
        
 
109
        
 
110
        if (loader != null)
 
111
        {
 
112
            if (Log.isDebugEnabled()) Log.debug("Using classloader of current org.mortbay.jetty.handler.ContextHandler");
 
113
        }
 
114
        else
 
115
        {
 
116
            //Not already in a webapp context, in that case, we try the
 
117
            //curren't thread's classloader instead
 
118
            loader = Thread.currentThread().getContextClassLoader();
 
119
            if (Log.isDebugEnabled()) Log.debug("Using thread context classloader");
 
120
        }
 
121
        
 
122
        //Get the context matching the classloader
 
123
        ctx = (Context)_contextMap.get(loader);
 
124
        
 
125
        //The map does not contain an entry for this classloader
 
126
        if (ctx == null)
 
127
        {
 
128
            //Check if a parent classloader has created the context
 
129
            ctx = getParentClassLoaderContext(loader);
 
130
 
 
131
            //Didn't find a context to match any of the ancestors
 
132
            //of the classloader, so make a context
 
133
            if (ctx == null)
 
134
            {
 
135
                Reference ref = (Reference)obj;
 
136
                StringRefAddr parserAddr = (StringRefAddr)ref.get("parser");
 
137
                String parserClassName = (parserAddr==null?null:(String)parserAddr.getContent());
 
138
                NameParser parser = (NameParser)(parserClassName==null?null:loader.loadClass(parserClassName).newInstance());
 
139
                
 
140
                ctx = new NamingContext (env,
 
141
                                         name.get(0),
 
142
                                         nameCtx,
 
143
                                         parser);
 
144
                if(Log.isDebugEnabled())Log.debug("No entry for classloader: "+loader);
 
145
                _contextMap.put (loader, ctx);
 
146
            }
 
147
        }
 
148
 
 
149
        return ctx;
 
150
    }
 
151
 
 
152
    /**
 
153
     * Keep trying ancestors of the given classloader to find one to which
 
154
     * the context is bound.
 
155
     * @param loader
 
156
     * @return
 
157
     */
 
158
    public Context getParentClassLoaderContext (ClassLoader loader)
 
159
    {
 
160
        Context ctx = null;
 
161
        ClassLoader cl = loader;
 
162
        for (cl = cl.getParent(); (cl != null) && (ctx == null); cl = cl.getParent())
 
163
        {
 
164
            ctx = (Context)_contextMap.get(cl);
 
165
        }
 
166
 
 
167
        return ctx;
 
168
    }
 
169
    
 
170
 
 
171
    /**
 
172
     * Associate the given Context with the current thread.
 
173
     * resetComponentContext method should be called to reset the context.
 
174
     * @param ctx the context to associate to the current thread.
 
175
     * @return the previous context associated on the thread (can be null)
 
176
     */
 
177
    public static Context setComponentContext(final Context ctx) 
 
178
    {
 
179
        Context previous = (Context)_threadContext.get();
 
180
        _threadContext.set(ctx);
 
181
        return previous;
 
182
    }
 
183
 
 
184
    /**
 
185
     * Set back the context with the given value.
 
186
     * Don't return the previous context, use setComponentContext() method for this.
 
187
     * @param ctx the context to associate to the current thread.
 
188
     */
 
189
    public static void resetComponentContext(final Context ctx) 
 
190
    {
 
191
        _threadContext.set(ctx);
 
192
    }
 
193
 
 
194