1 11 package org.eclipse.update.internal.configurator; 12 13 import java.io.*; 14 import java.net.*; 15 import java.util.*; 16 17 import org.eclipse.core.runtime.*; 18 import org.eclipse.osgi.framework.log.*; 19 import org.eclipse.osgi.service.datalocation.*; 20 import org.eclipse.osgi.service.debug.*; 21 import org.eclipse.osgi.util.ManifestElement; 22 import org.eclipse.osgi.util.NLS; 23 import org.eclipse.update.configurator.*; 24 import org.osgi.framework.*; 25 import org.osgi.service.packageadmin.*; 26 import org.osgi.service.startlevel.*; 27 import org.osgi.util.tracker.*; 28 29 public class ConfigurationActivator implements BundleActivator, IBundleGroupProvider, IConfigurationConstants { 30 31 public static String PI_CONFIGURATOR = "org.eclipse.update.configurator"; public static final String INSTALL_LOCATION = "osgi.installLocation"; public static final String LAST_CONFIG_STAMP = "last.config.stamp"; public static final String NAME_SPACE = "org.eclipse.update"; public static final String UPDATE_PREFIX = "update@"; private static final String INITIAL_PREFIX = "initial@"; 38 public static String OPTION_DEBUG = PI_CONFIGURATOR + "/debug"; public static boolean DEBUG = false; 42 43 private static BundleContext context; 44 private ServiceTracker platformTracker; 45 private ServiceRegistration configurationFactorySR; 46 private ServiceRegistration bundleGroupProviderSR; 47 private PlatformConfiguration configuration; 48 49 private Location configLocation; 51 52 private long lastTimeStamp; 54 55 private long lastStateTimeStamp; 57 58 private static ConfigurationActivator configurator; 60 61 public ConfigurationActivator() { 62 configurator = this; 63 } 64 65 public void start(BundleContext ctx) throws Exception { 66 context = ctx; 67 loadOptions(); 68 acquireFrameworkLogService(); 69 initialize(); 70 71 if (canRunWithCachedData()) { 73 Utils.debug("Running with cached data"); registerBundleGroupProvider(); 75 return; 76 } 77 78 Utils.debug("Starting update configurator..."); 80 String reconcile = System.getProperty("org.eclipse.update.reconcile"); if (reconcile == null || reconcile.equalsIgnoreCase("true")) installBundles(); 83 registerBundleGroupProvider(); 84 } 85 86 private void registerBundleGroupProvider() { 87 bundleGroupProviderSR = getBundleContext().registerService(IBundleGroupProvider.class.getName(), this, null); 88 } 89 90 private void initialize() throws Exception { 91 if (!Utils.isRunning()) 96 throw new Exception (Messages.ConfigurationActivator_initialize); 97 98 configLocation = Utils.getConfigurationLocation(); 99 if (!configLocation.isReadOnly()) { 101 try { 102 URL privateURL = new URL(configLocation.getURL(), NAME_SPACE); 103 File f = new File(privateURL.getFile()); 104 if(!f.exists()) 105 f.mkdirs(); 106 } catch (MalformedURLException e1) { 107 } 109 } 110 configurationFactorySR = context.registerService(IPlatformConfigurationFactory.class.getName(), new PlatformConfigurationFactory(), null); 111 configuration = getPlatformConfiguration(Utils.getInstallURL(), configLocation); 112 if (configuration == null) 113 throw Utils.newCoreException(NLS.bind(Messages.ConfigurationActivator_createConfig, (new String [] { configLocation.getURL().toExternalForm() })), null); 114 115 DataInputStream stream = null; 116 try { 117 stream = new DataInputStream(new URL(configLocation.getURL(),NAME_SPACE+'/'+LAST_CONFIG_STAMP).openStream()); 118 lastTimeStamp = stream.readLong(); 119 lastStateTimeStamp = stream.readLong(); 120 } catch (Exception e) { 121 lastTimeStamp = configuration.getChangeStamp() - 1; 122 lastStateTimeStamp = -1; 123 } finally { 124 if (stream != null) 125 try { 126 stream.close(); 127 } catch (IOException e1) { 128 Utils.log(e1.getLocalizedMessage()); 129 } 130 } 131 } 132 133 134 public void stop(BundleContext ctx) throws Exception { 135 try { 137 PlatformConfiguration.shutdown(); 138 } catch (IOException e) { 139 e.printStackTrace(); 141 } 142 configurationFactorySR.unregister(); 143 if (bundleGroupProviderSR != null) 144 bundleGroupProviderSR.unregister(); 145 Utils.shutdown(); 146 } 147 148 public boolean installBundles() { 149 Utils.debug("Installing bundles..."); ServiceReference reference = context.getServiceReference(StartLevel.class.getName()); 151 int startLevel = 4; 152 String defaultStartLevel = context.getProperty("osgi.bundles.defaultStartLevel"); if (defaultStartLevel != null) { 154 try { 155 startLevel = Integer.parseInt(defaultStartLevel); 156 } catch (NumberFormatException e1) { 157 startLevel = 4; 158 } 159 } 160 if (startLevel < 1) 161 startLevel = 4; 162 163 StartLevel start = null; 164 if (reference != null) 165 start = (StartLevel) context.getService(reference); 166 try { 167 Bundle[] cachedBundles = context.getBundles(); 170 URL[] plugins = configuration.getPluginPath(); 171 172 List toRefresh = getUnresolvedBundles(); 174 175 Bundle[] bundlesToUninstall = getBundlesToUninstall(cachedBundles, plugins); 176 for (int i=0; i<bundlesToUninstall.length; i++) { 177 try { 178 if (DEBUG) 179 Utils.debug("Uninstalling " + bundlesToUninstall[i].getLocation()); toRefresh.add(bundlesToUninstall[i]); 182 bundlesToUninstall[i].uninstall(); 183 } catch (Exception e) { 184 Utils.log(NLS.bind(Messages.ConfigurationActivator_uninstallBundle, (new String [] { bundlesToUninstall[i].getLocation() }))); 185 } 186 } 187 188 String [] bundlesToInstall = getBundlesToInstall(cachedBundles, plugins); 190 ArrayList lazyActivationBundles = new ArrayList(bundlesToInstall.length); 191 for (int i = 0; i < bundlesToInstall.length; i++) { 192 try { 193 if (DEBUG) 194 Utils.debug("Installing " + bundlesToInstall[i]); URL bundleURL = new URL("reference:file:"+bundlesToInstall[i]); Bundle target = context.installBundle(UPDATE_PREFIX+bundlesToInstall[i], bundleURL.openStream()); 198 toRefresh.add(target); 200 if (start != null) 201 start.setBundleStartLevel(target, startLevel); 202 if (hasLazyActivationPolicy(target)) 204 lazyActivationBundles.add(target); 205 } catch (Exception e) { 206 if (!Utils.isAutomaticallyStartedBundle(bundlesToInstall[i])) 207 Utils.log(NLS.bind(Messages.ConfigurationActivator_installBundle, (new String [] { bundlesToInstall[i] })) + " " + e.getMessage()); } 209 } 210 context.ungetService(reference); 211 removeInitialBundles(toRefresh, cachedBundles); 212 refreshPackages((Bundle[]) toRefresh.toArray(new Bundle[toRefresh.size()])); 213 for (Iterator activateBundles = lazyActivationBundles.iterator(); activateBundles.hasNext();) { 215 Bundle toActivate = (Bundle) activateBundles.next(); 216 try { 217 toActivate.start(Bundle.START_ACTIVATION_POLICY); 219 } catch (BundleException e) { 220 if ((toActivate.getState() & Bundle.RESOLVED) != 0) 221 Utils.log(NLS.bind(Messages.ConfigurationActivator_installBundle, (new String [] { toActivate.getLocation() })) + " " + e.getMessage()); } 224 } 225 writePlatformConfigurationTimeStamp(); 227 return true; 228 } catch (Exception e) { 229 return false; 230 } 231 } 232 233 private static boolean hasLazyActivationPolicy(Bundle target) { 234 Dictionary headers = target.getHeaders(""); String fragmentHost = (String ) headers.get(Constants.FRAGMENT_HOST); 238 if (fragmentHost != null) 239 return false; String activationPolicy = (String ) headers.get(Constants.BUNDLE_ACTIVATIONPOLICY); 242 try { 243 if (activationPolicy != null) { 244 ManifestElement[] elements = ManifestElement.parseHeader(Constants.BUNDLE_ACTIVATIONPOLICY, activationPolicy); 245 if (elements != null && elements.length > 0) { 246 if (Constants.ACTIVATION_LAZY.equals(elements[0].getValue())) 248 return true; 249 } 250 } else { 251 String eclipseLazyStart = (String ) headers.get("Eclipse-LazyStart"); if (eclipseLazyStart == null) 254 eclipseLazyStart = (String ) headers.get("Eclipse-AutoStart"); ManifestElement[] elements = ManifestElement.parseHeader("Eclipse-LazyStart", eclipseLazyStart); if (elements != null && elements.length > 0) { 257 if ("true".equals(elements[0].getValue())) return true; 260 else if (elements[0].getDirective("exceptions") != null) return true; 263 } 264 } 265 } catch (BundleException be) { 266 } 268 return false; 269 } 270 271 private void removeInitialBundles(List bundles, Bundle[] cachedBundles) { 272 String [] initialSymbolicNames = getInitialSymbolicNames(cachedBundles); 273 Iterator iter = bundles.iterator(); 274 while(iter.hasNext()) { 275 Bundle bundle = (Bundle) iter.next(); 276 String symbolicName = bundle.getSymbolicName(); 277 for(int i = 0; i < initialSymbolicNames.length; i++) { 278 if (initialSymbolicNames[i].equals(symbolicName)) { 279 iter.remove(); 280 break; 281 } 282 } 283 } 284 } 285 286 private String [] getInitialSymbolicNames(Bundle[] cachedBundles) { 287 ArrayList initial = new ArrayList(); 288 for (int i = 0; i < cachedBundles.length; i++) { 289 Bundle bundle = cachedBundles[i]; 290 if (bundle.getLocation().startsWith(INITIAL_PREFIX)) { 291 String symbolicName = bundle.getSymbolicName(); 292 if (symbolicName != null) 293 initial.add(symbolicName); 294 } 295 } 296 return (String []) initial.toArray(new String [initial.size()]); 297 } 298 299 private List getUnresolvedBundles() { 300 Bundle[] allBundles = context.getBundles(); 301 List unresolved = new ArrayList(); 302 for (int i = 0; i < allBundles.length; i++) 303 if (allBundles[i].getState() == Bundle.INSTALLED) 304 unresolved.add(allBundles[i]); 305 return unresolved; 306 } 307 308 private String [] getBundlesToInstall(Bundle[] cachedBundles, URL[] newPlugins) { 309 HashSet cachedBundlesSet = new HashSet(cachedBundles.length); 311 int offset = UPDATE_PREFIX.length(); 312 for (int i=0; i<cachedBundles.length; i++) { 313 if (cachedBundles[i].getBundleId() == 0) 314 continue; String bundleLocation = cachedBundles[i].getLocation(); 316 if (!bundleLocation.startsWith(UPDATE_PREFIX)) 318 continue; 319 320 bundleLocation = bundleLocation.substring(offset); 321 cachedBundlesSet.add(bundleLocation); 322 if (Utils.isWindows) 324 cachedBundlesSet.add(bundleLocation.toLowerCase()); 325 } 326 327 ArrayList bundlesToInstall = new ArrayList(newPlugins.length); 328 for (int i = 0; i < newPlugins.length; i++) { 329 String location = Utils.makeRelative(Utils.getInstallURL(), newPlugins[i]).getFile(); 330 if (cachedBundlesSet.contains(location)) 332 continue; 333 if (Utils.isWindows && cachedBundlesSet.contains(location.toLowerCase())) 334 continue; 335 336 bundlesToInstall.add(location); 337 } 338 return (String [])bundlesToInstall.toArray(new String [bundlesToInstall.size()]); 339 } 340 341 342 private Bundle[] getBundlesToUninstall(Bundle[] cachedBundles, URL[] newPlugins) { 343 HashSet newPluginsSet = new HashSet(newPlugins.length); 345 for (int i=0; i<newPlugins.length; i++) { 346 347 String pluginLocation = Utils.makeRelative(Utils.getInstallURL(), newPlugins[i]).getFile(); 348 newPluginsSet.add(pluginLocation); 349 if (Utils.isWindows) 351 newPluginsSet.add(pluginLocation.toLowerCase()); 352 } 353 354 ArrayList bundlesToUninstall = new ArrayList(); 355 int offset = UPDATE_PREFIX.length(); 356 for (int i=0; i<cachedBundles.length; i++) { 357 if (cachedBundles[i].getBundleId() == 0) 358 continue; String cachedBundleLocation = cachedBundles[i].getLocation(); 360 if (!cachedBundleLocation.startsWith(UPDATE_PREFIX)) 362 continue; 363 cachedBundleLocation = cachedBundleLocation.substring(offset); 364 365 if (newPluginsSet.contains(cachedBundleLocation)) 366 continue; 367 if (Utils.isWindows && newPluginsSet.contains(cachedBundleLocation.toLowerCase())) 368 continue; 369 370 bundlesToUninstall.add(cachedBundles[i]); 371 } 372 return (Bundle[])bundlesToUninstall.toArray(new Bundle[bundlesToUninstall.size()]); 373 } 374 375 376 380 private PlatformConfiguration getPlatformConfiguration(URL installURL, Location configLocation) { 381 try { 382 PlatformConfiguration.startup(installURL, configLocation); 383 } catch (Exception e) { 384 if (platformTracker != null) { 385 String message = e.getMessage(); 386 if (message == null) 387 message = ""; Utils.log(Utils.newStatus(message, e)); 389 } 390 } 391 return PlatformConfiguration.getCurrent(); 392 393 } 394 395 401 private void refreshPackages(Bundle[] bundles) { 402 if (bundles.length == 0) 403 return; 404 ServiceReference packageAdminRef = context.getServiceReference(PackageAdmin.class.getName()); 405 PackageAdmin packageAdmin = null; 406 if (packageAdminRef != null) { 407 packageAdmin = (PackageAdmin) context.getService(packageAdminRef); 408 if (packageAdmin == null) 409 return; 410 } 411 final boolean[] flag = new boolean[] {false}; 415 FrameworkListener listener = new FrameworkListener() { 416 public void frameworkEvent(FrameworkEvent event) { 417 if (event.getType() == FrameworkEvent.PACKAGES_REFRESHED) 418 synchronized (flag) { 419 flag[0] = true; 420 flag.notifyAll(); 421 } 422 } 423 }; 424 context.addFrameworkListener(listener); 425 packageAdmin.refreshPackages(bundles); 426 synchronized (flag) { 427 while (!flag[0]) { 428 try { 429 flag.wait(); 430 } catch (InterruptedException e) { 431 } 432 } 433 } 434 context.removeFrameworkListener(listener); 435 context.ungetService(packageAdminRef); 436 } 437 438 private void writePlatformConfigurationTimeStamp() { 439 DataOutputStream stream = null; 440 try { 441 if (configLocation.isReadOnly()) 442 return; 443 444 String configArea = configLocation.getURL().getFile(); 445 lastTimeStamp = configuration.getChangeStamp(); 446 lastStateTimeStamp = Utils.getStateStamp(); 447 stream = new DataOutputStream(new FileOutputStream(configArea +File.separator+ NAME_SPACE+ File.separator+ LAST_CONFIG_STAMP)); 448 stream.writeLong(lastTimeStamp); 449 stream.writeLong(lastStateTimeStamp); 450 } catch (Exception e) { 451 Utils.log(e.getLocalizedMessage()); 452 } finally { 453 if (stream != null) 454 try { 455 stream.close(); 456 } catch (IOException e1) { 457 Utils.log(e1.getLocalizedMessage()); 458 } 459 } 460 } 461 462 private void loadOptions() { 463 DebugOptions service = null; 465 ServiceReference reference = context.getServiceReference(DebugOptions.class.getName()); 466 if (reference != null) 467 service = (DebugOptions) context.getService(reference); 468 if (service == null) 469 return; 470 try { 471 DEBUG = service.getBooleanOption(OPTION_DEBUG, false); 472 } finally { 473 context.ungetService(reference); 475 } 476 } 477 478 private boolean canRunWithCachedData() { 479 return !"true".equals(context.getProperty("osgi.checkConfiguration")) && lastTimeStamp==configuration.getChangeStamp() && 481 lastStateTimeStamp==Utils.getStateStamp(); 482 } 483 484 public static BundleContext getBundleContext() { 485 return context; 486 } 487 488 491 public String getName() { 492 return Messages.BundleGroupProvider; 493 } 494 497 public IBundleGroup[] getBundleGroups() { 498 if (configuration == null) 499 return new IBundleGroup[0]; 500 501 IPlatformConfiguration.IFeatureEntry[] features = configuration.getConfiguredFeatureEntries(); 502 ArrayList bundleGroups = new ArrayList(features.length); 503 for (int i=0; i<features.length; i++) { 504 if (features[i] instanceof FeatureEntry 505 && ((FeatureEntry)features[i]).hasBranding()) 506 bundleGroups.add(features[i]); 507 } 508 return (IBundleGroup[])bundleGroups.toArray(new IBundleGroup[bundleGroups.size()]); 509 } 510 511 public static void setConfigurator(ConfigurationActivator configurator) { 512 ConfigurationActivator.configurator = configurator; 513 } 514 515 public static ConfigurationActivator getConfigurator() { 516 return configurator; 517 } 518 519 private void acquireFrameworkLogService() throws Exception { 520 ServiceReference logServiceReference = context.getServiceReference(FrameworkLog.class.getName()); 521 if (logServiceReference == null) 522 return; 523 Utils.log = (FrameworkLog) context.getService(logServiceReference); 524 } 525 } 526 527 | Popular Tags |