KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jboss > system > server > profileservice > VFSScanner


1 /*
2  * JBoss, Home of Professional Open Source
3  * Copyright 2005, JBoss Inc., and individual contributors as indicated
4  * by the @authors tag. See the copyright.txt in the distribution for a
5  * full listing of individual contributors.
6  *
7  * This is free software; you can redistribute it and/or modify it
8  * under the terms of the GNU Lesser General Public License as
9  * published by the Free Software Foundation; either version 2.1 of
10  * the License, or (at your option) any later version.
11  *
12  * This software is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this software; if not, write to the Free
19  * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20  * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
21  */

22 package org.jboss.system.server.profileservice;
23
24 import java.io.IOException JavaDoc;
25 import java.net.URI JavaDoc;
26 import java.net.URISyntaxException JavaDoc;
27 import java.util.ArrayList JavaDoc;
28 import java.util.Iterator JavaDoc;
29 import java.util.LinkedList JavaDoc;
30 import java.util.List JavaDoc;
31 import java.util.Map JavaDoc;
32 import java.util.StringTokenizer JavaDoc;
33 import java.util.concurrent.ConcurrentHashMap JavaDoc;
34 import java.util.concurrent.CopyOnWriteArrayList JavaDoc;
35
36 import org.jboss.deployers.spi.structure.DeploymentContext;
37 import org.jboss.profileservice.spi.Profile;
38 import org.jboss.profileservice.spi.ProfileKey;
39 import org.jboss.profileservice.spi.ProfileService;
40 import org.jboss.util.JBossObject;
41 import org.jboss.util.StringPropertyReplacer;
42 import org.jboss.virtual.VFS;
43 import org.jboss.virtual.VirtualFile;
44 import org.jboss.virtual.VirtualFileFilter;
45
46 /**
47  * A DeploymentScanner build on top of the VFS and ProfileService. This is a
48  * first pass to flesh out the APIs/concepts.
49  *
50  * @author <a HREF="mailto:dimitris@jboss.org">Dimitris Andreadis</a>
51  * @author Scott.Stark@jboss.org
52  * @author adrian@jboss.org
53  * @version $Revision$
54  */

