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