KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jboss > services > deployment > DeploymentManager


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.services.deployment;
23
24 import java.io.BufferedWriter JavaDoc;
25 import java.io.File JavaDoc;
26 import java.io.FileFilter JavaDoc;
27 import java.io.FileInputStream JavaDoc;
28 import java.io.FileOutputStream JavaDoc;
29 import java.io.FileWriter JavaDoc;
30 import java.io.IOException JavaDoc;
31 import java.io.InputStream JavaDoc;
32 import java.io.OutputStream JavaDoc;
33 import java.io.PrintWriter JavaDoc;
34 import java.io.StringBufferInputStream JavaDoc;
35 import java.io.StringWriter JavaDoc;
36 import java.net.URL JavaDoc;
37 import java.util.ArrayList JavaDoc;
38 import java.util.Collection JavaDoc;
39 import java.util.Collections JavaDoc;
40 import java.util.HashMap JavaDoc;
41 import java.util.Iterator JavaDoc;
42 import java.util.List JavaDoc;
43 import java.util.Map JavaDoc;
44 import java.util.Set JavaDoc;
45 import java.util.TreeMap JavaDoc;
46 import java.util.TreeSet JavaDoc;
47
48 import javax.management.ObjectName JavaDoc;
49
50 import org.apache.velocity.VelocityContext;
51 import org.apache.velocity.app.VelocityEngine;
52 import org.jboss.deployment.DeploymentInfo;
53 import org.jboss.logging.Logger;
54 import org.jboss.mx.util.MBeanServerLocator;
55 import org.jboss.services.deployment.metadata.ConfigInfo;
56 import org.jboss.services.deployment.metadata.ConfigInfoBinding;
57 import org.jboss.services.deployment.metadata.PropertyInfo;
58 import org.jboss.services.deployment.metadata.TemplateInfo;
59 import org.jboss.system.server.ServerConfig;
60 import org.jboss.system.server.ServerConfigLocator;
61 import org.jboss.util.file.Files;
62 import org.jboss.varia.deployment.convertor.XslTransformer;
63 import org.jboss.xb.binding.ObjectModelFactory;
64 import org.jboss.xb.binding.Unmarshaller;
65 import org.jboss.xb.binding.UnmarshallerFactory;
66
67 /**
68  * Class handling JBoss module generation. Uses apache velocity
69  * for generating deployment descriptors.
70  *
71  * @author <a HREF="mailto:dimitris@jboss.org">Dimitris Andreadis</a>
72  * @author <a HREF="mailto:peter.johnson2@unisys.com">Peter Johnson</a>
73  *
74  * @version $Revision: 42540 $
75  */

