/*******************************************************************************
* Copyright (c) Nov 28, 2011 Zend Technologies Ltd.
* 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
*******************************************************************************/
package org.zend.sdkcli.internal.commands;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URISyntaxException;
import java.text.MessageFormat;
import java.util.List;
import java.util.Random;
import org.eclipse.jgit.transport.URIish;
import org.zend.sdkcli.internal.monitor.StatusChangeListener;
import org.zend.sdkcli.internal.options.Option;
import org.zend.sdklib.SdkException;
import org.zend.sdklib.internal.repository.UserBasedRepositoryLoader;
import org.zend.sdklib.manager.RepositoryManager;
import org.zend.sdklib.repository.IRepository;
import org.zend.sdklib.repository.site.Application;
import org.zend.sdklib.target.IZendTarget;
import org.zend.webapi.core.connection.data.ApplicationInfo;
/**
* Abstract class which represents command related to transferring package
* during operation execution. It supports three kind of application sources:
* <ul>
* <li>local deployment package or application folder</li>
* <li>git repository</li>
* <li>Zend Reposiotry</li>
* </ul>
*
* @author Wojciech Galanciak, 2011
*
*/
public abstract class AbstractDeploymentCommand extends ApplicationAwareCommand {
private class DeploymentCloneCommand extends GitCloneProjectCommand {
private AbstractDeploymentCommand command;
private File directory;
private DeploymentCloneCommand(AbstractDeploymentCommand command) {
this.command = command;
}
@Override
public String getDir() {
try {
URIish uri = new URIish(command.getGitRepository());
return uri.getHumanishName();
} catch (URISyntaxException e) {
getLogger().error(e);
}
return null;
}
@Override
public String getRepo() {
return command.getGitRepository();
}
@Override
public String getUser() {
return command.getUser();
}
@Override
public String getPassword() {
return command.getPassword();
}
@Override
public String getKey() {
return command.getKey();
}
@Override
public String getBranch() {
return command.getBranch();
}
@Override
public boolean isVerbose() {
return command.isVerbose();
}
public File getProjectFile() {
try {
if (getRepo() != null) {
return getDirectory(getRepo());
}
} catch (URISyntaxException e) {
getLogger().error(e);
}
return null;
}
@Override
protected File getDirectory(String repo) throws URISyntaxException {
if (directory == null) {
String dir = getDir();
if (dir != null) {
directory = new File(getTempFile(dir), dir);
} else {
URIish uri = new URIish(repo);
String name = uri.getHumanishName();
directory = new File(getTempFile(name), name);
}
}
return directory;
}
private File getTempFile(String path) {
String tempDir = System.getProperty("java.io.tmpdir");
File tempFile = new File(tempDir + File.separator + path
+ new Random().nextInt());
if (!tempFile.exists()) {
tempFile.mkdir();
}
return tempFile;
}
}
private static final String PATH = "p";
private static final String PARAMS = "m";
private static final String IGNORE_FAILURES = "f";
private static final String REPO = "r";
private static final String USER = "u";
private static final String PASSWD = "d";
private static final String KEY = "k";
private static final String BRANCH = "g";
private static final String APP_ID = "i";
private static final String APP_REPO = "z";
private DeploymentCloneCommand cloneCommand = new DeploymentCloneCommand(
this);
@Option(opt = PATH, required = false, description = "Application package location or project's directory, if not provided current directory is considered", argName = "path")
public String getPath() {
final String value = getValue(PATH);
if (value == null) {
if (getGitRepository() != null
&& cloneCommand.getProjectFile() != null) {
return cloneCommand.getProjectFile().getAbsolutePath();
}
return getCurrentDirectory();
}
return value;
}
@Option(opt = PARAMS, required = false, description = "Properties file path of the parameters given to this application or a list of key=value separated by a comma", argName = "parameters")
public String getParams() {
return getValue(PARAMS);
}
@Option(opt = IGNORE_FAILURES, required = false, description = "Ignore failures")
public boolean isIgnoreFailures() {
return hasOption(IGNORE_FAILURES);
}
@Option(opt = REPO, required = false, description = "Repository to clone from", argName = "git repository")
public String getGitRepository() {
final String value = getValue(REPO);
return value;
}
@Option(opt = USER, required = false, description = "User name for git repository access", argName = "user")
public String getUser() {
final String value = getValue(USER);
return value;
}
@Option(opt = PASSWD, required = false, description = "Password for git repository access", argName = "password")
public String getPassword() {
final String value = getValue(PASSWD);
return value;
}
@Option(opt = KEY, required = false, description = "Path to SSH private key for git repository access", argName = "key")
public String getKey() {
final String value = getValue(KEY);
return value;
}
@Option(opt = BRANCH, required = false, description = "Initial branch to check out project from git repository", argName = "branch")
public String getBranch() {
final String value = getValue(BRANCH);
return value;
}
@Option(opt = APP_ID, required = false, description = "Application id in Zend Reposiotry", argName = "application id")
public String getAppName() {
final String value = getValue(APP_ID);
return value;
}
@Option(opt = APP_REPO, required = false, description = "URL of Zend Repository from which application should be downloaded", argName = "zend repository")
public String getRepositoryName() {
final String value = getValue(APP_REPO);
return value;
}
@Override
public boolean doExecute() {
ApplicationInfo info = null;
String targetId = getTargetId();
if (targetId != null) {
IZendTarget target = getTargetManager().getTargetById(targetId);
if (target == null) {
getLogger().error(
MessageFormat.format(
"Target with id {0} does not exist.", targetId));
return false;
}
}
getApplication().addStatusChangeListener(new StatusChangeListener());
if (getRepositoryName() != null && getAppName() != null) {
info = repositoryOperation();
} else if (getRepositoryName() != null || getAppName() != null) {
getLogger().error("Missing application id or Zend Repository URL.");
return true;
} else if (getGitRepository() != null) {
info = gitOperation();
} else {
info = doOperation();
}
return resolveResult(info);
}
protected abstract boolean resolveResult(ApplicationInfo info);
protected abstract ApplicationInfo doRepositoryOperation(
InputStream stream, Application app);
protected abstract ApplicationInfo doGitOperation();
protected abstract ApplicationInfo doOperation();
private ApplicationInfo repositoryOperation() {
RepositoryManager manager = new RepositoryManager(
new UserBasedRepositoryLoader());
IRepository repository = manager.getRepositoryById(getRepositoryName());
if (repository == null) {
getLogger().error("Incorrect Zend Repository URL");
return null;
}
try {
Application app = getApplicationFromRepository(repository);
if (app != null) {
InputStream stream = repository.getPackage(app);
return doRepositoryOperation(stream, app);
} else {
getLogger()
.error(MessageFormat
.format("There is no {0} application in {1} respository",
getAppName(), getRepositoryName()));
}
} catch (SdkException e) {
getLogger().error(e);
} catch (IOException e) {
getLogger().error(e);
}
return null;
}
private ApplicationInfo gitOperation() {
try {
if (cloneCommand.doExecute()) {
return doGitOperation();
}
} finally {
if (cloneCommand.getProjectFile() != null) {
delete(cloneCommand.getProjectFile().getParentFile());
}
}
return null;
}
protected Application getApplicationFromRepository(IRepository repository)
throws SdkException {
List<Application> apps = repository.getSite().getApplication();
if (apps != null) {
String name = getAppName();
for (Application app : apps) {
if (app.getName().equals(name)) {
return app;
}
}
}
return null;
}
private boolean delete(File file) {
if (file.isDirectory()) {
String[] children = file.list();
for (int i = 0; i < children.length; i++) {
boolean result = delete(new File(file, children[i]));
if (!result) {
return false;
}
}
}
return file.delete();
}
}