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