76 public class DeploymentManager
77 {
78    // Constants -----------------------------------------------------
79

80    /** the filename to look for in template subdirectories */
81    public static final String JavaDoc TEMPLATE_CONFIG_FILE = "template-config.xml";
82
83    /** an object to pass back from the template to trigger an error */
84    public static final String JavaDoc TEMPLATE_ERROR_PARAM = "template-error";
85
86    /** a helper object to pass in to the template */
87    public static final String JavaDoc CONTEXT_HELPER = "helper";
88
89    /** jndi name of main deployer, used to locate configuration files for mbeans */
90    private static final String JavaDoc MAIN_DEPLOYER_OBJECT_NAME = "jboss.system:service=MainDeployer";
91
92    /** name of operation used to locate configuration files for mbeans */
93    private static final String JavaDoc MAIN_DEPLOYER_LIST_OPERATION_NAME = "listDeployed";
94
95    // Private Data --------------------------------------------------
96

97    /** Logger */
98    private Logger log;
99
100    /** directory to hold the template subdirectories */
101    private File JavaDoc templateDir;
102
103    /** the directory to output generated modules */
104    private File JavaDoc undeployDir;
105
106    /** the directory to move modules for deployment */
107    private File JavaDoc deployDir;
108
109    /** config name string -> ConfigInfo */
110    private Map JavaDoc configMap;
111
112    /** the apache velocity engine */
113    VelocityEngine ve;
114
115    /**
116     * @param templateDir the root dir where templates are stored
117     * @param packageDir the directory to store generated packages
118     */

119    public DeploymentManager(String JavaDoc templateDir, String JavaDoc undeployDir, String JavaDoc deployDir, Logger log)
120       throws Exception JavaDoc
121    {
122       this.log = log;
123
124       // do the actuall initialization
125
initialize(templateDir, undeployDir, deployDir);
126    }
127
128    // Public Interface ----------------------------------------------
129

130    /**
131     * Return the list of available templates
132     */

133    public Set JavaDoc listModuleTemplates()
134    {
135       Set JavaDoc keys = configMap.keySet();
136
137       synchronized(configMap)
138       {
139          // return a new sorted copy
140
return new TreeSet JavaDoc(keys);
141       }
142    }
143
144    /**
145     * Get property metadata information for a particular template
146     *
147     * @param template
148     * @return list with PropertyInfo objects associated with the template
149     * @throws Exception if the template does not exist
150     */

151    public List JavaDoc getTemplatePropertyInfo(String JavaDoc template)
152       throws Exception JavaDoc
153    {
154       ConfigInfo ci = (ConfigInfo)configMap.get(template);
155
156       if (ci == null)
157       {
158          throw new Exception JavaDoc("template does not exist: " + template);
159       }
160       else
161       { // return a copy
162
List JavaDoc propertyList = ci.getPropertyInfoList();
163          List JavaDoc newList = new ArrayList JavaDoc(propertyList.size());
164
165          for (Iterator JavaDoc i = propertyList.iterator(); i.hasNext();)
166          {
167             newList.add(new PropertyInfo((PropertyInfo)i.next()));
168          }
169          return newList;
170       }
171    }
172
173    public String JavaDoc createModule(String JavaDoc module, String JavaDoc template, HashMap JavaDoc properties)
174       throws Exception JavaDoc
175    {
176       if (module == null || template == null || properties == null)
177          throw new Exception JavaDoc("Null argument: module=" + module +
178                                           ", template=" + template + ", properties=" + properties);
179
180       // make sure proposed module name is filesystem friendly
181
if (!module.equals(Files.encodeFileName(module)))
182          throw new Exception JavaDoc("not a filesystem friendly module name: " + module);
183
184       log.info("createModule(module=" + module +
185             ", template=" + template + ", properties=" + properties + ")");
186
187       ConfigInfo ci = (ConfigInfo)configMap.get(template);
188
189       if (ci == null)
190          throw new Exception JavaDoc("template does not exist: " + template);
191
192       // get optional package extension (e.g. .sar)
193
// and enforce it on the output package (file or directory)
194
File JavaDoc outputModule;
195
196       String JavaDoc extension = ci.getExtension();
197       if (extension == null || module.endsWith(extension))
198          outputModule = new File JavaDoc(this.undeployDir, module);
199       else
200          outputModule = new File JavaDoc(this.undeployDir, module + extension);
201
202       // check if module already exists in output dir
203
if (outputModule.exists())
204          throw new Exception JavaDoc("module already exist: " + outputModule);
205
206       String JavaDoc vmTemplate = ci.getTemplate();
207
208       // make sure we clean-up in case something goes wrong
209
try
210       {
211          // simple case - single descriptor package (e.g. xxx-service.xml)
212
if (vmTemplate != null )
213          {
214             VelocityContext ctx = createTemplateContext(ci, properties);
215
216             BufferedWriter JavaDoc out = new BufferedWriter JavaDoc(new FileWriter JavaDoc(outputModule));
217
218             try {
219                boolean success = ve.mergeTemplate(template + '/' + vmTemplate, ctx, out);
220
221                if (success == true)
222                {
223                   String JavaDoc errorMsg = (String JavaDoc)ctx.get(TEMPLATE_ERROR_PARAM);
224
225                   if (errorMsg.length() > 0)
226                      throw new Exception JavaDoc("Template error: " + errorMsg);
227                   else
228                      log.debug("created module '" + outputModule.getName() + "' based on template '" + template + "'");
229                }
230                else
231                   throw new Exception JavaDoc("Failed to create module '" + outputModule.getName());
232             }
233             finally
234             {
235                out.close();
236             }
237          }
238          else
239          {
240             // complex case - many descriptors and possibly files to copy
241
// now output will be a directory instead of a plain descriptor (e.g. xxx.sar)
242
VelocityContext ctx = createTemplateContext(ci, properties);
243
244             // deep copy files if copydir specified
245
String JavaDoc copydir = ci.getCopydir();
246
247             File JavaDoc sourceDir = new File JavaDoc(this.templateDir, template + '/' + copydir);
248
249             deepCopy(sourceDir, outputModule);
250
251             // go through all declared templates
252
List JavaDoc templateList = ci.getTemplateInfoList();
253
254             for (Iterator JavaDoc i = templateList.iterator(); i.hasNext(); )
255             {
256                TemplateInfo ti = (TemplateInfo)i.next();
257
258                File JavaDoc outputFile = new File JavaDoc(outputModule, ti.getOutput());
259                File JavaDoc outputPath = outputFile.getParentFile();
260
261                if (!outputPath.exists())
262                   if (!outputPath.mkdirs())
263                      throw new IOException JavaDoc("cannot create directory: " + outputPath);
264
265                BufferedWriter JavaDoc out = new BufferedWriter JavaDoc(new FileWriter JavaDoc(outputFile));
266
267                try {
268                   boolean success = ve.mergeTemplate(template + '/' + ti.getInput(), ctx, out);
269
270                   if (success == true)
271                   {
272                      String JavaDoc errorMsg = (String JavaDoc)ctx.get(TEMPLATE_ERROR_PARAM);
273
274                      if (errorMsg.length() > 0)
275                         throw new Exception JavaDoc("Template error: " + errorMsg);
276                      else
277                         log.debug("created module '" + outputModule.getName() + "' based on template '" + template + "'");
278                   }
279
280                   else
281                      throw new Exception JavaDoc("Failed to create package '" + outputModule.getName());
282                }
283                finally
284                {
285                   out.close();
286                }
287             }
288          }
289       }
290       catch (Exception JavaDoc e)
291       {
292          if (outputModule.exists())
293          {
294             boolean deleted = Files.delete(outputModule);
295             if (!deleted)
296                log.warn("Failed to clean-up erroneous module: " + outputModule);
297          }
298          throw e;
299       }
300       return outputModule.getName();
301    }
302
303    /**
304     * Remove a module if exists
305     *
306     * @param module the module to remove
307     * @return true if removed, false if module does not exist or an error occurs
308     */

309    public boolean removeModule(String JavaDoc module)
310    {
311       File JavaDoc target = new File JavaDoc(this.undeployDir, module);
312       return Files.delete(target);
313    }
314
315    /**
316     * @see org.jboss.services.deployment.DeploymentServiceMBean#updateMBean
317     */

318    public boolean updateMBean(MBeanData data) throws Exception JavaDoc
319    {
320       // Verify necessary parameters passed.
321
if (data == null)
322          throw new Exception JavaDoc("Null argument: data=" + data);
323       if (data.getName() == null || data.getTemplateName() == null
324           || data.getName().length() == 0 || data.getTemplateName().length() == 0
325          )
326          throw new Exception JavaDoc("Null required data: name=" + data.getName() + ", templateName=" + data.getTemplateName());
327       boolean result = true;
328
329       // Log the data passed.
330
if (log.isDebugEnabled())
331       {
332          log.debug("updateMBean(" + data + ")");
333          log.debug(" template=" + data.getTemplateName());
334          log.debug(" depends=" + data.getDepends());
335          log.debug(" attributes=" + data.getAttributes());
336          log.debug(" xpath=" + data.getXpath());
337       }
338
339       // Get the template to use, and ensure we have it:
340
String JavaDoc template = data.getTemplateName();
341       ConfigInfo ci = (ConfigInfo)configMap.get(template);
342       if (ci == null)
343          throw new Exception JavaDoc("template does not exist: " + template);
344
345       // Determine which configuration XML file holds the data for the
346
// specified MBean:
347
String JavaDoc configPath = configPathFor(data.getName());
348       log.debug("configPath=" + configPath);
349       if (configPath == null)
350          throw new Exception JavaDoc("No configuration file found for mbean " + data);
351
352       HashMap JavaDoc map = new HashMap JavaDoc();
353       map.put("mbean", data);
354
355       updateConfigFile(data.getName(), template, map, ci, configPath);
356
357       return result;
358    }
359
360    /**
361     * @see org.jboss.services.deployment.DeploymentServiceMBean#updateDataSource
362     */

363    public String JavaDoc updateDataSource(String JavaDoc module, String JavaDoc template, HashMap JavaDoc properties) throws Exception JavaDoc
364    {
365       if (module == null || template == null || properties == null)
366          throw new Exception JavaDoc("Null argument: module=" + module + ", template=" + template + ", properties="
367                + properties);
368
369       log.info("updateDataSource(module=" + module + ", template=" + template + ", properties=" + properties + ")");
370
371       // Append the suffix '-update' to the template if necessary
372
if (!template.endsWith("-update"))
373          template += "-update";
374
375       module = processDataSourceChanges(module, template, properties);
376
377       return module;
378    }
379
380    /**
381     * @see org.jboss.services.deployment.DeploymentServiceMBean#removeDataSource
382     */

383    public String JavaDoc removeDataSource(String JavaDoc module, String JavaDoc template, HashMap JavaDoc properties) throws Exception JavaDoc
384    {
385       if (module == null || template == null || properties == null)
386          throw new Exception JavaDoc("Null argument: module=" + module + ", template=" + template + ", properties="
387                + properties);
388
389       log.info("removeDataSource(module=" + module + ", template=" + template + ", properties=" + properties + ")");
390
391       // Append the suffix '-remove' to the template if necessary
392
if (!template.endsWith("-remove"))
393          template += "-remove";
394
395       module = processDataSourceChanges(module, template, properties);
396
397       return module;
398    }
399
400
401    /**
402     * Search for the configuration file that contains the specified MBean.
403     *
404     * @param name The MBean name, or a pattern that can be used to match an
405     * mbean name.
406     * @return The full path name for the configuration file.
407     */

408    public String JavaDoc configPathFor(String JavaDoc name) throws Exception JavaDoc
409    {
410       if (log.isDebugEnabled()) log.debug("configPathFor(" + name + ")");
411       String JavaDoc result = null;
412
413       // Get the collection of mbean deployment info objects:
414
Collection JavaDoc deploymentColl = (Collection JavaDoc) MBeanServerLocator.locateJBoss().invoke(
415             new ObjectName JavaDoc(MAIN_DEPLOYER_OBJECT_NAME), MAIN_DEPLOYER_LIST_OPERATION_NAME, null, null);
416
417       // Iterate through that collection, looking for the one that contains an
418
// mbean whose name matches the name (or pattern) provided:
419
ObjectName JavaDoc pattern = new ObjectName JavaDoc(name);
420       outer: for (Iterator JavaDoc iter = deploymentColl.iterator(); iter.hasNext();)
421       {
422          DeploymentInfo deploymentInfo = (DeploymentInfo) iter.next();
423          List JavaDoc associatedMBeanObjectNames = deploymentInfo.mbeans;
424          for (Iterator JavaDoc iterator = associatedMBeanObjectNames.iterator(); iterator.hasNext();)
425          {
426             ObjectName JavaDoc beanName = (ObjectName JavaDoc) iterator.next();
427             if (log.isDebugEnabled()) log.debug("beanName=" + beanName);
428             if (pattern.apply(beanName)) {
429                   result = deploymentInfo.watch.getFile();
430                   break outer;
431             }
432          }
433       }
434
435       if (log.isDebugEnabled()) log.debug("configPathFor()=" + result);
436       return result;
437    }
438
439    public void moveToDeployDir(String JavaDoc module)
440       throws Exception JavaDoc
441    {
442       File JavaDoc source = new File JavaDoc(this.undeployDir, module);
443       File JavaDoc target = new File JavaDoc(this.deployDir, module);
444
445       if (source.exists())
446       {
447          boolean moved = source.renameTo(target);
448          if (!moved)
449             throw new Exception JavaDoc("cannot move module: " + module);
450       }
451       else
452          throw new Exception JavaDoc("module does not exist: " + module);
453    }
454
455    public void moveToModuleDir(String JavaDoc module)
456       throws Exception JavaDoc
457    {
458       File JavaDoc source = new File JavaDoc(this.deployDir, module);
459       File JavaDoc target = new File JavaDoc(this.undeployDir, module);
460
461       if (source.exists())
462       {
463          boolean moved = source.renameTo(target);
464          if (!moved)
465             throw new Exception JavaDoc("cannot move module: " + module);
466       }
467       else
468          throw new Exception JavaDoc("module does not exist: " + module);
469    }
470
471    public URL JavaDoc getDeployedURL(String JavaDoc module)
472       throws Exception JavaDoc
473    {
474       File JavaDoc target = new File JavaDoc(this.deployDir, module);
475
476       if (!target.exists())
477          throw new Exception JavaDoc("module does not exist: " + target);
478
479       return target.toURL();
480    }
481
482    public URL JavaDoc getUndeployedURL(String JavaDoc module)
483       throws Exception JavaDoc
484    {
485       File JavaDoc target = new File JavaDoc(this.undeployDir, module);
486
487       if (!target.exists())
488          throw new Exception JavaDoc("module does not exist: " + target);
489
490       return target.toURL();
491    }
492
493    // Private Methods -----------------------------------------------
494

495    /**
496     * Performs the actual initialization
497     */

498    private void initialize(String JavaDoc templateDir, String JavaDoc undeployDir, String JavaDoc deployDir)
499       throws Exception JavaDoc
500    {
501       log.debug("DeploymentManager.initialize()");
502       // Find out template dir
503
this.templateDir = initDir(templateDir, false);
504       log.debug("template dir=" + this.templateDir);
505
506       // Initialize output dir
507
this.undeployDir = initDir(undeployDir, true);
508       log.debug("undeployDir dir=" + this.undeployDir);
509
510       this.deployDir = initDir(deployDir, false);
511       log.debug("deploy dir=" + this.deployDir);
512
513       // Discover all template config files
514
List JavaDoc configFiles = findTemplateConfigFiles(this.templateDir);
515
516       log.debug("template config files=" + configFiles);
517
518       Map JavaDoc map = Collections.synchronizedMap(new TreeMap JavaDoc());
519
520       // Parse each template config file and store metadata in configMap
521
for (Iterator JavaDoc i = configFiles.iterator(); i.hasNext(); ) {
522          File JavaDoc file = (File JavaDoc)i.next();
523          ConfigInfo ci = parseXMLconfig(file);
524
525          // derive template name from subdirectory name
526
ci.setName(file.getParentFile().getName());
527
528          if (log.isTraceEnabled())
529             log.trace("file: " + file + " ConfigInfo: " + ci);
530
531          Object JavaDoc existingValue = map.put(ci.getName(), ci);
532
533          // make sure not two configuration templates with the same name
534
if (existingValue != null)
535             throw new Exception JavaDoc("Duplicate template configuration entry: " + ci.getName());
536       }
537
538       this.configMap = map;
539
540       // Initialise velocity engine
541
this.ve = new VelocityEngine();
542
543       this.ve.setProperty("runtime.log.logsystem.class",
544                              "org.apache.velocity.runtime.log.SimpleLog4JLogSystem");
545       this.ve.setProperty("runtime.log.logsystem.log4j.category",
546                              log.getName() + ".VelocityEngine");
547       this.ve.setProperty("file.resource.loader.path", this.templateDir.getCanonicalPath());
548       this.ve.setProperty("stringliterals.interpolate", "false");
549
550       this.ve.init();
551    }
552
553    /**
554     * Check if directory exists as an absolute path,
555     * otherwise, try to find it under the jboss server
556     * directories (and optionally create it, if the
557     * create flag has been set)
558     */

559    private File JavaDoc initDir(String JavaDoc targetDir, boolean create)
560       throws Exception JavaDoc
561    {
562       File JavaDoc dir = null;
563
564      // Check if this is an existing absolute path
565
try {
566         URL JavaDoc fileURL = new URL JavaDoc(targetDir);
567
568         File JavaDoc file = new File JavaDoc(fileURL.getFile());
569
570         if(file.isDirectory() && file.canRead() && file.canWrite()) {
571            dir = file;
572         }
573      }
574      catch(Exception JavaDoc e) {
575        // Otherwise, try to see inside the jboss directory hierarchy
576

577         File JavaDoc homeDir = ServerConfigLocator.locate().getServerHomeDir();
578
579         dir = new File JavaDoc(homeDir, targetDir);
580
581         if (create == true)
582            dir.mkdirs();
583
584         if (!dir.isDirectory())
585            throw new Exception JavaDoc("The target directory is not valid: "
586                                + dir.getCanonicalPath());
587      }
588      return dir;
589    }
590
591    /**
592     * Find all files named TEMPLATE_CONFIG_FILE
593     * one level below basedir, i.e.
594     *
595     * basedir/YYY/template-config.xml
596     * ...
597     *
598     * @param basedir
599     * @return
600     */

601    private List JavaDoc findTemplateConfigFiles(File JavaDoc basedir)
602    {
603       // return val
604
List JavaDoc files = new ArrayList JavaDoc();
605
606       // anonymous class
607
FileFilter JavaDoc dirFilter = new FileFilter JavaDoc()
608       {
609          public boolean accept(File JavaDoc file)
610          {
611             return file.isDirectory() && !file.getName().startsWith(".");
612          }
613       };
614       // return all dirs not starting with "."
615
File JavaDoc[] dirs = basedir.listFiles(dirFilter);
616
617       for (int i = 0; i < dirs.length; i++) {
618          File JavaDoc file = new File JavaDoc(dirs[i], TEMPLATE_CONFIG_FILE);
619
620          if (file.isFile() && file.canRead())
621             files.add(file);
622       }
623       return files;
624    }
625
626    /**
627     * Parse an XML template config file into
628     * a ConfigInfo POJO model.
629     *
630     * @param file
631     * @return
632     * @throws Exception
633     */

634    private ConfigInfo parseXMLconfig(File JavaDoc file)
635       throws Exception JavaDoc
636    {
637       // get the XML stream
638
InputStream JavaDoc is = new FileInputStream JavaDoc(file);
639
640       // create unmarshaller
641
Unmarshaller unmarshaller = UnmarshallerFactory.newInstance().newUnmarshaller();
642
643       // create an instance of ObjectModelFactory
644
ObjectModelFactory factory = new ConfigInfoBinding();
645
646       // let the object model factory to create an instance of Book and populate it with data from XML
647
ConfigInfo ci = (ConfigInfo)unmarshaller.unmarshal(is, factory, null);
648
649       // close the XML stream
650
is.close();
651
652       return ci;
653    }
654
655    /**
656     * Copy values from HashMap to VelocityContext, following the
657     * metadata definition. Make sure types are correct, while
658     * required properties are all there. Throw an exception
659     * otherwise
660     *
661     * @param ci
662     * @param map
663     * @return
664     * @throws Exception
665     */

666    private VelocityContext createTemplateContext(ConfigInfo ci, HashMap JavaDoc map)
667       throws Exception JavaDoc
668    {
669       VelocityContext vc;
670
671       List JavaDoc propertyList = ci.getPropertyInfoList();
672
673       if (propertyList.size() > 0)
674       {
675          vc = new VelocityContext();
676
677          for (Iterator JavaDoc i = propertyList.iterator(); i.hasNext(); ) {
678             PropertyInfo pi = (PropertyInfo)i.next();
679
680             String JavaDoc name = pi.getName();
681             String JavaDoc type = pi.getType();
682             boolean optional = pi.isOptional();
683             Object JavaDoc defaultValue = pi.getDefaultValue();
684
685             if (name == null || name.length() == 0 || type == null || type.length() == 0)
686                throw new Exception JavaDoc("Null or empty name/type property metadata for template: " + ci.getName());
687
688             Object JavaDoc sentValue = map.get(name);
689
690             // a value was sent - pass it over after checking its type
691
if (sentValue != null)
692             {
693                if (!type.equals(sentValue.getClass().getName()))
694                   throw new Exception JavaDoc("Expected type '" + type + "' for property '" + name +
695                                       "', got '" + sentValue.getClass().getName());
696
697                vc.put(name, sentValue);
698             }
699             else if (optional == false) {
700                // a value was not sent - property is required
701
// so use the default value (if exists) or throw an exception
702
if (defaultValue != null) {
703                   vc.put(name, defaultValue);
704                }
705                else {
706                   throw new Exception JavaDoc("Required property missing: '" + name + "' of type '" + type + "'");
707                }
708             }
709             // property is optional and value was not sent
710
// do nothing even if a default is set
711
}
712       }
713       else
714       {
715          // property list empty, allow everything
716
// just embed the Hashmap
717
vc = new VelocityContext(map);
718       }
719       // add a parameter to allow the templates to report errors
720
vc.put(TEMPLATE_ERROR_PARAM, "");
721       // add a context helper
722
vc.put(CONTEXT_HELPER, new ContextHelper());
723
724       return vc;
725    }
726
727    /**
728     * Make sure sourceDir exist, then deep copy
729     * all files/dirs from sourceDir to targetDir
730     *
731     * @param sourceDir
732     * @param targetDir
733     */

734    private void deepCopy(File JavaDoc sourceDir, File JavaDoc targetDir)
735       throws IOException JavaDoc
736    {
737       if (!sourceDir.isDirectory())
738          throw new IOException JavaDoc("sourceDir not a directory: " + sourceDir);
739
740       if (!targetDir.mkdir())
741          throw new IOException JavaDoc("could not create directory: " + targetDir);
742
743       File JavaDoc[] files = sourceDir.listFiles();
744
745       for (int i = 0; i < files.length; i++)
746       {
747          File JavaDoc source = files[i];
748
749          if (!source.canRead())
750             throw new IOException JavaDoc("cannot read: " + source);
751
752          if (source.isFile())
753             Files.copy(source, new File JavaDoc(targetDir, source.getName()));
754          else
755             deepCopy(source, new File JavaDoc(targetDir, source.getName()));
756       }
757    }
758
759    /**
760     * Process the data source change request based on the specified template
761     * and the input properties.
762     *
763     * @param module
764     * @param template
765     * @param properties
766     * @return The full module name, with the suffix.
767     * @throws Exception
768     */

769    private String JavaDoc processDataSourceChanges (String JavaDoc module, String JavaDoc template, HashMap JavaDoc properties) throws Exception JavaDoc
770    {
771       ConfigInfo ci = (ConfigInfo) configMap.get(template);
772       if (ci == null)
773          throw new Exception JavaDoc("template does not exist: " + template);
774
775       // Append the extension if the module name does not contain it
776
String JavaDoc extension = ci.getExtension();
777       if (extension != null && !module.endsWith(extension))
778          module += extension;
779
780       // Build the mbean name from the jndi name. Note that we are actually building
781
// a pattern, any mbean whose name matches this pattern will do.
782
String JavaDoc path = configPathFor("jboss.jca:name=" + (String JavaDoc)properties.get("jndi-name") + ",*");
783
784       updateConfigFile(module, template, properties, ci, path);
785
786       return module;
787    }
788
789    /**
790     * Constructs the XSLT from the Velocity template, performas the tranformation,
791     * and then copies the resulting configuration file to the proper location,
792     * overwriting the existing configuration file.
793     * @param name Identifier used in error message should the deploy fail
794     * @param template The name of the template to use. This should be a Velocity
795     * template that generates an XSTL script.
796     * @param map The properties to use with Velocity.
797     * @param ci The configuration information for the template being used.
798     * @param path Full path name of the current configuration file. This file will
799     * be run through the XSL transform and be overwritten by the result.
800     */

801    private void updateConfigFile(String JavaDoc name, String JavaDoc template, HashMap JavaDoc map, ConfigInfo ci, String JavaDoc path)
802       throws Exception JavaDoc
803    {
804       String JavaDoc vmTemplate = ci.getTemplate();
805
806       // Generate the XSLT based on the properties and the template:
807
StringWriter JavaDoc sw = new StringWriter JavaDoc();
808       PrintWriter JavaDoc xslt = new PrintWriter JavaDoc(sw);
809       VelocityContext ctx = createTemplateContext(ci, map);
810       String JavaDoc tp = template + File.separator + vmTemplate;
811       ve.mergeTemplate(tp, ctx, xslt);
812       StringBuffer JavaDoc buf = sw.getBuffer();
813       xslt.close();
814
815       // Update the configuration XML file using the generated XSLT. For now,
816
// place the generated file into the undeploy directory:
817
File JavaDoc configFile = new File JavaDoc(path);
818       File JavaDoc outputFile = new File JavaDoc(this.undeployDir, configFile.getName());
819       InputStream JavaDoc configStream = new FileInputStream JavaDoc(configFile);
820       InputStream JavaDoc xsltStream = new StringBufferInputStream JavaDoc(buf.toString());
821       OutputStream JavaDoc outputStream = new FileOutputStream JavaDoc(outputFile);
822       XslTransformer.applyTransformation(configStream, outputStream, xsltStream, null);
823       configStream.close();
824       xsltStream.close();
825       outputStream.close();
826
827       // Now that we have the generated file, move it to its proper location
828
if (!configFile.delete())
829          throw new Exception JavaDoc("Update failed for '" + name + "', unable to delete old configuration file: " + path);
830       if (!outputFile.renameTo(configFile))
831          throw new Exception JavaDoc("Update failed for '" + name + "', unable to move configuration file to deploy directory: " + path);
832    }
833 }
834
Popular Tags