1 26 27 package com.opensugar.cube; 28 29 import com.opensugar.cube.java2.ManifestHelper; 30 import com.opensugar.cube.packageAdmin.ExportedPackageImpl; 31 import com.opensugar.cube.packageAdmin.PackageImport; 32 33 import org.osgi.framework.Bundle; 34 import org.osgi.framework.BundleException; 35 import org.osgi.framework.ServiceReference; 36 import org.osgi.framework.BundleEvent; 37 import org.osgi.framework.FrameworkEvent; 38 import org.osgi.framework.BundleActivator; 39 import org.osgi.framework.PackagePermission; 40 import org.osgi.framework.ServicePermission; 41 import org.osgi.framework.Constants; 42 43 import java.io.InputStream ; 44 import java.io.File ; 45 import java.io.FileInputStream ; 46 import java.io.FileOutputStream ; 47 import java.io.IOException ; 48 import java.util.Dictionary ; 49 import java.util.Hashtable ; 50 import java.net.URL ; 51 import java.net.MalformedURLException ; 52 import java.util.zip.ZipFile ; 53 import java.util.Vector ; 54 55 public class BundleImpl implements Bundle { 56 57 public int getState() { 58 return state; 59 } 60 61 public void start() throws BundleException { 62 getCube().checkAdminPermission(); 63 64 if ( getState() == UNINSTALLED ) { 66 throw new IllegalStateException ( "Cannot start a bundle after it has been uninstalled" ); 67 } 68 69 if ( getState() == STARTING || getState() == STOPPING ) { 73 if ( !waitUntilStartedOrStopped() ) { 74 throw new BundleException( "Cannot stop a bundle that is stuck in starting or stopping mode" ); 75 } 76 } 77 78 if ( getState() == ACTIVE ) { 80 return; 81 } 82 83 if ( getState() != RESOLVED ) { 86 getCube().getPackageAdmin().resolveBundles(); 90 if ( getState() != RESOLVED ) { 91 PackageImport[] unsatisfiedImports = getCube().getPackageAdmin().getUnsatisfiedImports( this ); 92 93 StringBuffer sb = new StringBuffer (); 94 String version; 95 for ( int i = 0; i < unsatisfiedImports.length; i++ ) { 96 sb.append( unsatisfiedImports[ i ].getName() ); 97 version = unsatisfiedImports[ i ].getSpecificationVersion(); 98 if ( version != null ) { 99 sb.append( " " + version ); 100 } 101 if ( i < unsatisfiedImports.length - 1 ) { 102 sb.append( ", " ); 103 } 104 } 105 throw new BundleException( "Cannot start a bundle that is not resolved. Missing packages: " + sb.toString() ); 106 } 107 } 108 109 state = STARTING; 111 112 bundleContext = new BundleContextImpl( cube, this ); 117 try { 118 String bundleActivatorName = (String )headers.get( "Bundle-Activator" ); 119 if ( bundleActivatorName != null ) { 120 Class bundleActivatorClass = classLoader.loadClass( bundleActivatorName.trim() ); 121 bundleActivator = (BundleActivator)bundleActivatorClass.newInstance(); 122 bundleActivator.start( bundleContext ); 123 } 124 } 125 catch( Throwable e ) { 126 state = RESOLVED; 127 bundleActivator = null; 128 cleanUp(); 130 throw new BundleException( "Exception occured in the bundle activator's start method", e ); 131 } 132 133 try { 136 getCube().registerBundleAsStarted( getBundleId() ); 137 } 138 catch( IOException e ) { 139 getCube().fireFrameworkEvent( FrameworkEvent.ERROR, this, e ); 140 } 141 142 state = ACTIVE; 144 145 getCube().fireBundleEvent( BundleEvent.STARTED, this ); 147 } 148 149 public void stop() throws BundleException { 150 stop( false ); 151 } 152 153 public void update() throws BundleException, SecurityException { 154 update( null ); 155 } 156 157 public void update( InputStream in ) throws BundleException, SecurityException { 158 160 getCube().checkAdminPermission(); 161 162 if ( getState() == UNINSTALLED ) { 164 throw new IllegalStateException ( "Cannot update a bundle after it has been uninstalled" ); 165 } 166 167 boolean restart = false; 170 if ( getState() == ACTIVE ) { 171 restart = true; 172 } 173 174 if ( getState() == ACTIVE || getState() == STARTING ) { 178 stop(); 179 } 180 181 String tempLocation = (String )headers.get( "Bundle-UpdateLocation" ); 183 if ( tempLocation == null || tempLocation.trim().length() == 0 ) { 184 tempLocation = location; 185 } 186 187 Throwable exceptionWhileInstalling = null; 190 String oldLocation = location; 191 File oldBundleJarFile = bundleJarFile; 192 File newBundleJarFile = getCube().getNewBundleJarFile( id ); 193 try { 194 if ( in == null ) { 197 URL url = new URL ( tempLocation ); 198 in = url.openStream(); 199 } 200 201 Util.transferData( in, new FileOutputStream ( newBundleJarFile ) ); 202 203 uninitializeBundle(); 205 206 initializeBundle( tempLocation, getCube().getCurrentBundleJarFile( id ) ); 208 } 209 catch( Throwable e ) { 210 exceptionWhileInstalling = e; 211 if ( getCube().deleteBundleJarFile( newBundleJarFile ) ) { 213 try { 214 initializeBundle( oldLocation, oldBundleJarFile ); 215 } 216 catch( Throwable e2 ) { 217 throw new BundleException( "Fatal bundle error: failure to restore original bundle version after unsuccessful bundle update attempt", e ); 218 } 219 } 220 else { 221 throw new BundleException( "Fatal bundle error: failure to delete jar file that was created during unsuccessful bundle update attempt", e ); 222 } 223 } 224 225 state = INSTALLED; 227 228 if ( exceptionWhileInstalling == null ) { 231 getCube().fireBundleEvent( BundleEvent.UPDATED, this ); 232 } 233 234 getCube().getPackageAdmin().resolveBundles(); 235 236 if ( restart ) { 240 try { 241 start(); 242 } 243 catch( Throwable e ) { 244 getCube().fireFrameworkErrorEvent( this, e ); 245 } 246 } 247 248 251 if ( exceptionWhileInstalling != null ) { 254 throw new BundleException( "Exception occured while attempting to install new version of bundle. Original version was restored.", exceptionWhileInstalling ); 255 } 256 } 257 258 public void uninstall() throws BundleException { 259 getCube().checkAdminPermission(); 260 261 if ( getState() == UNINSTALLED ) { 263 throw new IllegalStateException ( "Cannot uninstall bundle that is already uninstalled" ); 264 } 265 266 if ( getState() == ACTIVE || getState() == STARTING ) { 269 try { 270 stop(); 271 } 272 catch( Throwable e ) { 273 getCube().fireFrameworkErrorEvent( this, e ); 274 } 275 } 276 277 try { 279 uninitializeBundle(); 280 } 281 catch( IOException e ) { 282 getCube().fireFrameworkEvent( FrameworkEvent.ERROR, this, e ); 283 } 284 285 try { 286 getCube().setBundleUninstalled( id ); 287 } 288 catch ( IOException e ) { 289 getCube().fireFrameworkEvent( FrameworkEvent.ERROR, this, e ); 290 } 291 getCube().bundleUninstalled( id ); 292 293 getCube().fireBundleEvent( BundleEvent.UNINSTALLED, this ); 295 296 state = UNINSTALLED; 298 } 299 300 public Dictionary getHeaders() { 301 getCube().checkAdminPermission(); 302 return headers; 303 } 304 305 public long getBundleId() { 306 return id; 307 } 308 309 public String getLocation() { 310 getCube().checkAdminPermission(); 311 return getLocationWithoutAdminPermissionCheck(); 312 } 313 314 public String getLocationWithoutAdminPermissionCheck() { 318 return location.trim(); 319 } 320 321 public ServiceReference[] getRegisteredServices() { 322 if ( getState() == UNINSTALLED ) { 323 throw new IllegalStateException ( "Cannot get services registered by a bundle after it has been uninstalled" ); 324 } 325 326 ServiceRegistrationImpl[] serviceRegistrations = getCube().getServiceRegistry().getServicesRegisteredBy( this ); 327 if ( serviceRegistrations == null || serviceRegistrations.length == 0 ) { 328 return null; 329 } 330 331 Vector tmp = new Vector (); 332 ServiceReference serviceReference; 333 for ( int i = 0; i < serviceRegistrations.length; i++ ) { 334 serviceReference = serviceRegistrations[ i ].getReference(); 335 try { 336 getCube().checkServicePermissionForAtLeastOne( (String [])serviceReference.getProperty( "objectClass" ), ServicePermission.GET ); 337 tmp.addElement( serviceReference ); 338 } 339 catch( SecurityException ignore ) {} 340 } 341 342 if ( tmp.size() == 0 ) { 343 return null; 344 } 345 ServiceReference[] ret = new ServiceReference[ tmp.size() ]; 346 tmp.copyInto( ret ); 347 return ret; 348 } 349 350 public ServiceReference[] getServicesInUse() { 351 if ( getState() == UNINSTALLED ) { 352 throw new IllegalStateException ( "Cannot get services used by a bundle after it has been uninstalled" ); 353 } 354 355 ServiceReference[] serviceReferences = getCube().getServiceRegistry().getServicesUsedBy( this ); 356 if ( serviceReferences == null || serviceReferences.length == 0 ) { 357 return null; 358 } 359 360 Vector tmp = new Vector (); 361 for ( int i = 0; i < serviceReferences.length; i++ ) { 362 try { 363 getCube().checkServicePermissionForAtLeastOne( (String [])serviceReferences[ i ].getProperty( "objectClass" ), ServicePermission.GET ); 364 tmp.addElement( serviceReferences[ i ] ); 365 } 366 catch( SecurityException ignore ) {} 367 } 368 369 if ( tmp.size() == 0 ) { 370 return null; 371 } 372 ServiceReference[] ret = new ServiceReference[ tmp.size() ]; 373 tmp.copyInto( ret ); 374 return ret; 375 } 376 377 public boolean hasPermission( Object permission ) { 378 Util.checkNullParameter( permission, getClass().getName(), "hasPermission", "permission" ); 379 380 if ( getState() == UNINSTALLED ) { 381 throw new IllegalStateException ( "Cannot check a bundle's permissions after it has been uninstalled" ); 382 } 383 384 return getCube().hasPermission( this, permission ); 385 } 386 387 public int compareTo( Object obj ) { 388 Util.checkNullParameter( obj, getClass().getName(), "compareTo", "obj" ); 389 390 if ( obj instanceof Bundle ) { 391 Bundle bundleToCompareTo = (Bundle)obj; 392 return (int)( getBundleId() - bundleToCompareTo.getBundleId() ); 393 } 394 throw new IllegalArgumentException ( "Object to compare to must be of type org.osgi.framework.Bundle" ); 395 } 396 397 public URL getResource( String name ) throws IllegalStateException { 398 if ( getState() == UNINSTALLED ) { 399 throw new IllegalStateException ( "Cannot get resource after bundle has been uninstalled" ); 400 } 401 402 try { 403 getCube().checkAdminPermission(); 404 } 405 catch( SecurityException e ) { 406 return null; 407 } 408 409 422 423 return classLoader.getResource( name ); 427 } 428 429 public NamedPropertySet[] getExportedPackages() { 430 return exportedPackages; 431 } 432 433 public NamedPropertySet[] getExplicitlyImportedPackages() { 434 return explicitlyImportedPackages; 435 } 436 437 439 private AbstractCube cube; 441 private long id; 442 443 private String location; 445 private File bundleJarFile; 446 private Dictionary headers; 447 private NamedPropertySet[] exportedPackages; 448 private NamedPropertySet[] explicitlyImportedPackages; 449 private BundleClassLoader classLoader; 450 451 private BundleContextImpl bundleContext; 453 454 private int state; 455 private BundleActivator bundleActivator; 456 457 protected BundleImpl( AbstractCube cube, long id, String location, File bundleJarFile ) throws IOException , ClassNotFoundException , IllegalAccessException , InstantiationException { 458 this.cube = cube; 459 this.id = id; 460 461 bundleContext = new BundleContextImpl( cube, this ); 464 465 initializeBundle( location, bundleJarFile ); 466 } 467 468 public BundleContextImpl getBundleContext() { 469 return bundleContext; 470 } 471 472 public void setResolved() { 474 if ( getState() != INSTALLED ) { 475 throw new RuntimeException ( "Cannot resolve a bundle that is not in the installed state" ); 476 } 477 478 state = RESOLVED; 479 } 480 481 public void setInstalled() { 483 if ( getState() != RESOLVED ) { 484 throw new RuntimeException ( "Cannot unresolve a bundle that is not in the resolved state" ); 485 } 486 state = INSTALLED; 487 488 getCube().fireBundleEvent( BundleEvent.INSTALLED, this ); 490 } 491 492 public BundleClassLoader getClassLoader() { 493 return classLoader; 494 } 495 496 public AbstractCube getCube() { 497 return cube; 498 } 499 500 public void stop( boolean keepRegisteredAsStarted ) throws BundleException { 501 getCube().checkAdminPermission(); 502 503 if ( getState() == UNINSTALLED ) { 505 throw new IllegalStateException ( "Cannot stop a bundle after it has been uninstalled" ); 506 } 507 508 if ( getState() == STARTING || getState() == STOPPING ) { 512 if ( !waitUntilStartedOrStopped() ) { 513 throw new BundleException( "Cannot stop a bundle that is stuck in starting or stopping mode" ); 514 } 515 } 516 517 if ( getState() != ACTIVE ) { 519 return; 520 } 521 522 state = STOPPING; 524 525 if ( !keepRegisteredAsStarted ) { 528 if ( !getCube().unregisterBundleAsStarted( this ) ) { 529 getCube().fireFrameworkErrorEvent( this, new Exception ( "Bundle could not unregister as started bundle" ) ); 530 } 531 } 532 533 Throwable exceptionWhileStopping = null; 537 try { 538 if ( bundleActivator != null ) { 539 bundleActivator.stop( bundleContext ); 540 } 541 } 542 catch( Throwable e ) { 543 exceptionWhileStopping = e; 544 } 545 546 cleanUp(); 550 551 state = RESOLVED; 553 554 getCube().fireBundleEvent( BundleEvent.STOPPED, this ); 556 557 bundleContext.setStopped(); 560 561 if ( exceptionWhileStopping != null ) { 564 throw new BundleException( "Exception occured in the bundle activator's stop method", exceptionWhileStopping ); 565 } 566 } 567 568 570 private boolean waitUntilStartedOrStopped() { 571 int reasonableTime = getCube().getReasonableTimeToWait(); 572 long stopTime = System.currentTimeMillis() + reasonableTime; 573 int sleepTime = reasonableTime / 10; 574 while ( ( getState() == STARTING || getState() == STOPPING ) && System.currentTimeMillis() < stopTime ) { 575 try { 576 Thread.sleep( sleepTime ); 577 } 578 catch ( InterruptedException ignore ) {} 579 } 580 if ( getState() != STARTING && getState() != STOPPING ) { 581 return true; 582 } 583 else { 584 return false; 585 } 586 } 587 588 private void initializeBundle( String location, File bundleJarFile ) throws IOException , ClassNotFoundException { 590 this.location = location; 591 this.bundleJarFile = bundleJarFile; 592 593 ZipFile archive = new ZipFile ( bundleJarFile ); 595 ManifestHelper manifest = new ManifestHelper( archive ); 596 headers = new BundleHeaders( manifest.getMainAttributes() ); 597 archive.close(); 598 599 bundleActivator = null; 604 605 state = INSTALLED; 607 608 NamedPropertySet[] classPath = NamedPropertySet.createNamedPropertySets( (String )headers.get( Constants.BUNDLE_CLASSPATH ) ); 610 NamedPropertySet[] nativeLibraries = NamedPropertySet.createNamedPropertySets( (String )headers.get( Constants.BUNDLE_NATIVECODE ) ); 611 classLoader = getCube().createClassLoaderForBundle( this, bundleJarFile, nativeLibraries, classPath ); 612 613 exportedPackages = NamedPropertySet.createNamedPropertySets( (String )headers.get( Constants.EXPORT_PACKAGE ) ); 615 if ( exportedPackages != null ) { 616 getCube().checkPackagePermission( exportedPackages, PackagePermission.EXPORT, classLoader.getCodeSource() ); 617 } 618 else { 619 exportedPackages = new NamedPropertySet[ 0 ]; 620 } 621 explicitlyImportedPackages = NamedPropertySet.createNamedPropertySets( (String )headers.get( Constants.IMPORT_PACKAGE ) ); 622 if ( explicitlyImportedPackages != null ) { 623 getCube().checkPackagePermission( explicitlyImportedPackages, PackagePermission.IMPORT, classLoader.getCodeSource() ); 624 } 625 else { 626 explicitlyImportedPackages = new NamedPropertySet[ 0 ]; 627 } 628 629 Vector vec = new Vector (); 637 for ( int i = 0; i < explicitlyImportedPackages.length; i++ ) { 638 vec.addElement( explicitlyImportedPackages[ i ] ); 639 } 640 for ( int i = 0; i < exportedPackages.length; i++ ) { 641 boolean explicitlyExported = false; 642 for ( int j = 0; j < explicitlyImportedPackages.length; j++ ) { 643 if ( exportedPackages[ i ].getName().equals( explicitlyImportedPackages[ j ].getName() ) ) { 644 explicitlyExported = true; 645 } 646 } 647 if ( !explicitlyExported ) { 648 vec.addElement( exportedPackages[ i ] ); 649 } 650 } 651 NamedPropertySet[] importedPackages = new NamedPropertySet[ vec.size() ]; 652 vec.copyInto( importedPackages ); 653 654 for ( int i = 0; i < exportedPackages.length; i++ ) { 655 getCube().getPackageAdmin().exportPackage( this, exportedPackages[ i ].getName(), (String )exportedPackages[ i ].getProperty( Constants.PACKAGE_SPECIFICATION_VERSION ), classLoader ); 656 } 657 for ( int i = 0; i < importedPackages.length; i++ ) { 658 getCube().getPackageAdmin().importPackage( this, importedPackages[ i ].getName(), (String )importedPackages[ i ].getProperty( Constants.PACKAGE_SPECIFICATION_VERSION ) ); 659 } 660 } 661 662 private void uninitializeBundle() throws IOException { 664 666 bundleJarFile = null; 667 bundleActivator = null; 668 669 getCube().getPackageAdmin().bundleUpdatedOrUninstalled( this ); 670 } 671 672 private void cleanUp() { 674 getCube().removeServiceListenersRegisteredBy( this ); 676 getCube().removeBundleListenersRegisteredBy( this ); 677 getCube().removeFrameworkListenersRegisteredBy( this ); 678 679 ServiceRegistrationImpl[] serviceRegistrations = getCube().getServiceRegistry().getServicesRegisteredBy( this ); 681 if ( serviceRegistrations != null ) { 682 for ( int i = 0; i < serviceRegistrations.length; i++ ) { 683 serviceRegistrations[ i ].unregister(); 684 } 685 } 686 687 ServiceReferenceImpl[] serviceReferences = getCube().getServiceRegistry().getServicesUsedBy( this ); 690 if ( serviceReferences != null ) { 691 for ( int i = 0; i < serviceReferences.length; i++ ) { 692 getCube().getServiceRegistry().ungetService( serviceReferences[ i ], this ); 693 } 694 } 695 } 696 716 } | Popular Tags |