KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jboss > deployers > plugins > deployment > MainDeployerImpl


1 /*
2 * JBoss, Home of Professional Open Source
3 * Copyright 2006, 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.deployers.plugins.deployment;
23
24 import static org.jboss.deployers.spi.structure.DeploymentState.DEPLOYED;
25 import static org.jboss.deployers.spi.structure.DeploymentState.DEPLOYING;
26 import static org.jboss.deployers.spi.structure.DeploymentState.ERROR;
27 import static org.jboss.deployers.spi.structure.DeploymentState.UNDEPLOYED;
28 import static org.jboss.deployers.spi.structure.DeploymentState.UNDEPLOYING;
29 import static org.jboss.deployers.spi.structure.StructureDetermined.NO;
30 import static org.jboss.deployers.spi.structure.StructureDetermined.PREDETERMINED;
31 import static org.jboss.deployers.spi.structure.StructureDetermined.YES;
32
33 import java.util.ArrayList JavaDoc;
34 import java.util.Collection JavaDoc;
35 import java.util.Collections JavaDoc;
36 import java.util.HashSet JavaDoc;
37 import java.util.List JavaDoc;
38 import java.util.Map JavaDoc;
39 import java.util.Set JavaDoc;
40 import java.util.SortedSet JavaDoc;
41 import java.util.TreeSet JavaDoc;
42 import java.util.concurrent.ConcurrentHashMap JavaDoc;
43 import java.util.concurrent.CopyOnWriteArrayList JavaDoc;
44 import java.util.concurrent.atomic.AtomicBoolean JavaDoc;
45
46 import org.jboss.deployers.plugins.deployer.AbstractDeploymentUnit;
47 import org.jboss.deployers.plugins.deployer.DeployerWrapper;
48 import org.jboss.deployers.plugins.structure.BasicStructuredDeployers;
49 import org.jboss.deployers.plugins.structure.DefaultStructureBuilder;
50 import org.jboss.deployers.plugins.structure.StructureMetaDataImpl;
51 import org.jboss.deployers.spi.DeploymentException;
52 import org.jboss.deployers.spi.deployer.Deployer;
53 import org.jboss.deployers.spi.deployer.DeploymentUnit;
54 import org.jboss.deployers.spi.deployment.MainDeployer;
55 import org.jboss.deployers.spi.structure.DeploymentContext;
56 import org.jboss.deployers.spi.structure.vfs.StructureBuilder;
57 import org.jboss.deployers.spi.structure.vfs.StructureDeployer;
58 import org.jboss.deployers.spi.structure.vfs.StructureMetaData;
59 import org.jboss.logging.Logger;
60 import org.jboss.virtual.VirtualFile;
61
62 /**
63  * MainDeployerImpl.
64  *
65  * TODO full deployer protocol
66  * TODO sort out a proper state machine
67  * @author <a HREF="adrian@jboss.com">Adrian Brock</a>
68  * @version $Revision: 1.1 $
69  */

