/** * Loads the class <code>qualifiedName</code> from the specified <code>bundle</code> if possible. * * @param bundle The bundle from which to load the sought class. * @param qualifiedName Qualified name of the class that is to be loaded. * @return An instance of the class if it could be loaded, <code>null</code> otherwise. */ private Class<?> internalLoadClass(Bundle bundle, String qualifiedName) { try { WorkspaceClassInstance workspaceInstance = workspaceLoadedClasses.get(qualifiedName); final Class<?> clazz; if (workspaceInstance == null) { clazz = bundle.loadClass(qualifiedName); workspaceLoadedClasses.put( qualifiedName, new WorkspaceClassInstance(clazz, bundle.getSymbolicName())); } else if (workspaceInstance.isStale()) { clazz = bundle.loadClass(qualifiedName); workspaceInstance.setStale(false); workspaceInstance.setClass(clazz); } else { clazz = workspaceInstance.getClassInstance(); } return clazz; } catch (ClassNotFoundException e) { e.fillInStackTrace(); AcceleoCommonPlugin.log( AcceleoCommonMessages.getString( "BundleClassLookupFailure", //$NON-NLS-1$ qualifiedName, bundle.getSymbolicName()), e, false); } return null; }
/** * This will refresh the workspace contributions if needed, then search through the workspace * loaded bundles for a class corresponding to <code>qualifiedName</code>. * * @param qualifiedName The qualified name of the class we seek to load. * @param honorOSGiVisibility If <code>true</code>, this will only search through exported * packages for the class <code>qualifiedName</code>. Otherwise we'll search through all * bundles by simply trying to load the class and catching the {@link ClassNotFoundException} * if it isn't loadable. * @return The class <code>qualifiedName</code> if it could be found in the workspace bundles, * <code>null</code> otherwise. */ public synchronized Class<?> getClass(String qualifiedName, boolean honorOSGiVisibility) { if (changedContributions.size() > 0) { refreshContributions(); } // Has an instance of this class already been loaded? Class<?> clazz = null; final WorkspaceClassInstance workspaceInstance = workspaceLoadedClasses.get(qualifiedName); if (workspaceInstance != null) { if (workspaceInstance.isStale()) { for (Map.Entry<IPluginModelBase, Bundle> entry : workspaceInstalledBundles.entrySet()) { final IPluginModelBase model = entry.getKey(); if (workspaceInstance .getBundle() .equals(model.getBundleDescription().getSymbolicName())) { clazz = internalLoadClass(entry.getValue(), qualifiedName); workspaceInstance.setStale(false); workspaceInstance.setClass(clazz); break; } } } else { clazz = workspaceInstance.getInstance().getClass(); } } if (clazz != null) { return clazz; } // The class hasn't been instantiated yet ; search for the class without instantiating it Iterator<Map.Entry<IPluginModelBase, Bundle>> iterator = workspaceInstalledBundles.entrySet().iterator(); while (clazz == null && iterator.hasNext()) { Map.Entry<IPluginModelBase, Bundle> entry = iterator.next(); /* * If we're asked to honor OSGi package visibility, we'll first check the "Export-Package" header * of this bundle's MANIFEST. */ if (!honorOSGiVisibility || hasCorrespondingExportPackage(entry.getKey(), qualifiedName)) { try { clazz = entry.getValue().loadClass(qualifiedName); } catch (ClassNotFoundException e) { // Swallow this ; we'll log the issue later on if we cannot find the class at all } } } if (clazz == null) { AcceleoCommonPlugin.log( AcceleoCommonMessages.getString( "BundleClassLookupFailure", //$NON-NLS-1$ qualifiedName), false); } return clazz; }
/** * Retrieves the singleton instance of the given service class after refreshing it if needed. * * @param serviceClass The service class we need an instance of. * @return The singleton instance of the given service class if any. */ public synchronized Object getServiceInstance(Class<?> serviceClass) { String qualifiedName = serviceClass.getName(); for (Map.Entry<String, WorkspaceClassInstance> workspaceClass : workspaceLoadedClasses.entrySet()) { if (workspaceClass.getKey().equals(qualifiedName)) { WorkspaceClassInstance workspaceInstance = workspaceClass.getValue(); if (workspaceInstance.isStale()) { for (Map.Entry<IPluginModelBase, Bundle> entry : workspaceInstalledBundles.entrySet()) { final IPluginModelBase model = entry.getKey(); if (workspaceInstance .getBundle() .equals(model.getBundleDescription().getSymbolicName())) { Class<?> clazz = internalLoadClass(entry.getValue(), qualifiedName); workspaceInstance.setStale(false); workspaceInstance.setClass(clazz); break; } } } return workspaceInstance.getInstance(); } } return null; }
/** * This will process IResourceChangeEvent.POST_BUILD events so that we can react to builds of * our workspace loaded services. * * @param event The event that is to be processed. Assumes that <code> * event.getType() == IResourceChangeEvent.POST_BUILD</code>. */ private void processBuildEvent(IResourceChangeEvent event) { final IResourceDelta delta = event.getDelta(); switch (event.getBuildKind()) { case IncrementalProjectBuilder.AUTO_BUILD: // Nothing built in such cases if (!ResourcesPlugin.getWorkspace().isAutoBuilding()) { break; } // Fall through to the incremental build handling otherwise // $FALL-THROUGH$ case IncrementalProjectBuilder.INCREMENTAL_BUILD: final AcceleoDeltaVisitor visitor = new AcceleoDeltaVisitor(); try { delta.accept(visitor); } catch (CoreException e) { AcceleoCommonPlugin.log(e, false); } for (IProject changed : visitor.getChangedProjects()) { IPluginModelBase model = PluginRegistry.findModel(changed); if (model != null) { changedContributions.add(model); } } for (String changedClass : visitor.getChangedClasses()) { final WorkspaceClassInstance workspaceInstance = workspaceLoadedClasses.get(changedClass); if (workspaceInstance != null) { workspaceInstance.setStale(true); } } break; case IncrementalProjectBuilder.FULL_BUILD: for (Map.Entry<IPluginModelBase, Bundle> entry : workspaceInstalledBundles.entrySet()) { IPluginModelBase model = entry.getKey(); if (model != null) { changedContributions.add(model); } } for (WorkspaceClassInstance workspaceInstance : workspaceLoadedClasses.values()) { workspaceInstance.setStale(true); } break; case IncrementalProjectBuilder.CLEAN_BUILD: // workspace has been cleaned. Unload every service until next they're built final Iterator<Map.Entry<IPluginModelBase, Bundle>> workspaceBundleIterator = workspaceInstalledBundles.entrySet().iterator(); while (workspaceBundleIterator.hasNext()) { Map.Entry<IPluginModelBase, Bundle> entry = workspaceBundleIterator.next(); final Bundle bundle = entry.getValue(); try { uninstallBundle(bundle); } catch (BundleException e) { AcceleoCommonPlugin.log( new Status( IStatus.ERROR, AcceleoCommonPlugin.PLUGIN_ID, AcceleoCommonMessages.getString( UNINSTALLATION_FAILURE_KEY, bundle.getSymbolicName()), e)); } workspaceBundleIterator.remove(); } for (WorkspaceClassInstance workspaceInstance : workspaceLoadedClasses.values()) { workspaceInstance.setStale(true); } break; default: // no default action } }