001 /** 002 * Copyright 2005 The Apache Software Foundation 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017 package org.apache.geronimo.plugin.car; 018 019 import java.io.File; 020 import java.net.URI; 021 import java.util.Collection; 022 import java.util.HashSet; 023 import java.util.Iterator; 024 import java.util.List; 025 import java.util.Set; 026 027 import org.apache.commons.logging.Log; 028 import org.apache.commons.logging.LogFactory; 029 import org.apache.geronimo.gbean.AbstractName; 030 import org.apache.geronimo.gbean.AbstractNameQuery; 031 import org.apache.geronimo.gbean.GBeanData; 032 import org.apache.geronimo.gbean.GBeanInfo; 033 import org.apache.geronimo.gbean.ReferencePatterns; 034 import org.apache.geronimo.kernel.Kernel; 035 import org.apache.geronimo.kernel.KernelFactory; 036 import org.apache.geronimo.kernel.KernelRegistry; 037 import org.apache.geronimo.kernel.Naming; 038 import org.apache.geronimo.kernel.config.ConfigurationData; 039 import org.apache.geronimo.kernel.config.ConfigurationManager; 040 import org.apache.geronimo.kernel.config.ConfigurationUtil; 041 import org.apache.geronimo.kernel.config.KernelConfigurationManager; 042 import org.apache.geronimo.kernel.log.GeronimoLogging; 043 import org.apache.geronimo.kernel.management.State; 044 import org.apache.geronimo.kernel.repository.Artifact; 045 import org.apache.geronimo.kernel.repository.DefaultArtifactManager; 046 import org.apache.geronimo.system.resolver.ExplicitDefaultArtifactResolver; 047 048 /** 049 * Builds a Geronimo Configuration using the local Maven infrastructure. 050 * 051 * @version $Rev:385659 $ $Date: 2006-08-12 12:22:18 +0200 (sam., 12 août 2006) $ 052 */ 053 public class PackageBuilder 054 { 055 private static final String KERNEL_NAME = "geronimo.maven"; 056 057 private static final String[] ARG_TYPES = { 058 boolean.class.getName(), 059 File.class.getName(), 060 File.class.getName(), 061 File.class.getName(), 062 Boolean.TYPE.getName(), 063 String.class.getName(), 064 String.class.getName(), 065 String.class.getName(), 066 String.class.getName(), 067 String.class.getName(), 068 String.class.getName(), 069 String.class.getName(), 070 String.class.getName(), 071 }; 072 073 private static final Log log = LogFactory.getLog(PackageBuilder.class); 074 075 /** 076 * Reference to the kernel that will last the lifetime of this classloader. 077 * The KernelRegistry keeps soft references that may be garbage collected. 078 */ 079 private static Kernel kernel; 080 081 private static AbstractName targetConfigStoreAName; 082 083 private static AbstractName targetRepositoryAName; 084 085 private String repositoryClass; 086 087 private String configurationStoreClass; 088 089 private String targetRepositoryClass; 090 091 private String targetConfigurationStoreClass; 092 093 private File repository; 094 095 private File targetRepository; 096 097 private Collection deploymentConfigs; 098 099 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 }