/** * Copyright (c) 2013-2016 Angelo ZERR. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Angelo Zerr <angelo.zerr@gmail.com> - initial API and implementation */ package tern.eclipse.ide.server.nodejs.internal.core; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import org.eclipse.core.runtime.IConfigurationElement; import org.eclipse.core.runtime.IExtensionDelta; import org.eclipse.core.runtime.IExtensionRegistry; import org.eclipse.core.runtime.IRegistryChangeEvent; import org.eclipse.core.runtime.IRegistryChangeListener; import org.eclipse.core.runtime.Platform; import tern.eclipse.ide.server.nodejs.core.INodejsInstall; import tern.eclipse.ide.server.nodejs.core.INodejsInstallManager; import tern.eclipse.ide.server.nodejs.core.TernNodejsCorePlugin; public class NodejsInstallManager implements INodejsInstallManager, IRegistryChangeListener { private static final String EXTENSION_NODEJS_INSTALLS = "nodeJSInstalls"; private static final NodejsInstallManager INSTANCE = new NodejsInstallManager(); // cached copy of all Nodejs install private List<INodejsInstall> nodeJSInstalls; private boolean registryListenerIntialized; public static NodejsInstallManager getManager() { return INSTANCE; } public NodejsInstallManager() { this.registryListenerIntialized = false; } @Override public void registryChanged(final IRegistryChangeEvent event) { IExtensionDelta[] deltas = event.getExtensionDeltas( TernNodejsCorePlugin.PLUGIN_ID, EXTENSION_NODEJS_INSTALLS); if (deltas != null) { for (IExtensionDelta delta : deltas) handleNodejsInstallDelta(delta); } } /** * Returns an array of all known Nodejs installs. * <p> * A new array is returned on each call, so clients may store or modify the * result. * </p> * * @return the array of Nodejs installs {@link INodejsInstall} */ public INodejsInstall[] getNodejsInstalls() { if (nodeJSInstalls == null) loadNodejsInstalls(); INodejsInstall[] st = new INodejsInstall[nodeJSInstalls.size()]; nodeJSInstalls.toArray(st); return st; } /** * Returns the Nodejs install with the given id, or <code>null</code> if * none. This convenience method searches the list of known Nodejs installs * ({@link #getNodejsInstalls()}) for the one with a matching Nodejs install * id ({@link INodejsInstall#getId()}). The id may not be null. * * @param id * the Nodejs install id * @return the Nodejs install, or <code>null</code> if there is no generator * type with the given id */ public INodejsInstall findNodejsInstall(String id) { if (id == null) throw new IllegalArgumentException(); if (nodeJSInstalls == null) loadNodejsInstalls(); Iterator<INodejsInstall> iterator = nodeJSInstalls.iterator(); while (iterator.hasNext()) { INodejsInstall nodeJSInstall = (INodejsInstall) iterator.next(); if (id.equals(nodeJSInstall.getId())) return nodeJSInstall; } return null; } /** * Load the Nodejs installs. */ private synchronized void loadNodejsInstalls() { if (nodeJSInstalls != null) return; Trace.trace(Trace.EXTENSION_POINT, "->- Loading .nodeJSInstalls extension point ->-"); IExtensionRegistry registry = Platform.getExtensionRegistry(); IConfigurationElement[] cf = registry.getConfigurationElementsFor( TernNodejsCorePlugin.PLUGIN_ID, EXTENSION_NODEJS_INSTALLS); List<INodejsInstall> list = new ArrayList<INodejsInstall>(cf.length); addNodejsInstalls(cf, list); addRegistryListenerIfNeeded(); nodeJSInstalls = list; Trace.trace(Trace.EXTENSION_POINT, "-<- Done loading .nodeJSInstalls extension point -<-"); } /** * Load the Nodejs installs. */ private synchronized void addNodejsInstalls(IConfigurationElement[] cf, List<INodejsInstall> list) { for (IConfigurationElement ce : cf) { try { list.add(new NodejsInstall(ce)); Trace.trace(Trace.EXTENSION_POINT, " Loaded nodeJSInstall: " + ce.getAttribute("id")); } catch (Throwable t) { Trace.trace(Trace.SEVERE, " Could not load nodeJSInstall: " + ce.getAttribute("id"), t); } } } protected void handleNodejsInstallDelta(IExtensionDelta delta) { if (nodeJSInstalls == null) // not loaded yet return; IConfigurationElement[] cf = delta.getExtension() .getConfigurationElements(); List<INodejsInstall> list = new ArrayList<INodejsInstall>( nodeJSInstalls); if (delta.getKind() == IExtensionDelta.ADDED) { addNodejsInstalls(cf, list); } else { int size = list.size(); NodejsInstall[] st = new NodejsInstall[size]; list.toArray(st); int size2 = cf.length; for (int i = 0; i < size; i++) { for (int j = 0; j < size2; j++) { if (st[i].getId().equals(cf[j].getAttribute("id"))) { st[i].dispose(); list.remove(st[i]); } } } } nodeJSInstalls = list; } private void addRegistryListenerIfNeeded() { if (registryListenerIntialized) return; IExtensionRegistry registry = Platform.getExtensionRegistry(); registry.addRegistryChangeListener(this, TernNodejsCorePlugin.PLUGIN_ID); registryListenerIntialized = true; } public void initialize() { } public void destroy() { Platform.getExtensionRegistry().removeRegistryChangeListener(this); } }