View Javadoc

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