KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jboss > deployment > scanner > HttpURLDeploymentScanner


1 /*
2  * JBoss, the OpenSource J2EE webOS
3  *
4  * Distributable under LGPL license.
5  * See terms of license at gnu.org.
6  */

7
8 package org.jboss.deployment.scanner;
9
10 import java.io.UnsupportedEncodingException JavaDoc;
11 import java.net.MalformedURLException JavaDoc;
12 import java.net.URL JavaDoc;
13 import java.util.ArrayList JavaDoc;
14 import java.util.Collections JavaDoc;
15 import java.util.HashMap JavaDoc;
16 import java.util.Iterator JavaDoc;
17 import java.util.LinkedList JavaDoc;
18 import java.util.List JavaDoc;
19 import java.util.Set JavaDoc;
20 import java.util.StringTokenizer JavaDoc;
21
22 import org.jboss.deployment.IncompleteDeploymentException;
23 import org.jboss.deployment.NetBootFile;
24 import org.jboss.deployment.NetBootHelper;
25 import org.jboss.util.NullArgumentException;
26
27 /**
28  * Implement a scanner for HTTP server with un- re- deploy features. To enable these
29  * features, a "lister" is used on the server: it allows to list some arbitrary
30  * directory and return an XML string containing the detail of the directory.
31  *
32  * The Filtering feature is not yet implemented (because it relies on the File class
33  * which cannot be used in our case, or should be tricked)
34  *
35  * The class extends URLDeploymentScanner but it doesn't really extends its code
36  * instead, it will delegate to it everything related to:
37  * - absolute http url that identify a single file, such as http://server/bla.jar
38  * WARNING: such explicit JARs are NOT re- un- deployable!
39  * - file: urls (must be identified as a file: URL in the MBean definition)
40  *
41  * Remote expanded directory are not supported.
42  *
43  * The scanner would be able to work with multiple different Lister (one for
44  * each URL for example): the processing and data structure are already there.
45  * Nevertheless, there is currently no way to indicate this explicitly (in the MBean
46  * definition for example). We would have to build a new naming scheme such as
47  * LISTER_URL#DOWNLOAD_URL#REMOTE_FOLDER_NAME
48  *
49  * @see org.jboss.deployment.scanner.URLDeploymentScanner
50  * @see org.jboss.deployment.NetBootHelper
51  *
52  * @author <a HREF="mailto:sacha.labourey@cogito-info.ch">Sacha Labourey</a>.
53  * @version $Revision: 1.5.2.1 $
54  *
55  * <p><b>Revisions:</b>
56  *
57  * <p><b>6th of november 2002 Sacha Labourey:</b>
58  * <ul>
59  * <li> First implementation </li>
60  * </ul>
61  */

62
63 /**
64  *
65  * @jmx:mbean extends="org.jboss.deployment.scanner.URLDeploymentScannerMBean"
66  *
67  */

