View Javadoc

1   //
2   //  ========================================================================
3   //  Copyright (c) 1995-2016 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  public class EnvConfiguration extends AbstractConfiguration
52  {
53      private static final Logger LOG = Log.getLogger(EnvConfiguration.class);
54  
55      private static final String JETTY_ENV_BINDINGS = "org.eclipse.jetty.jndi.EnvConfiguration";
56      private URL jettyEnvXmlUrl;
57  
58      public void setJettyEnvXml (URL url)
59      {
60          this.jettyEnvXmlUrl = url;
61      }
62  
63      @Override
64      public void preConfigure (WebAppContext context) throws Exception
65      {
66          //create a java:comp/env
67          createEnvContext(context);
68      }
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      * @throws Exception if unable to deconfigure
134      */
135     @Override
136     public void deconfigure (WebAppContext context) throws Exception
137     {
138         //get rid of any bindings for comp/env for webapp
139         ClassLoader oldLoader = Thread.currentThread().getContextClassLoader();
140         Thread.currentThread().setContextClassLoader(context.getClassLoader());
141         ContextFactory.associateClassLoader(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             ContextFactory.disassociateClassLoader();
166             Thread.currentThread().setContextClassLoader(oldLoader);
167         }
168     }
169 
170 
171     /**
172      * Remove all jndi setup
173      * @throws Exception if unable to destroy
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 jndi entries scoped to webapp {}", context);
188         }
189         catch (NamingException e)
190         {
191             LOG.debug("Error unbinding jndi entries scoped to webapp "+context, e);
192         }
193     }
194 
195     /**
196      * Bind all EnvEntries that have been declared, so that the processing of the
197      * web.xml file can potentially override them.
198      *
199      * We first bind EnvEntries declared in Server scope, then WebAppContext scope.
200      * @param context the context to use for the object scope
201      * @throws NamingException if unable to bind env entries
202      */
203     public void bindEnvEntries (WebAppContext context)
204     throws NamingException
205     {
206         LOG.debug("Binding env entries from the jvm scope");
207         InitialContext ic = new InitialContext();
208         Context envCtx = (Context)ic.lookup("java:comp/env");
209         Object scope = null;
210         List<Object> list = NamingEntryUtil.lookupNamingEntries(scope, EnvEntry.class);
211         Iterator<Object> itor = list.iterator();
212         while (itor.hasNext())
213         {
214             EnvEntry ee = (EnvEntry)itor.next();
215             ee.bindToENC(ee.getJndiName());
216             Name namingEntryName = NamingEntryUtil.makeNamingEntryName(null, ee);
217             NamingUtil.bind(envCtx, namingEntryName.toString(), ee);//also save the EnvEntry in the context so we can check it later
218         }
219 
220         LOG.debug("Binding env entries from the server scope");
221 
222         scope = context.getServer();
223         list = NamingEntryUtil.lookupNamingEntries(scope, EnvEntry.class);
224         itor = list.iterator();
225         while (itor.hasNext())
226         {
227             EnvEntry ee = (EnvEntry)itor.next();
228             ee.bindToENC(ee.getJndiName());
229             Name namingEntryName = NamingEntryUtil.makeNamingEntryName(null, ee);
230             NamingUtil.bind(envCtx, namingEntryName.toString(), ee);//also save the EnvEntry in the context so we can check it later
231         }
232 
233         LOG.debug("Binding env entries from the context scope");
234         scope = context;
235         list = NamingEntryUtil.lookupNamingEntries(scope, EnvEntry.class);
236         itor = list.iterator();
237         while (itor.hasNext())
238         {
239             EnvEntry ee = (EnvEntry)itor.next();
240             ee.bindToENC(ee.getJndiName());
241             Name namingEntryName = NamingEntryUtil.makeNamingEntryName(null, ee);
242             NamingUtil.bind(envCtx, namingEntryName.toString(), ee);//also save the EnvEntry in the context so we can check it later
243         }
244     }
245 
246     protected void createEnvContext (WebAppContext wac)
247     throws NamingException
248     {
249         ClassLoader old_loader = Thread.currentThread().getContextClassLoader();
250         Thread.currentThread().setContextClassLoader(wac.getClassLoader());
251         ContextFactory.associateClassLoader(wac.getClassLoader());
252         try
253         {
254             Context context = new InitialContext();
255             Context compCtx =  (Context)context.lookup ("java:comp");
256             compCtx.createSubcontext("env");
257         }
258         finally
259         {
260             ContextFactory.disassociateClassLoader();
261             Thread.currentThread().setContextClassLoader(old_loader);
262         }
263     }
264 
265     private static class Bound
266     {
267         final NamingContext _context;
268         final String _name;
269         Bound(NamingContext context, String name)
270         {
271             _context=context;
272             _name=name;
273         }
274     }
275 }