View Javadoc

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