55 public abstract class VFSScanner extends JBossObject
56 {
57    /** The profile service */
58    private ProfileService profileService;
59
60    /** The profile service key */
61    private ProfileKey profileKey;
62
63    /** The URIfied ServerHomeURL */
64    private URI JavaDoc serverHomeURI;
65    
66    /** The list of URIs to scan */
67    private List JavaDoc<URI JavaDoc> uriList = new CopyOnWriteArrayList JavaDoc<URI JavaDoc>();
68    
69    /** The list of VirtualFiles to scan */
70    private List JavaDoc<VirtualFile> vdfList = new CopyOnWriteArrayList JavaDoc<VirtualFile>();;
71    
72    /** Allow a filter for scanned directories */
73    private VirtualFileFilter filter;
74
75    /** Whether to search for files inside directories whose names containing no dots */
76    private boolean doRecursiveSearch = true;
77    
78    /** A map of deployed virtual files to their names */
79    private Map JavaDoc<VirtualFile, String JavaDoc> deployedSet = new ConcurrentHashMap JavaDoc<VirtualFile, String JavaDoc>();
80
81     /**
82     * Get the profileKey.
83     *
84     * @return the profileKey.
85     */

86    public ProfileKey getProfileKey()
87    {
88       return profileKey;
89    }
90
91    /**
92     * Set the profileKey.
93     *
94     * @param profileKey the profileKey.
95     */

96    public void setProfileKey(ProfileKey profileKey)
97    {
98       this.profileKey = profileKey;
99    }
100
101    /**
102     * Get the profileService.
103     *
104     * @return the profileService.
105     */

106    public ProfileService getProfileService()
107    {
108       return profileService;
109    }
110
111    /**
112     * Set the profileService.
113     *
114     * @param profileService the profileService.
115     */

116    public void setProfileService(ProfileService profileService)
117    {
118       this.profileService = profileService;
119    }
120
121    /**
122     * Set the uris
123     *
124     * @param listspec the uris
125     * @throws URISyntaxException
126     * @throws IOException
127     */

128    public void setURIs(final String JavaDoc listspec) throws URISyntaxException JavaDoc, IOException JavaDoc
129    {
130       if (listspec == null)
131       {
132          throw new NullPointerException JavaDoc("listspec argument cannot be null");
133       }
134       List JavaDoc<URI JavaDoc> list = new LinkedList JavaDoc<URI JavaDoc>();
135    
136       StringTokenizer JavaDoc stok = new StringTokenizer JavaDoc(listspec, ",");
137       while (stok.hasMoreTokens())
138       {
139          String JavaDoc urispec = stok.nextToken().trim();
140    
141          log.debug("Adding URI from spec: " + urispec);
142    
143          URI JavaDoc uri = makeURI(urispec);
144
145          log.debug("URI: " + uri);
146
147          list.add(uri);
148       }
149       setURIList(list);
150    }
151
152    /**
153     * Set the uri list
154     *
155     * @param list the list
156     * @throws IOException
157     */

158    public void setURIList(final List JavaDoc<URI JavaDoc> list) throws IOException JavaDoc
159    {
160       if (list == null)
161       {
162          throw new NullPointerException JavaDoc("list argument cannot be null");
163       }
164    
165       // start out with a fresh list
166
uriList.clear();
167    
168       for(int n = 0; n < list.size(); n ++)
169       {
170          URI JavaDoc uri = list.get(n);
171          if (uri == null)
172          {
173             throw new IllegalArgumentException JavaDoc("list element["+n+"] is null");
174          }
175          addURI(uri);
176       }
177       log.debug("URI list: " + uriList);
178    }
179
180    /**
181     * Get the uri list
182     *
183     * @return the list
184     */

185    public List JavaDoc<URI JavaDoc> getURIList()
186    {
187       return new ArrayList JavaDoc<URI JavaDoc>(uriList);
188    }
189
190    /**
191     * Set whether to do recursive search
192     *
193     * @param recurse true when recurisve
194     */

195    public void setRecursiveSearch(boolean recurse)
196    {
197       doRecursiveSearch = recurse;
198    }
199
200    /**
201     * Get the recursive search
202     *
203     * @return true when recursive
204     */

205    public boolean getRecursiveSearch()
206    {
207       return doRecursiveSearch;
208    }
209
210    /**
211     * Set the filter
212     *
213     * @param classname the filter class name
214     * @throws ClassNotFoundException when the class is not found
215     * @throws IllegalAccessException when the class's default constructor is not public
216     * @throws InstantiationException when there is an error constructing the class
217     */

218    public void setFilter(String JavaDoc classname)
219       throws ClassNotFoundException JavaDoc, IllegalAccessException JavaDoc, InstantiationException JavaDoc
220    {
221       ClassLoader JavaDoc loader = Thread.currentThread().getContextClassLoader();
222       Class JavaDoc<VirtualFileFilter> filterClass = (Class JavaDoc<VirtualFileFilter>) loader.loadClass(classname);
223       filter = filterClass.newInstance();
224    }
225
226    /**
227     * Get the filer
228     *
229     * @return the filter
230     */

231    public String JavaDoc getFilter()
232    {
233       if (filter == null)
234       {
235          return null;
236       }
237       return filter.getClass().getName();
238    }
239
240    /**
241     * Set the filter instance
242     *
243     * @param filter ther filter
244     */

245    public void setFilterInstance(VirtualFileFilter filter)
246    {
247       this.filter = filter;
248    }
249
250    /**
251     * Get the filter instance
252     *
253     * @return the filter
254     */

255    public VirtualFileFilter getFilterInstance()
256    {
257       return filter;
258    }
259
260    /**
261     * Add a uri
262     *
263     * @param uri the uri
264     * @throws IOException for an error accessing the uri
265     */

266    public void addURI(final URI JavaDoc uri) throws IOException JavaDoc
267    {
268       if (uri == null)
269       {
270          throw new NullPointerException JavaDoc("uri argument cannot be null");
271       }
272       if( uriList.add(uri) == true )
273       {
274          log.debug("Added URI: " + uri);
275          VirtualFile vf = getVFforURI(uri);
276          vdfList.add(vf);
277       }
278    }
279
280    /**
281     * Remove a uri
282     *
283     * @param uri the uri
284     * @throws IOException for an error accessing the uri
285     */

286    public void removeURI(final URI JavaDoc uri)
287       throws IOException JavaDoc
288    {
289       if (uri == null)
290       {
291          throw new NullPointerException JavaDoc("uri argument cannot be null");
292       }
293       VirtualFile vf = getVFforURI(uri);
294       vdfList.remove(vf);
295       boolean success = uriList.remove(uri);
296       
297       if (success)
298       {
299          log.debug("Removed URI: " + uri);
300       }
301    }
302
303    /**
304     * Whether it has the uri
305     *
306     * @param uri the uri
307     * @return when the uri is configured
308     */

309    public boolean hasURI(final URI JavaDoc uri)
310    {
311       if (uri == null)
312       {
313          throw new NullPointerException JavaDoc("uri argument cannot be null");
314       }
315       return uriList.contains(uri);
316    }
317
318    /**
319     * Start the scan
320     *
321     * @throws Exception for any error
322     */

323    public void start() throws Exception JavaDoc
324    {
325       // synchronize uriList and vdfList because only at this point
326
// setVirtualFileFactory() injection has been performed
327
vdfList.clear();
328       for (Iterator JavaDoc<URI JavaDoc> i = uriList.iterator(); i.hasNext(); )
329       {
330          URI JavaDoc uri = i.next();
331          VirtualFile vf = this.getVFforURI(uri);
332          vdfList.add(vf);
333       }
334       if( profileKey == null )
335       {
336          profileKey = new ProfileKey("default");
337       }
338       scan();
339    }
340
341    /**
342     * Scan
343     *
344     * @throws Exception for any error
345     */

346    public synchronized void scan() throws Exception JavaDoc
347    {
348       if (vdfList == null)
349       {
350          throw new IllegalStateException JavaDoc("not initialized");
351       }
352    
353       boolean trace = log.isTraceEnabled();
354     
355       // Scan for deployments
356
if (trace)
357       {
358          log.trace("Scanning for new deployments");
359       }
360
361       // VirtualFiles to deploy
362
List JavaDoc<VirtualFile> toDeployList = new LinkedList JavaDoc<VirtualFile>();
363       synchronized (vdfList)
364       {
365          for (Iterator JavaDoc i = vdfList.iterator(); i.hasNext();)
366          {
367             VirtualFile component = (VirtualFile)i.next();
368             if (component.isLeaf())
369             {
370                // treat this as a deployable unit
371
toDeployList.add(component);
372             }
373             else
374             {
375                // process (possibly recursively) the dir
376
addDeployments(toDeployList, component);
377             }
378          }
379       }
380       
381       if (trace)
382       {
383          log.trace("toDeployList");
384          for (Iterator JavaDoc i = toDeployList.iterator(); i.hasNext();)
385          {
386             log.trace(i.next());
387          }
388       }
389       LinkedList JavaDoc<VirtualFile> toRemoveList = new LinkedList JavaDoc<VirtualFile>();
390       LinkedList JavaDoc<VirtualFile> toCheckForUpdateList = new LinkedList JavaDoc<VirtualFile>();
391
392       synchronized (deployedSet)
393       {
394          // remove previously deployed URLs no longer needed
395
for (VirtualFile deployedComponent : deployedSet.keySet())
396          {
397             if (toDeployList.contains(deployedComponent))
398             {
399                toCheckForUpdateList.add(deployedComponent);
400             }
401             else
402             {
403                toRemoveList.add(deployedComponent);
404             }
405          }
406       }
407
408       // ********
409
// Undeploy
410
// ********
411

412       for (Iterator JavaDoc i = toRemoveList.iterator(); i.hasNext();)
413       {
414          VirtualFile deployedComponent = (VirtualFile)i.next();
415          undeploy(deployedComponent);
416       }
417
418       // ********
419
// Redeploy
420
// ********
421

422       // compute the DeployedURL list to update
423
ArrayList JavaDoc<VirtualFile> toUpdateList = new ArrayList JavaDoc<VirtualFile>(toCheckForUpdateList.size());
424       for (Iterator JavaDoc i = toCheckForUpdateList.iterator(); i.hasNext();)
425       {
426          VirtualFile deployedComponent = (VirtualFile)i.next();
427          if (isModified(deployedComponent))
428          {
429             if (trace)
430             {
431                log.trace("Re-deploying " + deployedComponent);
432             }
433             toUpdateList.add(deployedComponent);
434          }
435       }
436
437       // sort to update list
438
//Collections.sort(toUpdateList, sorter);
439

440       // Undeploy in order
441
for (int i = toUpdateList.size() - 1; i >= 0; i--)
442       {
443          VirtualFile vf = toUpdateList.get(i);
444          undeploy(vf);
445       }
446
447       // Deploy in order
448
for (int i = 0; i < toUpdateList.size(); i++)
449       {
450          VirtualFile vf = toUpdateList.get(i);
451          deploy(vf);
452       }
453    
454       // ******
455
// Deploy
456
// ******
457

458       //Collections.sort(toDeployList, sorter);
459
for (Iterator JavaDoc i = toDeployList.iterator(); i.hasNext();)
460       {
461          VirtualFile component = (VirtualFile)i.next();
462          
463          // if component is not deployed already, deploy it
464
if (!deployedSet.containsKey(component))
465          {
466             deploy(component);
467          }
468
469          // component must have been deployed by now, so remove it from list
470
i.remove();
471          
472          /* Check to see if mainDeployer suffix list has changed, if so, then resort
473          if (i.hasNext() && updateSorter())
474          {
475             Collections.sort(toDeployList, sorter);
476             i = toDeployList.iterator();
477          }
478          */

479       }
480    
481       /* TODO: Validate that there are still incomplete deployments
482       if (lastIncompleteDeploymentException != null)
483       {
484          try
485          {
486             Object[] args = {};
487             String[] sig = {};
488             getServer().invoke(getDeployer(), "checkIncompleteDeployments", args, sig);
489          }
490          catch (Exception e)
491          {
492             Throwable t = JMXExceptionDecoder.decode(e);
493             log.error(t);
494          }
495       }
496       */

497    }
498
499    /**
500     * Make a uri
501     *
502     * @param urispec the uri spec
503     * @return the uri
504     * @throws URISyntaxException for an error parsing he uri
505     */

506    private URI JavaDoc makeURI(String JavaDoc urispec) throws URISyntaxException JavaDoc
507    {
508       // First replace URI with appropriate properties
509
urispec = StringPropertyReplacer.replaceProperties(urispec);
510       return serverHomeURI.resolve(urispec);
511    }
512    
513    /**
514     * A helper to find all deployments under a directory component
515     * and add them to the supplied list.
516     *
517     * We may recurse.
518     *
519     * @param list the list of virtual files
520     * @param root the root file
521     * @throws IOException for any error
522     */

523    private void addDeployments(List JavaDoc<VirtualFile> list, VirtualFile root)
524       throws IOException JavaDoc
525    {
526       List JavaDoc<VirtualFile> components = root.getChildren();
527       
528       for (VirtualFile component : components)
529       {
530          // Filter the component regardless of its type
531
if( filter != null && filter.accepts(component) == false)
532             continue;
533          if (component.isLeaf())
534          {
535             list.add(component);
536          }
537          // TODO replace . in the name with isArchive() == false?
538
else if (component.getName().indexOf('.') == -1 && this.doRecursiveSearch)
539          {
540             // recurse if not '.' in name and recursive search is enabled
541
addDeployments(list, component);
542          }
543          else
544          {
545             list.add(component);
546          }
547       }
548    }
549
550    /**
551     * A helper to deploy the given component using the deployer.
552     *
553     * @param component the virtual file
554     */

555    private void deploy(final VirtualFile component)
556    {
557       // If the deployer is null simply ignore the request
558
if (profileService == null)
559       {
560          return;
561       }
562       if (log.isTraceEnabled())
563       {
564          log.trace("Deploying: " + component);
565       }
566
567       DeploymentContext deployment = null;
568       try
569       {
570          Profile profile = profileService.getProfile(profileKey);
571          deployment = add(profile, component);
572       }
573       catch (Exception JavaDoc e)
574       {
575          log.debug("Failed to deploy: " + component, e);
576       }
577
578       /* TODO
579       String watchPath = getWatchURL(deployment);
580       VirtualFile watchComponent = null;
581       long deployedLastModified = -1;
582       try
583       {
584          if (watchPath != null)
585          {
586             watchComponent = component.findChild(watchPath);
587             deployedLastModified = watchComponent.getLastModified();
588          }
589          else
590          {
591             deployedLastModified = component.getLastModified();
592          }
593       }
594       catch (IOException e)
595       {
596          log.warn(e);
597       }
598       component.setContext(new ComponentContext(watchComponent, deployedLastModified));
599       */

600    
601       if (!deployedSet.containsKey(component))
602       {
603          deployedSet.put(component, deployment.getName());
604       }
605    }
606    
607    /**
608     * A helper to undeploy the given component using the deployer.
609     *
610     * @param component the component
611     */

612    private void undeploy(final VirtualFile component)
613    {
614       try
615       {
616          if (log.isTraceEnabled())
617          {
618             log.trace("Undeploying: " + component);
619          }
620          String JavaDoc name = deployedSet.remove(component);
621          Profile profile = profileService.getProfile(profileKey);
622          remove(profile, name);
623       }
624       catch (Exception JavaDoc e)
625       {
626          log.error("Failed to undeploy: " + component, e);
627       }
628    }
629    
630    /**
631     * Remove the component
632     *
633     * @param profile the profile
634     * @param file the virtual file
635     * @return the deployment context or null if not added, e.g. it already exists
636     * @throws Exception for any error
637     */

638    protected abstract DeploymentContext add(Profile profile, VirtualFile file) throws Exception JavaDoc;
639    
640    /**
641     * Remove the component
642     *
643     * @param profile the profile
644     * @param name the name
645     */

646    protected abstract void remove(Profile profile, String JavaDoc name);
647    
648    /**
649     * Helper to get the watchURL for a deployment, if different.
650     * Returns null otherwise
651     *
652     * @param deployment the deployment
653     * @return the watch url
654     */

655    /* TODO
656    private String getWatchURL(DeploymentContext deployment)
657    {
658       String watchPath = (String) deployment.getPredeterminedManagedObjects().getAttachment("WATCH_URL");
659       return watchPath;
660    }
661    /*/

662
663    /**
664     * Helper to find out if a deployed component has been modified
665     * TODO: How should this be implemented
666     *
667     * @param component the component
668     * @return true when modified
669     * @throws IOException for any error accessing the file
670     */

671    public boolean isModified(VirtualFile component) throws IOException JavaDoc
672    {
673       // get the context stored with every deployed component
674
ComponentContext cc = null; //(ComponentContext)component.getContext();
675

676       // get modification time at the time of deployment
677
long deployedLastModified = cc.deployedLastModified;
678       
679       // find out the current lastModified time either from
680
// the component or the watched component, if exists
681
long lastModified = (cc.watchComponent != null) ? cc.watchComponent.getLastModified()
682                                                       : component.getLastModified();
683
684        return deployedLastModified != lastModified;
685     }
686    
687    private VirtualFile getVFforURI(URI JavaDoc uri)
688       throws IOException JavaDoc
689    {
690       VFS vfs = VFS.getVFS(uri);
691       return vfs.getRoot();
692    }
693
694    /**
695     * Simple holder class to let us store extra info
696     * on a VirtualFile object
697     */

698    private static class ComponentContext
699    {
700       public VirtualFile watchComponent;
701       public long deployedLastModified;
702       
703       public ComponentContext(VirtualFile watchComponent, long deployedLastModified)
704       {
705          this.watchComponent = watchComponent;
706          this.deployedLastModified = deployedLastModified;
707       }
708    }
709 }
710
Popular Tags