View Javadoc

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