package org.docear.plugin.core; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.Hashtable; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import org.docear.plugin.core.workspace.compatible.DocearConversionURLHandler; import org.docear.plugin.core.workspace.controller.DocearConversionDescriptor; import org.freeplane.core.util.LogUtils; import org.freeplane.features.mode.Controller; import org.freeplane.features.mode.ModeController; import org.freeplane.plugin.workspace.IWorkspaceDependingControllerExtension; import org.freeplane.plugin.workspace.WorkspaceDependingService; import org.osgi.framework.BundleContext; import org.osgi.framework.InvalidSyntaxException; import org.osgi.framework.ServiceReference; import org.osgi.service.url.URLConstants; import org.osgi.service.url.URLStreamHandlerService; public class Activator extends WorkspaceDependingService { CoreConfiguration config; public final void startPlugin(BundleContext context, ModeController modeController) { Hashtable<String, String[]>properties = new Hashtable<String, String[]>(); properties.put(URLConstants.URL_HANDLER_PROTOCOL, new String[] { DocearConversionDescriptor.OLD_WORKSPACE_URL_HANDLE }); context.registerService(URLStreamHandlerService.class.getName(), new DocearConversionURLHandler(), properties); getConfig().initMode(modeController); startPluginServices(context, modeController); DocearController.getController().getEventQueue().start(); } protected Collection<IWorkspaceDependingControllerExtension> getControllerExtensions() { List<IWorkspaceDependingControllerExtension> controllerExtensions = new ArrayList<IWorkspaceDependingControllerExtension>(); controllerExtensions.add(new IWorkspaceDependingControllerExtension() { public void installExtension(BundleContext context, Controller controller) { getConfig().initController(controller); LogUtils.info("Docear Core controller extension initiated."); startControllerExtensions(context, controller); } }); return controllerExtensions; } private CoreConfiguration getConfig() { if(config == null) { config = new CoreConfiguration(); } return config; } @SuppressWarnings("rawtypes") protected final void startPluginServices(BundleContext context, ModeController modeController) { try { final ServiceReference[] dependends = context.getServiceReferences(DocearService.class.getName(), "(dependsOn="+DocearService.DEPENDS_ON+")"); if (dependends != null) { List<DocearService> services = sortOnDependencies(dependends, context); for(DocearService service : services) { if(isValid(service)) { service.startService(context, modeController); } } } } catch (final InvalidSyntaxException e) { e.printStackTrace(); } } @SuppressWarnings("rawtypes") protected final void startControllerExtensions(BundleContext context, Controller controller) { try { final ServiceReference[] extensions = context.getServiceReferences(IDocearControllerExtension.class.getName(), "(dependsOn="+DocearService.DEPENDS_ON+")"); // if (extensions != null) { // List<?> extensions = sortOnDependencies(extensions, context); // for(Object extension : extensions) { // ((IControllerExtensionProvider) extension).installExtension(controller); // } // // } if (extensions != null) { for (ServiceReference serviceReference : extensions) { final IDocearControllerExtension extension = (IDocearControllerExtension) context.getService(serviceReference); extension.installExtension(context, controller); context.ungetService(serviceReference); } } } catch (final InvalidSyntaxException e) { e.printStackTrace(); } } private boolean isValid(DocearService service) { if(isBlacklisted(service.getBundleInfo().getBundleName())) { return false; } return true; } private boolean isBlacklisted(String packageName) { if("org.docear.plugin.backup".equals(packageName)) { return true; } return false; } @SuppressWarnings({ "rawtypes", "unchecked" }) private List<DocearService> sortOnDependencies(ServiceReference[] dependends, BundleContext context) { ArrayList<DocearService> list = new ArrayList<DocearService>(); HashMap<String, Set<DocearService>> requiredFor = new HashMap<String, Set<DocearService>>(); for(ServiceReference serviceReference : dependends) { final DocearService service = (DocearService) context.getService(serviceReference); for(DocearBundleInfo info : service.getBundleInfo().getRequiredBundles()) { if(info.getBundleName().startsWith("org.docear") && !info.getBundleName().equals("org.docear.plugin.core") && !inList(info, list)) { Set<DocearService> services = requiredFor.get(info.getBundleName()); if (services == null) { services = new HashSet<DocearService>(); requiredFor.put(info.getBundleName(), services); } services.add(service); } } if(!hasDependencies(service, requiredFor.values())) { if(!list.contains(service)) { list.add(service); } continue; } // resolveDependencies(list, requiredFor); } while( requiredFor.size() > 0) { resolveDependencies(list, requiredFor); } return list; } private boolean hasDependencies(DocearService service, Collection<Set<DocearService>> collection) { for(Set<DocearService> set : collection) { if(set.contains(service)) { return true; } } return false; } /** * @param list * @param requiredFor */ private void resolveDependencies(List<DocearService> list, Map<String, Set<DocearService>> map) { ArrayList<DocearService> buffer = new ArrayList<DocearService>(); for(DocearService plugin : list) { if(map.containsKey(plugin.getBundleInfo().getBundleName())) { Set<DocearService> services = map.get(plugin.getBundleInfo().getBundleName()); if (services != null) { Iterator<DocearService> iter = services.iterator(); map.remove(plugin.getBundleInfo().getBundleName()); while (iter.hasNext()) { DocearService inDept = iter.next(); iter.remove(); if(!hasMoreDepencies(map, inDept)) { buffer.add(inDept); } } } } } for(DocearService plugin : buffer) { if(!list.contains(plugin)) { list.add(plugin); } } } private boolean hasMoreDepencies(Map<String, Set<DocearService>> map, DocearService inDept) { for(Set<DocearService> services : map.values()) { if(services.contains(inDept)) { return true; } } return false; } /** * @param info * @param list * @return <code>true</code> if ..., else <code>false</code> */ private boolean inList(DocearBundleInfo info, List<DocearService> list) { for(DocearService plugin : list) { if(plugin.getBundleInfo().getBundleName().equals(info.getBundleName())) { return true; } } return false; } public void stop(BundleContext context) throws Exception { } @Override protected void setupDefaults(BundleContext context) { // TODO Auto-generated method stub } }