View Javadoc

1   //========================================================================
2   //$Id: WebAppDeployer.java 5859 2010-03-05 13:40:17Z janb $
3   //Copyright 2006 Mort Bay Consulting Pty. Ltd.
4   //------------------------------------------------------------------------
5   //Licensed under the Apache License, Version 2.0 (the "License");
6   //you may not use this file except in compliance with the License.
7   //You may obtain a copy of the License at 
8   //http://www.apache.org/licenses/LICENSE-2.0
9   //Unless required by applicable law or agreed to in writing, software
10  //distributed under the License is distributed on an "AS IS" BASIS,
11  //WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  //See the License for the specific language governing permissions and
13  //limitations under the License.
14  //========================================================================
15  
16  package org.mortbay.jetty.deployer;
17  
18  import java.util.ArrayList;
19  
20  import org.mortbay.component.AbstractLifeCycle;
21  import org.mortbay.jetty.Handler;
22  import org.mortbay.jetty.HandlerContainer;
23  import org.mortbay.jetty.handler.ContextHandler;
24  import org.mortbay.jetty.handler.ContextHandlerCollection;
25  import org.mortbay.jetty.webapp.WebAppContext;
26  import org.mortbay.log.Log;
27  import org.mortbay.resource.Resource;
28  import org.mortbay.util.URIUtil;
29  
30  /**
31   * Web Application Deployer.
32   * 
33   * The class searches a directory for and deploys standard web application.
34   * At startup, the directory specified by {@link #setWebAppDir(String)} is searched 
35   * for subdirectories (excluding hidden and CVS) or files ending with ".zip"
36   * or "*.war".  For each webapp discovered is passed to a new instance
37   * of {@link WebAppContext} (or a subclass specified by {@link #getContexts()}.
38   * {@link ContextHandlerCollection#getContextClass()}
39   * 
40   * This deployer does not do hot deployment or undeployment. Nor does
41   * it support per webapplication configuration. For these features 
42   * see {@link ContextDeployer}.
43   * 
44   * @see {@link ContextDeployer}
45   */
46  public class WebAppDeployer extends AbstractLifeCycle
47  {
48      private HandlerContainer _contexts;
49      private String _webAppDir;
50      private String _defaultsDescriptor;
51      private String[] _configurationClasses;
52      private boolean _extract;
53      private boolean _parentLoaderPriority;
54      private boolean _allowDuplicates;
55      private ArrayList _deployed;
56  
57      public String[] getConfigurationClasses()
58      {
59          return _configurationClasses;
60      }
61  
62      public void setConfigurationClasses(String[] configurationClasses)
63      {
64          _configurationClasses=configurationClasses;
65      }
66  
67      public HandlerContainer getContexts()
68      {
69          return _contexts;
70      }
71  
72      public void setContexts(HandlerContainer contexts)
73      {
74          _contexts=contexts;
75      }
76  
77      public String getDefaultsDescriptor()
78      {
79          return _defaultsDescriptor;
80      }
81  
82      public void setDefaultsDescriptor(String defaultsDescriptor)
83      {
84          _defaultsDescriptor=defaultsDescriptor;
85      }
86  
87      public boolean isExtract()
88      {
89          return _extract;
90      }
91  
92      public void setExtract(boolean extract)
93      {
94          _extract=extract;
95      }
96  
97      public boolean isParentLoaderPriority()
98      {
99          return _parentLoaderPriority;
100     }
101 
102     public void setParentLoaderPriority(boolean parentPriorityClassLoading)
103     {
104         _parentLoaderPriority=parentPriorityClassLoading;
105     }
106 
107     public String getWebAppDir()
108     {
109         return _webAppDir;
110     }
111 
112     public void setWebAppDir(String dir)
113     {
114         _webAppDir=dir;
115     }
116 
117     public boolean getAllowDuplicates()
118     {
119         return _allowDuplicates;
120     }
121 
122     /* ------------------------------------------------------------ */
123     /**
124      * @param allowDuplicates If false, do not deploy webapps that have already been deployed or duplicate context path
125      */
126     public void setAllowDuplicates(boolean allowDuplicates)
127     {
128         _allowDuplicates=allowDuplicates;
129     }
130 
131     /* ------------------------------------------------------------ */
132     /**
133      * @throws Exception 
134      */
135     public void doStart() throws Exception
136     {
137         _deployed=new ArrayList();
138         
139         scan();
140         
141     }
142     
143     /* ------------------------------------------------------------ */
144     /** Scan for webapplications.
145      * 
146      * @throws Exception
147      */
148     public void scan() throws Exception
149     {
150         if (_contexts==null)
151             throw new IllegalArgumentException("No HandlerContainer");
152 
153         Resource r=Resource.newResource(_webAppDir);
154         if (!r.exists())
155             throw new IllegalArgumentException("No such webapps resource "+r);
156 
157         if (!r.isDirectory())
158             throw new IllegalArgumentException("Not directory webapps resource "+r);
159 
160         String[] files=r.list();
161 
162         files: for (int f=0; files!=null&&f<files.length; f++)
163         {
164             String context=files[f];
165 
166             if (context.equalsIgnoreCase("CVS/")||context.equalsIgnoreCase("CVS")||context.startsWith("."))
167                 continue;
168 
169             Resource app=r.addPath(r.encode(context));
170 
171             if (context.toLowerCase().endsWith(".war")||context.toLowerCase().endsWith(".jar"))
172             {
173                 context=context.substring(0,context.length()-4);
174                 Resource unpacked=r.addPath(context);
175                 if (unpacked!=null&&unpacked.exists()&&unpacked.isDirectory())
176                     continue;
177             }
178             else if (!app.isDirectory())
179                 continue;
180 
181             if (context.equalsIgnoreCase("root")||context.equalsIgnoreCase("root/"))
182                 context=URIUtil.SLASH;
183             else
184                 context="/"+context;
185             if (context.endsWith("/")&&context.length()>0)
186                 context=context.substring(0,context.length()-1);
187 
188             // Check the context path has not already been added or the webapp itself is not already deployed
189             if (!_allowDuplicates)
190             {
191                 Handler[] installed=_contexts.getChildHandlersByClass(ContextHandler.class);
192                 for (int i=0; i<installed.length; i++)
193                 {
194                     ContextHandler c=(ContextHandler)installed[i];
195         
196                     if (context.equals(c.getContextPath()))
197                         continue files;
198 
199                     try
200                     {
201                         String path=null;
202                         if (c instanceof WebAppContext)
203                             path = Resource.newResource(((WebAppContext)c).getWar()).getFile().getAbsolutePath();
204                         else if (c.getBaseResource()!=null)
205                             path = c.getBaseResource().getFile().getAbsolutePath();
206 
207                         if (path!=null && path.equals(app.getFile().getAbsolutePath()))
208                             continue files;
209                     }
210                     catch (Exception e)
211                     {
212                         Log.ignore(e);
213                     }
214                 }
215             }
216 
217             // create a webapp
218             WebAppContext wah=null;
219             if (_contexts instanceof ContextHandlerCollection && 
220                 WebAppContext.class.isAssignableFrom(((ContextHandlerCollection)_contexts).getContextClass()))
221             {
222                 try
223                 {
224                     wah=(WebAppContext)((ContextHandlerCollection)_contexts).getContextClass().newInstance();
225                 }
226                 catch (Exception e)
227                 {
228                     throw new Error(e);
229                 }
230             }
231             else
232             {
233                 wah=new WebAppContext();
234             }
235             
236             // configure it
237             wah.setContextPath(context);
238             if (_configurationClasses!=null)
239                 wah.setConfigurationClasses(_configurationClasses);
240             if (_defaultsDescriptor!=null)
241                 wah.setDefaultsDescriptor(_defaultsDescriptor);
242             wah.setExtractWAR(_extract);
243             wah.setWar(app.toString());
244             wah.setParentLoaderPriority(_parentLoaderPriority);
245             // add it
246             _contexts.addHandler(wah);
247             _deployed.add(wah);
248             
249             if (_contexts.isStarted())
250                wah.start();  // TODO Multi exception
251         }
252     }
253     
254     public void doStop() throws Exception
255     {
256         for (int i=_deployed.size();i-->0;)
257         {
258             ContextHandler wac = (ContextHandler)_deployed.get(i);
259             wac.stop();// TODO Multi exception
260         }
261     }
262 }