View Javadoc

1   // ========================================================================
2   // Copyright (c) 1999-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.net.URL;
17  import java.util.ArrayList;
18  import java.util.Collections;
19  import java.util.Iterator;
20  import java.util.List;
21  
22  import javax.naming.Binding;
23  import javax.naming.Context;
24  import javax.naming.InitialContext;
25  import javax.naming.Name;
26  import javax.naming.NameNotFoundException;
27  import javax.naming.NamingException;
28  
29  import org.eclipse.jetty.jndi.NamingContext;
30  import org.eclipse.jetty.jndi.NamingUtil;
31  import org.eclipse.jetty.jndi.local.localContextRoot;
32  import org.eclipse.jetty.plus.jndi.EnvEntry;
33  import org.eclipse.jetty.plus.jndi.NamingEntryUtil;
34  import org.eclipse.jetty.util.log.Log;
35  import org.eclipse.jetty.webapp.AbstractConfiguration;
36  import org.eclipse.jetty.webapp.Configuration;
37  import org.eclipse.jetty.webapp.WebAppContext;
38  import org.eclipse.jetty.xml.XmlConfiguration;
39  
40  
41  /**
42   * EnvConfiguration
43   *
44   *
45   */
46  public class EnvConfiguration extends AbstractConfiguration
47  {
48      private static final String JETTY_ENV_BINDINGS = "org.eclipse.jetty.jndi.EnvConfiguration";
49      private URL jettyEnvXmlUrl;
50  
51      public void setJettyEnvXml (URL url)
52      {
53          this.jettyEnvXmlUrl = url;
54      }
55  
56      /** 
57       * @see Configuration#configure(WebAppContext)
58       * @throws Exception
59       */
60      @Override
61      public void preConfigure (WebAppContext context) throws Exception
62      {        
63          //create a java:comp/env
64          createEnvContext(context);
65      }
66  
67      /** 
68       * @throws Exception
69       */
70      @Override
71      public void configure (WebAppContext context) throws Exception
72      {  
73          if (Log.isDebugEnabled())
74              Log.debug("Created java:comp/env for webapp "+context.getContextPath());
75          
76          //check to see if an explicit file has been set, if not,
77          //look in WEB-INF/jetty-env.xml
78          if (jettyEnvXmlUrl == null)
79          {
80              //look for a file called WEB-INF/jetty-env.xml
81              //and process it if it exists
82              org.eclipse.jetty.util.resource.Resource web_inf = context.getWebInf();
83              if(web_inf!=null && web_inf.isDirectory())
84              {
85                  org.eclipse.jetty.util.resource.Resource jettyEnv = web_inf.addPath("jetty-env.xml");
86                  if(jettyEnv.exists())
87                  {
88                      jettyEnvXmlUrl = jettyEnv.getURL();
89                  }
90              }
91          }
92          
93          if (jettyEnvXmlUrl != null)
94          {
95              synchronized (localContextRoot.getRoot())
96              {
97                  // create list and listener to remember the bindings we make.
98                  final List<Bound> bindings = new ArrayList<Bound>();
99                  NamingContext.Listener listener = new NamingContext.Listener()
100                 {
101                     public void unbind(NamingContext ctx, Binding binding)
102                     {
103                     }
104 
105                     public Binding bind(NamingContext ctx, Binding binding)
106                     {
107                         bindings.add(new Bound(ctx,binding.getName()));
108                         return binding;
109                     }
110                 };
111 
112                 try
113                 {
114                     localContextRoot.getRoot().addListener(listener);
115                     XmlConfiguration configuration = new XmlConfiguration(jettyEnvXmlUrl);
116                     configuration.configure(context);
117                 }
118                 finally
119                 {
120                     localContextRoot.getRoot().removeListener(listener);
121                     context.setAttribute(JETTY_ENV_BINDINGS,bindings);
122                 }
123             }
124         }
125 
126         //add java:comp/env entries for any EnvEntries that have been defined so far
127         bindEnvEntries(context);
128     }
129 
130     
131     /** 
132      * Remove jndi setup from start
133      * @see Configuration#deconfigure(WebAppContext)
134      * @throws Exception
135      */
136     @Override
137     public void deconfigure (WebAppContext context) throws Exception
138     {
139         //get rid of any bindings for comp/env for webapp
140         ClassLoader oldLoader = Thread.currentThread().getContextClassLoader();
141         Thread.currentThread().setContextClassLoader(context.getClassLoader());
142         try
143         {
144             Context ic = new InitialContext();
145             Context compCtx =  (Context)ic.lookup ("java:comp");
146             compCtx.destroySubcontext("env");
147 
148             //unbind any NamingEntries that were configured in this webapp's name space
149             @SuppressWarnings("unchecked")
150             List<Bound> bindings = (List<Bound>)context.getAttribute(JETTY_ENV_BINDINGS);
151             context.setAttribute(JETTY_ENV_BINDINGS,null);
152             if (bindings!=null)
153             {
154                 Collections.reverse(bindings);
155                 for (Bound b:bindings)
156                     b._context.destroySubcontext(b._name);
157             }
158         }
159         catch (NameNotFoundException e)
160         {
161             Log.warn(e);
162         }
163         finally
164         {
165             Thread.currentThread().setContextClassLoader(oldLoader);
166         }
167     }
168 
169     
170     /** 
171      * Remove all jndi setup
172      * @see Configuration#deconfigure(WebAppContext)
173      * @throws Exception
174      */
175     @Override
176     public void destroy (WebAppContext context) throws Exception
177     {
178         try
179         {            
180             //unbind any NamingEntries that were configured in this webapp's name space
181             NamingContext scopeContext = (NamingContext)NamingEntryUtil.getContextForScope(context);
182             scopeContext.getParent().destroySubcontext(scopeContext.getName());
183         }
184         catch (NameNotFoundException e)
185         {
186             Log.ignore(e);
187             Log.debug("No naming entries configured in environment for webapp "+context);
188         }
189     }
190     
191     /**
192      * Bind all EnvEntries that have been declared, so that the processing of the
193      * web.xml file can potentially override them.
194      * 
195      * We first bind EnvEntries declared in Server scope, then WebAppContext scope.
196      * @throws NamingException
197      */
198     public void bindEnvEntries (WebAppContext context)
199     throws NamingException
200     {
201         Log.debug("Binding env entries from the jvm scope");
202         InitialContext ic = new InitialContext();
203         Context envCtx = (Context)ic.lookup("java:comp/env");
204         Object scope = null;
205         List<Object> list = NamingEntryUtil.lookupNamingEntries(scope, EnvEntry.class);
206         Iterator<Object> itor = list.iterator();
207         while (itor.hasNext())
208         {
209             EnvEntry ee = (EnvEntry)itor.next();
210             ee.bindToENC(ee.getJndiName());
211             Name namingEntryName = NamingEntryUtil.makeNamingEntryName(null, ee);
212             NamingUtil.bind(envCtx, namingEntryName.toString(), ee);//also save the EnvEntry in the context so we can check it later          
213         }
214         
215         Log.debug("Binding env entries from the server scope");
216         
217         scope = context.getServer();
218         list = NamingEntryUtil.lookupNamingEntries(scope, EnvEntry.class);
219         itor = list.iterator();
220         while (itor.hasNext())
221         {
222             EnvEntry ee = (EnvEntry)itor.next();
223             ee.bindToENC(ee.getJndiName());
224             Name namingEntryName = NamingEntryUtil.makeNamingEntryName(null, ee);
225             NamingUtil.bind(envCtx, namingEntryName.toString(), ee);//also save the EnvEntry in the context so we can check it later          
226         }
227         
228         Log.debug("Binding env entries from the context scope");
229         scope = context;
230         list = NamingEntryUtil.lookupNamingEntries(scope, EnvEntry.class);
231         itor = list.iterator();
232         while (itor.hasNext())
233         {
234             EnvEntry ee = (EnvEntry)itor.next();
235             ee.bindToENC(ee.getJndiName());
236             Name namingEntryName = NamingEntryUtil.makeNamingEntryName(null, ee);
237             NamingUtil.bind(envCtx, namingEntryName.toString(), ee);//also save the EnvEntry in the context so we can check it later
238         }
239     }  
240     
241     protected void createEnvContext (WebAppContext wac)
242     throws NamingException
243     {
244         ClassLoader old_loader = Thread.currentThread().getContextClassLoader();
245         Thread.currentThread().setContextClassLoader(wac.getClassLoader());
246         try
247         {
248             Context context = new InitialContext();
249             Context compCtx =  (Context)context.lookup ("java:comp");
250             compCtx.createSubcontext("env");
251         }
252         finally 
253         {
254            Thread.currentThread().setContextClassLoader(old_loader);
255        }
256     }
257     
258     private static class Bound
259     {
260         final NamingContext _context;
261         final String _name;
262         Bound(NamingContext context, String name)
263         {
264             _context=context;
265             _name=name;
266         }
267     }
268 }