1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.jetspeed.deployment.impl;
18
19 import java.io.File;
20 import java.io.FileFilter;
21 import java.io.FileNotFoundException;
22 import java.io.IOException;
23 import java.util.ArrayList;
24 import java.util.Arrays;
25 import java.util.Collection;
26 import java.util.HashMap;
27 import java.util.Iterator;
28 import java.util.StringTokenizer;
29
30 import org.apache.commons.logging.Log;
31 import org.apache.commons.logging.LogFactory;
32 import org.apache.jetspeed.components.portletregistry.PortletRegistry;
33 import org.apache.jetspeed.deployment.DeploymentEvent;
34 import org.apache.jetspeed.deployment.DeploymentEventListener;
35 import org.apache.jetspeed.deployment.DeploymentException;
36 import org.apache.jetspeed.deployment.DeploymentManager;
37 import org.apache.jetspeed.deployment.DeploymentObject;
38 import org.apache.jetspeed.deployment.DeploymentStatus;
39
40 /***
41 * <p>
42 * StandardDeploymentManager
43 * </p>
44 * Implementation of {@link org.apache.jetspeed.deployment.DeploymentManager}
45 *
46 * @author <a href="mailto:weaver@apache.org">Scott T. Weaver </a>
47 * @version $Id: StandardDeploymentManager.java 517121 2007-03-12 07:45:49Z ate $
48 */
49 public class StandardDeploymentManager implements DeploymentManager
50 {
51 private static final FileFilter readmeIgnoringFileFilter = new FileFilter()
52 {
53 public boolean accept(File file)
54 {
55 return !file.getName().equalsIgnoreCase("README.txt");
56 }
57 };
58
59 protected Log log = LogFactory.getLog("deployment");
60 protected FileSystemScanner scanner;
61 protected PortletRegistry registry;
62 protected Collection deploymentListeners;
63 protected long scanningDelay;
64 protected String stagingDirectories;
65 protected File[] stagingDirectoriesAsFiles;
66 protected HashMap ignoredFiles;
67
68 /***
69 * @param stagingDirectories
70 * @param scanningDelay
71 * @param deploymentListeners
72 */
73 public StandardDeploymentManager(String stagingDirectories, long scanningDelay, Collection deploymentListeners)
74 {
75 this.scanningDelay = scanningDelay;
76 this.stagingDirectories = stagingDirectories;
77 StringTokenizer dirTokenizer = new StringTokenizer(stagingDirectories, ",");
78 this.stagingDirectoriesAsFiles = new File[dirTokenizer.countTokens()];
79 int i = 0;
80 while (dirTokenizer.hasMoreTokens())
81 {
82 this.stagingDirectoriesAsFiles[i] = new File(dirTokenizer.nextToken());
83 i++;
84 }
85
86 this.deploymentListeners = deploymentListeners;
87 this.ignoredFiles = new HashMap();
88 }
89
90 /***
91 * <p>
92 * start
93 * </p>
94 *
95 * @see org.picocontainer.Startable#start()
96 */
97 public void start()
98 {
99
100 log.info("Starting auto deployment service: " + getClass().getName());
101
102 log.info("Deployment scanning delay: " + scanningDelay);
103
104 log.info("Deployment staging directory: " + stagingDirectories);
105
106 for (int i = 0; i < stagingDirectoriesAsFiles.length; i++)
107 {
108 if (!stagingDirectoriesAsFiles[i].exists())
109 {
110 log
111 .error(stagingDirectoriesAsFiles[i].getAbsolutePath()
112 + " does not exist, auto deployment disabled.");
113 stop();
114 return;
115 }
116 }
117
118
119 Iterator itr = deploymentListeners.iterator();
120 while (itr.hasNext())
121 {
122 ((DeploymentEventListener) itr.next()).initialize();
123 }
124
125 if (scanningDelay > -1)
126 {
127 try
128 {
129 scanner = new FileSystemScanner(Thread.currentThread().getThreadGroup(),
130 "Autodeployment File Scanner Thread");
131
132 scanner.setDaemon(true);
133
134 scanner.setContextClassLoader(getClass().getClassLoader());
135 scanner.start();
136 log.info("Deployment scanner successfuly started!");
137 }
138 catch (Exception e)
139 {
140 log.warn(
141 "Unable to intialize Catalina Portlet Application Manager. Auto deployment will be disabled: "
142 + e.toString(), e);
143
144 stop();
145 return;
146 }
147 }
148 else
149 {
150 log.info("Scanning delay set to " + scanningDelay
151 + " has disabled automatic scanning of staging directory.");
152 }
153
154 }
155
156 /***
157 * <p>
158 * stop
159 * </p>
160 *
161 * @see org.picocontainer.Startable#stop()
162 */
163 public void stop()
164 {
165 if (scanner != null)
166 {
167 scanner.safeStop();
168 }
169 }
170
171 public synchronized DeploymentStatus deploy(File aFile) throws DeploymentException
172 {
173 DeploymentObject deploymentObject = new StandardDeploymentObject(aFile);
174 DeploymentEvent event = null;
175 try
176 {
177 event = new DeploymentEventImpl(deploymentObject);
178 dispatch(event);
179 }
180 finally
181 {
182 if ( deploymentObject != null )
183 {
184 try
185 {
186 deploymentObject.close();
187 }
188 catch (IOException e)
189 {
190 }
191 }
192 }
193 return event;
194 }
195
196 public void fireDeploymentEvent()
197 {
198 File[] stagedFiles = getAllStagedFiles();
199 for (int i = 0; i < stagedFiles.length; i++)
200 {
201
202 File aFile = stagedFiles[i];
203 if (aFile.isFile() && !ignoreFile(aFile))
204 {
205 DeploymentStatus status = null;
206 Exception de = null;
207 try
208 {
209 status = deploy(aFile);
210 }
211 catch (Exception e)
212 {
213 de = e;
214 }
215
216 if ( status != null && status.getStatus() == DeploymentStatus.STATUS_OKAY )
217 {
218 if (aFile.exists())
219 {
220 log.info("File: " + aFile.getAbsolutePath() + " deployed");
221 boolean result = aFile.delete();
222 if (!result)
223 {
224 log.error("Failed to remove: " + aFile);
225 }
226 }
227 }
228 else
229 {
230 if (status == null || status.getStatus() == DeploymentStatus.STATUS_EVAL)
231 {
232 log.warn("Unrecognized file " + aFile.getAbsolutePath());
233 }
234 else if ( de != null )
235 {
236 log.error("Failure deploying " + aFile.getAbsolutePath(), de);
237 }
238 else
239 {
240 log.error("Failure deploying " + aFile.getAbsolutePath());
241 }
242 ignoredFiles.put(aFile.getAbsolutePath(), new Long(aFile.lastModified()));
243 }
244 }
245 }
246 }
247
248 /***
249 * <p>
250 * dispatch
251 * </p>
252 *
253 * @see org.apache.jetspeed.deployment.DeploymentManager#dispatch(org.apache.jetspeed.deployment.DeploymentEvent)
254 * @param event
255 */
256 public void dispatch(DeploymentEvent event)
257 {
258 try
259 {
260 Iterator itr = deploymentListeners.iterator();
261 while (itr.hasNext())
262 {
263 DeploymentEventListener listener = (DeploymentEventListener) itr.next();
264 listener.invokeDeploy(event);
265 if (event.getStatus() != DeploymentStatus.STATUS_EVAL)
266 {
267 break;
268 }
269 }
270 }
271 catch (DeploymentException e)
272 {
273 log.error(e.getMessage(), e);
274 event.setStatus(DeploymentStatus.STATUS_FAILED);
275 }
276 }
277
278 /***
279 * <p>
280 * ignoreFile
281 * </p>
282 *
283 * @param fileName
284 * @return
285 */
286 protected boolean ignoreFile(File aFile)
287 {
288 Long previousModified = (Long) ignoredFiles.get(aFile.getAbsolutePath());
289 if (previousModified != null)
290 {
291 if (previousModified.longValue() != aFile.lastModified())
292 {
293 ignoredFiles.remove(aFile.getAbsolutePath());
294 }
295 else
296 {
297 return true;
298 }
299 }
300 return false;
301 }
302
303 /***
304 * <p>
305 * getAllStagedFiles
306 * </p>
307 *
308 * @return
309 */
310 protected File[] getAllStagedFiles()
311 {
312 ArrayList fileList = new ArrayList();
313 for (int i = 0; i < stagingDirectoriesAsFiles.length; i++)
314 {
315 fileList.addAll(Arrays.asList(stagingDirectoriesAsFiles[i].listFiles(readmeIgnoringFileFilter)));
316 }
317
318 return (File[]) fileList.toArray(new File[fileList.size()]);
319 }
320
321 public class FileSystemScanner extends Thread
322 {
323
324 private boolean started = true;
325
326 public FileSystemScanner(ThreadGroup threadGroup, String name) throws FileNotFoundException, IOException
327 {
328 super(threadGroup, name);
329 setPriority(MIN_PRIORITY);
330 }
331
332 /***
333 * @see java.lang.Runnable#run()
334 */
335 public void run()
336 {
337
338
339 try
340 {
341
342
343
344
345
346
347
348
349
350 sleep(scanningDelay);
351 }
352 catch (InterruptedException e)
353 {
354 }
355 while (started)
356 {
357 fireDeploymentEvent();
358
359 try
360 {
361 sleep(scanningDelay);
362 }
363 catch (InterruptedException e)
364 {
365
366 }
367 }
368 }
369
370 /***
371 * notifies a switch variable that exits the watcher's montior loop started in the <code>run()</code> method.
372 */
373 public void safeStop()
374 {
375 started = false;
376 }
377
378 }
379
380 }