1 11 12 package org.eclipse.equinox.internal.app; 13 14 import java.lang.reflect.InvocationTargetException ; 15 import java.lang.reflect.Method ; 16 import java.security.AccessController ; 17 import java.security.PrivilegedAction ; 18 import java.util.*; 19 import org.eclipse.core.runtime.*; 20 import org.eclipse.equinox.app.IApplicationContext; 21 import org.eclipse.osgi.framework.log.FrameworkLogEntry; 22 import org.eclipse.osgi.service.runnable.ApplicationLauncher; 23 import org.eclipse.osgi.service.runnable.ParameterizedRunnable; 24 import org.eclipse.osgi.util.NLS; 25 import org.osgi.framework.*; 26 import org.osgi.service.application.*; 27 import org.osgi.util.tracker.ServiceTracker; 28 import org.osgi.util.tracker.ServiceTrackerCustomizer; 29 30 35 public class EclipseAppContainer implements IRegistryChangeListener, SynchronousBundleListener, ServiceTrackerCustomizer { 36 private static final String PI_RUNTIME = "org.eclipse.core.runtime"; private static final String PT_APPLICATIONS = "applications"; private static final String PT_APP_VISIBLE = "visible"; private static final String PT_APP_THREAD = "thread"; private static final String PT_APP_THREAD_ANY = "any"; private static final String PT_APP_CARDINALITY = "cardinality"; private static final String PT_APP_CARDINALITY_SINGLETON_GLOBAL = "singleton-global"; private static final String PT_APP_CARDINALITY_SINGLETON_SCOPED = "singleton-scoped"; private static final String PT_APP_CARDINALITY_UNLIMITED = "*"; private static final String PT_PRODUCTS = "products"; private static final String EXT_ERROR_APP = "org.eclipse.equinox.app.error"; 48 private static final String PROP_PRODUCT = "eclipse.product"; private static final String PROP_ECLIPSE_APPLICATION = "eclipse.application"; private static final String PROP_ECLIPSE_APPLICATION_LAUNCH_DEFAULT = "eclipse.application.launchDefault"; private static final String PROP_ECLIPSE_REGISTER_APP_DESC = "eclipse.application.registerDescriptors"; 53 static final int NOT_LOCKED = 0; 54 static final int LOCKED_SINGLETON_GLOBAL_RUNNING = 1; 55 static final int LOCKED_SINGLETON_GLOBAL_APPS_RUNNING = 2; 56 static final int LOCKED_SINGLETON_SCOPED_RUNNING = 3; 57 static final int LOCKED_SINGLETON_LIMITED_RUNNING = 4; 58 static final int LOCKED_MAIN_THREAD_RUNNING = 5; 59 60 final BundleContext context; 61 final private HashMap apps = new HashMap(); 63 64 final private IExtensionRegistry extensionRegistry; 65 final private ServiceTracker launcherTracker; 66 private IBranding branding; 67 private boolean missingProductReported; 68 69 final private Collection activeHandles = new ArrayList(); 71 private EclipseAppHandle activeMain; 72 private EclipseAppHandle activeGlobalSingleton; 73 private EclipseAppHandle activeScopedSingleton; 74 private HashMap activeLimited; 75 private String defaultAppId; 76 private DefaultApplicationListener defaultAppListener; 77 private ParameterizedRunnable defaultMainThreadAppHandle; 79 public EclipseAppContainer(BundleContext context, IExtensionRegistry extensionRegistry) { 80 this.context = context; 81 this.extensionRegistry = extensionRegistry; 82 launcherTracker = new ServiceTracker(context, ApplicationLauncher.class.getName(), this); 83 } 84 85 void start() { 86 launcherTracker.open(); 87 extensionRegistry.addRegistryChangeListener(this); 88 context.addBundleListener(this); 90 String startDefaultProp = context.getProperty(EclipseAppContainer.PROP_ECLIPSE_APPLICATION_LAUNCH_DEFAULT); 91 if (startDefaultProp == null || "true".equalsIgnoreCase(startDefaultProp)) { boolean registerDescs = "true".equalsIgnoreCase(context.getProperty(EclipseAppContainer.PROP_ECLIPSE_REGISTER_APP_DESC)); if (registerDescs) 95 registerAppDescriptors(); 96 try { 98 startDefaultApp(); 99 } catch (ApplicationException e) { 100 Activator.log(new FrameworkLogEntry(Activator.PI_APP, FrameworkLogEntry.ERROR, 0, Messages.application_errorStartDefault, 0, e, null)); 101 if (!registerDescs) 102 registerAppDescriptors(); 104 } 105 } else { 106 registerAppDescriptors(); 108 } 109 } 110 111 void stop() { 112 stopAllApps(); 114 context.removeBundleListener(this); 115 extensionRegistry.removeRegistryChangeListener(this); 116 apps.clear(); 118 branding = null; 119 missingProductReported = false; 120 launcherTracker.close(); 121 } 122 123 126 private EclipseAppDescriptor getAppDescriptor(String applicationId) { 127 EclipseAppDescriptor result = null; 128 synchronized (apps) { 129 result = (EclipseAppDescriptor) apps.get(applicationId); 130 } 131 if (result == null) { 132 registerAppDescriptor(applicationId); synchronized (apps) { 134 result = (EclipseAppDescriptor) apps.get(applicationId); 135 } 136 } 137 return result; 138 } 139 140 private EclipseAppDescriptor createAppDescriptor(IExtension appExtension) { 141 synchronized (apps) { 142 EclipseAppDescriptor appDescriptor = (EclipseAppDescriptor) apps.get(appExtension.getUniqueIdentifier()); 143 if (appDescriptor != null) 144 return appDescriptor; 145 IConfigurationElement[] configs = appExtension.getConfigurationElements(); 147 int flags = EclipseAppDescriptor.FLAG_CARD_SINGLETON_GLOGAL | EclipseAppDescriptor.FLAG_VISIBLE | EclipseAppDescriptor.FLAG_TYPE_MAIN_THREAD; 148 int cardinality = 0; 149 if (configs.length > 0) { 150 String sVisible = configs[0].getAttribute(PT_APP_VISIBLE); 151 if (sVisible != null && !Boolean.valueOf(sVisible).booleanValue()) 152 flags &= ~(EclipseAppDescriptor.FLAG_VISIBLE); 153 String sThread = configs[0].getAttribute(PT_APP_THREAD); 154 if (PT_APP_THREAD_ANY.equals(sThread)) { 155 flags |= EclipseAppDescriptor.FLAG_TYPE_ANY_THREAD; 156 flags &= ~(EclipseAppDescriptor.FLAG_TYPE_MAIN_THREAD); 157 } 158 String sCardinality = configs[0].getAttribute(PT_APP_CARDINALITY); 159 if (sCardinality != null) { 160 flags &= ~(EclipseAppDescriptor.FLAG_CARD_SINGLETON_GLOGAL); if (PT_APP_CARDINALITY_SINGLETON_SCOPED.equals(sCardinality)) 162 flags |= EclipseAppDescriptor.FLAG_CARD_SINGLETON_SCOPED; 163 else if (PT_APP_CARDINALITY_UNLIMITED.equals(sCardinality)) 164 flags |= EclipseAppDescriptor.FLAG_CARD_UNLIMITED; 165 else if (PT_APP_CARDINALITY_SINGLETON_GLOBAL.equals(sCardinality)) 166 flags |= EclipseAppDescriptor.FLAG_CARD_SINGLETON_GLOGAL; 167 else { 168 try { 169 cardinality = Integer.parseInt(sCardinality); 170 flags |= EclipseAppDescriptor.FLAG_CARD_LIMITED; 171 } catch (NumberFormatException e) { 172 flags |= EclipseAppDescriptor.FLAG_CARD_SINGLETON_GLOGAL; 175 } 176 } 177 } 178 String defaultApp = getDefaultAppId(); 179 if (defaultApp != null && defaultApp.equals(appExtension.getUniqueIdentifier())) 180 flags |= EclipseAppDescriptor.FLAG_DEFAULT_APP; 181 } 182 appDescriptor = new EclipseAppDescriptor(Activator.getBundle(appExtension.getContributor()), appExtension.getUniqueIdentifier(), appExtension.getLabel(), flags, cardinality, this); 183 ServiceRegistration sr = (ServiceRegistration) AccessController.doPrivileged(new RegisterService(new String [] {ApplicationDescriptor.class.getName()}, appDescriptor, appDescriptor.getServiceProperties())); 185 appDescriptor.setServiceRegistration(sr); 186 apps.put(appExtension.getUniqueIdentifier(), appDescriptor); 188 return appDescriptor; 189 } 190 } 191 192 private EclipseAppDescriptor removeAppDescriptor(String applicationId) { 193 synchronized (apps) { 194 EclipseAppDescriptor appDescriptor = (EclipseAppDescriptor) apps.remove(applicationId); 195 if (appDescriptor == null) 196 return null; 197 appDescriptor.unregister(); 198 return appDescriptor; 199 } 200 } 201 202 205 PrivilegedAction getRegServiceAction(String [] serviceClasses, Object serviceObject, Dictionary serviceProps) { 206 return new RegisterService(serviceClasses, serviceObject, serviceProps); 207 } 208 209 212 private class RegisterService implements PrivilegedAction { 213 String [] serviceClasses; 214 Object serviceObject; 215 Dictionary serviceProps; 216 217 RegisterService(String [] serviceClasses, Object serviceObject, Dictionary serviceProps) { 218 this.serviceClasses = serviceClasses; 219 this.serviceObject = serviceObject; 220 this.serviceProps = serviceProps; 221 } 222 223 public Object run() { 224 return context.registerService(serviceClasses, serviceObject, serviceProps); 225 } 226 } 227 228 private void startDefaultApp() throws ApplicationException { 229 String applicationId = getDefaultAppId(); 231 EclipseAppDescriptor defaultDesc = null; 232 Map args = new HashMap(2); 233 args.put(EclipseAppDescriptor.APP_DEFAULT, Boolean.TRUE); 234 if (applicationId == null) { 235 args.put(ErrorApplication.ERROR_EXCEPTION, new RuntimeException (Messages.application_noIdFound)); 237 defaultDesc = getAppDescriptor(EXT_ERROR_APP); 238 } else { 239 defaultDesc = getAppDescriptor(applicationId); 240 if (defaultDesc == null) { 241 args.put(ErrorApplication.ERROR_EXCEPTION, new RuntimeException (NLS.bind(Messages.application_notFound, applicationId, getAvailableAppsMsg()))); 243 defaultDesc = getAppDescriptor(EXT_ERROR_APP); 244 } 245 } 246 if (defaultDesc != null) 247 defaultDesc.launch(args); 248 else 249 throw new ApplicationException(ApplicationException.APPLICATION_INTERNAL_ERROR, Messages.application_noIdFound); 250 } 251 252 256 private void registerAppDescriptors() { 257 IExtension[] availableApps = getAvailableAppExtensions(); 258 for (int i = 0; i < availableApps.length; i++) 259 createAppDescriptor(availableApps[i]); 260 } 261 262 private void registerAppDescriptor(String applicationId) { 263 IExtension appExtension = getAppExtension(applicationId); 264 if (appExtension != null) 265 createAppDescriptor(appExtension); 266 } 267 268 272 private IExtension[] getAvailableAppExtensions() { 273 IExtensionPoint point = extensionRegistry.getExtensionPoint(PI_RUNTIME + '.' + PT_APPLICATIONS); 274 if (point == null) 275 return new IExtension[0]; 276 return point.getExtensions(); 277 } 278 279 String getAvailableAppsMsg() { 280 IExtension[] availableApps = getAvailableAppExtensions(); 281 String availableAppsMsg = "<NONE>"; if (availableApps.length != 0) { 283 availableAppsMsg = availableApps[0].getUniqueIdentifier(); 284 for (int i = 1; i < availableApps.length; i++) 285 availableAppsMsg = availableAppsMsg + ", " + availableApps[i].getUniqueIdentifier(); } 287 return availableAppsMsg; 288 } 289 290 295 IExtension getAppExtension(String applicationId) { 296 return extensionRegistry.getExtension(PI_RUNTIME, PT_APPLICATIONS, applicationId); 297 } 298 299 void launch(EclipseAppHandle appHandle) throws Exception { 300 lock(appHandle); 301 boolean isDefault = appHandle.isDefault(); 302 if (((EclipseAppDescriptor) appHandle.getApplicationDescriptor()).getThreadType() == EclipseAppDescriptor.FLAG_TYPE_MAIN_THREAD) { 303 DefaultApplicationListener curDefaultApplicationListener = null; 305 ApplicationLauncher appLauncher = null; 306 synchronized (this) { 307 appLauncher = (ApplicationLauncher) launcherTracker.getService(); 308 if (appLauncher == null) { 309 if (isDefault) { 310 defaultMainThreadAppHandle = appHandle; 313 return; 314 } 315 throw new ApplicationException(ApplicationException.APPLICATION_INTERNAL_ERROR); 316 } 317 curDefaultApplicationListener = defaultAppListener; 318 } 319 if (curDefaultApplicationListener != null) 320 curDefaultApplicationListener.launch(appHandle); 321 else 322 appLauncher.launch(appHandle, appHandle.getArguments().get(IApplicationContext.APPLICATION_ARGS)); 323 } else { 324 AnyThreadAppLauncher.launchEclipseApplication(appHandle); 325 DefaultApplicationListener curDefaultApplicationListener = null; 326 if (isDefault) { 327 ApplicationLauncher appLauncher = null; 328 synchronized (this) { 329 appLauncher = (ApplicationLauncher) launcherTracker.getService(); 330 if (defaultAppListener == null) 331 defaultAppListener = new DefaultApplicationListener(appHandle); 332 curDefaultApplicationListener = defaultAppListener; 333 if (appLauncher == null) { 334 defaultMainThreadAppHandle = curDefaultApplicationListener; 337 return; 338 } 339 } 340 appLauncher.launch(curDefaultApplicationListener, null); 341 } 342 } 343 } 344 345 public void registryChanged(IRegistryChangeEvent event) { 346 processAppDeltas(event.getExtensionDeltas(PI_RUNTIME, PT_APPLICATIONS)); 347 processAppDeltas(event.getExtensionDeltas(Activator.PI_APP, PT_APPLICATIONS)); 348 } 349 350 private void processAppDeltas(IExtensionDelta[] deltas) { 351 for (int i = 0; i < deltas.length; i++) { 352 switch (deltas[i].getKind()) { 353 case IExtensionDelta.ADDED : 354 createAppDescriptor(deltas[i].getExtension()); 355 break; 356 case IExtensionDelta.REMOVED : 357 removeAppDescriptor(deltas[i].getExtension().getUniqueIdentifier()); 358 break; 359 } 360 } 361 } 362 363 public void bundleChanged(BundleEvent event) { 364 if ((BundleEvent.STOPPING & event.getType()) == 0 || event.getBundle().getBundleId() != 0) 366 return; 367 stopAllApps(); 369 } 370 371 private void stopAllApps() { 372 try { 374 ServiceReference[] runningRefs = context.getServiceReferences(ApplicationHandle.class.getName(), "(!(application.state=STOPPING))"); if (runningRefs != null) 376 for (int i = 0; i < runningRefs.length; i++) { 377 ApplicationHandle handle = (ApplicationHandle) context.getService(runningRefs[i]); 378 try { 379 if (handle != null) 380 handle.destroy(); 381 } catch (Throwable t) { 382 String message = NLS.bind(Messages.application_error_stopping, handle.getInstanceId()); 383 Activator.log(new FrameworkLogEntry(Activator.PI_APP, FrameworkLogEntry.WARNING, 0, message, 0, t, null)); 384 } finally { 385 if (handle != null) 386 context.ungetService(runningRefs[i]); 387 } 388 } 389 } catch (InvalidSyntaxException e) { 390 } 392 } 393 394 private String getDefaultAppId() { 395 if (defaultAppId != null) 396 return defaultAppId; 397 defaultAppId = CommandLineArgs.getApplication(); 399 if (defaultAppId != null) 400 return defaultAppId; 401 402 defaultAppId = context.getProperty(EclipseAppContainer.PROP_ECLIPSE_APPLICATION); 404 if (defaultAppId != null) 405 return defaultAppId; 406 407 defaultAppId = getBranding() == null ? null : getBranding().getApplication(); 409 return defaultAppId; 410 } 411 412 public IBranding getBranding() { 413 if (branding != null) 414 return branding; 415 String productId = CommandLineArgs.getProduct(); 417 if (productId == null) { 418 if (context == null) 420 return null; 421 productId = context.getProperty(PROP_PRODUCT); 422 if (productId == null) 423 return null; 424 } 425 IConfigurationElement[] entries = extensionRegistry.getConfigurationElementsFor(PI_RUNTIME, PT_PRODUCTS, productId); 426 if (entries.length > 0) { 427 branding = new ProductExtensionBranding(productId, entries[0]); 429 return branding; 430 } 431 IConfigurationElement[] elements = extensionRegistry.getConfigurationElementsFor(PI_RUNTIME, PT_PRODUCTS); 432 List logEntries = null; 433 for (int i = 0; i < elements.length; i++) { 434 IConfigurationElement element = elements[i]; 435 if (element.getName().equalsIgnoreCase("provider")) { try { 437 Object provider = element.createExecutableExtension("run"); Object [] products = (Object []) EclipseAppContainer.callMethod(provider, "getProducts", null, null); for (int j = 0; j < products.length; j++) { 440 if (productId.equalsIgnoreCase((String ) EclipseAppContainer.callMethod(products[j], "getId", null, null))) { 441 branding = new ProviderExtensionBranding(products[j]); 442 return branding; 443 } 444 } 445 } catch (CoreException e) { 446 if (logEntries == null) 447 logEntries = new ArrayList(3); 448 logEntries.add(new FrameworkLogEntry(Activator.PI_APP, NLS.bind(Messages.provider_invalid, element.getParent().toString()), 0, e, null)); 449 } 450 } 451 } 452 if (logEntries != null) 453 Activator.log(new FrameworkLogEntry(Activator.PI_APP, Messages.provider_invalid_general, 0, null, (FrameworkLogEntry[]) logEntries.toArray(new FrameworkLogEntry[logEntries.size()]))); 454 455 if (!missingProductReported) { 456 Activator.log(new FrameworkLogEntry(Activator.PI_APP, NLS.bind(Messages.product_notFound, productId), 0, null, null)); 457 missingProductReported = true; 458 } 459 return null; 460 } 461 462 private void refreshAppDescriptors() { 463 synchronized (apps) { 464 for (Iterator allApps = apps.values().iterator(); allApps.hasNext();) 465 ((EclipseAppDescriptor) allApps.next()).refreshProperties(); 466 } 467 } 468 469 synchronized void lock(EclipseAppHandle appHandle) throws ApplicationException { 470 EclipseAppDescriptor eclipseApp = (EclipseAppDescriptor) appHandle.getApplicationDescriptor(); 471 switch (isLocked(eclipseApp)) { 472 case NOT_LOCKED : 473 break; 474 case LOCKED_SINGLETON_GLOBAL_RUNNING : 475 throw new ApplicationException(ApplicationException.APPLICATION_INTERNAL_ERROR, NLS.bind(Messages.singleton_running, activeGlobalSingleton.getInstanceId())); 476 case LOCKED_SINGLETON_GLOBAL_APPS_RUNNING : 477 throw new ApplicationException(ApplicationException.APPLICATION_INTERNAL_ERROR, Messages.apps_running); 478 case LOCKED_SINGLETON_SCOPED_RUNNING : 479 throw new ApplicationException(ApplicationException.APPLICATION_INTERNAL_ERROR, NLS.bind(Messages.singleton_running, activeScopedSingleton.getInstanceId())); 480 case LOCKED_SINGLETON_LIMITED_RUNNING : 481 throw new ApplicationException(ApplicationException.APPLICATION_INTERNAL_ERROR, NLS.bind(Messages.max_running, eclipseApp.getApplicationId())); 482 case LOCKED_MAIN_THREAD_RUNNING : 483 throw new ApplicationException(ApplicationException.APPLICATION_INTERNAL_ERROR, NLS.bind(Messages.main_running, activeMain.getInstanceId())); 484 default : 485 break; 486 } 487 488 if (eclipseApp.getThreadType() == EclipseAppDescriptor.FLAG_TYPE_MAIN_THREAD) { 489 if (activeMain != null) 490 throw new IllegalStateException (Messages.main_running + activeMain.getInstanceId()); 491 } 492 switch (eclipseApp.getCardinalityType()) { 494 case EclipseAppDescriptor.FLAG_CARD_SINGLETON_GLOGAL : 495 activeGlobalSingleton = appHandle; 496 break; 497 case EclipseAppDescriptor.FLAG_CARD_SINGLETON_SCOPED : 498 activeScopedSingleton = appHandle; 499 break; 500 case EclipseAppDescriptor.FLAG_CARD_LIMITED : 501 if (activeLimited == null) 502 activeLimited = new HashMap(3); 503 ArrayList limited = (ArrayList) activeLimited.get(eclipseApp.getApplicationId()); 504 if (limited == null) { 505 limited = new ArrayList(eclipseApp.getCardinality()); 506 activeLimited.put(eclipseApp.getApplicationId(), limited); 507 } 508 limited.add(appHandle); 509 break; 510 case EclipseAppDescriptor.FLAG_CARD_UNLIMITED : 511 break; 512 default : 513 break; 514 } 515 if (eclipseApp.getThreadType() == EclipseAppDescriptor.FLAG_TYPE_MAIN_THREAD) 516 activeMain = appHandle; 517 activeHandles.add(appHandle); 518 refreshAppDescriptors(); 519 } 520 521 synchronized void unlock(EclipseAppHandle appHandle) { 522 if (activeGlobalSingleton == appHandle) 523 activeGlobalSingleton = null; 524 else if (activeScopedSingleton == appHandle) 525 activeScopedSingleton = null; 526 else if (((EclipseAppDescriptor) appHandle.getApplicationDescriptor()).getCardinalityType() == EclipseAppDescriptor.FLAG_CARD_LIMITED) { 527 if (activeLimited != null) { 528 ArrayList limited = (ArrayList) activeLimited.get(((EclipseAppDescriptor) appHandle.getApplicationDescriptor()).getApplicationId()); 529 if (limited != null) 530 limited.remove(appHandle); 531 } 532 } 533 if (activeMain == appHandle) 534 activeMain = null; 535 if (activeHandles.remove(appHandle)) 536 refreshAppDescriptors(); } 538 539 synchronized int isLocked(EclipseAppDescriptor eclipseApp) { 540 if (activeGlobalSingleton != null) 541 return LOCKED_SINGLETON_GLOBAL_RUNNING; 542 switch (eclipseApp.getCardinalityType()) { 543 case EclipseAppDescriptor.FLAG_CARD_SINGLETON_GLOGAL : 544 if (activeHandles.size() > 0) 545 return LOCKED_SINGLETON_GLOBAL_APPS_RUNNING; 546 break; 547 case EclipseAppDescriptor.FLAG_CARD_SINGLETON_SCOPED : 548 if (activeScopedSingleton != null) 549 return LOCKED_SINGLETON_SCOPED_RUNNING; 550 break; 551 case EclipseAppDescriptor.FLAG_CARD_LIMITED : 552 if (activeLimited != null) { 553 ArrayList limited = (ArrayList) activeLimited.get(eclipseApp.getApplicationId()); 554 if (limited != null && limited.size() >= eclipseApp.getCardinality()) 555 return LOCKED_SINGLETON_LIMITED_RUNNING; 556 } 557 break; 558 case EclipseAppDescriptor.FLAG_CARD_UNLIMITED : 559 break; 560 default : 561 break; 562 } 563 if (eclipseApp.getThreadType() == EclipseAppDescriptor.FLAG_TYPE_MAIN_THREAD && activeMain != null) 564 return LOCKED_MAIN_THREAD_RUNNING; 565 return NOT_LOCKED; 566 } 567 568 static Object callMethod(Object obj, String methodName, Class [] argTypes, Object [] args) { 569 Throwable error = null; 570 try { 571 Method method = obj.getClass().getMethod(methodName, argTypes); 572 return method.invoke(obj, args); 573 } catch (SecurityException e) { 574 error = e; 575 } catch (NoSuchMethodException e) { 576 error = e; 577 } catch (IllegalArgumentException e) { 578 error = e; 579 } catch (IllegalAccessException e) { 580 error = e; 581 } catch (InvocationTargetException e) { 582 error = e.getTargetException(); 583 } 584 if (error != null) { 585 Activator.log(new FrameworkLogEntry(Activator.PI_APP, FrameworkLogEntry.ERROR, 0, "Error in invoking method.", 0, error, null)); 586 } 587 return null; 588 } 589 590 public Object addingService(ServiceReference reference) { 591 ApplicationLauncher appLauncher; 592 ParameterizedRunnable appRunnable; 593 synchronized (this) { 594 appLauncher = (ApplicationLauncher) context.getService(reference); 595 appRunnable = defaultMainThreadAppHandle; 597 defaultMainThreadAppHandle = null; 599 } 600 if (appRunnable != null) 601 appLauncher.launch(appRunnable, appRunnable instanceof EclipseAppHandle ? ((EclipseAppHandle) appRunnable).getArguments().get(IApplicationContext.APPLICATION_ARGS) : null); 603 return appLauncher; 604 } 605 606 public void modifiedService(ServiceReference reference, Object service) { 607 } 609 610 public void removedService(ServiceReference reference, Object service) { 611 } 613 } 614 | Popular Tags |