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
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
282 if (kernel != null) {
283 return kernel;
284 }
285
286
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
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
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
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
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
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,
397 planFile,
398 moduleFile,
399 null,
400 Boolean.TRUE,
401 null,
402 null,
403 null,
404 null,
405 null,
406 null,
407 null,
408 targetConfigStore
409 };
410
411 return (List) kernel.invoke(deployer, "deploy", args, ARG_TYPES);
412 }
413 }