View Javadoc

1   // ========================================================================
2   // Copyright (c) 2006-2009 Mort Bay Consulting Pty. Ltd.
3   // ------------------------------------------------------------------------
4   // All rights reserved. This program and the accompanying materials
5   // are made available under the terms of the Eclipse Public License v1.0
6   // and Apache License v2.0 which accompanies this distribution.
7   // The Eclipse Public License is available at 
8   // http://www.eclipse.org/legal/epl-v10.html
9   // The Apache License v2.0 is available at
10  // http://www.opensource.org/licenses/apache2.0.php
11  // You may elect to redistribute this code under either of these licenses. 
12  // ========================================================================
13  
14  package org.eclipse.jetty.plus.webapp;
15  
16  import java.util.Random;
17  
18  import javax.naming.Context;
19  import javax.naming.InitialContext;
20  import javax.naming.NameNotFoundException;
21  
22  import org.eclipse.jetty.jndi.NamingUtil;
23  import org.eclipse.jetty.plus.jndi.EnvEntry;
24  import org.eclipse.jetty.plus.jndi.Link;
25  import org.eclipse.jetty.plus.jndi.NamingEntry;
26  import org.eclipse.jetty.plus.jndi.NamingEntryUtil;
27  import org.eclipse.jetty.plus.jndi.Transaction;
28  import org.eclipse.jetty.util.log.Log;
29  import org.eclipse.jetty.webapp.WebAppContext;
30  
31  
32  /**
33   * Configuration
34   *
35   *
36   */
37  public class Configuration extends AbstractConfiguration
38  {
39  
40      private Integer _key;
41      
42      
43      /** 
44       * @see org.eclipse.jetty.plus.webapp.AbstractConfiguration#bindEnvEntry(java.lang.String, java.lang.String)
45       * @param name
46       * @param value
47       * @throws Exception
48       */
49      public void bindEnvEntry(WebAppContext context, String name, Object value) throws Exception
50      {    
51          InitialContext ic = null;
52          boolean bound = false;
53          //check to see if we bound a value and an EnvEntry with this name already
54          //when we processed the server and the webapp's naming environment
55          //@see EnvConfiguration.bindEnvEntries()
56          ic = new InitialContext();
57          try
58          {
59              NamingEntry ne = (NamingEntry)ic.lookup("java:comp/env/"+NamingEntryUtil.makeNamingEntryName(ic.getNameParser(""), name));
60              if (ne!=null && ne instanceof EnvEntry)
61              {
62                  EnvEntry ee = (EnvEntry)ne;
63                  bound = ee.isOverrideWebXml();
64              }
65          }
66          catch (NameNotFoundException e)
67          {
68              bound = false;
69          }
70  
71          if (!bound)
72          {
73              //either nothing was bound or the value from web.xml should override
74              Context envCtx = (Context)ic.lookup("java:comp/env");
75              NamingUtil.bind(envCtx, name, value);
76          }
77      }
78  
79      /** 
80       * Bind a resource reference.
81       * 
82       * If a resource reference with the same name is in a jetty-env.xml
83       * file, it will already have been bound.
84       * 
85       * @see org.eclipse.jetty.plus.webapp.AbstractConfiguration#bindResourceRef(java.lang.String)
86       * @param name
87       * @throws Exception
88       */
89      public void bindResourceRef(WebAppContext context, String name, Class typeClass)
90      throws Exception
91      {
92          bindEntry(context, name, typeClass);
93      }
94  
95      /** 
96       * @see org.eclipse.jetty.plus.webapp.AbstractConfiguration#bindResourceEnvRef(java.lang.String)
97       * @param name
98       * @throws Exception
99       */
100     public void bindResourceEnvRef(WebAppContext context, String name, Class typeClass)
101     throws Exception
102     {
103         bindEntry(context, name, typeClass);
104     }
105     
106     
107     public void bindMessageDestinationRef(WebAppContext context, String name, Class typeClass)
108     throws Exception
109     {
110         bindEntry(context, name, typeClass);
111     }
112     
113     public void bindUserTransaction (WebAppContext context)
114     throws Exception
115     {
116         try
117         {
118            Transaction.bindToENC();
119         }
120         catch (NameNotFoundException e)
121         {
122             Log.info("No Transaction manager found - if your webapp requires one, please configure one.");
123         }
124     }
125     
126     public void preConfigure (WebAppContext context)
127     throws Exception
128     {      
129         super.preConfigure(context);
130     }
131 
132   
133 
134     public void configure (WebAppContext context)
135     throws Exception
136     {
137         super.configure (context);
138     }
139     
140     public void postConfigure (WebAppContext context)
141     throws Exception
142     {
143       //lock this webapp's java:comp namespace as per J2EE spec
144         ClassLoader oldLoader = Thread.currentThread().getContextClassLoader();
145         Thread.currentThread().setContextClassLoader(context.getClassLoader());
146         lockCompEnv();
147         Thread.currentThread().setContextClassLoader(oldLoader);
148     }
149     
150     public void deconfigure (WebAppContext context) throws Exception
151     {
152         ClassLoader oldLoader = Thread.currentThread().getContextClassLoader();
153         Thread.currentThread().setContextClassLoader(context.getClassLoader());
154         unlockCompEnv();
155         _key = null;
156         Thread.currentThread().setContextClassLoader(oldLoader);
157         super.deconfigure (context);
158     }
159     
160     protected void lockCompEnv ()
161     throws Exception
162     {
163         Random random = new Random ();
164         _key = new Integer(random.nextInt());
165         Context context = new InitialContext();
166         Context compCtx = (Context)context.lookup("java:comp");
167         compCtx.addToEnvironment("org.eclipse.jndi.lock", _key);
168     }
169     
170     protected void unlockCompEnv ()
171     throws Exception
172     {
173         if (_key!=null)
174         {
175             Context context = new InitialContext();
176             Context compCtx = (Context)context.lookup("java:comp");
177             compCtx.addToEnvironment("org.eclipse.jndi.unlock", _key); 
178         }
179     }
180 
181     /** 
182      * @see org.eclipse.jetty.plus.webapp.AbstractConfiguration#parseAnnotations()
183      */
184     public void parseAnnotations(WebAppContext context) throws Exception
185     {
186         //Noop unless you want to do annotation discovery. 
187         //Use org.eclipse.jetty.annotations.Configuration instead.
188     }
189     
190     /**
191      * Bind a resource with the given name from web.xml of the given type
192      * with a jndi resource from either the server or the webapp's naming 
193      * environment.
194      * 
195      * As the servlet spec does not cover the mapping of names in web.xml with
196      * names from the execution environment, jetty uses the concept of a Link, which is
197      * a subclass of the NamingEntry class. A Link defines a mapping of a name
198      * from web.xml with a name from the execution environment (ie either the server or the
199      * webapp's naming environment).
200      * 
201      * @param name name of the resource from web.xml
202      * @param typeClass 
203      * @throws Exception
204      */
205     private void bindEntry (WebAppContext context, String name, Class typeClass)
206     throws Exception
207     {
208         String nameInEnvironment = name;
209         boolean bound = false;
210         
211         //check if the name in web.xml has been mapped to something else
212         //check a context-specific naming environment first
213         Object scope = context;
214         NamingEntry ne = NamingEntryUtil.lookupNamingEntry(scope, name);
215     
216         if (ne!=null && (ne instanceof Link))
217         {
218             //if we found a mapping, get out name it is mapped to in the environment
219             nameInEnvironment = (String)((Link)ne).getObjectToBind();
220             Link l = (Link)ne;
221         }
222 
223         //try finding that mapped name in the webapp's environment first
224         scope = context;
225         bound = NamingEntryUtil.bindToENC(scope, name, nameInEnvironment);
226         
227         if (bound)
228             return;
229         
230         //try the server's environment
231         scope = context.getServer();
232         bound = NamingEntryUtil.bindToENC(scope, name, nameInEnvironment);
233         if (bound)
234             return;
235 
236         //try the jvm environment
237         bound = NamingEntryUtil.bindToENC(null, name, nameInEnvironment);
238         if (bound)
239             return;
240 
241         //There is no matching resource so try a default name.
242         //The default name syntax is: the [res-type]/default
243         //eg       javax.sql.DataSource/default
244         nameInEnvironment = typeClass.getName()+"/default";
245         //First try the server scope
246         NamingEntry defaultNE = NamingEntryUtil.lookupNamingEntry(context.getServer(), nameInEnvironment);
247         if (defaultNE==null)
248             defaultNE = NamingEntryUtil.lookupNamingEntry(null, nameInEnvironment);
249         
250         if (defaultNE!=null)
251             defaultNE.bindToENC(name);
252         else
253             throw new IllegalStateException("Nothing to bind for name "+nameInEnvironment);
254     }
255 }