| /******************************************************************************* |
| * Copyright (c) 2014 Obeo. |
| * 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: |
| * Obeo - initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.emf.compare.git.pgm.internal.cmd; |
| |
| import static org.eclipse.emf.compare.git.pgm.internal.Options.GIT_DIR_OPT; |
| import static org.eclipse.emf.compare.git.pgm.internal.Options.HELP_OPT; |
| import static org.eclipse.emf.compare.git.pgm.internal.Options.SHOW_STACK_TRACE_OPT; |
| import static org.eclipse.emf.compare.git.pgm.internal.exception.Die.DeathType.FATAL; |
| import static org.eclipse.emf.compare.git.pgm.internal.exception.Die.DeathType.SOFTWARE_ERROR; |
| import static org.eclipse.emf.compare.git.pgm.internal.util.EMFCompareGitPGMUtil.EOL; |
| import static org.eclipse.emf.compare.git.pgm.internal.util.EMFCompareGitPGMUtil.SEP; |
| import static org.eclipse.emf.compare.git.pgm.internal.util.EMFCompareGitPGMUtil.toFileWithAbsolutePath; |
| |
| import java.io.BufferedReader; |
| import java.io.BufferedWriter; |
| import java.io.ByteArrayOutputStream; |
| import java.io.File; |
| import java.io.FileInputStream; |
| import java.io.FilenameFilter; |
| import java.io.IOException; |
| import java.io.InputStream; |
| import java.io.InputStreamReader; |
| import java.io.OutputStreamWriter; |
| import java.io.PrintWriter; |
| import java.security.MessageDigest; |
| import java.security.NoSuchAlgorithmException; |
| import java.security.cert.Certificate; |
| import java.util.Collection; |
| |
| import org.eclipse.emf.common.util.EList; |
| import org.eclipse.emf.common.util.URI; |
| import org.eclipse.emf.compare.git.pgm.Returns; |
| import org.eclipse.emf.compare.git.pgm.internal.ProgressPageLog; |
| import org.eclipse.emf.compare.git.pgm.internal.args.CmdLineParserRepositoryBuilder; |
| import org.eclipse.emf.compare.git.pgm.internal.args.GitDirHandler; |
| import org.eclipse.emf.compare.git.pgm.internal.args.SetupFileOptionHandler; |
| import org.eclipse.emf.compare.git.pgm.internal.exception.ArgumentValidationError; |
| import org.eclipse.emf.compare.git.pgm.internal.exception.Die; |
| import org.eclipse.emf.compare.git.pgm.internal.exception.Die.DeathType; |
| import org.eclipse.emf.compare.git.pgm.internal.exception.Die.DiesOn; |
| import org.eclipse.emf.ecore.resource.Resource; |
| import org.eclipse.emf.ecore.resource.ResourceSet; |
| import org.eclipse.emf.ecore.resource.URIConverter; |
| import org.eclipse.emf.ecore.util.EcoreUtil; |
| import org.eclipse.emf.edit.domain.AdapterFactoryEditingDomain; |
| import org.eclipse.emf.edit.provider.ComposedAdapterFactory; |
| import org.eclipse.equinox.p2.metadata.ILicense; |
| import org.eclipse.jgit.lib.Repository; |
| import org.eclipse.jgit.util.io.ThrowingPrintWriter; |
| import org.eclipse.oomph.base.provider.BaseEditUtil; |
| import org.eclipse.oomph.internal.setup.SetupPrompter; |
| import org.eclipse.oomph.setup.Index; |
| import org.eclipse.oomph.setup.InstallationTask; |
| import org.eclipse.oomph.setup.Product; |
| import org.eclipse.oomph.setup.ProductCatalog; |
| import org.eclipse.oomph.setup.ProductVersion; |
| import org.eclipse.oomph.setup.Project; |
| import org.eclipse.oomph.setup.SetupPackage; |
| import org.eclipse.oomph.setup.SetupTask; |
| import org.eclipse.oomph.setup.Trigger; |
| import org.eclipse.oomph.setup.VariableTask; |
| import org.eclipse.oomph.setup.WorkspaceTask; |
| import org.eclipse.oomph.setup.internal.core.SetupContext; |
| import org.eclipse.oomph.setup.internal.core.SetupTaskPerformer; |
| import org.eclipse.oomph.setup.internal.core.util.ECFURIHandlerImpl; |
| import org.eclipse.oomph.setup.internal.core.util.SetupUtil; |
| import org.eclipse.oomph.setup.log.ProgressLog; |
| import org.eclipse.oomph.setup.p2.P2Task; |
| import org.eclipse.oomph.util.Confirmer; |
| import org.kohsuke.args4j.Argument; |
| import org.kohsuke.args4j.CmdLineException; |
| import org.kohsuke.args4j.CmdLineParser; |
| import org.kohsuke.args4j.Option; |
| |
| /** |
| * Abstract class for any logical command. |
| * |
| * @author <a href="mailto:arthur.daussy@obeo.fr">Arthur Daussy</a> |
| */ |
| @SuppressWarnings("restriction") |
| public abstract class AbstractLogicalCommand { |
| |
| /** Oomph option. */ |
| protected static final String PROP_SETUP_CONFIRM_SKIP = "oomph.setup.confirm.skip"; //$NON-NLS-1$ |
| |
| /** Oomph option. */ |
| protected static final String PROP_SETUP_OFFLINE_STARTUP = "oomph.setup.offline.startup"; //$NON-NLS-1$ |
| |
| /** Oomph option. */ |
| protected static final String PROP_SETUP_MIRRORS_STARTUP = "oomph.setup.mirrors.startup"; //$NON-NLS-1$ |
| |
| /** VM Args option. */ |
| protected static final String VMARGS_OPTION = "-D"; //$NON-NLS-1$ |
| |
| /** Buffer size of the array use to generate an unique id. */ |
| private static final int GEN_ID_BUFFER_SIZE = 1024; |
| |
| /** Eclipse string. */ |
| private static final String ECLIPSE = "eclipse"; //$NON-NLS-1$ |
| |
| /** |
| * Holds true if a user has set the help option to true. |
| */ |
| @Option(name = HELP_OPT, usage = "Dispays help for this command.", aliases = {"-h" }) |
| private boolean help; |
| |
| /** |
| * Holds the Oomph model setup file. |
| */ |
| @Argument(index = 0, metaVar = "<setup>", required = true, usage = "Path to the setup file. The setup file is a Oomph model.", handler = SetupFileOptionHandler.class) |
| private File setupFile; |
| |
| /** |
| * Holds true if the java stack trace should be displayed in the console if any. |
| */ |
| @Option(name = SHOW_STACK_TRACE_OPT, usage = "Use this option to display java stack trace in console on error.") |
| private boolean showStackTrace; |
| |
| /** |
| * Holds git directory location. |
| */ |
| @Option(name = GIT_DIR_OPT, metaVar = "gitFolderPath", usage = "Path to the .git folder of your repository.", handler = GitDirHandler.class) |
| private String gitdir; |
| |
| /** |
| * Name of this command. |
| */ |
| private String commandName; |
| |
| /** |
| * Writer to output to, typically this is standard output. |
| */ |
| private ThrowingPrintWriter out; |
| |
| /** |
| * Usage of this command. This field is filled only if the help parameter has been provided. |
| */ |
| private String usage; |
| |
| /** |
| * Git repository for this command to be executed in. |
| */ |
| private Repository repo; |
| |
| /** |
| * SetupTaskPerformer of this command. |
| */ |
| private SetupTaskPerformer performer; |
| |
| /** |
| * Log. |
| */ |
| private ProgressLog progressPageLog; |
| |
| /** |
| * Constructor. |
| */ |
| protected AbstractLogicalCommand() { |
| // Force the command to be built in the CommandFactory. |
| } |
| |
| /** |
| * Executes the command. |
| * |
| * @return The {@link Returns} for this command. |
| * @throws Die |
| * if the program stop prematurely. |
| * @throws IOException |
| * propagation. |
| */ |
| public final Integer execute() throws Die, IOException { |
| if (!help) { |
| return internalRun(); |
| } else { |
| out.print(usage); |
| } |
| return Returns.COMPLETE.code(); |
| } |
| |
| /** |
| * Builds this command. |
| * |
| * @param args |
| * The arguments for this command. |
| * @param environmentSetupURI |
| * URI to the environment setup file. |
| * @throws Die |
| * exception on error. |
| * @throws IOException |
| * e |
| */ |
| public void build(Collection<String> args, URI environmentSetupURI) throws Die, IOException { |
| |
| repo = parseArgumentsAndBuildRepo(args); |
| |
| try { |
| final String outputEncoding; |
| if (repo != null) { |
| outputEncoding = repo.getConfig().getString("i18n", null, "logOutputEncoding"); //$NON-NLS-1$ //$NON-NLS-2$ |
| } else { |
| outputEncoding = null; |
| } |
| BufferedWriter outbufw; |
| if (outputEncoding != null) { |
| outbufw = new BufferedWriter(new OutputStreamWriter(System.out, outputEncoding)); |
| } else { |
| outbufw = new BufferedWriter(new OutputStreamWriter(System.out)); |
| } |
| out = new ThrowingPrintWriter(outbufw); |
| } catch (IOException e) { |
| throw new DiesOn(SOFTWARE_ERROR).displaying("Cannot create input stream").ready(); |
| } |
| |
| if (!help) { |
| // CHECKSTYLE.OFF: IllegalCatch - No choice since Oomph launch such an exception |
| try { |
| // Loads eclipse environment setup model. |
| performer = createSetupTaskPerformer(setupFile.getAbsolutePath(), environmentSetupURI); |
| performer.perform(); |
| |
| if (!performer.hasSuccessfullyPerformed()) { |
| throw new DiesOn(DeathType.FATAL).displaying("Error durring Oomph operation").ready(); |
| } |
| } catch (Die e) { |
| throw e; |
| } catch (Exception e) { |
| throw new DiesOn(DeathType.FATAL).duedTo(e).ready(); |
| } |
| // CHECKSTYLE.ON: IllegalCatch |
| } |
| |
| } |
| |
| /** |
| * Returns the value of the show-stack-trace argument. |
| * |
| * @return the value of the show-stack-trace argument. |
| */ |
| public boolean isShowStackTrace() { |
| return showStackTrace; |
| } |
| |
| /** |
| * Returns the user setup file associated with this command. |
| * |
| * @return the user setup file associated with this command. |
| */ |
| public File getSetupFile() { |
| return setupFile; |
| } |
| |
| /** |
| * Flush the out stream. This is mainly use to handle premature exit. |
| * |
| * @throws IOException |
| * if any problem with the stream. |
| */ |
| public void flushOutW() throws IOException { |
| if (out != null) { |
| out.flush(); |
| } |
| } |
| |
| /** |
| * Runs the command. |
| * |
| * @return Return code. |
| * @throws Die |
| * e |
| * @throws IOException |
| * exception on error. |
| */ |
| protected abstract Integer internalRun() throws Die, IOException; |
| |
| /** |
| * Gets the git repository. |
| * |
| * @return the repository this command uses. |
| */ |
| protected Repository getRepository() { |
| return repo; |
| } |
| |
| /** |
| * Gets the SetupTaskPerformer. |
| * |
| * @return the SetupTaskPerformer. |
| */ |
| protected SetupTaskPerformer getPerformer() { |
| return performer; |
| } |
| |
| /** |
| * Parses the arguments related to this command. It also in charge of building the git repository. |
| * <p> |
| * Since the --git-dir option can be passed through the command line, the parser is also in charge of |
| * building the repository |
| * </p> |
| * |
| * @param args |
| * arguments. |
| * @return the Repository. |
| * @throws Die |
| * if the program exits prematurely. |
| */ |
| protected Repository parseArgumentsAndBuildRepo(Collection<String> args) throws Die { |
| final CmdLineParserRepositoryBuilder clp = CmdLineParserRepositoryBuilder |
| .newJGitRepoBuilderCmdParser(this); |
| try { |
| clp.parseArgument(args); |
| } catch (ArgumentValidationError err) { |
| // Only throw an error if the user has not required help. |
| if (!help) { |
| if (err.getCause() instanceof Die) { |
| // Do not wrap a Die exception |
| throw (Die)err.getCause(); |
| } else { |
| throw new DiesOn(FATAL).displaying(err.getMessage()).ready(); |
| } |
| } |
| } catch (CmdLineException err) { |
| // Only throw an error if the user has not required help. |
| if (!help) { |
| ByteArrayOutputStream localOut = new ByteArrayOutputStream(); |
| PrintWriter printWritter = new PrintWriter(localOut); |
| printUsage(err.getMessage() + " in:" + EOL, clp, printWritter); |
| printWritter.close(); |
| throw new DiesOn(FATAL).displaying(localOut.toString()).ready(); |
| } |
| } |
| |
| if (help) { |
| // The user has used the help option. Saves the usage message for later |
| ByteArrayOutputStream localOut = new ByteArrayOutputStream(); |
| PrintWriter printWritter = new PrintWriter(localOut); |
| printUsage("", clp, printWritter); |
| printWritter.close(); |
| usage = localOut.toString(); |
| } |
| return clp.getRepo(); |
| } |
| |
| /** |
| * Prints the usage of this command. |
| * |
| * @param message |
| * a prefix message. |
| * @param clp |
| * the current command line parser. |
| * @param printWritter |
| * A {@link PrintWriter}. |
| */ |
| protected void printUsage(final String message, final CmdLineParser clp, PrintWriter printWritter) { |
| printWritter.println(message); |
| printWritter.print(commandName); |
| clp.printSingleLineUsage(printWritter, null); |
| printWritter.println(); |
| printWritter.println(); |
| |
| clp.printUsage(printWritter, null); |
| printWritter.println(); |
| |
| printWritter.flush(); |
| } |
| |
| /** |
| * Returns the printer to write message in console. |
| * |
| * @return {@link ThrowingPrintWriter} |
| */ |
| protected ThrowingPrintWriter out() { |
| return out; |
| } |
| |
| /** |
| * Sets the command name. |
| * |
| * @param name |
| * the command name. |
| */ |
| final void setCommandName(final String name) { |
| commandName = name; |
| } |
| |
| /** |
| * Create and configure the setup task performer to provision the eclipse environment. |
| * |
| * @param userSetupFilePath |
| * the path of the user setup model. |
| * @param environmentSetupURI |
| * URI of the setup file that contains the environment used to execute the logical commands. |
| * @return a SetupTaskPerformer. |
| * @throws Die |
| * e |
| * @throws IOException |
| * e |
| */ |
| private SetupTaskPerformer createSetupTaskPerformer(String userSetupFilePath, URI environmentSetupURI) |
| throws IOException, Die { |
| // Load user setup model. |
| ComposedAdapterFactory adapterFactory = new ComposedAdapterFactory(BaseEditUtil |
| .createAdapterFactory()); |
| |
| ResourceSet rs = SetupUtil.createResourceSet(); |
| rs.eAdapters().add( |
| new AdapterFactoryEditingDomain.EditingDomainProvider(new AdapterFactoryEditingDomain( |
| adapterFactory, null, rs))); |
| rs.getLoadOptions().put(ECFURIHandlerImpl.OPTION_CACHE_HANDLING, |
| ECFURIHandlerImpl.CacheHandling.CACHE_WITHOUT_ETAG_CHECKING); |
| |
| URI startupSetupURI = URI.createFileURI(userSetupFilePath); |
| Resource startupSetup = null; |
| // CHECKSTYLE.OFF: IllegalCatch - No choice since EMF launch can run a runtime exception if it does |
| // not succeed in creating the resource. We want to handle this exception ourself |
| try { |
| startupSetup = rs.getResource(startupSetupURI, true); |
| } catch (RuntimeException e) { |
| // Does nothing handle later |
| } |
| // CHECKSTYLE.ON: IllegalCatch |
| if (startupSetup == null) { |
| throw new DiesOn(FATAL).displaying(userSetupFilePath + " is not a valid setup file").ready(); |
| } |
| |
| Object startupSetupRoot = EcoreUtil.getObjectByType(startupSetup.getContents(), |
| SetupPackage.Literals.PROJECT); |
| final Project startupSetupProject; |
| if (startupSetupRoot instanceof Project) { |
| startupSetupProject = (Project)startupSetupRoot; |
| } else { |
| throw new DiesOn(SOFTWARE_ERROR).displaying( |
| "The root of the setup file should be a Setup::PROJECT").ready(); |
| } |
| |
| progressPageLog = new ProgressPageLog(System.out); |
| |
| Resource environmentSetup = rs.getResource(environmentSetupURI, true); |
| Index eclipseSetupIndex = (Index)EcoreUtil.getObjectByType(environmentSetup.getContents(), |
| SetupPackage.Literals.INDEX); |
| |
| handleWorkspace(startupSetupProject, eclipseSetupIndex); |
| handleInstallation(startupSetupProject, eclipseSetupIndex); |
| |
| EList<ProductCatalog> productCatalogs = eclipseSetupIndex.getProductCatalogs(); |
| ProductCatalog catalog = productCatalogs.get(0); |
| Product product = catalog.getProducts().get(0); |
| ProductVersion productVersion = product.getVersions().get(0); |
| |
| // Add extra plugins to install from user setup model. |
| for (SetupTask setupTask : startupSetupProject.getSetupTasks()) { |
| if (setupTask instanceof P2Task) { |
| SetupTask copy = EcoreUtil.copy(setupTask); |
| catalog.getSetupTasks().add(copy); |
| } |
| } |
| |
| // Create Oomph setup context. |
| final SetupContext setupContext = SetupContext.create(rs); |
| setupContext.getInstallation().setProductVersion(productVersion); |
| Trigger triggerBootstrap = Trigger.BOOTSTRAP; |
| URIConverter uriConverter = rs.getURIConverter(); |
| SetupTaskPerformer aPerformer; |
| // CHECKSTYLE.OFF: IllegalCatch - No choice since Oomph launch such an exception |
| try { |
| aPerformer = SetupTaskPerformer.create(uriConverter, SetupPrompter.CANCEL, triggerBootstrap, |
| setupContext, false); |
| } catch (Exception e) { |
| throw new DiesOn(DeathType.ERROR).duedTo(e).displaying("Error during processing of setup mdoel") |
| .ready(); |
| } |
| // CHECKSTYLE.ON: IllegalCatch |
| Confirmer confirmer = Confirmer.ACCEPT; |
| aPerformer.put(ILicense.class, confirmer); |
| aPerformer.put(Certificate.class, confirmer); |
| aPerformer.setProgress(progressPageLog); |
| aPerformer.setOffline(false); |
| aPerformer.setMirrors(true); |
| |
| final String installationPath = getInstallationPath(startupSetupProject); |
| if (installationPathContainsExistingEclipse(installationPath)) { |
| aPerformer.getTriggeredSetupTasks().clear(); |
| progressPageLog.log("Existing eclipse environment found at : " + installationPath); //$NON-NLS-1$ |
| } |
| |
| return aPerformer; |
| } |
| |
| /** |
| * Check if there is an existing eclipse environment at the given path. |
| * |
| * @param installationPath |
| * the given installation path. |
| * @return true if there is an existing eclipse environment at the given path, false otherwise. |
| */ |
| private boolean installationPathContainsExistingEclipse(String installationPath) { |
| if (installationPath != null) { |
| File file = new File(installationPath); |
| if (file.exists()) { |
| File[] eclipseFolder = file.listFiles(new FilenameFilter() { |
| public boolean accept(File dir, String name) { |
| return ECLIPSE.equals(name); |
| } |
| }); |
| if (eclipseFolder != null && eclipseFolder.length == 1) { |
| return isEclipseIntallationFolder(eclipseFolder[0]); |
| } |
| } |
| } |
| return false; |
| } |
| |
| /** |
| * Returns <code>true</code> if the file is a eclipse installation folder, <code>false</code> otherwise. |
| * |
| * @param eclipseFolder |
| * file to test. |
| * @return <code>true</code> if the file is a eclipse installation folder, <code>false</code> otherwise. |
| */ |
| private boolean isEclipseIntallationFolder(File eclipseFolder) { |
| if (eclipseFolder.exists()) { |
| String[] eclipseExe = eclipseFolder.list(new FilenameFilter() { |
| public boolean accept(File dir, String name) { |
| return ECLIPSE.equals(name) || "eclipse.exe".equals(name); //$NON-NLS-1$ |
| } |
| }); |
| if (eclipseExe.length == 1) { |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| /** |
| * Handle the creation/reuse of the workspace path. |
| * |
| * @param project |
| * the root object of the user model. |
| * @param index |
| * the root object of the environment model. |
| * @throws IOException |
| * e |
| * @throws Die |
| * e |
| */ |
| private void handleWorkspace(Project project, Index index) throws IOException, Die { |
| final String workspaceLocation; |
| if (modelDefinesWorkspacePath(project)) { |
| workspaceLocation = getWorkspacePath(project); |
| } else { |
| workspaceLocation = genWorkspacePath(project); |
| } |
| |
| for (ProductCatalog productCatalog : index.getProductCatalogs()) { |
| for (SetupTask setupTask : productCatalog.getSetupTasks()) { |
| if (setupTask instanceof WorkspaceTask) { |
| ((WorkspaceTask)setupTask).setLocation(workspaceLocation); |
| return; |
| } |
| } |
| } |
| } |
| |
| /** |
| * Handle the creation/reuse of the installation path. |
| * |
| * @param project |
| * the root object of the user model. |
| * @param index |
| * the root object of the environment model. |
| * @throws IOException |
| * e |
| * @throws Die |
| * e |
| */ |
| private void handleInstallation(Project project, Index index) throws IOException, Die { |
| final String installationLocation; |
| if (modelDefinesWorkspacePath(project)) { |
| installationLocation = getInstallationPath(project); |
| } else { |
| installationLocation = genInstallationPath(project); |
| } |
| |
| for (ProductCatalog productCatalog : index.getProductCatalogs()) { |
| for (SetupTask setupTask : productCatalog.getSetupTasks()) { |
| if (setupTask instanceof InstallationTask) { |
| ((InstallationTask)setupTask).setLocation(installationLocation); |
| return; |
| } |
| } |
| } |
| } |
| |
| /** |
| * Returns true if the given Project contains a variable task with a non null workspace location. |
| * |
| * @param project |
| * the given Project. |
| * @return true if the given Project contains a variable task with a non null workspace location, false |
| * otherwise. |
| */ |
| private boolean modelDefinesWorkspacePath(Project project) { |
| String workspacePath = getWorkspacePath(project); |
| if (workspacePath != null) { |
| return true; |
| } |
| return false; |
| } |
| |
| /** |
| * Search a variable task with name "workspace.location" in the given Project. |
| * |
| * @param project |
| * the given Project. |
| * @return the variable task if found, null otherwise. |
| */ |
| private VariableTask getVariableTaskForWorkspace(Project project) { |
| for (SetupTask setupTask : project.getSetupTasks()) { |
| if (setupTask instanceof VariableTask) { |
| if ("workspace.location".equals(((VariableTask)setupTask).getName())) { //$NON-NLS-1$ |
| return (VariableTask)setupTask; |
| } |
| } |
| } |
| return null; |
| } |
| |
| /** |
| * Search a variable task with name "installation.location" in the given Project. |
| * |
| * @param project |
| * the given Project. |
| * @return the variable task if found, null otherwise. |
| */ |
| private VariableTask getVariableTaskForInstallation(Project project) { |
| for (SetupTask setupTask : project.getSetupTasks()) { |
| if (setupTask instanceof VariableTask) { |
| if ("installation.location".equals(((VariableTask)setupTask).getName())) { //$NON-NLS-1$ |
| return (VariableTask)setupTask; |
| } |
| } |
| } |
| return null; |
| } |
| |
| /** |
| * Search a workspace task in the given Project. If found, return his location attribute value. |
| * |
| * @param project |
| * the given Project. |
| * @return the location attribute value of the workspace task if found, null otherwise. |
| */ |
| private String getWorkspacePath(Project project) { |
| final String path; |
| final VariableTask task = getVariableTaskForWorkspace(project); |
| if (task != null) { |
| String resourcePath = project.eResource().getURI().toFileString(); |
| String resourceBasePath = resourcePath.substring(0, resourcePath.lastIndexOf(SEP)); |
| path = toFileWithAbsolutePath(resourceBasePath, task.getValue()).toString(); |
| } else { |
| path = null; |
| } |
| |
| return path; |
| } |
| |
| /** |
| * Search an installation task in the given Project. If found, return his location attribute value. |
| * |
| * @param project |
| * the given Project. |
| * @return the location attribute value of the installation task if found, null otherwise. |
| */ |
| private String getInstallationPath(Project project) { |
| final String path; |
| final VariableTask task = getVariableTaskForInstallation(project); |
| if (task != null) { |
| String resourcePath = project.eResource().getURI().toFileString(); |
| String resourceBasePath = resourcePath.substring(0, resourcePath.lastIndexOf(SEP)); |
| path = toFileWithAbsolutePath(resourceBasePath, task.getValue()).toString(); |
| } else { |
| path = null; |
| } |
| return path; |
| } |
| |
| /** |
| * Generates a unique id in the temporary folder of the system according to the given Project. If the |
| * generated id already exists (cause a command already been called with the same Project), it is reused. |
| * |
| * @param project |
| * the given Project. |
| * @return the location of the workspace. |
| * @throws IOException |
| * e |
| * @throws Die |
| * e |
| */ |
| private String genWorkspacePath(Project project) throws IOException, Die { |
| String id = generateIDForSetup(project.eResource().getURI().toFileString()); |
| File ws = createOrGetTempDir("emfcWs" + id); //$NON-NLS-1$ |
| return ws.getAbsolutePath(); |
| } |
| |
| /** |
| * Generates a unique id in the temporary folder of the system according to the given Project. If the |
| * generated id already exists (cause a command already been called with the same Project), it is reused. |
| * |
| * @param project |
| * the given Project. |
| * @return the location of the workspace. |
| * @throws IOException |
| * e |
| * @throws Die |
| * e |
| */ |
| private String genInstallationPath(Project project) throws IOException, Die { |
| String id = generateIDForSetup(project.eResource().getURI().toFileString()); |
| File ws = createOrGetTempDir("emfcInstall" + id); //$NON-NLS-1$ |
| return ws.getAbsolutePath(); |
| } |
| /** |
| * Creates a temporary directory in the system temp directory. |
| * |
| * @param name |
| * the name of the temp directory to create. |
| * @return the new created directory. |
| */ |
| private static File createOrGetTempDir(String name) { |
| final File baseDir = new File(System.getProperty("java.io.tmpdir")); //$NON-NLS-1$ |
| final String baseName = name; |
| |
| for (int counter = 0; counter < 10000; counter++) { |
| final File tempDir = new File(baseDir, baseName); |
| if (tempDir.exists()) { |
| return tempDir; |
| } |
| if (tempDir.mkdir()) { |
| return tempDir; |
| } |
| } |
| throw new IllegalStateException("Failed to create directory within " + 10000 + " attempts (tried " |
| + baseName + "0 to " + baseName + (10000 - 1) + ')'); |
| } |
| |
| /** |
| * Generate a unique ID for the a given file. |
| * |
| * @param setupFilePath |
| * the absolute path of the given file. |
| * @return a unique ID for the a given file. |
| * @throws IOException |
| * e |
| * @throws Die |
| * On any other program error. |
| */ |
| private static String generateIDForSetup(String setupFilePath) throws IOException, Die { |
| File f = new File(setupFilePath); |
| MessageDigest digest; |
| try { |
| digest = MessageDigest.getInstance("SHA-1"); //$NON-NLS-1$ |
| } catch (NoSuchAlgorithmException e) { |
| throw new DiesOn(DeathType.ERROR).duedTo(e).ready(); |
| } |
| FileInputStream inputStream = new FileInputStream(f); |
| byte[] bytesBuffer = new byte[GEN_ID_BUFFER_SIZE]; |
| int bytesRead = -1; |
| |
| while ((bytesRead = inputStream.read(bytesBuffer)) != -1) { |
| digest.update(bytesBuffer, 0, bytesRead); |
| } |
| inputStream.close(); |
| |
| byte[] hashedBytes = digest.digest(); |
| |
| return convertByteArrayToHexString(hashedBytes); |
| } |
| |
| /** |
| * Converts an array of bytes into a string of hexadecimal values. |
| * |
| * @param arrayBytes |
| * the given array of bytes. |
| * @return a string of hexadecimal values. |
| */ |
| private static String convertByteArrayToHexString(byte[] arrayBytes) { |
| StringBuffer stringBuffer = new StringBuffer(); |
| for (int i = 0; i < arrayBytes.length; i++) { |
| // CHECKSTYLE.OFF: MagicNumber |
| stringBuffer.append(Integer.toString((arrayBytes[i] & 0xff) + 0x100, 16).substring(1)); |
| // CHECKSTYLE.ON: MagicNumber |
| } |
| return stringBuffer.toString(); |
| } |
| |
| /** |
| * Stream goobler. |
| * |
| * @author <a href="mailto:axel.richard@obeo.fr">Axel Richard</a> |
| */ |
| class StreamGobbler implements Runnable { |
| /** The stream. */ |
| private InputStream is; |
| |
| /** |
| * Reads everything from is until empty. |
| * |
| * @param is |
| * the stream to read. |
| */ |
| StreamGobbler(InputStream is) { |
| this.is = is; |
| } |
| |
| /** |
| * {@inheritDoc}. |
| */ |
| public void run() { |
| try { |
| InputStreamReader isr = new InputStreamReader(is); |
| BufferedReader br = new BufferedReader(isr); |
| String line = null; |
| while ((line = br.readLine()) != null) { |
| // performer.log(line); |
| out().println(line); |
| } |
| } catch (IOException ioe) { |
| ioe.printStackTrace(); |
| } |
| } |
| } |
| } |