70 public class MainDeployerImpl implements MainDeployer
71 {
72    /** The log */
73    private static final Logger log = Logger.getLogger(MainDeployerImpl.class);
74    
75    /** Whether we are shutdown */
76    private AtomicBoolean JavaDoc shutdown = new AtomicBoolean JavaDoc(false);
77    
78    /** The structure deployers */
79    private BasicStructuredDeployers structureDeployers = new BasicStructuredDeployers();
80
81    /** The structure builder that translates structure metadata to deployments */
82    private StructureBuilder structureBuilder = new DefaultStructureBuilder();
83
84    /** The deployers */
85    private SortedSet JavaDoc<Deployer> deployers = new TreeSet JavaDoc<Deployer>(Deployer.COMPARATOR);
86    
87    /** The deployments by name */
88    private Map JavaDoc<String JavaDoc, DeploymentContext> topLevelDeployments = new ConcurrentHashMap JavaDoc<String JavaDoc, DeploymentContext>();
89    
90    /** All deployments by name */
91    private Map JavaDoc<String JavaDoc, DeploymentContext> allDeployments = new ConcurrentHashMap JavaDoc<String JavaDoc, DeploymentContext>();
92    
93    /** Deployments in error by name */
94    private Map JavaDoc<String JavaDoc, DeploymentContext> errorDeployments = new ConcurrentHashMap JavaDoc<String JavaDoc, DeploymentContext>();
95    
96    /** Deployments missing deployers */
97    private Map JavaDoc<String JavaDoc, DeploymentContext> missingDeployers = new ConcurrentHashMap JavaDoc<String JavaDoc, DeploymentContext>();
98
99    /** The undeploy work */
100    private List JavaDoc<DeploymentContext> undeploy = new CopyOnWriteArrayList JavaDoc<DeploymentContext>();
101    
102    /** The deploy work */
103    private List JavaDoc<DeploymentContext> deploy = new CopyOnWriteArrayList JavaDoc<DeploymentContext>();
104    
105    /**
106     * Get the structure deployers
107     *
108     * @return the structure deployers
109     */

110    public synchronized Set JavaDoc<StructureDeployer> getStructureDeployers()
111    {
112       SortedSet JavaDoc<StructureDeployer> sdeployers = structureDeployers.getDeployers();
113       return sdeployers;
114    }
115
116    /**
117     * Set the structure deployers
118     *
119     * @param deployers the deployers
120     * @throws IllegalArgumentException for null deployers
121     */

122    public synchronized void setStructureDeployers(Set JavaDoc<StructureDeployer> deployers)
123    {
124       if (deployers == null)
125          throw new IllegalArgumentException JavaDoc("Null deployers");
126       structureDeployers.setDeployers(deployers);
127    }
128    
129    /**
130     * Add a structure deployer
131     *
132     * @param deployer the deployer
133     */

134    public synchronized void addStructureDeployer(StructureDeployer deployer)
135    {
136       if (deployer == null)
137          throw new IllegalArgumentException JavaDoc("Null deployer");
138       structureDeployers.addDeployer(deployer);
139       // TODO recheck failed deployments
140
log.debug("Added structure deployer: " + deployer);
141    }
142    
143    /**
144     * Remove a structure deployer
145     *
146     * @param deployer the deployer
147     */

148    public synchronized void removeStructureDeployer(StructureDeployer deployer)
149    {
150       if (deployer == null)
151          throw new IllegalArgumentException JavaDoc("Null deployer");
152       structureDeployers.removeDeployer(deployer);
153       log.debug("Remove structure deployer: " + deployer);
154       // TODO remove deployments for this structure?
155
}
156    
157    /**
158     * Get the deployers
159     *
160     * @return the deployers
161     */

162    public synchronized Set JavaDoc<Deployer> getDeployers()
163    {
164       return new TreeSet JavaDoc<Deployer>(deployers);
165    }
166    
167    /**
168     * Set the deployers
169     *
170     * @param deployers the deployers
171     * @throws IllegalArgumentException for null deployers
172     */

173    public synchronized void setDeployers(Set JavaDoc<Deployer> deployers)
174    {
175       if (deployers == null)
176          throw new IllegalArgumentException JavaDoc("Null deployers");
177       
178       // Remove all the old deployers that are not in the new set
179
HashSet JavaDoc<Deployer> oldDeployers = new HashSet JavaDoc<Deployer>(this.deployers);
180       oldDeployers.removeAll(deployers);
181       for (Deployer deployer : oldDeployers)
182          removeDeployer(deployer);
183       
184       // Add all the new deployers that were not already present
185
HashSet JavaDoc<Deployer> newDeployers = new HashSet JavaDoc<Deployer>(deployers);
186       newDeployers.removeAll(this.deployers);
187       for (Deployer deployer : newDeployers)
188          addDeployer(deployer);
189    }
190    
191    /**
192     * Add a deployer
193     *
194     * @param deployer the deployer
195     */

196    public synchronized void addDeployer(Deployer deployer)
197    {
198       if (deployer == null)
199          throw new IllegalArgumentException JavaDoc("Null deployer");
200       DeployerWrapper wrapper = new DeployerWrapper(deployer);
201       deployers.add(wrapper);
202       log.debug("Added deployer: " + deployer);
203       // TODO process existing deployments
204
}
205    
206    /**
207     * Remove a deployer
208     *
209     * @param deployer the deployer
210     */

211    public synchronized void removeDeployer(Deployer deployer)
212    {
213       if (deployer == null)
214          throw new IllegalArgumentException JavaDoc("Null deployer");
215       deployers.remove(deployer);
216       log.debug("Removed deployer: " + deployer);
217       // TODO unprocess existing deployments
218
}
219
220    public DeploymentContext getDeploymentContext(String JavaDoc name)
221    {
222       if (name == null)
223          throw new IllegalArgumentException JavaDoc("Null name");
224       return allDeployments.get(name);
225    }
226
227    public StructureBuilder getStructureBuilder()
228    {
229       return structureBuilder;
230    }
231    public void setStructureBuilder(StructureBuilder builder)
232    {
233       this.structureBuilder = builder;
234    }
235
236    public synchronized void addDeploymentContext(DeploymentContext context) throws DeploymentException
237    {
238       if (context == null)
239          throw new DeploymentException("Null context");
240       
241       if (shutdown.get())
242          throw new DeploymentException("The main deployer is shutdown");
243
244       log.debug("Add deployment context: " + context.getName());
245       
246       if (context.isTopLevel() == false)
247          throw new DeploymentException("Context is not a top level deployment: " + context.getName());
248       
249       String JavaDoc name = context.getName();
250       DeploymentContext previous = topLevelDeployments.get(name);
251       boolean topLevelFound = false;
252       if (previous != null)
253       {
254          log.debug("Removing previous deployment: " + previous.getName());
255          removeContext(previous);
256          topLevelFound = true;
257       }
258
259       if (topLevelFound == false)
260       {
261          previous = allDeployments.get(name);
262          if (previous != null)
263             throw new IllegalStateException JavaDoc("Deployment already exists as a subdeployment: " + context.getName());
264       }
265
266       reset(context);
267
268       topLevelDeployments.put(name, context);
269       try
270       {
271          determineStructure(context);
272       }
273       catch (Throwable JavaDoc t)
274       {
275          log.error("Unable to determine structure of deployment: " + name, t);
276          context.setState(ERROR);
277          context.setProblem(t);
278          errorDeployments.put(name, context);
279       }
280       
281       addContext(context);
282    }
283
284    public synchronized boolean removeDeploymentContext(String JavaDoc name) throws DeploymentException
285    {
286       if (name == null)
287          throw new DeploymentException("Null name");
288
289       if (shutdown.get())
290          throw new IllegalStateException JavaDoc("The main deployer is shutdown");
291
292       log.debug("Remove deployment context: " + name);
293       
294       DeploymentContext context = topLevelDeployments.remove(name);
295       if (context == null)
296          return false;
297       
298       removeContext(context);
299       
300       return true;
301    }
302
303    public Collection JavaDoc<DeploymentContext> getAll()
304    {
305       return Collections.unmodifiableCollection(allDeployments.values());
306    }
307
308    public Collection JavaDoc<DeploymentContext> getErrors()
309    {
310       return Collections.unmodifiableCollection(errorDeployments.values());
311    }
312
313    public Collection JavaDoc<DeploymentContext> getMissingDeployer()
314    {
315       return Collections.unmodifiableCollection(missingDeployers.values());
316    }
317
318    public Collection JavaDoc<DeploymentContext> getTopLevel()
319    {
320       return Collections.unmodifiableCollection(topLevelDeployments.values());
321    }
322
323    public void process()
324    {
325       if (shutdown.get())
326          throw new IllegalStateException JavaDoc("The main deployer is shutdown");
327
328       List JavaDoc<DeploymentContext> undeployContexts = null;
329       List JavaDoc<DeploymentContext> deployContexts = null;
330       Deployer[] theDeployers;
331       synchronized (this)
332       {
333          if (deployers.isEmpty())
334             throw new IllegalStateException JavaDoc("No deployers");
335          if (undeploy.isEmpty() == false)
336          {
337             // Undeploy in reverse order (subdeployments first)
338
undeployContexts = new ArrayList JavaDoc<DeploymentContext>(undeploy.size());
339             for (int i = undeploy.size() -1; i >= 0; --i)
340                undeployContexts.add(undeploy.get(i));
341             undeploy.clear();
342          }
343          if (deploy.isEmpty() == false)
344          {
345             deployContexts = new ArrayList JavaDoc<DeploymentContext>(deploy);
346             deploy.clear();
347          }
348          theDeployers = deployers.toArray(new Deployer[deployers.size()]);
349       }
350       
351       if (undeployContexts != null)
352       {
353          for (int i = theDeployers.length-1; i >= 0; --i)
354          {
355             Deployer deployer = theDeployers[i];
356             for (DeploymentContext context : undeployContexts)
357                prepareUndeploy(deployer, context, true);
358          }
359          for (DeploymentContext context : undeployContexts)
360          {
361             // TODO perform with the deployer that created the classloader?
362
context.removeClassLoader();
363
364             context.setState(UNDEPLOYED);
365             log.debug("Undeployed: " + context.getName());
366          }
367       }
368       
369       if (deployContexts != null)
370       {
371          for (int i = 0; i < theDeployers.length; ++i)
372          {
373             Deployer deployer = theDeployers[i];
374
375             Set JavaDoc<DeploymentContext> errors = new HashSet JavaDoc<DeploymentContext>();
376             for (DeploymentContext context : deployContexts)
377             {
378                try
379                {
380                   Set JavaDoc<DeploymentContext> components = context.getComponents();
381                   commitDeploy(deployer, context, components);
382                }
383                catch (DeploymentException e)
384                {
385                   context.setState(ERROR);
386                   context.setProblem(e);
387                   errors.add(context);
388                   errorDeployments.put(context.getName(), context);
389                   // Unwind the deployment
390
for (int j = i-1; j >= 0; --j)
391                   {
392                      Deployer other = theDeployers[j];
393                      prepareUndeploy(other, context, true);
394                   }
395                   context.removeClassLoader();
396                }
397             }
398             deployContexts.removeAll(errors);
399          }
400          for (DeploymentContext context : deployContexts)
401          {
402             String JavaDoc name = context.getName();
403             // TODO Need some metadata that says we expect a deployment to only provide classes
404
boolean isJar = false;
405             VirtualFile root = context.getRoot();
406             if (root != null && root.getName().endsWith(".jar"))
407                isJar = true;
408             if (context.isDeployed() == false && isJar == false)
409                missingDeployers.put(name, context);
410             context.setState(DEPLOYED);
411             log.debug("Deployed: " + name);
412          }
413       }
414    }
415
416    private void prepareUndeploy(Deployer deployer, DeploymentContext context, boolean doComponents)
417    {
418       DeploymentUnit unit = context.getDeploymentUnit();
419       deployer.prepareUndeploy(unit);
420       
421       if (doComponents)
422       {
423          Set JavaDoc<DeploymentContext> components = context.getComponents();
424          if (components != null && components.isEmpty() == false)
425          {
426             DeploymentContext[] theComponents = components.toArray(new DeploymentContext[components.size()]);
427             for (int i = theComponents.length-1; i >= 0; --i)
428                prepareUndeploy(deployer, theComponents[i], true);
429          }
430       }
431    }
432    
433    private void commitDeploy(Deployer deployer, DeploymentContext context, Set JavaDoc<DeploymentContext> components) throws DeploymentException
434    {
435       DeploymentContext[] theComponents = null;
436       if (components != null && components.isEmpty() == false)
437          theComponents = components.toArray(new DeploymentContext[components.size()]);
438       
439       DeploymentUnit unit = context.getDeploymentUnit();
440       deployer.commitDeploy(unit);
441       
442       try
443       {
444          if (theComponents != null)
445          {
446             for (int i = 0; i < theComponents.length; ++i)
447             {
448                try
449                {
450                   Set JavaDoc<DeploymentContext> componentComponents = theComponents[i].getComponents();
451                   commitDeploy(deployer, theComponents[i], componentComponents);
452                }
453                catch (DeploymentException e)
454                {
455                   // Unwind the previous components
456
for (int j = i-1; j >=0; --j)
457                      prepareUndeploy(deployer, theComponents[j], true);
458                   throw e;
459                }
460             }
461          }
462       }
463       catch (DeploymentException e)
464       {
465          prepareUndeploy(deployer, context, false);
466          throw e;
467       }
468    }
469    
470    public void shutdown()
471    {
472       while (topLevelDeployments.isEmpty() == false)
473       {
474          // Remove all the contexts
475
for (DeploymentContext context : topLevelDeployments.values())
476          {
477             topLevelDeployments.remove(context.getName());
478             removeContext(context);
479          }
480          
481          // Do it
482
process();
483       }
484       
485       shutdown.set(true);
486    }
487
488    /**
489     * Reset a deployment context
490     *
491     * @param context the context
492     * @throws IllegalArgumentException for a null context
493     */

494    protected void reset(DeploymentContext context)
495    {
496       if (context == null)
497          throw new IllegalArgumentException JavaDoc("Null context");
498
499       if (context.getStructureDetermined() == YES)
500          context.setStructureDetermined(NO);
501       context.setProblem(null);
502       context.reset();
503    }
504
505    /**
506     * Determine the deployment structure
507     *
508     * @param context the context
509     */

510    private void determineStructure(DeploymentContext context)
511       throws DeploymentException
512    {
513       if (context.getStructureDetermined() == PREDETERMINED)
514          return;
515
516       if (context.getRoot() == null)
517          throw new DeploymentException("Unable to determine structure context has not root " + context.getName());
518       
519       synchronized (this)
520       {
521          if (structureDeployers.isEmpty())
522             throw new IllegalStateException JavaDoc("No structure deployers");
523       }
524       VirtualFile root = context.getRoot();
525
526       // TODO: does the StructureMetaData impl need to be externalized?
527
StructureMetaData metaData = new StructureMetaDataImpl();
528       boolean result = structureDeployers.determineStructure(root, metaData);
529       if (result == false)
530          throw new DeploymentException("No structural deployer recognised the deployment. " + context.getName());
531       // Build the deployment context from the structure metadata
532
structureBuilder.populateContext(context, metaData);
533    }
534
535    /**
536     * Determine the structure
537     *
538     * @param context the context
539     * @param theDeployers the deployers
540     * @return true when determined
541     * @throws DeploymentException for any problem
542    private boolean determineStructure(DeploymentContext context) throws DeploymentException
543    {
544       boolean trace = log.isTraceEnabled();
545       if (trace)
546          log.trace("Trying to determine structure: " + context.getName());
547
548       boolean result = this.structureDeployers.determineStructure(context);
549       for (StructureDeployer deployer : theDeployers)
550       {
551          if (deployer.determineStructure(context, deployers))
552          {
553             result = true;
554             break;
555          }
556       }
557       if (result == false && context.isCandidate() == false)
558          throw new DeploymentException("No structural deployer recognised the deployment. " + context.getName());
559       
560       Set<DeploymentContext> children = context.getChildren();
561       for (DeploymentContext child : children)
562       {
563          if (child.getRoot() == null)
564             throw new DeploymentException("Unable to determine structure context has no root: " + context.getName());
565          
566          // This must be a candidate that doesn't match
567          if (determineStructure(child, theDeployers) == false)
568             context.removeChild(child);
569       }
570       
571       return result;
572    }
573    */

574    
575    /**
576     * Add a context
577     *
578     * @param context the context
579     */

580    private void addContext(DeploymentContext context)
581    {
582       allDeployments.put(context.getName(), context);
583       if (context.getState() == ERROR)
584       {
585          log.debug("Not scheduling addition of context already in error: " + context.getName());
586          return;
587       }
588       context.setDeploymentUnit(new AbstractDeploymentUnit(context));
589       context.setState(DEPLOYING);
590       log.debug("Scheduling deployment: " + context.getName());
591       deploy.add(context);
592       
593       // Add all the children
594
Set JavaDoc<DeploymentContext> children = context.getChildren();
595       if (children != null)
596       {
597          for (DeploymentContext child : children)
598             addContext(child);
599       }
600    }
601    
602    /**
603     * Remove a context
604     *
605     * @param context the context
606     */

607    private void removeContext(DeploymentContext context)
608    {
609       String JavaDoc name = context.getName();
610       allDeployments.remove(name);
611       errorDeployments.remove(name);
612       missingDeployers.remove(name);
613       if (context.getState() == ERROR)
614       {
615          log.debug("Not scheduling removal of context already in error: " + name);
616          return;
617       }
618       context.setState(UNDEPLOYING);
619       log.debug("Scheduling undeployment: " + name);
620       undeploy.add(context);
621       
622       // Remove all the children
623
Set JavaDoc<DeploymentContext> children = context.getChildren();
624       if (children != null)
625       {
626          for (DeploymentContext child : children)
627             removeContext(child);
628       }
629    }
630 }
631
Popular Tags