/** * Copyright (C) 2012 - 2014 Eric Van Dewoestine * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package org.eclim.installer.step; import java.io.File; import java.net.URL; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.xml.parsers.DocumentBuilderFactory; import org.apache.commons.lang.StringUtils; import org.apache.tools.ant.taskdefs.condition.Os; import org.eclim.installer.step.command.Command; import org.eclim.installer.step.command.InfoCommand; import org.eclim.installer.step.command.InstallCommand; import org.eclim.installer.step.command.OutputHandler; import org.eclim.installer.step.command.UninstallCommand; import org.formic.Installer; import org.formic.util.Extractor; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.NodeList; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class EclipseInfo { private static final Logger logger = LoggerFactory.getLogger(EclipseInfo.class); private static final String DEPENDENCIES = "/resources/dependencies.xml"; private static final String PROFILE = " Profile: "; private static final String CONFIGURATION = " Configuration: "; private static final String FEATURE = " Feature: "; private Map<String,Feature> installedFeatures; private Map<String,String> featureStatuses = new HashMap<String,String>(); private Map<String,List<Dependency>> dependencies = new HashMap<String,List<Dependency>>(); private String profileName; private String localPath; /** * Contstruct a new EclipseInfo instance containing installed features and * required dependencies. */ public EclipseInfo( String profileName, String localPath, Map<String,Feature> installedFeatures) throws Exception { this.profileName = profileName; this.localPath = localPath; this.installedFeatures = installedFeatures; Document document = DocumentBuilderFactory.newInstance() .newDocumentBuilder().parse( EclipseInfo.class.getResource(DEPENDENCIES).toString()); Element root = document.getDocumentElement(); NodeList features = root.getElementsByTagName("feature"); for(int i = 0; i < features.getLength(); i++){ Element feature = (Element)features.item(i); String id = feature.getAttribute("id"); String status = feature.getAttribute("status"); if (status != null && status.length() > 0){ featureStatuses.put(id, status); } List<Dependency> dependencies = new ArrayList<Dependency>(); NodeList deps = feature.getElementsByTagName("dependency"); for(int j = 0; j < deps.getLength(); j++){ Element node = (Element)deps.item(j); NodeList sites = node.getElementsByTagName("site"); Element site = sites.getLength() > 0 ? (Element)sites.item(0) : null; dependencies.add(new Dependency( node.getAttribute("id"), site != null ? site.getAttribute("url") : null, node.getAttribute("version"), node.getAttribute("match"), this.installedFeatures.get(node.getAttribute("id")))); } this.dependencies.put(id, dependencies); } } public String getProfileName() { return profileName; } public String getLocalPath() { return localPath; } public boolean hasFeature(String name) { return this.installedFeatures.containsKey(name); } public String getStatus(String plugin) { return featureStatuses.get(plugin); } public List<Dependency> getDependencies(String plugin) { List<Dependency> deps = dependencies.get(plugin); if (deps == null){ return new ArrayList<Dependency>(); } return deps; } public List<Dependency> getUninstalledDependencies(String plugin) { List<Dependency> deps = new ArrayList<Dependency>(); for(Dependency dep : getDependencies(plugin)){ if(!dep.isInstalled()){ deps.add(dep); } } return deps; } public List<Dependency> getUnsatisfiedDependencies(String plugin) { List<Dependency> deps = new ArrayList<Dependency>(); for(Dependency dep : getDependencies(plugin)){ if(!dep.isInstalled() || dep.isUpgrade()){ deps.add(dep); } } return deps; } /** * Installs the eclipse plugin used to install eclipse features. */ public static boolean installInstallerPlugin() throws Exception { File updateDir = Installer.tempDir("update"); Extractor.extractResource("/files/installer-update-site.zip", updateDir); String url = "file://" + updateDir; Command command = new InstallCommand( null, url, "org.eclim.installer", "org.eclipse.equinox.p2.director"); try{ command.start(); command.join(); if(command.getReturnCode() != 0){ if (command.isShutdown()){ return false; } RuntimeException re = new RuntimeException( "error: " + command.getErrorMessage() + " out: " + command.getResult()); logger.warn( "Error installing eclim installer feature, " + "attempting uninstall/reinstall."); // attempt to uninstall the feature Command uninstall = new UninstallCommand( null, url, "org.eclim.installer", "org.eclipse.equinox.p2.director"); uninstall.start(); uninstall.join(); // now try to install again command = new InstallCommand( null, url, "org.eclim.installer", "org.eclipse.equinox.p2.director"); command.start(); command.join(); if(command.getReturnCode() != 0){ if (command.isShutdown()){ return false; } throw re; } } Installer.getProject().setProperty("eclim.installer.feature.installed", "true"); Installer.getProject().setProperty("eclim.installer.feature.location", url); }finally{ command.destroy(); } return true; } public static EclipseInfo gatherEclipseInfo() throws Exception { final Map<String,Feature> installedFeatures = new HashMap<String,Feature>(); // run eclipse to get a list of existing installed features Command command = new InfoCommand(new OutputHandler(){ public void process(String line){ logger.info(line); if(line.startsWith(FEATURE)){ String[] attrs = StringUtils.split(line.substring(FEATURE.length())); File site = null; try{ site = new File(new URL(attrs[2]).getFile()); }catch(Exception e){ logger.error("Failed to parse feature: " + line, e); } installedFeatures.put(attrs[0], new Feature(attrs[1], site)); }else if(line.startsWith(CONFIGURATION)){ String config = line.substring(CONFIGURATION.length()); if (config.startsWith("file:")){ config = config.substring(5); } if(Os.isFamily(Os.FAMILY_WINDOWS) && config.startsWith("/")){ config = config.substring(1); } String local = new File(config).getParent(); logger.info("eclipse.local=" + local); Installer.getContext().setValue("eclipse.local", local); }else if(line.startsWith(PROFILE)){ String profile = line.substring(PROFILE.length()); logger.info("eclipse.profile=" + profile); Installer.getContext().setValue("eclipse.profile", profile); } } }); try{ command.start(); command.join(); if(command.getReturnCode() != 0){ if (command.isShutdown()){ return null; } throw new RuntimeException( "error: " + command.getErrorMessage() + " out: " + command.getResult()); } }finally{ command.destroy(); } return new EclipseInfo( (String)Installer.getContext().getValue("eclipse.profile"), (String)Installer.getContext().getValue("eclipse.local"), installedFeatures); } }