1 8 package org.apache.avalon.phoenix.components.deployer; 9 10 import java.io.File ; 11 import java.io.IOException ; 12 import java.net.MalformedURLException ; 13 import java.net.URL ; 14 import java.util.Hashtable ; 15 import java.util.Map ; 16 import java.util.Set ; 17 import java.util.Arrays ; 18 import org.apache.avalon.excalibur.i18n.ResourceManager; 19 import org.apache.avalon.excalibur.i18n.Resources; 20 import org.apache.avalon.excalibur.io.FileUtil; 21 import org.apache.avalon.framework.activity.Disposable; 22 import org.apache.avalon.framework.activity.Initializable; 23 import org.apache.avalon.framework.configuration.Configuration; 24 import org.apache.avalon.framework.configuration.ConfigurationException; 25 import org.apache.avalon.framework.logger.AbstractLogEnabled; 26 import org.apache.avalon.framework.logger.Logger; 27 import org.apache.avalon.framework.parameters.ParameterException; 28 import org.apache.avalon.framework.parameters.Parameterizable; 29 import org.apache.avalon.framework.parameters.Parameters; 30 import org.apache.avalon.framework.service.ServiceException; 31 import org.apache.avalon.framework.service.ServiceManager; 32 import org.apache.avalon.framework.service.Serviceable; 33 import org.apache.avalon.phoenix.components.deployer.installer.Installation; 34 import org.apache.avalon.phoenix.components.deployer.installer.InstallationException; 35 import org.apache.avalon.phoenix.components.deployer.installer.Installer; 36 import org.apache.avalon.phoenix.interfaces.Application; 37 import org.apache.avalon.phoenix.interfaces.ClassLoaderManager; 38 import org.apache.avalon.phoenix.interfaces.ConfigurationRepository; 39 import org.apache.avalon.phoenix.interfaces.ConfigurationValidator; 40 import org.apache.avalon.phoenix.interfaces.Deployer; 41 import org.apache.avalon.phoenix.interfaces.DeployerMBean; 42 import org.apache.avalon.phoenix.interfaces.DeploymentException; 43 import org.apache.avalon.phoenix.interfaces.Kernel; 44 import org.apache.avalon.phoenix.interfaces.LogManager; 45 import org.apache.avalon.phoenix.metadata.BlockListenerMetaData; 46 import org.apache.avalon.phoenix.metadata.BlockMetaData; 47 import org.apache.avalon.phoenix.metadata.SarMetaData; 48 import org.apache.avalon.phoenix.metainfo.BlockDescriptor; 49 import org.apache.avalon.phoenix.tools.assembler.Assembler; 50 import org.apache.avalon.phoenix.tools.assembler.AssemblyException; 51 import org.apache.avalon.phoenix.tools.configuration.ConfigurationBuilder; 52 import org.apache.avalon.phoenix.tools.verifier.SarVerifier; 53 import org.apache.avalon.phoenix.tools.verifier.VerifyException; 54 55 60 public class DefaultDeployer 61 extends AbstractLogEnabled 62 implements Deployer, Parameterizable, Serviceable, Initializable, Disposable, DeployerMBean 63 { 64 private static final Resources REZ = 65 ResourceManager.getPackageResources( DefaultDeployer.class ); 66 67 private final Assembler m_assembler = new Assembler(); 68 private final SarVerifier m_verifier = new SarVerifier(); 69 private final Installer m_installer = new Installer(); 70 private final Map m_installations = new Hashtable (); 71 private LogManager m_logManager; 72 private Kernel m_kernel; 73 private ConfigurationRepository m_repository; 74 private ClassLoaderManager m_classLoaderManager; 75 private ConfigurationValidator m_validator; 76 77 83 private File m_baseWorkDirectory; 84 85 88 private File m_baseDirectory; 89 90 96 public void parameterize( final Parameters parameters ) 97 throws ParameterException 98 { 99 final String phoenixHome = parameters.getParameter( "phoenix.home" ); 100 final String defaultWorkDir = phoenixHome + File.separator + "work"; 101 final String defaultAppsDir = phoenixHome + File.separator + "apps"; 102 final String rawWorkDir = 103 parameters.getParameter( "phoenix.work.dir", defaultWorkDir ); 104 final String rawAppsDir = 105 parameters.getParameter( "phoenix.apps.dir", defaultAppsDir ); 106 107 final File workDir = new File ( rawWorkDir ); 108 try 109 { 110 m_baseWorkDirectory = workDir.getCanonicalFile(); 111 } 112 catch( final IOException ioe ) 113 { 114 m_baseWorkDirectory = workDir.getAbsoluteFile(); 115 } 116 117 final File appsDir = new File ( rawAppsDir ); 118 try 119 { 120 m_baseDirectory = appsDir.getCanonicalFile(); 121 } 122 catch( final IOException ioe ) 123 { 124 m_baseDirectory = appsDir.getAbsoluteFile(); 125 } 126 } 127 128 134 public void service( final ServiceManager serviceManager ) 135 throws ServiceException 136 { 137 m_kernel = (Kernel)serviceManager.lookup( Kernel.ROLE ); 138 m_repository = (ConfigurationRepository)serviceManager. 139 lookup( ConfigurationRepository.ROLE ); 140 m_classLoaderManager = (ClassLoaderManager)serviceManager. 141 lookup( ClassLoaderManager.ROLE ); 142 m_logManager = (LogManager)serviceManager.lookup( LogManager.ROLE ); 143 m_validator = (ConfigurationValidator)serviceManager.lookup( ConfigurationValidator.ROLE ); 144 } 145 146 public void initialize() 147 throws Exception 148 { 149 initWorkDirectory(); 150 try 151 { 152 FileUtil.cleanDirectory( m_baseWorkDirectory ); 153 } 154 catch( final IOException ioe ) 155 { 156 final String message = 157 REZ.getString( "nodelete-workdir.error", 158 m_baseWorkDirectory, 159 ioe.getMessage() ); 160 getLogger().warn( message, ioe ); 161 } 162 163 setupLogger( m_installer ); 164 setupLogger( m_assembler ); 165 setupLogger( m_verifier ); 166 m_installer.setBaseDirectory( m_baseDirectory ); 167 m_installer.setBaseWorkDirectory( m_baseWorkDirectory ); 168 } 169 170 174 public void dispose() 175 { 176 final Set set = m_installations.keySet(); 177 final String [] applications = 178 (String [])set.toArray( new String [ set.size() ] ); 179 for( int i = 0; i < applications.length; i++ ) 180 { 181 final String name = applications[ i ]; 182 try 183 { 184 undeploy( name ); 185 } 186 catch( final DeploymentException de ) 187 { 188 final String message = 189 REZ.getString( "deploy.undeploy-indispose.error", 190 name, 191 de.getMessage() ); 192 getLogger().error( message, de ); 193 } 194 } 195 } 196 197 203 public void redeploy( final String name ) 204 throws DeploymentException 205 { 206 final Installation installation = 207 (Installation)m_installations.get( name ); 208 if( null == installation ) 209 { 210 final String message = 211 REZ.getString( "deploy.no-deployment.error", name ); 212 throw new DeploymentException( message ); 213 } 214 try 215 { 216 final URL location = installation.getSource().toURL(); 217 undeploy( name ); 218 deploy( name, location ); 219 } 220 catch( final Exception e ) 221 { 222 throw new DeploymentException( e.getMessage(), e ); 223 } 224 } 225 226 232 public void undeploy( final String name ) 233 throws DeploymentException 234 { 235 final Installation installation = 236 (Installation)m_installations.remove( name ); 237 if( null == installation ) 238 { 239 final String message = 240 REZ.getString( "deploy.no-deployment.error", name ); 241 throw new DeploymentException( message ); 242 } 243 try 244 { 245 final Application application = m_kernel.getApplication( name ); 246 final String [] blocks = application.getBlockNames(); 247 248 m_kernel.removeApplication( name ); 249 250 for( int i = 0; i < blocks.length; i++ ) 251 { 252 m_repository.removeConfiguration( name, blocks[ i ] ); 254 m_validator.removeSchema( name, blocks[ i ] ); 255 } 256 257 m_installer.uninstall( installation ); 258 } 259 catch( final Exception e ) 260 { 261 throw new DeploymentException( e.getMessage(), e ); 262 } 263 } 264 265 272 public void deploy( final String name, final String sarURL ) 273 throws DeploymentException 274 { 275 try 276 { 277 try 278 { 279 deploy( name, new URL ( sarURL ) ); 280 } 281 catch( DeploymentException e ) 282 { 283 e.printStackTrace(); 284 } 285 } 286 catch( MalformedURLException mue ) 287 { 288 mue.printStackTrace(); 289 throw new DeploymentException( mue.getMessage(), mue ); 290 } 291 } 292 293 300 public void deploy( final String name, final URL location ) 301 throws DeploymentException 302 { 303 if( m_installations.containsKey( name ) ) 304 { 305 final String message = 306 REZ.getString( "deploy.already-deployed.error", 307 name ); 308 throw new DeploymentException( message ); 309 } 310 311 316 ResourceManager.clearResourceCache(); 317 318 Installation installation = null; 319 boolean success = false; 320 try 321 { 322 installation = m_installer.install( name, location ); 324 325 final Configuration config = getConfigurationFor( installation.getConfig() ); 326 final Configuration environment = getConfigurationFor( installation.getEnvironment() ); 327 final Configuration assembly = getConfigurationFor( installation.getAssembly() ); 328 329 final File directory = installation.getDirectory(); 330 331 final ClassLoader classLoader = 332 m_classLoaderManager.createClassLoader( environment, 333 installation.getSource(), 334 installation.getDirectory(), 335 installation.getWorkDirectory(), 336 installation.getClassPath() ); 337 final SarMetaData metaData = 339 m_assembler.assembleSar( name, assembly, directory, classLoader ); 340 341 storeConfigurationSchemas( metaData, classLoader ); 342 343 verify( metaData, classLoader ); 344 345 setupConfiguration( metaData, config.getChildren() ); 347 348 final Configuration logs = environment.getChild( "logs" ); 349 final Logger logger = 350 m_logManager.createHierarchy( metaData, logs, classLoader ); 351 352 m_kernel.addApplication( metaData, 354 installation.getWorkDirectory(), 355 classLoader, 356 logger, 357 environment ); 358 359 m_installations.put( metaData.getName(), installation ); 360 361 final String message = 362 REZ.getString( "deploy.notice.sar.add", 363 metaData.getName(), 364 Arrays.asList( installation.getClassPath() ) ); 365 getLogger().debug( message ); 366 success = true; 367 } 368 catch( final DeploymentException de ) 369 { 370 throw de; 371 } 372 catch( final AssemblyException ae ) 373 { 374 throw new DeploymentException( ae.getMessage(), ae ); 375 } 376 catch( final Exception e ) 377 { 378 throw new DeploymentException( e.getMessage(), e ); 380 } 381 finally 382 { 383 if( !success && null != installation ) 384 { 385 try 386 { 387 m_installer.uninstall( installation ); 388 } 389 catch( final InstallationException ie ) 390 { 391 getLogger().error( ie.getMessage(), ie ); 392 } 393 } 394 } 395 } 396 397 404 protected void verify( final SarMetaData metaData, 405 final ClassLoader classLoader ) 406 throws VerifyException 407 { 408 m_verifier.verifySar( metaData, classLoader ); 409 } 410 411 417 private void storeConfigurationSchemas( final SarMetaData metaData, ClassLoader classLoader ) 418 throws DeploymentException 419 { 420 final BlockMetaData[] blocks = metaData.getBlocks(); 421 int i = 0; 422 423 try 424 { 425 for( i = 0; i < blocks.length; i++ ) 426 { 427 final String name = blocks[ i ].getName(); 428 final BlockDescriptor descriptor = blocks[ i ].getBlockInfo().getBlockDescriptor(); 429 final String type = descriptor.getSchemaType(); 430 431 if( null != type ) 432 { 433 m_validator.addSchema( metaData.getName(), 434 name, 435 type, 436 getConfigurationSchemaURL( name, 437 descriptor.getImplementationKey(), 438 classLoader ) 439 ); 440 } 441 } 442 } 443 catch( ConfigurationException e ) 444 { 445 final String message = REZ.getString( "deploy.error.config.schema.invalid", 447 blocks[ i ].getName() ); 448 449 while( --i >= 0 ) 451 { 452 m_validator.removeSchema( metaData.getName(), 453 blocks[ i ].getName() ); 454 } 455 456 throw new DeploymentException( message, e ); 457 } 458 } 459 460 private String getConfigurationSchemaURL( final String name, 461 final String classname, 462 final ClassLoader classLoader ) 463 throws DeploymentException 464 { 465 final String resourceName = classname.replace( '.', '/' ) + "-schema.xml"; 466 467 final URL resource = classLoader.getResource( resourceName ); 468 if( null == resource ) 469 { 470 471 throw new DeploymentException( REZ.getString( "deploy.error.config.schema.missing", 472 name, 473 resourceName ) ); 474 } 475 else 476 { 477 return resource.toString(); 478 } 479 } 480 481 488 private Configuration getConfigurationFor( final String location ) 489 throws DeploymentException 490 { 491 try 492 { 493 return ConfigurationBuilder.build( location ); 494 } 495 catch( final Exception e ) 496 { 497 final String message = REZ.getString( "deploy.error.config.create", location ); 498 getLogger().error( message, e ); 499 throw new DeploymentException( message, e ); 500 } 501 } 502 503 510 private void setupConfiguration( final SarMetaData metaData, 511 final Configuration[] configurations ) 512 throws DeploymentException 513 { 514 final String application = metaData.getName(); 515 516 for( int i = 0; i < configurations.length; i++ ) 517 { 518 final Configuration configuration = configurations[ i ]; 519 final String name = configuration.getName(); 520 final boolean listener = hasBlockListener( name, metaData.getListeners() ); 521 522 if( !hasBlock( name, metaData.getBlocks() ) && !listener ) 523 { 524 final String message = 525 REZ.getString( "deploy.error.extra.config", 526 name ); 527 throw new DeploymentException( message ); 528 } 529 530 try 531 { 532 if( listener || m_validator.isFeasiblyValid( application, name, configuration ) ) 534 { 535 m_repository.storeConfiguration( application, 536 name, 537 configuration ); 538 } 539 else 540 { 541 final String message = REZ.getString( "deploy.error.config.invalid", name ); 542 543 throw new DeploymentException( message ); 544 } 545 } 546 catch( final ConfigurationException ce ) 547 { 548 throw new DeploymentException( ce.getMessage(), ce ); 549 } 550 } 551 } 552 553 560 private boolean hasBlock( final String name, final BlockMetaData[] blocks ) 561 { 562 for( int i = 0; i < blocks.length; i++ ) 563 { 564 final String other = blocks[ i ].getName(); 565 if( other.equals( name ) ) 566 { 567 return true; 568 } 569 } 570 571 return false; 572 } 573 574 581 private boolean hasBlockListener( final String name, 582 final BlockListenerMetaData[] listeners ) 583 { 584 for( int i = 0; i < listeners.length; i++ ) 585 { 586 if( listeners[ i ].getName().equals( name ) ) 587 { 588 return true; 589 } 590 } 591 592 return false; 593 } 594 595 600 private void initWorkDirectory() 601 throws Exception 602 { 603 if( !m_baseWorkDirectory.exists() ) 604 { 605 final String message = 606 REZ.getString( "deploy.create-dir.notice", 607 m_baseWorkDirectory ); 608 getLogger().info( message ); 609 610 if( !m_baseWorkDirectory.mkdirs() ) 611 { 612 final String error = 613 REZ.getString( "deploy.workdir-nocreate.error", 614 m_baseWorkDirectory ); 615 throw new Exception ( error ); 616 } 617 } 618 619 if( !m_baseWorkDirectory.isDirectory() ) 620 { 621 final String message = 622 REZ.getString( "deploy.workdir-notadir.error", 623 m_baseWorkDirectory ); 624 throw new Exception ( message ); 625 } 626 } 627 } 628 | Popular Tags |