/*******************************************************************************
* Copyright (c) 2012, 2016, 2017 PDT Extension Group and others.
* 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:
* PDT Extension Group - initial API and implementation
* Kaloyan Raev - [501269] externalize strings
*******************************************************************************/
package org.eclipse.php.composer.ui.job;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.exec.ExecuteException;
import org.apache.commons.io.FileUtils;
import org.eclipse.core.internal.resources.Project;
import org.eclipse.core.internal.resources.Workspace;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Platform;
import org.eclipse.php.composer.api.packages.PharDownloader;
import org.eclipse.php.composer.core.launch.ScriptLauncher;
import org.eclipse.php.composer.core.launch.execution.ExecutionResponseListener;
import org.eclipse.php.composer.core.log.Logger;
public class CreateProjectJob extends ComposerJob {
private final String projectName;
private final String packageName;
private IPath composerPath;
private IPath path;
private JobListener initListener;
private String packageVersion;
private boolean startNotified = false;
private boolean existed;
private File composerFile;
public CreateProjectJob(IPath path, String projectName, String packageName) {
this(path, projectName, packageName, null);
}
public CreateProjectJob(IPath path, String projectName, String packageName, String packageVersion) {
super(Messages.CreateProjectJob_Name);
this.projectName = projectName;
this.packageName = packageName;
this.packageVersion = packageVersion;
this.path = path;
if (Logger.isDebugging()) {
String msg = "Creating new project " + projectName + " from package " + packageName; //$NON-NLS-1$ //$NON-NLS-2$
if (packageVersion != null) {
msg += " / " + packageVersion; //$NON-NLS-1$
}
Logger.debug(msg);
}
ResourcesPlugin.getWorkspace();
DummyProject project = new DummyProject(path);
setProject(project);
try {
// TODO: cache the phar file locally
composerPath = path.append("composer.phar"); //$NON-NLS-1$
composerFile = composerPath.toFile();
existed = true;
if (!composerFile.exists()) {
existed = false;
PharDownloader downloader = new PharDownloader();
InputStream resource = downloader.download();
FileUtils.copyInputStreamToFile(resource, composerFile);
}
} catch (Exception e) {
Logger.logException(e);
}
}
@Override
protected void doOnLauncherRunException(Exception e) {
// to avoid deadlocks in
// PackageProjectWizardSecondPage#beforeFinish() at
// latch.await()
notifyOnFail();
}
@Override
protected void launch(ScriptLauncher launcher) throws ExecuteException, IOException, InterruptedException {
// cloning large projects can take a long time...
// TODO: make this configurable via preferences
launcher.setTimeout(5 * 60000);
launcher.addResponseListener(new ExecutionResponseListener() {
@Override
public void executionStarted() {
}
@Override
public void executionMessage(String message) {
try {
if (composerExists() /*
* message != null && message.
* equals("Loading composer repositories with package information"
* )
*/) {
notifyOnStart();
}
} catch (Exception e) {
Logger.logException(e);
}
}
@Override
public void executionFinished(String response, int exitValue) {
notifyOnFinish();
}
@Override
public void executionFailed(String response, Exception exception) {
notifyOnFail();
}
@Override
public void executionError(String message) {
notifyOnFail();
}
@Override
public void executionAboutToStart() {
}
});
List<String> params = new ArrayList<>();
// workaround for incorrect progress displaying on Windows
if (Platform.OS_WIN32.equals(Platform.getOS())) {
params.add("--no-progress"); //$NON-NLS-1$
}
params.add(packageName);
params.add(projectName);
if (packageVersion != null) {
params.add(packageVersion);
}
launcher.launch("create-project", params.toArray(new String[params.size()])); //$NON-NLS-1$
}
protected class DummyProject extends Project {
public DummyProject(IPath path) {
this(path, (Workspace) ResourcesPlugin.getWorkspace());
}
protected DummyProject(IPath path, Workspace container) {
super(path, container);
}
@Override
public IResource findMember(String path) {
return new DummyResource();
}
@Override
public IPath getLocation() {
return path;
}
}
private boolean composerExists() {
IPath projectPath = path.append(projectName).append("composer.json"); //$NON-NLS-1$
return projectPath.toFile().exists();
}
public class DummyResource extends org.eclipse.core.internal.resources.File {
protected DummyResource() {
super(new Path("/"), null); //$NON-NLS-1$
}
public IPath getFullPath() {
return new Path("/dummy/composer.phar"); //$NON-NLS-1$
}
}
public void setJobListener(JobListener latch) {
this.initListener = latch;
}
private void notifyOnStart() {
try {
if (startNotified || initListener == null) {
return;
}
initListener.jobStarted();
startNotified = true;
} catch (Exception e) {
Logger.logException(e);
}
}
private void notifyOnFinish() {
try {
if (initListener == null) {
return;
}
initListener.jobFinished(projectName);
} catch (Exception e) {
Logger.logException(e);
}
}
private void notifyOnFail() {
try {
if (initListener == null) {
return;
}
initListener.jobFailed();
} catch (Exception e) {
Logger.logException(e);
}
}
public interface JobListener {
void jobStarted();
void jobFinished(String projectName);
void jobFailed();
}
protected void cleanup() {
if (existed == false && composerFile != null) {
composerFile.delete();
}
}
}