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