View Javadoc

1   //
2   //  ========================================================================
3   //  Copyright (c) 1995-2012 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.deploy.providers;
20  
21  import java.io.File;
22  import java.io.FilenameFilter;
23  import java.io.IOException;
24  import java.net.MalformedURLException;
25  
26  import org.eclipse.jetty.deploy.App;
27  import org.eclipse.jetty.deploy.util.FileID;
28  import org.eclipse.jetty.server.handler.ContextHandler;
29  import org.eclipse.jetty.util.URIUtil;
30  import org.eclipse.jetty.util.resource.Resource;
31  import org.eclipse.jetty.webapp.WebAppContext;
32  
33  /* ------------------------------------------------------------ */
34  /** Context directory App Provider.
35   * <p>This specialization of {@link ScanningAppProvider} is the
36   * replacement for old (and deprecated) <code>org.eclipse.jetty.deploy.WebAppDeployer</code> and it will scan a directory
37   * only for war files or directories files.</p>
38   * <p>
39   * Webapps with names root or starting with root- are deployed at /.
40   * If the name is in the format root-hostname, then the webapp is deployed
41   * at / in the virtual host hostname.
42   */
43  public class WebAppProvider extends ScanningAppProvider
44  {
45      private boolean _extractWars = false;
46      private boolean _parentLoaderPriority = false;
47      private String _defaultsDescriptor;
48      private Filter _filter;
49      private File _tempDirectory;
50      private String[] _configurationClasses;
51  
52      public static class Filter implements FilenameFilter
53      {
54          private File _contexts;
55          
56          public boolean accept(File dir, String name)
57          {
58              if (!dir.exists())
59              {
60                  return false;
61              }
62              String lowername = name.toLowerCase();
63              
64              File file = new File(dir,name);
65              // is it not a directory and not a war ?
66              if (!file.isDirectory() && !lowername.endsWith(".war"))
67              {
68                  return false;
69              }
70              
71              //ignore hidden files
72              if (lowername.startsWith("."))
73                  return false;
74                     
75              if (file.isDirectory())
76              {
77                  // is it a directory for an existing war file?
78                  if (new File(dir,name+".war").exists() ||
79                      new File(dir,name+".WAR").exists())
80  
81                      return false;
82   
83                  //is it a sccs dir?
84                  if ("cvs".equals(lowername) || "cvsroot".equals(lowername))
85                      return false;
86              }
87              
88              // is there a contexts config file
89              if (_contexts!=null)
90              {
91                  String context=name;
92                  if (!file.isDirectory())
93                  {
94                      context=context.substring(0,context.length()-4);
95                  }
96                  if (new File(_contexts,context+".xml").exists() ||
97                      new File(_contexts,context+".XML").exists() )
98                  {
99                      return false;
100                 }
101             }
102                
103             return true;
104         }
105     }
106     
107     /* ------------------------------------------------------------ */
108     public WebAppProvider()
109     {
110         super(new Filter());
111         _filter=(Filter)_filenameFilter;
112         setScanInterval(0);
113     }
114 
115     /* ------------------------------------------------------------ */
116     /** Get the extractWars.
117      * @return the extractWars
118      */
119     public boolean isExtractWars()
120     {
121         return _extractWars;
122     }
123 
124     /* ------------------------------------------------------------ */
125     /** Set the extractWars.
126      * @param extractWars the extractWars to set
127      */
128     public void setExtractWars(boolean extractWars)
129     {
130         _extractWars = extractWars;
131     }
132 
133     /* ------------------------------------------------------------ */
134     /** Get the parentLoaderPriority.
135      * @return the parentLoaderPriority
136      */
137     public boolean isParentLoaderPriority()
138     {
139         return _parentLoaderPriority;
140     }
141 
142     /* ------------------------------------------------------------ */
143     /** Set the parentLoaderPriority.
144      * @param parentLoaderPriority the parentLoaderPriority to set
145      */
146     public void setParentLoaderPriority(boolean parentLoaderPriority)
147     {
148         _parentLoaderPriority = parentLoaderPriority;
149     }
150     
151     /* ------------------------------------------------------------ */
152     /** Get the defaultsDescriptor.
153      * @return the defaultsDescriptor
154      */
155     public String getDefaultsDescriptor()
156     {
157         return _defaultsDescriptor;
158     }
159 
160     /* ------------------------------------------------------------ */
161     /** Set the defaultsDescriptor.
162      * @param defaultsDescriptor the defaultsDescriptor to set
163      */
164     public void setDefaultsDescriptor(String defaultsDescriptor)
165     {
166         _defaultsDescriptor = defaultsDescriptor;
167     }
168 
169     /* ------------------------------------------------------------ */
170     public String getContextXmlDir()
171     {
172         return _filter._contexts==null?null:_filter._contexts.toString();
173     }
174 
175     /* ------------------------------------------------------------ */
176     /**
177      * Set the directory in which to look for context XML files.
178      * <p>
179      * If a webapp call "foo/" or "foo.war" is discovered in the monitored
180      * directory, then the ContextXmlDir is examined to see if a foo.xml
181      * file exists.  If it does, then this deployer will not deploy the webapp
182      * and the ContextProvider should be used to act on the foo.xml file.
183      * @see ContextProvider
184      * @param contextsDir
185      */
186     public void setContextXmlDir(String contextsDir)
187     {
188         try
189         {
190             _filter._contexts=Resource.newResource(contextsDir).getFile();
191         }
192         catch (MalformedURLException e)
193         {
194             throw new RuntimeException(e);
195         }
196         catch (IOException e)
197         {
198             throw new RuntimeException(e);
199         }
200     }
201     
202     
203     /* ------------------------------------------------------------ */
204     /**
205      * @param configurations The configuration class names.
206      */
207     public void setConfigurationClasses(String[] configurations)
208     {
209         _configurationClasses = configurations==null?null:(String[])configurations.clone();
210     }  
211     
212     /* ------------------------------------------------------------ */
213     /**
214      * 
215      */
216     public String[] getConfigurationClasses()
217     {
218         return _configurationClasses;
219     }
220     
221     /**
222      * Set the Work directory where unpacked WAR files are managed from.
223      * <p>
224      * Default is the same as the <code>java.io.tmpdir</code> System Property.
225      * 
226      * @param directory the new work directory
227      */
228     public void setTempDir(File directory)
229     {
230         _tempDirectory = directory;
231     }
232     
233     /**
234      * Get the user supplied Work Directory.
235      * 
236      * @return the user supplied work directory (null if user has not set Temp Directory yet)
237      */
238     public File getTempDir()
239     {
240         return _tempDirectory;
241     }
242     
243     /* ------------------------------------------------------------ */
244     public ContextHandler createContextHandler(final App app) throws Exception
245     {
246         Resource resource = Resource.newResource(app.getOriginId());
247         File file = resource.getFile();
248         if (!resource.exists())
249             throw new IllegalStateException("App resouce does not exist "+resource);
250 
251         String context = file.getName();
252         
253         if (file.isDirectory())
254         {
255             // must be a directory
256         }
257         else if (FileID.isWebArchiveFile(file))
258         {
259             // Context Path is the same as the archive.
260             context = context.substring(0,context.length() - 4);
261         }
262         else 
263         {
264             throw new IllegalStateException("unable to create ContextHandler for "+app);
265         }
266 
267         // Ensure "/" is Not Trailing in context paths.
268         if (context.endsWith("/") && context.length() > 0) 
269         {
270             context = context.substring(0,context.length() - 1);
271         }
272         
273         // Start building the webapplication
274         WebAppContext wah = new WebAppContext();
275         wah.setDisplayName(context);
276         
277         // special case of archive (or dir) named "root" is / context
278         if (context.equalsIgnoreCase("root"))
279         {
280             context = URIUtil.SLASH;
281         }
282         else if (context.toLowerCase().startsWith("root-"))
283         {
284             int dash=context.toLowerCase().indexOf('-');
285             String virtual = context.substring(dash+1);
286             wah.setVirtualHosts(new String[]{virtual});
287             context = URIUtil.SLASH;
288         }
289 
290         // Ensure "/" is Prepended to all context paths.
291         if (context.charAt(0) != '/') 
292         {
293             context = "/" + context;
294         }
295 
296 
297         wah.setContextPath(context);
298         wah.setWar(file.getAbsolutePath());
299         if (_defaultsDescriptor != null) 
300         {
301             wah.setDefaultsDescriptor(_defaultsDescriptor);
302         }
303         wah.setExtractWAR(_extractWars);
304         wah.setParentLoaderPriority(_parentLoaderPriority);
305         if (_configurationClasses != null) 
306         {
307             wah.setConfigurationClasses(_configurationClasses);
308         }
309 
310         if (_tempDirectory != null)
311         {
312             /* Since the Temp Dir is really a context base temp directory,
313              * Lets set the Temp Directory in a way similar to how WebInfConfiguration does it,
314              * instead of setting the
315              * WebAppContext.setTempDirectory(File).  
316              * If we used .setTempDirectory(File) all webapps will wind up in the
317              * same temp / work directory, overwriting each others work.
318              */
319             wah.setAttribute(WebAppContext.BASETEMPDIR,_tempDirectory);
320         }
321         return wah; 
322     }
323     
324 }