View Javadoc

1   /**
2    *  Copyright 2005 The Apache Software Foundation
3    *
4    *  Licensed under the Apache License, Version 2.0 (the "License");
5    *  you may not use this file except in compliance with the License.
6    *  You may obtain a copy of the License at
7    *
8    *     http://www.apache.org/licenses/LICENSE-2.0
9    *
10   *  Unless required by applicable law or agreed to in writing, software
11   *  distributed under the License is distributed on an "AS IS" BASIS,
12   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   *  See the License for the specific language governing permissions and
14   *  limitations under the License.
15   */
16  
17  package org.apache.geronimo.plugin.car;
18  
19  import java.io.File;
20  import java.net.URI;
21  import java.util.Collection;
22  import java.util.HashSet;
23  import java.util.Iterator;
24  import java.util.List;
25  import java.util.Set;
26  
27  import org.apache.commons.logging.Log;
28  import org.apache.commons.logging.LogFactory;
29  import org.apache.geronimo.gbean.AbstractName;
30  import org.apache.geronimo.gbean.AbstractNameQuery;
31  import org.apache.geronimo.gbean.GBeanData;
32  import org.apache.geronimo.gbean.GBeanInfo;
33  import org.apache.geronimo.gbean.ReferencePatterns;
34  import org.apache.geronimo.kernel.Kernel;
35  import org.apache.geronimo.kernel.KernelFactory;
36  import org.apache.geronimo.kernel.KernelRegistry;
37  import org.apache.geronimo.kernel.Naming;
38  import org.apache.geronimo.kernel.config.ConfigurationData;
39  import org.apache.geronimo.kernel.config.ConfigurationManager;
40  import org.apache.geronimo.kernel.config.ConfigurationUtil;
41  import org.apache.geronimo.kernel.config.KernelConfigurationManager;
42  import org.apache.geronimo.kernel.log.GeronimoLogging;
43  import org.apache.geronimo.kernel.management.State;
44  import org.apache.geronimo.kernel.repository.Artifact;
45  import org.apache.geronimo.kernel.repository.DefaultArtifactManager;
46  import org.apache.geronimo.system.resolver.ExplicitDefaultArtifactResolver;
47  
48  /**
49   * Builds a Geronimo Configuration using the local Maven infrastructure.
50   *
51   * @version $Rev:385659 $ $Date: 2006-08-12 12:22:18 +0200 (sam., 12 août 2006) $
52   */
53  public class PackageBuilder
54  {
55      private static final String KERNEL_NAME = "geronimo.maven";
56  
57      private static final String[] ARG_TYPES = {
58          boolean.class.getName(),
59          File.class.getName(),
60          File.class.getName(),
61          File.class.getName(),
62          Boolean.TYPE.getName(),
63          String.class.getName(),
64          String.class.getName(),
65          String.class.getName(),
66          String.class.getName(),
67          String.class.getName(),
68          String.class.getName(),
69          String.class.getName(),
70          String.class.getName(),
71      };
72  
73      private static final Log log = LogFactory.getLog(PackageBuilder.class);
74  
75      /**
76       * Reference to the kernel that will last the lifetime of this classloader.
77       * The KernelRegistry keeps soft references that may be garbage collected.
78       */
79      private static Kernel kernel;
80  
81      private static AbstractName targetConfigStoreAName;
82  
83      private static AbstractName targetRepositoryAName;
84  
85      private String repositoryClass;
86  
87      private String configurationStoreClass;
88  
89      private String targetRepositoryClass;
90  
91      private String targetConfigurationStoreClass;
92  
93      private File repository;
94  
95      private File targetRepository;
96  
97      private Collection deploymentConfigs;
98  
99      private AbstractName deployerName;
100 
101     private File planFile;
102 
103     private File moduleFile;
104 
105     private File packageFile;
106 
107     private String explicitResolutionLocation;
108 
109     private boolean targetSet;
110 
111     public String getRepositoryClass() {
112         return repositoryClass;
113     }
114 
115     public void setRepositoryClass(final String repositoryClass) {
116         this.repositoryClass = repositoryClass;
117     }
118 
119     public String getConfigurationStoreClass() {
120         return configurationStoreClass;
121     }
122 
123     public void setConfigurationStoreClass(final String configurationStoreClass) {
124         this.configurationStoreClass = configurationStoreClass;
125     }
126 
127     public File getRepository() {
128         return repository;
129     }
130 
131     public void setRepository(final File repository) {
132         this.repository = repository;
133     }
134 
135     public String getTargetRepositoryClass() {
136         return targetRepositoryClass;
137     }
138 
139     public void setTargetRepositoryClass(final String targetRepositoryClass) {
140         this.targetRepositoryClass = targetRepositoryClass;
141     }
142 
143     public String getTargetConfigurationStoreClass() {
144         return targetConfigurationStoreClass;
145     }
146 
147     public void setTargetConfigurationStoreClass(final String targetConfigurationStoreClass) {
148         this.targetConfigurationStoreClass = targetConfigurationStoreClass;
149     }
150 
151     public File getTargetRepository() {
152         return targetRepository;
153     }
154 
155     public void setTargetRepository(final File targetRepository) {
156         this.targetRepository = targetRepository;
157     }
158 
159     public Collection getDeploymentConfig() {
160         return deploymentConfigs;
161     }
162 
163     /**
164      * Set the id of the Configuration to use to perform the packaging.
165      *
166      * @param deploymentConfigString comma-separated list of the ids of the Configurations performing the deployment
167      */
168     public void setDeploymentConfig(final Collection deploymentConfigString) {
169         this.deploymentConfigs = deploymentConfigString;
170     }
171 
172     public String getDeployerName() {
173         return deployerName.toString();
174     }
175 
176     /**
177      * Set the name of the GBean that is the Deployer.
178      *
179      * @param deployerName the name of the Deployer GBean
180      */
181     public void setDeployerName(final String deployerName) {
182         this.deployerName = new AbstractName(URI.create(deployerName));
183     }
184 
185     public File getPlanFile() {
186         return planFile;
187     }
188 
189     /**
190      * Set the File that is the deployment plan.
191      *
192      * @param planFile the deployment plan
193      */
194     public void setPlanFile(final File planFile) {
195         this.planFile = planFile;
196     }
197 
198     public File getModuleFile() {
199         return moduleFile;
200     }
201 
202     /**
203      * Set the File that is the module being deployed.
204      *
205      * @param moduleFile the module to deploy
206      */
207     public void setModuleFile(final File moduleFile) {
208         this.moduleFile = moduleFile;
209     }
210 
211     public File getPackageFile() {
212         return packageFile;
213     }
214 
215     /**
216      * Set the File where the Configuration will be stored; normally the artifact being produced.
217      *
218      * @param packageFile the package file to produce
219      */
220     public void setPackageFile(final File packageFile) {
221         this.packageFile = packageFile;
222     }
223 
224     public String getExplicitResolutionLocation() {
225         return explicitResolutionLocation;
226     }
227 
228     public void setExplicitResolutionLocation(final String explicitResolutionLocation) {
229         this.explicitResolutionLocation = explicitResolutionLocation;
230     }
231 
232     public void execute() throws Exception {
233         System.out.println("Packaging module configuration: " + planFile);
234 
235         try {
236             Kernel kernel = createKernel();
237             if (!targetSet) {
238                 setTargetConfigStore();
239             }
240 
241             // start the Configuration we're going to use for this deployment
242             ConfigurationManager configurationManager = ConfigurationUtil.getConfigurationManager(kernel);
243             try {
244                 for (Iterator iterator = deploymentConfigs.iterator(); iterator.hasNext();) {
245                     String artifactName = (String) iterator.next();
246                     Artifact configName = Artifact.create(artifactName);
247                     if (!configurationManager.isLoaded(configName)) {
248                         configurationManager.loadConfiguration(configName);
249                         configurationManager.startConfiguration(configName);
250                     }
251                 }
252             } finally {
253                 ConfigurationUtil.releaseConfigurationManager(kernel, configurationManager);
254             }
255 
256             AbstractName deployer = locateDeployer(kernel);
257             invokeDeployer(kernel, deployer, targetConfigStoreAName.toString());
258         }
259         catch (Exception e) {
260             log.error(e.getClass().getName() + ": " + e.getMessage(), e);
261             throw e;
262         }
263     }
264 
265     private void setTargetConfigStore() throws Exception {
266         kernel.stopGBean(targetRepositoryAName);
267         kernel.setAttribute(targetRepositoryAName, "root", targetRepository.toURI());
268         kernel.startGBean(targetRepositoryAName);
269 
270         if (kernel.getGBeanState(targetConfigStoreAName) != State.RUNNING_INDEX) {
271             throw new IllegalStateException("After restarted repository then config store is not running");
272         }
273 
274         targetSet = true;
275     }
276 
277     /**
278      * Create a Geronimo Kernel to contain the deployment configurations.
279      */
280     private synchronized Kernel createKernel() throws Exception {
281         // first return our cached version
282         if (kernel != null) {
283             return kernel;
284         }
285 
286         // check the registry in case someone else created one
287         kernel = KernelRegistry.getKernel(KERNEL_NAME);
288         if (kernel != null) {
289             return kernel;
290         }
291 
292         GeronimoLogging geronimoLogging = GeronimoLogging.getGeronimoLogging("WARN");
293         if (geronimoLogging == null) {
294             geronimoLogging = GeronimoLogging.DEBUG;
295         }
296         GeronimoLogging.initialize(geronimoLogging);
297 
298         // boot one ourselves
299         kernel = KernelFactory.newInstance().createKernel(KERNEL_NAME);
300         kernel.boot();
301 
302         bootDeployerSystem();
303 
304         return kernel;
305     }
306 
307     /**
308      * Boot the in-Maven deployment system.
309      *
310      * This contains Repository and ConfigurationStore GBeans that map to
311      * the local maven installation.
312      */
313     private void bootDeployerSystem() throws Exception {
314         Artifact baseId = new Artifact("geronimo", "packaging", "fixed", "car");
315         Naming naming = kernel.getNaming();
316         ConfigurationData bootstrap = new ConfigurationData(baseId, naming);
317         ClassLoader cl = PackageBuilder.class.getClassLoader();
318         Set repoNames = new HashSet();
319 
320         // Source repo
321         GBeanData repoGBean = bootstrap.addGBean("SourceRepository", GBeanInfo.getGBeanInfo(repositoryClass, cl));
322         URI repositoryURI = repository.toURI();
323         repoGBean.setAttribute("root", repositoryURI);
324         repoNames.add(repoGBean.getAbstractName());
325 
326         // Target repo
327         GBeanData targetRepoGBean = bootstrap.addGBean("TargetRepository", GBeanInfo.getGBeanInfo(targetRepositoryClass, cl));
328         URI targetRepositoryURI = targetRepository.toURI();
329         targetRepoGBean.setAttribute("root", targetRepositoryURI);
330         repoNames.add(targetRepoGBean.getAbstractName());
331         targetRepositoryAName = targetRepoGBean.getAbstractName();
332 
333         GBeanData artifactManagerGBean = bootstrap.addGBean("ArtifactManager", DefaultArtifactManager.GBEAN_INFO);
334         GBeanData artifactResolverGBean = bootstrap.addGBean("ArtifactResolver", ExplicitDefaultArtifactResolver.GBEAN_INFO);
335         artifactResolverGBean.setAttribute("versionMapLocation", explicitResolutionLocation);
336         ReferencePatterns repoPatterns = new ReferencePatterns(repoNames);
337         artifactResolverGBean.setReferencePatterns("Repositories", repoPatterns);
338         artifactResolverGBean.setReferencePattern("ArtifactManager", artifactManagerGBean.getAbstractName());
339 
340         Set storeNames = new HashSet();
341 
342         // Source config store
343         GBeanInfo configStoreInfo = GBeanInfo.getGBeanInfo(configurationStoreClass, cl);
344         GBeanData storeGBean = bootstrap.addGBean("ConfigStore", configStoreInfo);
345         if (configStoreInfo.getReference("Repository") != null) {
346             storeGBean.setReferencePattern("Repository", repoGBean.getAbstractName());
347         }
348         storeNames.add(storeGBean.getAbstractName());
349 
350         // Target config store
351         GBeanInfo targetConfigStoreInfo = GBeanInfo.getGBeanInfo(targetConfigurationStoreClass, cl);
352         GBeanData targetStoreGBean = bootstrap.addGBean("TargetConfigStore", targetConfigStoreInfo);
353         if (targetConfigStoreInfo.getReference("Repository") != null) {
354             targetStoreGBean.setReferencePattern("Repository", targetRepoGBean.getAbstractName());
355         }
356         storeNames.add(targetStoreGBean.getAbstractName());
357 
358         targetConfigStoreAName = targetStoreGBean.getAbstractName();
359         targetSet = true;
360 
361         GBeanData attrManagerGBean = bootstrap.addGBean("AttributeStore", MavenAttributeStore.GBEAN_INFO);
362         GBeanData configManagerGBean = bootstrap.addGBean("ConfigManager", KernelConfigurationManager.GBEAN_INFO);
363         configManagerGBean.setReferencePatterns("Stores", new ReferencePatterns(storeNames));
364         configManagerGBean.setReferencePattern("AttributeStore", attrManagerGBean.getAbstractName());
365         configManagerGBean.setReferencePattern("ArtifactManager", artifactManagerGBean.getAbstractName());
366         configManagerGBean.setReferencePattern("ArtifactResolver", artifactResolverGBean.getAbstractName());
367         configManagerGBean.setReferencePatterns("Repositories", repoPatterns);
368 
369         ConfigurationUtil.loadBootstrapConfiguration(kernel, bootstrap, cl);
370     }
371 
372     /**
373      * Locate a Deployer GBean matching the deployerName pattern.
374      *
375      * @param kernel the kernel to search.
376      * @return the ObjectName of the Deployer GBean
377      *
378      * @throws IllegalStateException if there is not exactly one GBean matching the deployerName pattern
379      */
380     private AbstractName locateDeployer(final Kernel kernel) {
381         Iterator i = kernel.listGBeans(new AbstractNameQuery(deployerName)).iterator();
382         if (!i.hasNext()) {
383             throw new IllegalStateException("No deployer found matching deployerName: " + deployerName);
384         }
385 
386         AbstractName deployer = (AbstractName) i.next();
387         if (i.hasNext()) {
388             throw new IllegalStateException("Multiple deployers found matching deployerName: " + deployerName);
389         }
390 
391         return deployer;
392     }
393 
394     private List invokeDeployer(final Kernel kernel, final AbstractName deployer, final String targetConfigStore) throws Exception {
395         Object[] args = {
396             Boolean.FALSE, // Not in-place
397             planFile,
398             moduleFile,
399             null, // Target file
400             Boolean.TRUE, // Install
401             null, // main-class
402             null, // main-gbean
403             null, // main-method
404             null, // Manifest configurations
405             null, // class-path
406             null, // endorsed-dirs
407             null, // extension-dirs
408             targetConfigStore
409         };
410 
411         return (List) kernel.invoke(deployer, "deploy", args, ARG_TYPES);
412     }
413 }