68 public class HttpURLDeploymentScanner
69    extends URLDeploymentScanner
70    implements HttpURLDeploymentScannerMBean
71 {
72    
73    // Constants -----------------------------------------------------
74

75    // Attributes ----------------------------------------------------
76

77    protected String JavaDoc defaultHttpDirectoryListerUrl = null;
78    protected String JavaDoc httpDirectoryDownload = null;
79
80    protected HttpLister defaultHttpLister = null;
81    
82    protected HashMap JavaDoc scannedHttpUrls = new HashMap JavaDoc (); // lister to array of HttpDeploymentFolder map
83

84    // Static --------------------------------------------------------
85

86    // Constructors --------------------------------------------------
87

88    public HttpURLDeploymentScanner () { super (); }
89    
90    // Public --------------------------------------------------------
91

92    /**
93     * Default URL to be used when listing files on a remote HTTP folder
94     * If none is provided, the one found in jboss.netboot.listing.url is used
95     * If the URL is X, the resulting URL that is used to list the content of folder
96     * "foo" will be "Xdir=foo": the provided URL must support this naming convention
97     *
98     * @jmx:managed-attribute
99     */

100    public String JavaDoc getDefaultHttpDirectoryListerUrl ()
101    {
102       if (defaultHttpDirectoryListerUrl == null)
103          defaultHttpDirectoryListerUrl = NetBootHelper.getDefaultListUrl ();
104       
105       return this.defaultHttpDirectoryListerUrl;
106    }
107    
108    /**
109     * @jmx:managed-attribute
110     */

111    public void setDefaultHttpDirectoryListerUrl (String JavaDoc url)
112    {
113       this.defaultHttpDirectoryListerUrl = url;
114    }
115    
116    /**
117     * Default URL to be used when downloading files from a remote HTTP folder
118     * If none is provided, the one found in jboss.server.home.url is used
119     *
120     * @jmx:managed-attribute
121     */

122    public String JavaDoc getDefaultHttpDirectoryDownloadUrl ()
123    {
124       if (httpDirectoryDownload == null)
125          httpDirectoryDownload = NetBootHelper.getDefaultDownloadUrl ();
126       
127       return this.httpDirectoryDownload;
128    }
129    
130    /**
131     * @jmx:managed-attribute
132     */

133    public void setDefaultHttpDirectoryDownloadUrl (String JavaDoc url)
134    {
135       this.httpDirectoryDownload = url;
136    }
137    
138    /**
139     * @jmx:managed-attribute
140     */

141    public void setURLList(final List JavaDoc list)
142    {
143       // shouldn't be called. TODO setURLs is enough for now
144
}
145
146    /**
147     * @jmx:managed-attribute
148     */

149    public void setURLs(final String JavaDoc listspec) throws MalformedURLException JavaDoc
150    {
151       if (listspec == null)
152          throw new NullArgumentException("listspec");
153       
154       boolean debug = log.isDebugEnabled();
155       
156       List JavaDoc fileList = new LinkedList JavaDoc();
157       
158       StringTokenizer JavaDoc stok = new StringTokenizer JavaDoc(listspec, ",");
159       while (stok.hasMoreTokens())
160       {
161          String JavaDoc urlspec = stok.nextToken().trim();
162          
163          if (debug)
164          {
165             log.debug("Adding URL from spec: " + urlspec);
166          }
167          
168          // here we split between file based URL (or absolute JARs) that will
169
// be directly managed by our
170
// ancestor, and HTTP based URL that WE will manage
171
//
172
if (urlspec.startsWith ("file:") || urlspec.startsWith ("http:"))
173          {
174             URL JavaDoc url = makeURL(urlspec);
175             if (debug) log.debug("File URL: " + url);
176             fileList.add(url);
177          }
178          else
179          {
180             URL JavaDoc url = makeURL(urlspec);
181             if (debug) log.debug("HTTP URL: " + url);
182             
183             addHttpDeployment (urlspec, this.getDefaultHttpDirectoryLister ());
184          }
185       }
186       
187       // we call our father: he will still manage URLs that we don't
188
// => processing is split!
189
//
190
super.setURLList(fileList);
191    }
192
193    public synchronized void scan() throws Exception JavaDoc
194    {
195       
196       // call our father first: we split the process
197
//
198
super.scan ();
199       
200       boolean trace = log.isTraceEnabled();
201       
202       // Scan for new deployements
203
if (trace) log.trace("Scanning for new http deployments");
204
205       // we deploy, for each lister, every deploy name
206
synchronized (scannedHttpUrls)
207       {
208          // we may have several Listers...
209
//
210
Iterator JavaDoc listers = this.getAllDeploymentListers().iterator ();
211          while (listers.hasNext ())
212          {
213             HttpLister lister = (HttpLister)listers.next ();
214             
215             // ...Each Lister may have a set of associated folder to list...
216
//
217
Iterator JavaDoc deployments = this.getHttpDeploymentsForLister (lister).iterator ();
218             while (deployments.hasNext ())
219             {
220                // ... And each folder possibly has a set of deployed files
221
//
222
HttpDeploymentFolder deploymentFolder = (HttpDeploymentFolder)deployments.next ();
223                scanRemoteDirectory (deploymentFolder);
224             }
225          }
226       }
227       
228       // Now that all new files have been deployed, we
229
// scan for removed or changed deployments
230
// we do it lister by lister to avoid to have an http read for each deployment
231
// (instead we have one http read for each lister)
232
//
233
if (trace) log.trace("Scanning existing deployments for removal or modification");
234       
235       List JavaDoc removed = new LinkedList JavaDoc();
236       List JavaDoc modified = new LinkedList JavaDoc();
237       
238       Iterator JavaDoc listers = this.getAllDeploymentListers().iterator ();
239       while (listers.hasNext ())
240       {
241          HttpLister lister = (HttpLister)listers.next ();
242          
243          Iterator JavaDoc deployments = this.getHttpDeploymentsForLister (lister).iterator ();
244          while (deployments.hasNext ())
245          {
246             HttpDeploymentFolder deploymentFolder = (HttpDeploymentFolder)deployments.next ();
247             
248             // get remote view for this lister/deployment folder couple
249
//
250
NetBootFile[] remoteFiles = NetBootHelper.listFilesFromDirectory (deploymentFolder.getCompleteListingUrl ());;
251             
252             Iterator JavaDoc deployedFiles = deploymentFolder.getDeployedFiles ().iterator ();
253             while (deployedFiles.hasNext ())
254             {
255                DeployedRemoteURL deployed = (DeployedRemoteURL)deployedFiles.next ();
256                
257                NetBootFile alreadyDeployed = findFileWithName (deployed.getFile ().getName (), remoteFiles);
258                
259                if (alreadyDeployed == null)
260                {
261                   removed.add (deployed);
262                }
263                else if (alreadyDeployed.LastModified () > deployed.getFile ().LastModified ())
264                {
265                   deployed.updateFile (alreadyDeployed); // important! Required to update size and timestamp
266
modified.add (deployed);
267                }
268                               
269             }
270                                                                                               
271          }
272       }
273       
274       for (Iterator JavaDoc iter=removed.iterator(); iter.hasNext();)
275       {
276          DeployedRemoteURL du = (DeployedRemoteURL)iter.next();
277          undeploy(du);
278       }
279       
280       for (Iterator JavaDoc iter=modified.iterator(); iter.hasNext();)
281       {
282          DeployedRemoteURL du = (DeployedRemoteURL)iter.next();
283          undeploy(du);
284          deploy(du);
285       }
286
287       // Validate that there are still incomplete deployments
288
if( lastIncompleteDeploymentException != null )
289       {
290          try
291          {
292             Object JavaDoc[] args = {};
293             String JavaDoc[] sig = {};
294             Object JavaDoc o = getServer().invoke(getDeployer(),
295                "checkIncompleteDeployments", args, sig);
296          }
297          catch (Exception JavaDoc e)
298          {
299             log.error(e);
300          }
301       }
302    }
303
304    
305    
306
307    protected void scanRemoteDirectory(HttpDeploymentFolder httpFolder) throws Exception JavaDoc
308    {
309       boolean trace = log.isTraceEnabled();
310       
311       if (trace) log.trace("Scanning directory: " + httpFolder.getRelativeFolder ());
312       
313       NetBootFile[] content = null;
314       try
315       {
316          content = NetBootHelper.listFilesFromDirectory (httpFolder.getCompleteListingUrl ());
317       }
318       catch (Exception JavaDoc e)
319       {
320          log.trace(e);
321          return;
322       }
323      
324       /*
325        * TODO LATER
326       File[] files = filter == null ? file.listFiles() : file.listFiles(filter);
327       if (files == null)
328       {
329          throw new Exception("Null files returned from directory listing");
330       }
331        */

332       
333       // list of urls to deploy
334
List JavaDoc list = new LinkedList JavaDoc();
335       HashMap JavaDoc linkNameToObjects = new HashMap JavaDoc ();
336       
337       for (int i = 0; i < content.length; i++)
338       {
339          if (trace) log.trace("Checking deployment file: " + content[i]);
340          
341          // Is it a new file
342
//
343
NetBootFile found = findFileWithName(content[i].getName (), httpFolder.getDeployedFiles());
344          if (found == null)
345          {
346             URL JavaDoc target = httpFolder.getUrlForFile (content[i]);
347             list.add(target);
348             linkNameToObjects.put (target, content[i]);
349          }
350       }
351
352       //
353
// HACK, sort the elements so dependencies have a better chance of working
354
//
355
if (sorter != null)
356       {
357          updateSorter();
358          Collections.sort(list, sorter);
359       }
360
361       // deploy each url
362
Iterator JavaDoc iter = list.iterator();
363       while (iter.hasNext())
364       {
365          URL JavaDoc url = (URL JavaDoc)iter.next();
366          NetBootFile dep = (NetBootFile)linkNameToObjects.get (url);
367          
368          deploy( new DeployedRemoteURL(httpFolder, dep) );
369          iter.remove();
370          if (sorter != null && iter.hasNext() && updateSorter())
371          {
372             Collections.sort(list, sorter);
373             iter = list.iterator();
374          }
375       }
376    }
377    
378    
379    // Z implementation ----------------------------------------------
380

381    // Y overrides ---------------------------------------------------
382

383    // Package protected ---------------------------------------------
384

385    // Protected -----------------------------------------------------
386

387    protected void undeploy(DeployedRemoteURL deployedUrl)
388    {
389       URL JavaDoc url = null;
390       try
391       {
392          url = deployedUrl.getFolder ().getUrlForFile (deployedUrl.getFile ());
393
394          if (log.isTraceEnabled()) log.trace("Undeploying: " + url);
395
396          deployer.undeploy(url);
397          
398          deployedUrl.getFolder ().removeDeployedFile (deployedUrl);
399       }
400       catch (Exception JavaDoc e)
401       {
402          log.error("Failed to undeploy: " + url, e);
403       }
404    }
405    
406    protected void deploy(DeployedRemoteURL deployedUrl)
407       throws MalformedURLException JavaDoc
408    {
409       
410       URL JavaDoc url = deployedUrl.getFolder ().getUrlForFile (deployedUrl.getFile ());
411       
412       if( url == null ) return;
413
414       if (log.isTraceEnabled()) log.trace("Deploying: " + url);
415       
416       try
417       {
418          deployer.deploy(url);
419       }
420       catch (IncompleteDeploymentException e)
421       {
422          lastIncompleteDeploymentException = e;
423       }
424       catch (Exception JavaDoc e)
425       {
426          log.error("Failed to deploy: " + url, e);
427       }
428       
429       deployedUrl.getFolder ().addDeployedFile (deployedUrl);
430    }
431      
432    // Find for file presence in a set of files
433
//
434

435    protected NetBootFile findFileWithName (String JavaDoc name, NetBootFile[] files)
436    {
437       for (int i=0; i<files.length; i++)
438       {
439          if (files[i].getName ().equals (name))
440             return files[i];
441       }
442       return null;
443    }
444    
445    protected NetBootFile findFileWithName (String JavaDoc name, List JavaDoc deployedRemoteURL)
446    {
447       NetBootFile[] tmp = new NetBootFile[deployedRemoteURL.size ()];
448       Iterator JavaDoc iter = deployedRemoteURL.iterator ();
449       int i=0;
450       while (iter.hasNext())
451       {
452          DeployedRemoteURL url = (DeployedRemoteURL)iter.next ();
453          tmp[i] = url.getFile ();
454          i++;
455       }
456       return findFileWithName(name, tmp);
457    }
458    
459    // Manage Lister and associated Directories that must be watched
460
//
461

462    protected synchronized void addHttpDeployment (String JavaDoc relativeName, HttpLister lister)
463    {
464       ArrayList JavaDoc deps = (ArrayList JavaDoc)scannedHttpUrls.get (lister);
465       if (deps == null)
466       {
467          deps = new ArrayList JavaDoc();
468          scannedHttpUrls.put (lister, deps);
469       }
470       deps.add (new HttpDeploymentFolder (relativeName, lister));
471    }
472    
473    protected List JavaDoc getHttpDeploymentsForLister (HttpLister lister)
474    {
475       ArrayList JavaDoc deps = (ArrayList JavaDoc)scannedHttpUrls.get (lister);
476       if (deps == null)
477       {
478          deps = new ArrayList JavaDoc();
479       }
480       return deps;
481    }
482    
483    protected Set JavaDoc getAllDeploymentListers ()
484    {
485       return this.scannedHttpUrls.keySet ();
486    }
487    
488    /**
489     * Default Lister object when no other lister is specified in the URLs
490     */

491    protected HttpLister getDefaultHttpDirectoryLister ()
492    {
493       if (defaultHttpLister == null)
494          defaultHttpLister = new HttpLister (getDefaultHttpDirectoryDownloadUrl(),
495                                              getDefaultHttpDirectoryListerUrl());
496       
497       return this.defaultHttpLister;
498    }
499    
500    // Private -------------------------------------------------------
501

502    // Inner classes -------------------------------------------------
503

504    protected class HttpLister
505    {
506       public String JavaDoc downloadUrl = null;
507       public String JavaDoc httpListerUrl = null;
508       
509       public HttpLister (String JavaDoc download, String JavaDoc list)
510       {
511          downloadUrl = download;
512          httpListerUrl = list;
513       }
514       
515       public String JavaDoc getDownloadUrl () { return this.downloadUrl; }
516       public String JavaDoc getHttpListerUrl () { return this.httpListerUrl; }
517       
518       public int hashCode () { return this.httpListerUrl.hashCode (); }
519       
520       public boolean equals (Object JavaDoc obj)
521       {
522          if (obj instanceof HttpLister)
523             return ((HttpLister)obj).httpListerUrl.equals (this.httpListerUrl);
524          else
525             return false;
526       }
527       
528    }
529    
530    protected class HttpDeploymentFolder
531    {
532       public String JavaDoc folder = null;
533       public HttpLister myLister = null;
534       public ArrayList JavaDoc deployedFiles = new ArrayList JavaDoc ();
535       
536       public HttpDeploymentFolder (String JavaDoc folder, HttpLister accessor)
537       {
538          this.folder = folder;
539          this.myLister = accessor;
540       }
541       
542       public String JavaDoc getRelativeFolder () { return this.folder; }
543       public HttpLister getAssociatedLister () { return this.myLister; }
544       
545       public void addDeployedFile (DeployedRemoteURL file) { deployedFiles.add (file); }
546       public void removeDeployedFile (DeployedRemoteURL file) { deployedFiles.remove (file); }
547       
548       public List JavaDoc getDeployedFiles () { return this.deployedFiles; }
549       
550       public String JavaDoc getCompleteListingUrl ()
551          throws UnsupportedEncodingException JavaDoc
552       {
553          return NetBootHelper.buildListUrlForFolder (this.myLister.getHttpListerUrl (), this.folder);
554       }
555       
556       public URL JavaDoc getUrlForFile (NetBootFile file)
557          throws MalformedURLException JavaDoc
558       {
559          return new URL JavaDoc (NetBootHelper.buildDownloadUrlForFile (this.myLister.getDownloadUrl (),
560                                                                 this.folder,
561                                                                 file.getName ()));
562       }
563       
564    }
565     
566    protected class DeployedRemoteURL
567    {
568       HttpDeploymentFolder folder = null;
569       NetBootFile file = null;
570       
571       public DeployedRemoteURL (HttpDeploymentFolder folder, NetBootFile file)
572       {
573          this.folder = folder;
574          this.file = file;
575       }
576       
577       public HttpDeploymentFolder getFolder () { return this.folder; }
578       public NetBootFile getFile () { return this.file; }
579       
580       public void updateFile (NetBootFile newer) { this.file = newer; }
581    }
582
583 }
584
Popular Tags