1 87 package org.codehaus.loom.components.installer; 88 89 import java.io.File ; 90 import java.io.FileOutputStream ; 91 import java.io.IOException ; 92 import java.io.InputStream ; 93 import java.io.OutputStream ; 94 import java.net.MalformedURLException ; 95 import java.net.URL ; 96 import java.util.Enumeration ; 97 import java.util.HashMap ; 98 import java.util.Map ; 99 import java.util.zip.ZipEntry ; 100 import java.util.zip.ZipFile ; 101 102 import org.codehaus.loom.interfaces.ContainerConstants; 103 import org.codehaus.loom.interfaces.Installer; 104 import org.codehaus.loom.interfaces.LoomException; 105 import org.codehaus.spice.salt.i18n.ResourceManager; 106 import org.codehaus.spice.salt.i18n.Resources; 107 import org.codehaus.spice.salt.io.FileUtil; 108 import org.codehaus.spice.salt.io.IOUtil; 109 import org.codehaus.dna.AbstractLogEnabled; 110 import org.codehaus.dna.Active; 111 import org.codehaus.dna.Configurable; 112 import org.codehaus.dna.Configuration; 113 import org.codehaus.dna.ConfigurationException; 114 115 122 public class DefaultInstaller 123 extends AbstractLogEnabled 124 implements Installer, Configurable, Active 125 { 126 private static final Resources REZ = 127 ResourceManager.getPackageResources( DefaultInstaller.class ); 128 129 private static final String META_INF = "META-INF"; 130 private static final String SAR_INF = "SAR-INF"; 131 private static final String LIB = "SAR-INF/lib"; 132 private static final String CLASSES = "SAR-INF/classes/"; 133 134 private static final String FS_CONFIG_XML = "SAR-INF" + 136 File.separator + 137 "config.xml"; 138 private static final String FS_ASSEMBLY_XML = "SAR-INF" + 139 File.separator + 140 "assembly.xml"; 141 private static final String FS_ENV_XML = "SAR-INF" + 142 File.separator + 143 "environment.xml"; 144 private static final String FS_CLASSES = 145 "SAR-INF" + File.separator + "classes" + File.separator; 146 147 152 private File m_baseWorkDirectory; 153 154 155 private File m_baseDirectory; 156 157 public void configure( final Configuration configuration ) 158 throws ConfigurationException 159 { 160 final String workDir = 161 configuration.getChild( "base-work-dir" ).getValue(); 162 final String appDir = 163 configuration.getChild( "base-application-dir" ).getValue(); 164 m_baseWorkDirectory = new File ( workDir ); 165 m_baseDirectory = new File ( appDir ); 166 } 167 168 public void initialize() 169 throws Exception 170 { 171 initWorkDirectory(); 172 try 173 { 174 FileUtil.cleanDirectory( m_baseWorkDirectory ); 175 } 176 catch( final IOException ioe ) 177 { 178 final String message = 179 REZ.format( "nodelete-workdir.error", 180 m_baseWorkDirectory, 181 ioe.getMessage() ); 182 getLogger().warn( message, ioe ); 183 } 184 } 185 186 public void dispose() 187 throws Exception 188 { 189 } 190 191 197 public void uninstall( final Map installation ) 198 throws LoomException 199 { 200 final File work = 201 (File )installation.get( ContainerConstants.INSTALL_WORK ); 202 deleteWorkDir( work ); 203 } 204 205 210 private void deleteWorkDir( final File dir ) 211 { 212 try 213 { 214 FileUtil.deleteDirectory( dir ); 215 } 216 catch( final IOException ioe ) 217 { 218 try 219 { 220 FileUtil.forceDeleteOnExit( dir ); 223 } 224 catch( final IOException ioe2 ) 225 { 226 } 228 final String message = 229 REZ.format( "nodelete-workdir.error", 230 dir, 231 ioe.getMessage() ); 232 getLogger().warn( message, ioe ); 233 } 234 } 235 236 242 public Map install( final String name, final URL url ) 243 throws LoomException 244 { 245 lock(); 246 try 247 { 248 final String notice = REZ.format( "installing-sar", url ); 249 getLogger().info( notice ); 250 251 final File file = getFileFor( url ); 252 if( file.isDirectory() ) 253 { 254 final String message = 255 REZ.format( "install.sar-isa-dir.error", name, url ); 256 throw new LoomException( message ); 257 } 258 259 final ZipFile zipFile = new ZipFile ( file ); 261 return installArchive( name, url, file, zipFile ); 262 } 263 catch( final IOException ioe ) 264 { 265 final String message = REZ.format( "bad-zip-file", url ); 266 throw new LoomException( message, ioe ); 267 } 268 finally 269 { 270 unlock(); 271 } 272 } 273 274 278 private void lock() 279 { 280 } 281 282 286 private void unlock() 287 { 288 } 289 290 298 private Map installArchive( final String name, 299 final URL url, 300 final File file, 301 final ZipFile zipFile ) 302 throws LoomException 303 { 304 final File directory = 305 new File ( m_baseDirectory, name ).getAbsoluteFile(); 306 307 directory.mkdirs(); 310 311 final File workDir = getRelativeWorkDir( name ); 312 boolean success = false; 313 try 314 { 315 workDir.mkdirs(); 316 expandZipFile( zipFile, directory, workDir, url ); 317 318 final String assembly = getURLAsString( 320 new File ( directory, FS_ASSEMBLY_XML ) ); 321 final String config = getURLAsString( 322 new File ( directory, FS_CONFIG_XML ) ); 323 final String environment = getURLAsString( 324 new File ( directory, FS_ENV_XML ) ); 325 326 success = true; 327 final Map install = new HashMap (); 328 install.put( ContainerConstants.INSTALL_SOURCE, file ); 329 install.put( ContainerConstants.INSTALL_HOME, directory ); 330 install.put( ContainerConstants.INSTALL_WORK, workDir ); 331 install.put( ContainerConstants.INSTALL_CONFIG, config ); 332 install.put( ContainerConstants.INSTALL_ASSEMBLY, assembly ); 333 install.put( ContainerConstants.INSTALL_ENVIRONMENT, environment ); 334 return install; 335 } 336 finally 337 { 338 if( !success ) 339 { 340 deleteWorkDir( workDir ); 341 } 342 } 343 } 344 345 355 private void expandZipFile( final ZipFile zipFile, 356 final File directory, 357 final File workDir, 358 final URL url ) 359 throws LoomException 360 { 361 final Enumeration entries = zipFile.entries(); 362 while( entries.hasMoreElements() ) 363 { 364 final ZipEntry entry = (ZipEntry )entries.nextElement(); 365 final String name = fixName( entry.getName() ); 366 367 if( name.startsWith( META_INF ) ) 368 { 369 continue; 370 } 371 372 if( handleDirs( entry, name, directory ) ) 373 { 374 continue; 375 } 376 377 if( handleClasses( zipFile, 378 entry, 379 name, 380 workDir ) ) 381 { 382 continue; 383 } 384 385 if( handleJars( zipFile, entry, name, workDir ) ) 386 { 387 continue; 388 } 389 390 final File destination = new File ( directory, name ); 393 handleFile( zipFile, entry, destination, url ); 394 } 395 } 396 397 400 private void handleFile( final ZipFile zipFile, 401 final ZipEntry entry, 402 final File destination, 403 final URL url ) 404 throws LoomException 405 { 406 if( !destination.exists() ) 407 { 408 expandFile( zipFile, entry, destination ); 409 } 410 else 411 { 412 final String message = 413 REZ.format( "file-in-the-way", 414 url, 415 entry.getName(), 416 destination ); 417 getLogger().warn( message ); 418 } 419 } 420 421 430 private boolean handleJars( final ZipFile zipFile, 431 final ZipEntry entry, 432 final String name, 433 final File workDir ) 434 throws LoomException 435 { 436 if( name.startsWith( LIB ) 437 && 438 name.endsWith( ".jar" ) 439 && LIB.length() == name.lastIndexOf( "/" ) ) 440 { 441 final File file = new File ( workDir, name ); 442 expandFile( zipFile, entry, file ); 443 return true; 444 } 445 else 446 { 447 return false; 448 } 449 } 450 451 460 private boolean handleClasses( final ZipFile zipFile, 461 final ZipEntry entry, 462 final String name, 463 final File workDir ) 464 throws LoomException 465 { 466 if( name.startsWith( CLASSES ) ) 467 { 468 final File classDir = new File ( workDir, FS_CLASSES ); 469 if( !classDir.exists() ) 470 { 471 final File file = new File ( workDir, name ); 472 expandFile( zipFile, entry, file ); 473 } 474 return true; 475 } 476 else 477 { 478 return false; 479 } 480 } 481 482 490 private boolean handleDirs( final ZipEntry entry, 491 final String name, 492 final File directory ) 493 { 494 if( entry.isDirectory() ) 495 { 496 if( !name.startsWith( SAR_INF ) ) 497 { 498 final File newDir = 499 new File ( directory, name ); 500 newDir.mkdirs(); 501 } 502 return true; 503 } 504 else 505 { 506 return false; 507 } 508 } 509 510 516 private File getRelativeWorkDir( final String name ) 517 { 518 final String filename = 519 name + "-" + System.currentTimeMillis(); 520 return new File ( m_baseWorkDirectory, filename ); 521 } 522 523 529 private String fixName( final String name ) 530 { 531 if( name.startsWith( "/" ) ) 532 { 533 return name.substring( 1 ); 534 } 535 else 536 { 537 return name; 538 } 539 } 540 541 550 private File getFileFor( final URL url ) 551 throws LoomException 552 { 553 if( !url.getProtocol().equals( "file" ) ) 554 { 555 final String message = REZ.format( "install-nonlocal", url ); 556 throw new LoomException( message ); 557 } 558 559 File file = new File ( url.getFile() ); 560 file = file.getAbsoluteFile(); 561 562 if( !file.exists() ) 563 { 564 final String message = REZ.format( "install-nourl", file ); 565 throw new LoomException( message ); 566 } 567 568 return file; 569 } 570 571 574 private void expandFile( final ZipFile zipFile, 575 final ZipEntry entry, 576 final File file ) 577 throws LoomException 578 { 579 InputStream input = null; 580 OutputStream output = null; 581 582 try 583 { 584 file.getParentFile().mkdirs(); 585 output = new FileOutputStream ( file ); 586 input = zipFile.getInputStream( entry ); 587 IOUtil.copy( input, output ); 588 } 589 catch( final IOException ioe ) 590 { 591 final String message = 592 REZ.format( "failed-to-expand", 593 entry.getName(), 594 file, 595 ioe.getMessage() ); 596 throw new LoomException( message, ioe ); 597 } 598 finally 599 { 600 IOUtil.shutdownStream( input ); 601 IOUtil.shutdownStream( output ); 602 } 603 } 604 605 611 private String getURLAsString( final File file ) 612 { 613 try 614 { 615 return file.toURL().toExternalForm(); 616 } 617 catch( final MalformedURLException mue ) 618 { 619 return null; 620 } 622 } 623 624 629 private void initWorkDirectory() 630 throws Exception 631 { 632 if( !m_baseWorkDirectory.exists() ) 633 { 634 final String message = 635 REZ.format( "install.create-dir.notice", 636 m_baseWorkDirectory ); 637 getLogger().info( message ); 638 639 if( !m_baseWorkDirectory.mkdirs() ) 640 { 641 final String error = 642 REZ.format( "install.workdir-nocreate.error", 643 m_baseWorkDirectory ); 644 throw new Exception ( error ); 645 } 646 } 647 648 if( !m_baseWorkDirectory.isDirectory() ) 649 { 650 final String message = 651 REZ.format( "install.workdir-notadir.error", 652 m_baseWorkDirectory ); 653 throw new Exception ( message ); 654 } 655 } 656 } 657 | Popular Tags |