| package org.eclipse.dltk.tcl.core; |
| |
| import java.io.ByteArrayInputStream; |
| import java.io.File; |
| import java.io.IOException; |
| import java.io.StringReader; |
| import java.util.ArrayList; |
| import java.util.Collections; |
| import java.util.Date; |
| import java.util.HashMap; |
| import java.util.HashSet; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Set; |
| |
| import javax.xml.parsers.DocumentBuilder; |
| import javax.xml.parsers.DocumentBuilderFactory; |
| import javax.xml.parsers.ParserConfigurationException; |
| |
| import org.eclipse.core.runtime.CoreException; |
| import org.eclipse.core.runtime.IPath; |
| import org.eclipse.core.runtime.IProgressMonitor; |
| import org.eclipse.core.runtime.Platform; |
| import org.eclipse.dltk.core.DLTKCore; |
| import org.eclipse.dltk.core.ProgressMonitoringJob; |
| import org.eclipse.dltk.core.RuntimePerformanceMonitor; |
| import org.eclipse.dltk.core.RuntimePerformanceMonitor.PerformanceNode; |
| import org.eclipse.dltk.core.environment.IDeployment; |
| import org.eclipse.dltk.core.environment.IEnvironment; |
| import org.eclipse.dltk.core.environment.IExecutionEnvironment; |
| import org.eclipse.dltk.core.environment.IFileHandle; |
| import org.eclipse.dltk.launching.EnvironmentVariable; |
| import org.eclipse.dltk.launching.IInterpreterInstall; |
| import org.eclipse.dltk.launching.IInterpreterInstallChangedListener; |
| import org.eclipse.dltk.launching.InterpreterConfig; |
| import org.eclipse.dltk.launching.InterpreterStandin; |
| import org.eclipse.dltk.launching.PropertyChangeEvent; |
| import org.eclipse.dltk.launching.ScriptLaunchUtil; |
| import org.eclipse.dltk.launching.ScriptRuntime; |
| import org.eclipse.dltk.tcl.core.packages.TclInterpreterInfo; |
| import org.eclipse.dltk.tcl.core.packages.TclModuleInfo; |
| import org.eclipse.dltk.tcl.core.packages.TclPackageInfo; |
| import org.eclipse.dltk.tcl.core.packages.TclPackagesFactory; |
| import org.eclipse.dltk.tcl.core.packages.TclPackagesPackage; |
| import org.eclipse.dltk.tcl.core.packages.TclProjectInfo; |
| import org.eclipse.dltk.tcl.core.packages.VariableMap; |
| import org.eclipse.dltk.tcl.core.packages.VariableValue; |
| import org.eclipse.dltk.tcl.internal.core.packages.ProcessOutputCollector; |
| import org.eclipse.emf.common.util.BasicEMap; |
| import org.eclipse.emf.common.util.ECollections; |
| import org.eclipse.emf.common.util.EList; |
| import org.eclipse.emf.common.util.EMap; |
| import org.eclipse.emf.common.util.URI; |
| import org.eclipse.emf.ecore.EObject; |
| import org.eclipse.emf.ecore.resource.Resource; |
| import org.eclipse.emf.ecore.util.EcoreUtil; |
| import org.eclipse.emf.ecore.xmi.impl.XMIResourceImpl; |
| import org.eclipse.osgi.util.NLS; |
| import org.w3c.dom.Document; |
| import org.w3c.dom.Element; |
| import org.w3c.dom.Node; |
| import org.w3c.dom.NodeList; |
| import org.xml.sax.InputSource; |
| import org.xml.sax.SAXException; |
| import org.xml.sax.helpers.DefaultHandler; |
| |
| public class TclPackagesManager { |
| private static final String DLTK_TCL = "scripts/dltk.tcl"; //$NON-NLS-1$ |
| public static final String END_OF_STREAM = "DLTK-TCL-HELPER-9E7A168E-5EEF-4a46-A86D-0C82E90686E4-END-OF-STREAM"; //$NON-NLS-1$ |
| private static final String PKG_VERSION = "v20090505"; //$NON-NLS-1$ |
| |
| private static Resource infos = null; |
| private static final Map<String, Resource> projectInfos = new HashMap<String, Resource>(); |
| |
| private static IInterpreterInstallChangedListener installChangedListener = null; |
| private static Set<IInterpreterInstall> packageFetchingSet = new HashSet<IInterpreterInstall>(); |
| private static Set<IInterpreterInstall> sourcesFetchingSet = new HashSet<IInterpreterInstall>(); |
| |
| public static List<TclPackageInfo> getPackageInfos( |
| IInterpreterInstall install, Set<String> packageNames, |
| boolean fetchIfRequired) { |
| initialize(); |
| TclInterpreterInfo interpreterInfo = getTclInterpreter(install); |
| List<TclPackageInfo> collection; |
| synchronized (TclPackagesManager.class) { |
| collection = Collections |
| .unmodifiableList(getPackagesForInterpreter(packageNames, |
| fetchIfRequired, interpreterInfo, install)); |
| } |
| return collection; |
| } |
| |
| public static List<TclPackageInfo> getPackageInfos( |
| IInterpreterInstall install) { |
| initialize(); |
| TclInterpreterInfo interpreterInfo = getTclInterpreter(install); |
| List<TclPackageInfo> collection = null; |
| synchronized (TclPackagesManager.class) { |
| collection = Collections |
| .unmodifiableList(new ArrayList<TclPackageInfo>( |
| interpreterInfo.getPackages())); |
| } |
| return collection; |
| } |
| |
| public static TclPackageInfo getPackageInfo(IInterpreterInstall install, |
| String name, boolean fetchIfRequired) { |
| initialize(); |
| TclInterpreterInfo interpreterInfo = getTclInterpreter(install); |
| EList<TclPackageInfo> packages = interpreterInfo.getPackages(); |
| Set<TclPackageInfo> toFetch = new HashSet<TclPackageInfo>(); |
| TclPackageInfo result = null; |
| |
| synchronized (TclPackagesManager.class) { |
| for (TclPackageInfo tclPackageInfo : packages) { |
| if (name.equals(tclPackageInfo.getName())) { |
| if (tclPackageInfo.isFetched() || !fetchIfRequired) { |
| return tclPackageInfo; |
| } else { |
| toFetch.add(tclPackageInfo); |
| fetchSources(toFetch, install, interpreterInfo, null); |
| result = tclPackageInfo; |
| break; |
| } |
| } |
| } |
| } |
| return result; |
| } |
| |
| public static Set<TclPackageInfo> getDependencies( |
| IInterpreterInstall install, String name, boolean fetchIfRequired) { |
| initialize(); |
| TclPackageInfo info = getPackageInfo(install, name, fetchIfRequired); |
| if (info != null) { |
| Set<TclPackageInfo> result = new HashSet<TclPackageInfo>(); |
| Set<TclPackageInfo> toFetch = new HashSet<TclPackageInfo>(); |
| processPackage(info, result, toFetch, fetchIfRequired); |
| if (toFetch.size() > 0) { |
| TclInterpreterInfo interpreter = getTclInterpreter(install); |
| fetchSources(toFetch, install, interpreter, null); |
| processPackage(info, result, toFetch, fetchIfRequired); |
| } |
| result.remove(info); |
| return result; |
| } |
| return null; |
| } |
| |
| private static TclInterpreterInfo getTclInterpreter( |
| IInterpreterInstall install) { |
| return getTclInterpreter(install, true); |
| } |
| |
| /** |
| * @since 2.0 |
| * @param install |
| * @return |
| */ |
| public static long getTclInterpreterFetchDate(IInterpreterInstall install) { |
| TclInterpreterInfo interpreter = getTclInterpreter(install, true); |
| if (interpreter != null) { |
| return interpreter.getFetchedAt().getTime(); |
| } |
| return 0; |
| } |
| |
| private static TclInterpreterInfo getTclInterpreter( |
| IInterpreterInstall install, boolean allowCreate) { |
| TclInterpreterInfo interpreterInfo = null; |
| String interpreterLocation = install.getInstallLocation().getPath() |
| .toString(); |
| String environmentId = install.getInstallLocation().getEnvironmentId(); |
| synchronized (TclPackagesManager.class) { |
| for (EObject eObject : infos.getContents()) { |
| if (eObject instanceof TclInterpreterInfo) { |
| TclInterpreterInfo info = (TclInterpreterInfo) eObject; |
| String location = info.getInstallLocation(); |
| String name = info.getName(); |
| String env = info.getEnvironment(); |
| if (interpreterLocation.equals(location) |
| && install.getName().equals(name) && env != null |
| && env.equals(environmentId)) { |
| interpreterInfo = info; |
| break; |
| } |
| } |
| } |
| if (interpreterInfo == null) { |
| if (!allowCreate) { |
| return null; |
| } |
| interpreterInfo = TclPackagesFactory.eINSTANCE |
| .createTclInterpreterInfo(); |
| interpreterInfo.setInstallLocation(interpreterLocation); |
| interpreterInfo.setName(install.getName()); |
| interpreterInfo.setEnvironment(environmentId); |
| interpreterInfo.setFetched(false); |
| infos.getContents().add(interpreterInfo); |
| } |
| } |
| fetchPackagesForInterpreter(install, interpreterInfo); |
| |
| return interpreterInfo; |
| } |
| |
| private static long getPackagesRefreshInterval(IInterpreterInstall install) { |
| if (install == null) { |
| return 0; |
| } |
| final String refreshIntervalKey; |
| final IEnvironment environment = install.getEnvironment(); |
| if (environment != null && environment.isLocal()) { |
| refreshIntervalKey = TclCorePreferences.PACKAGES_REFRESH_INTERVAL_LOCAL; |
| } else { |
| refreshIntervalKey = TclCorePreferences.PACKAGES_REFRESH_INTERVAL_REMOTE; |
| } |
| return Platform.getPreferencesService().getLong(TclPlugin.PLUGIN_ID, |
| refreshIntervalKey, 15 * 60 * 1000, null); |
| } |
| |
| public static TclProjectInfo getTclProject(String name) { |
| Resource resource = getProjectInfoResource(name); |
| synchronized (resource) { |
| TclProjectInfo info = null; |
| for (EObject eObject : resource.getContents()) { |
| if (eObject instanceof TclProjectInfo) { |
| TclProjectInfo pinfo = (TclProjectInfo) eObject; |
| String pname = pinfo.getName(); |
| if (name != null && name.equals(pname)) { |
| info = pinfo; |
| } |
| } |
| } |
| if (info == null) { |
| info = TclPackagesFactory.eINSTANCE.createTclProjectInfo(); |
| info.setName(name); |
| resource.getContents().add(info); |
| } |
| return info; |
| } |
| } |
| |
| private static void fetchPackagesForInterpreter( |
| IInterpreterInstall install, TclInterpreterInfo interpreterInfo) { |
| synchronized (TclPackagesManager.class) { |
| while (packageFetchingSet.contains(install)) { |
| // White until it will be removed from fetches list |
| try { |
| TclPackagesManager.class.wait(50); |
| } catch (InterruptedException e) { |
| TclPlugin.error(e); |
| } |
| } |
| if (!(!interpreterInfo.isFetched() |
| || interpreterInfo.getFetchedAt() == null || interpreterInfo |
| .getFetchedAt().getTime() |
| + getPackagesRefreshInterval(install) < System |
| .currentTimeMillis())) { |
| return; // Info already fetched and ok |
| } |
| packageFetchingSet.add(install); |
| } |
| try { |
| PerformanceNode p = RuntimePerformanceMonitor.begin(); |
| IExecutionEnvironment exeEnv = install.getExecEnvironment(); |
| if (exeEnv == null) { |
| return; |
| } |
| ProgressMonitoringJob monitor = new ProgressMonitoringJob( |
| Messages.TclInterpreterMessages_RetrieveListOfAvailablePackages |
| + " " + install.getName(), 100); |
| try { |
| List<String> content = deployExecute(exeEnv, install, |
| new String[] { "get-pkgs" }, install //$NON-NLS-1$ |
| .getEnvironmentVariables(), monitor); |
| synchronized (TclPackagesManager.class) { |
| if (content != null) { |
| /* Progress monitoring */monitor |
| .subTask(Messages.TclInterpreterMessages_ProcessingPackagesInfo); |
| processContent(content, false, true, interpreterInfo); |
| /* Progress monitoring */monitor.worked(20); |
| interpreterInfo.setFetched(true); |
| interpreterInfo.setFetchedAt(new Date()); |
| monitor |
| .subTask(Messages.TclInterpreterMessages_SavePackagesInfo); |
| save(); |
| monitor.worked(10); |
| } |
| } |
| String msg = Messages.TclInterpreterMessages_FetchInterpreterPackagesInfo; |
| p.done("Tcl", msg, 0); //$NON-NLS-1$ |
| } finally { |
| monitor.done(); |
| } |
| } finally { |
| synchronized (TclPackagesManager.class) { |
| packageFetchingSet.remove(install); |
| TclPackagesManager.class.notifyAll(); |
| } |
| } |
| } |
| |
| public static void save() { |
| if (infos != null) { |
| try { |
| infos.save(null); |
| } catch (IOException e) { |
| if (DLTKCore.DEBUG) { |
| // TclPlugin.error(e); |
| } |
| } |
| } |
| synchronized (projectInfos) { |
| for (Map.Entry<String, Resource> entry : projectInfos.entrySet()) { |
| try { |
| entry.getValue().save(null); |
| } catch (IOException e) { |
| String msg = NLS.bind(Messages.TclInterpreterMessages_6, |
| entry.getKey(), e.getMessage()); |
| TclPlugin.error(msg, e); |
| } |
| } |
| } |
| } |
| |
| private static String getXMLContent(List<String> content) { |
| StringBuffer newList = new StringBuffer(); |
| if (content != null) { |
| for (Iterator<String> iterator = content.iterator(); iterator |
| .hasNext();) { |
| String line = iterator.next(); |
| if (line.trim().startsWith("<")) { //$NON-NLS-1$ |
| newList.append(line).append("\n"); //$NON-NLS-1$ |
| } |
| } |
| } |
| return newList.toString(); |
| } |
| |
| private static Document getDocument(String text) { |
| try { |
| DocumentBuilder parser = DocumentBuilderFactory.newInstance() |
| .newDocumentBuilder(); |
| parser.setErrorHandler(new DefaultHandler()); |
| InputSource source = new InputSource(new StringReader(text)); |
| Document document = parser.parse(source); |
| return document; |
| } catch (IOException e) { |
| if (DLTKCore.DEBUG) { |
| e.printStackTrace(); |
| } |
| } catch (ParserConfigurationException e) { |
| if (DLTKCore.DEBUG) { |
| e.printStackTrace(); |
| } |
| } catch (SAXException e) { |
| if (DLTKCore.DEBUG) { |
| e.printStackTrace(); |
| } |
| } |
| return null; |
| } |
| |
| private static synchronized void processContent(List<String> content, |
| boolean markAsFetched, boolean purgePackages, |
| TclInterpreterInfo info) { |
| String text = getXMLContent(content); |
| Document document = getDocument(text); |
| |
| if (document != null) { |
| final Set<String> processedPackages = new HashSet<String>(); |
| Element element = document.getDocumentElement(); |
| NodeList childNodes = element.getChildNodes(); |
| int len = childNodes.getLength(); |
| for (int i = 0; i < len; i++) { |
| Node nde = childNodes.item(i); |
| if (isElementName(nde, "path")) { //$NON-NLS-1$ |
| Element el = (Element) nde; |
| NodeList elChilds = el.getChildNodes(); |
| for (int j = 0; j < elChilds.getLength(); j++) { |
| Node pkgNde = elChilds.item(j); |
| if (isElementName(pkgNde, "package")) { //$NON-NLS-1$ |
| Element pkgElement = (Element) pkgNde; |
| String name = pkgElement.getAttribute("name"); //$NON-NLS-1$ |
| processedPackages.add(name); |
| TclPackageInfo pkg = getCreatePackage(info, name); |
| if (markAsFetched) { |
| pkg.setFetched(markAsFetched); |
| } |
| populatePackage(pkg, pkgNde, info); |
| } |
| } |
| } |
| } |
| if (purgePackages) { |
| for (Iterator<TclPackageInfo> i = info.getPackages().iterator(); i |
| .hasNext();) { |
| TclPackageInfo packageInfo = i.next(); |
| if (!processedPackages.contains(packageInfo.getName())) { |
| i.remove(); |
| } |
| } |
| } |
| } |
| } |
| |
| private static synchronized TclPackageInfo getCreatePackage( |
| TclInterpreterInfo info, String name) { |
| TclPackageInfo packageInfo = null; |
| for (TclPackageInfo pkgInfo : info.getPackages()) { |
| if (pkgInfo.getName().equals(name)) { |
| packageInfo = pkgInfo; |
| break; |
| } |
| } |
| if (packageInfo == null) { |
| packageInfo = TclPackagesFactory.eINSTANCE.createTclPackageInfo(); |
| packageInfo.setFetched(false); |
| packageInfo.setName(name); |
| info.getPackages().add(packageInfo); |
| } |
| return packageInfo; |
| } |
| |
| private static void populatePackage(TclPackageInfo info, Node pkgNde, |
| TclInterpreterInfo interpreterInfo) { |
| Element pkg = (Element) pkgNde; |
| |
| info.setVersion(pkg.getAttribute("version")); //$NON-NLS-1$ |
| NodeList childs = pkg.getChildNodes(); |
| for (int i = 0; i < childs.getLength(); i++) { |
| Node nde = childs.item(i); |
| if (isElementName(nde, "source")) { //$NON-NLS-1$ |
| Element el = (Element) nde; |
| String name = el.getAttribute("name"); //$NON-NLS-1$ |
| info.getSources().add(name); |
| } else if (isElementName(nde, "require")) { //$NON-NLS-1$ |
| Element el = (Element) nde; |
| String name = el.getAttribute("name"); //$NON-NLS-1$ |
| info.getDependencies().add( |
| getCreatePackage(interpreterInfo, name)); |
| } else if (isElementName(nde, "load")) { //$NON-NLS-1$ |
| Element el = (Element) nde; |
| String name = el.getAttribute("name"); //$NON-NLS-1$ |
| info.getLibraries().add(name); |
| } |
| } |
| } |
| |
| private static List<TclPackageInfo> getPackagesForInterpreter( |
| Set<String> packageName, boolean fetchIfRequired, |
| TclInterpreterInfo interpreterInfo, IInterpreterInstall install) { |
| Set<TclPackageInfo> result = new HashSet<TclPackageInfo>(); |
| Set<TclPackageInfo> toFetch = new HashSet<TclPackageInfo>(); |
| synchronized (TclPackagesManager.class) { |
| for (TclPackageInfo tclPackageInfo : interpreterInfo.getPackages()) { |
| if (packageName.contains(tclPackageInfo.getName())) { |
| processPackage(tclPackageInfo, result, toFetch, |
| fetchIfRequired); |
| } |
| } |
| } |
| fetchSources(toFetch, install, interpreterInfo, null); |
| synchronized (TclPackagesManager.class) { |
| for (TclPackageInfo tclPackageInfo : interpreterInfo.getPackages()) { |
| if (packageName.contains(tclPackageInfo.getName())) { |
| processPackage(tclPackageInfo, result, toFetch, |
| fetchIfRequired); |
| } |
| } |
| } |
| return new ArrayList<TclPackageInfo>(result); |
| } |
| |
| private static void processPackage(TclPackageInfo tclPackageInfo, |
| Set<TclPackageInfo> result, Set<TclPackageInfo> toFetch, |
| boolean fetchIfRequired) { |
| if (tclPackageInfo.isFetched() || !fetchIfRequired) { |
| result.add(tclPackageInfo); |
| } else if (fetchIfRequired) { |
| result.add(tclPackageInfo); |
| toFetch.add(tclPackageInfo); |
| } |
| EList<TclPackageInfo> dependencies = tclPackageInfo.getDependencies(); |
| for (TclPackageInfo tclPackageInfo2 : dependencies) { |
| if (!result.contains(tclPackageInfo2)) { |
| processPackage(tclPackageInfo2, result, toFetch, |
| fetchIfRequired); |
| } |
| } |
| } |
| |
| private static void fetchSources(Set<TclPackageInfo> toFetch, |
| IInterpreterInstall install, TclInterpreterInfo interpreterInfo, |
| IProgressMonitor topMonitor) { |
| synchronized (TclPackagesManager.class) { |
| while (sourcesFetchingSet.contains(install)) { |
| // White until it will be removed from fetches list |
| try { |
| TclPackagesManager.class.wait(50); |
| } catch (InterruptedException e) { |
| TclPlugin.error(e); |
| } |
| } |
| // Check for consistency |
| Set<TclPackageInfo> toRemove = new HashSet<TclPackageInfo>(); |
| for (TclPackageInfo tclPackageInfo : toFetch) { |
| if (tclPackageInfo.isFetched()) { |
| toRemove.add(tclPackageInfo); |
| } |
| } |
| toFetch.removeAll(toRemove); |
| if (toFetch.size() == 0) { |
| return; |
| } |
| sourcesFetchingSet.add(install); |
| } |
| |
| /* Progress monitoring */IProgressMonitor monitor = topMonitor; |
| if (monitor == null) { |
| monitor = new ProgressMonitoringJob( |
| Messages.TclInterpreterMessages_RetrievePackageInformationSources |
| + " " + install.getName(), 100); |
| } |
| try { |
| PerformanceNode p = RuntimePerformanceMonitor.begin(); |
| IExecutionEnvironment exeEnv = install.getExecEnvironment(); |
| if (exeEnv == null) { |
| return; |
| } |
| String envName = install.getEnvironment().getName(); |
| /* Progress monitoring */monitor |
| .subTask(Messages.TclInterpreterMessages_DeployingPackageInformationScript); |
| IDeployment deployment = exeEnv.createDeployment(); |
| if (deployment == null) { |
| return; |
| } |
| IFileHandle script = deploy(deployment); |
| |
| if (script == null) { |
| deployment.dispose(); |
| return; |
| } |
| /* Progress monitoring */monitor.worked(10); |
| |
| IFileHandle workingDir = script.getParent(); |
| InterpreterConfig config = ScriptLaunchUtil |
| .createInterpreterConfig(exeEnv, script, workingDir, |
| install.getEnvironmentVariables()); |
| TclLibpathUtils.addTclLibPath(config, |
| install.getLibraryLocations(), install.getEnvironment()); |
| StringBuffer buf = new StringBuffer(); |
| for (TclPackageInfo tclPackageInfo : toFetch) { |
| buf.append(tclPackageInfo.getName()).append(" "); //$NON-NLS-1$ |
| } |
| String names = buf.toString(); |
| ByteArrayInputStream bais = new ByteArrayInputStream(names |
| .getBytes()); |
| /* Progress monitoring */monitor |
| .subTask(Messages.TclInterpreterMessages_DeployingFileWithListOfPackages); |
| IPath packagesPath = null; |
| try { |
| packagesPath = deployment.add(bais, "packages.txt"); //$NON-NLS-1$ |
| } catch (IOException e1) { |
| if (DLTKCore.DEBUG) { |
| e1.printStackTrace(); |
| } |
| deployment.dispose(); |
| return; |
| } |
| /* Progress monitoring */monitor.worked(10); |
| IFileHandle file = deployment.getFile(packagesPath); |
| // For wish |
| config.removeEnvVar("DISPLAY"); //$NON-NLS-1$ |
| String[] arguments = new String[] { "get-srcs", "-fpkgs", //$NON-NLS-1$ //$NON-NLS-2$ |
| file.toOSString() }; |
| |
| config.addScriptArgs(arguments); |
| |
| /* Progress monitoring */monitor |
| .subTask(Messages.TclInterpreterMessages_RunningPackageInfoScript);// MONITORING |
| Process process = null; |
| try { |
| process = ScriptLaunchUtil.runScriptWithInterpreter(exeEnv, |
| install.getInstallLocation().toOSString(), config); |
| } catch (CoreException e) { |
| if (DLTKCore.DEBUG) { |
| e.printStackTrace(); |
| } |
| deployment.dispose(); |
| } |
| if (process == null) { |
| deployment.dispose(); |
| return; |
| } |
| /* Progress monitoring */monitor.worked(10); |
| List<String> output = ProcessOutputCollector.execute(process); |
| /* Progress monitoring */monitor.worked(40); |
| // deployment.dispose(); |
| /* Progress monitoring */monitor |
| .subTask(Messages.TclInterpreterMessages_ProcessingPackagesInfo); |
| processContent(output, true, false, interpreterInfo); |
| /* Progress monitoring */monitor.worked(20); |
| |
| // Mark all toFetch as fetched. |
| for (TclPackageInfo info : toFetch) { |
| info.setFetched(true); |
| } |
| deployment.dispose(); |
| /* Progress monitoring */monitor |
| .subTask(Messages.TclInterpreterMessages_SavePackagesInfo); |
| save(); |
| /* Progress monitoring */monitor.worked(10); |
| p |
| .done( |
| "Tcl", Messages.TclInterpreterMessages_FetchInterpreterSources, 0); //$NON-NLS-1$ |
| } finally { |
| monitor.done(); |
| synchronized (TclPackagesManager.class) { |
| sourcesFetchingSet.remove(install); |
| TclPackagesManager.class.notifyAll(); |
| } |
| } |
| } |
| |
| private static URI getInfoLocation() { |
| final IPath path = TclPlugin.getDefault().getStateLocation().append( |
| "tclPackages_" + PKG_VERSION + ".info"); //$NON-NLS-2$ //$NON-NLS-2$ |
| return URI.createFileURI(path.toOSString()); |
| } |
| |
| private static URI getProjectLocation(String projectName) { |
| final IPath path = TclPlugin.getDefault().getStateLocation().append( |
| "project-" + projectName + ".info"); //$NON-NLS-1$ //$NON-NLS-2$ |
| return URI.createFileURI(path.toOSString()); |
| } |
| |
| private static boolean canLoad(URI location) { |
| if (location.isFile()) { |
| return new File(location.toFileString()).exists(); |
| } else { |
| return true; |
| } |
| } |
| |
| private static class InterpreterInstallChangedListener implements |
| IInterpreterInstallChangedListener { |
| |
| public void defaultInterpreterInstallChanged( |
| IInterpreterInstall previous, IInterpreterInstall current) { |
| // NOP |
| } |
| |
| public void interpreterAdded(IInterpreterInstall Interpreter) { |
| // TODO Auto-generated method stub |
| } |
| |
| public void interpreterChanged(PropertyChangeEvent event) { |
| if (IInterpreterInstallChangedListener.PROPERTY_EXTENSIONS |
| .equals(event.getProperty())) { |
| VariableMap oldVars = locateVariableMap(event.getOldValue()); |
| VariableMap newVars = locateVariableMap(event.getNewValue()); |
| if (oldVars != null || newVars != null) { |
| if (oldVars != null && newVars != null) { |
| if (!EcoreUtil.equals(oldVars, newVars)) { |
| new RebuildProjectsJob((IInterpreterInstall) event |
| .getSource()).schedule(500); |
| } |
| } else { |
| new RebuildProjectsJob((IInterpreterInstall) event |
| .getSource()).schedule(500); |
| } |
| } |
| } |
| } |
| |
| private VariableMap locateVariableMap(Object value) { |
| if (value instanceof List<?>) { |
| for (Object item : (List<?>) value) { |
| if (item instanceof VariableMap) { |
| return (VariableMap) item; |
| } |
| } |
| } |
| return null; |
| } |
| |
| public void interpreterRemoved(IInterpreterInstall Interpreter) { |
| // TODO Auto-generated method stub |
| } |
| |
| } |
| |
| private synchronized static void initialize() { |
| if (installChangedListener == null) { |
| installChangedListener = new InterpreterInstallChangedListener(); |
| ScriptRuntime |
| .addInterpreterInstallChangedListener(installChangedListener); |
| } |
| if (infos == null) { |
| final URI location = getInfoLocation(); |
| infos = new XMIResourceImpl(location); |
| try { |
| if (canLoad(location)) { |
| infos.load(null); |
| } |
| } catch (IOException e) { |
| TclPlugin.error(e); |
| } |
| } |
| } |
| |
| /** |
| * @param name |
| * @return |
| */ |
| private static Resource getProjectInfoResource(String projectName) { |
| synchronized (projectInfos) { |
| final Resource resource = projectInfos.get(projectName); |
| if (resource != null) { |
| return resource; |
| } |
| } |
| final URI location = getProjectLocation(projectName); |
| final Resource resource = new XMIResourceImpl(location); |
| try { |
| if (canLoad(location)) { |
| resource.load(null); |
| } |
| } catch (IOException e) { |
| TclPlugin.error(e); |
| } |
| synchronized (projectInfos) { |
| final Resource r = projectInfos.get(projectName); |
| if (r != null) { |
| return r; |
| } else { |
| projectInfos.put(projectName, resource); |
| return resource; |
| } |
| } |
| } |
| |
| private static List<String> deployExecute(IExecutionEnvironment exeEnv, |
| IInterpreterInstall install, String[] arguments, |
| EnvironmentVariable[] env, ProgressMonitoringJob monitor) { |
| // /* Progress monitoring */String envName = install.getEnvironment() |
| // .getName(); |
| monitor |
| .subTask(Messages.TclInterpreterMessages_DeployingPackageInformationScript); |
| IDeployment deployment = exeEnv.createDeployment(); |
| if (deployment == null) { |
| return null; |
| } |
| IFileHandle script = deploy(deployment); |
| if (script == null) { |
| deployment.dispose(); |
| return null; |
| } |
| /* Progress monitoring */monitor.worked(10); |
| |
| /* Progress monitoring */monitor |
| .subTask(Messages.TclInterpreterMessages_RunningPackageInfoScript); |
| IFileHandle workingDir = script.getParent(); |
| InterpreterConfig config = ScriptLaunchUtil.createInterpreterConfig( |
| exeEnv, script, workingDir, env); |
| TclLibpathUtils.addTclLibPath(config, install.getLibraryLocations(), |
| install.getEnvironment()); |
| // For wish |
| config.removeEnvVar("DISPLAY"); //$NON-NLS-1$ |
| |
| if (arguments != null) { |
| config.addScriptArgs(arguments); |
| } |
| |
| Process process = null; |
| try { |
| process = ScriptLaunchUtil.runScriptWithInterpreter(exeEnv, install |
| .getInstallLocation().toOSString(), config); |
| } catch (CoreException e) { |
| if (DLTKCore.DEBUG) { |
| e.printStackTrace(); |
| } |
| } |
| if (process == null) { |
| deployment.dispose(); |
| return null; |
| } |
| List<String> output = ProcessOutputCollector.execute(process); |
| /* Progress monitoring */monitor.worked(70); |
| deployment.dispose(); |
| return output; |
| } |
| |
| private static IFileHandle deploy(IDeployment deployment) { |
| IFileHandle script; |
| try { |
| IPath path = deployment.add(TclPlugin.getDefault().getBundle(), |
| DLTK_TCL); |
| script = deployment.getFile(path); |
| } catch (IOException e) { |
| if (DLTKCore.DEBUG) { |
| e.printStackTrace(); |
| } |
| return null; |
| } |
| return script; |
| } |
| |
| private static boolean isElementName(Node nde, String name) { |
| if (nde != null) { |
| if (nde.getNodeType() == Node.ELEMENT_NODE) { |
| if (name.equalsIgnoreCase(nde.getNodeName())) { |
| return true; |
| } |
| } |
| } |
| return false; |
| } |
| |
| public static boolean isValidName(String packageName) { |
| return packageName != null && packageName.length() != 0 |
| && packageName.indexOf('$') == -1 |
| && packageName.indexOf('[') == -1 |
| && packageName.indexOf(']') == -1; |
| } |
| |
| /** |
| * Return copy of all modules. |
| * |
| * @param name |
| * @return |
| */ |
| public static synchronized List<TclModuleInfo> getProjectModules(String name) { |
| TclProjectInfo info = getTclProject(name); |
| List<TclModuleInfo> results = new ArrayList<TclModuleInfo>(); |
| |
| EList<TclModuleInfo> modules = info.getModules(); |
| for (TclModuleInfo tclModuleInfo : modules) { |
| TclModuleInfo copy = EcoreUtil.copy(tclModuleInfo); |
| results.add(copy); |
| } |
| return Collections.unmodifiableList(results); |
| } |
| |
| public static synchronized void setProjectModules(String name, |
| List<TclModuleInfo> modules) { |
| TclProjectInfo info = getTclProject(name); |
| info.getModules().clear(); |
| info.getModules().addAll(modules); |
| save(); |
| } |
| |
| public static synchronized void removeInterpreterInfo( |
| IInterpreterInstall install) { |
| initialize(); |
| final TclInterpreterInfo info = getTclInterpreter(install, false); |
| if (info != null) { |
| if (!info.getPackages().isEmpty() || info.isFetched() |
| || info.getFetchedAt() != null) { |
| info.getPackages().clear(); |
| info.setFetched(false); |
| info.setFetchedAt(null); |
| save(); |
| } |
| } |
| } |
| |
| /** |
| * @since 2.0 |
| */ |
| public static synchronized void markInterprterAsNotFetched( |
| IInterpreterInstall install) { |
| initialize(); |
| final TclInterpreterInfo info = getTclInterpreter(install, false); |
| if (info != null) { |
| info.setFetched(false); |
| info.setFetchedAt(null); |
| save(); |
| } |
| } |
| |
| public static Set<String> getPackageInfosAsString( |
| IInterpreterInstall install) { |
| initialize(); |
| Set<String> result = new HashSet<String>(); |
| List<TclPackageInfo> list = getPackageInfos(install); |
| for (TclPackageInfo tclPackageInfo : list) { |
| result.add(tclPackageInfo.getName()); |
| } |
| return result; |
| } |
| |
| private static EMap<String, VariableValue> convertVariablesToEMap( |
| Map<String, String> variables) { |
| final EMap<String, VariableValue> result = new BasicEMap<String, VariableValue>(); |
| for (Map.Entry<String, String> entry : variables.entrySet()) { |
| final VariableValue value = TclPackagesFactory.eINSTANCE |
| .createVariableValue(); |
| value.setValue(entry.getValue()); |
| result.put(entry.getKey(), value); |
| } |
| return result; |
| } |
| |
| private static Map<String, String> convertVariablesToMap( |
| EMap<String, VariableValue> variables) { |
| final Map<String, String> result = new HashMap<String, String>(); |
| for (Map.Entry<String, VariableValue> entry : variables.entrySet()) { |
| result.put(entry.getKey(), entry.getValue().getValue()); |
| } |
| return result; |
| } |
| |
| /** |
| * @since 2.0 |
| */ |
| public static Map<String, String> getVariables(IInterpreterInstall install) { |
| return convertVariablesToMap(getVariablesEMap(install)); |
| } |
| |
| /** |
| * @since 2.0 |
| */ |
| public static EMap<String, VariableValue> getVariablesEMap( |
| IInterpreterInstall install) { |
| final EObject variables = install |
| .findExtension(TclPackagesPackage.Literals.VARIABLE_MAP); |
| if (variables != null) { |
| return ECollections.unmodifiableEMap(((VariableMap) variables) |
| .getVariables()); |
| } else { |
| return ECollections.emptyEMap(); |
| } |
| } |
| |
| /** |
| * @since 2.0 |
| */ |
| public static void setVariables(IInterpreterInstall install, |
| Map<String, String> variables) { |
| setVariables(install, convertVariablesToEMap(variables)); |
| } |
| |
| /** |
| * @since 2.0 |
| */ |
| public static void setVariables(IInterpreterInstall install, |
| EMap<String, VariableValue> variables) { |
| if (variables != null && !variables.isEmpty()) { |
| final VariableMap variableMap = TclPackagesFactory.eINSTANCE |
| .createVariableMap(); |
| variableMap.getVariables().putAll(variables); |
| install.replaceExtension(TclPackagesPackage.Literals.VARIABLE_MAP, |
| variableMap); |
| } else { |
| install.replaceExtension(TclPackagesPackage.Literals.VARIABLE_MAP, |
| null); |
| } |
| } |
| |
| /** |
| * @since 2.0 |
| */ |
| public static Map<String, String> getVariables(String projectName) { |
| return convertVariablesToMap(getVariablesEMap(projectName)); |
| } |
| |
| /** |
| * @since 2.0 |
| */ |
| public static synchronized EMap<String, VariableValue> getVariablesEMap( |
| String projectName) { |
| TclProjectInfo projectInfo = getTclProject(projectName); |
| return ECollections.unmodifiableEMap(projectInfo.getVariables()); |
| } |
| |
| /** |
| * @since 2.0 |
| */ |
| public static void setVariables(String projectName, |
| Map<String, String> variables) { |
| setVariables(projectName, convertVariablesToEMap(variables)); |
| } |
| |
| /** |
| * @since 2.0 |
| */ |
| public static synchronized void setVariables(String projectName, |
| EMap<String, VariableValue> variables) { |
| TclProjectInfo projectInfo = getTclProject(projectName); |
| projectInfo.getVariables().clear(); |
| projectInfo.getVariables().putAll(variables); |
| save(); |
| } |
| |
| /** |
| * @since 2.0 |
| */ |
| public static void fillPackagesFromContent(List<String> content, |
| TclInterpreterInfo info) { |
| String text = getXMLContent(content); |
| Document document = getDocument(text); |
| Set<TclPackageInfo> packages = new HashSet<TclPackageInfo>(); |
| |
| if (document != null) { |
| Element element = document.getDocumentElement(); |
| NodeList childNodes = element.getChildNodes(); |
| int len = childNodes.getLength(); |
| for (int i = 0; i < len; i++) { |
| Node nde = childNodes.item(i); |
| if (isElementName(nde, "path")) { //$NON-NLS-1$ |
| Element el = (Element) nde; |
| NodeList elChilds = el.getChildNodes(); |
| for (int j = 0; j < elChilds.getLength(); j++) { |
| Node pkgNde = elChilds.item(j); |
| if (isElementName(pkgNde, "package")) { //$NON-NLS-1$ |
| Element pkgElement = (Element) pkgNde; |
| String name = pkgElement.getAttribute("name"); //$NON-NLS-1$ |
| |
| TclPackageInfo pkg = getCreatePackage(info, name); |
| populatePackage(pkg, pkgNde, info); |
| packages.add(pkg); |
| } |
| } |
| } |
| } |
| } |
| } |
| |
| /** |
| * |
| * Fetch only one package information to info |
| * |
| * @since 2.0 |
| */ |
| public static TclPackageInfo getPackageInfo(InterpreterStandin install, |
| String name, boolean fetch, TclInterpreterInfo info, |
| IProgressMonitor monitor) { |
| EList<TclPackageInfo> packages = info.getPackages(); |
| Set<TclPackageInfo> toFetch = new HashSet<TclPackageInfo>(); |
| TclPackageInfo result = null; |
| |
| synchronized (TclPackagesManager.class) { |
| for (TclPackageInfo tclPackageInfo : packages) { |
| if (name.equals(tclPackageInfo.getName())) { |
| if (tclPackageInfo.isFetched()) { |
| return tclPackageInfo; |
| } else { |
| toFetch.add(tclPackageInfo); |
| fetchSources(toFetch, install, info, monitor); |
| result = tclPackageInfo; |
| break; |
| } |
| } |
| } |
| } |
| return result; |
| } |
| } |