Major refactoring:
o Further decoupling of Deployer(s) from notion of artifact. o Deployers are now generic utility classes which can be used for deploying artifacts, sites, distributions etc. o Connection/session caching git-svn-id: https://svn.apache.org/repos/asf/maven/maven-1/plugins/trunk@113662 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
@@ -59,15 +59,17 @@ import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.text.DateFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.apache.maven.MavenConstants;
|
||||
import org.apache.maven.MavenException;
|
||||
import org.apache.maven.deploy.DeployRequest;
|
||||
import org.apache.maven.deploy.RepositoryInfo;
|
||||
import org.apache.maven.deploy.DeployTool;
|
||||
import org.apache.maven.deploy.exceptions.WrongParameterException;
|
||||
import org.apache.maven.deploy.deployers.Deployer;
|
||||
import org.apache.maven.project.Project;
|
||||
import org.apache.maven.util.MD5Sum;
|
||||
|
||||
@@ -77,7 +79,7 @@ import org.apache.maven.util.MD5Sum;
|
||||
*
|
||||
*
|
||||
* @author <a href="michal.maczka@dimatics.com">Michal Maczka</a>
|
||||
* @version $Id: DefaultArtifactDeployer.java,v 1.11 2003/07/02 12:42:23 michal Exp $
|
||||
* @version $Id: DefaultArtifactDeployer.java,v 1.12 2003/07/17 11:13:17 michal Exp $
|
||||
*/
|
||||
public class DefaultArtifactDeployer implements ArtifactDeployer
|
||||
{
|
||||
@@ -104,19 +106,20 @@ public class DefaultArtifactDeployer implements ArtifactDeployer
|
||||
throws MavenException
|
||||
{
|
||||
|
||||
project.getFile();
|
||||
File file = getFileForArtifact(artifact);
|
||||
File md5File = createMD5Checksum(file);
|
||||
String repositoryPath =
|
||||
getRepositoryPath(type, project, project.getCurrentVersion());
|
||||
String repositoryFile =
|
||||
getRepositoryFile(type, project, project.getCurrentVersion());
|
||||
|
||||
String[] srcFilenames =
|
||||
{ file.getAbsolutePath(), md5File.getAbsolutePath()};
|
||||
List srcFiles = new ArrayList();
|
||||
srcFiles.add(file.getAbsolutePath());
|
||||
srcFiles.add(md5File.getAbsolutePath());
|
||||
|
||||
String[] destFilenames = { repositoryFile, repositoryFile + ".md5" };
|
||||
|
||||
doDeploy(srcFilenames, destFilenames, repositoryPath, project);
|
||||
List destFiles = new ArrayList();
|
||||
destFiles.add(repositoryPath);
|
||||
destFiles.add(repositoryPath + ".md5");
|
||||
doDeploy(srcFiles, destFiles, project);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -134,24 +137,24 @@ public class DefaultArtifactDeployer implements ArtifactDeployer
|
||||
String repositoryPath =
|
||||
getRepositoryPath(type, project, MavenConstants.SNAPSHOT_SIGNIFIER);
|
||||
|
||||
String[] srcFilenames = new String[5];
|
||||
srcFilenames[0] = file.getAbsolutePath();
|
||||
srcFilenames[1] = file.getAbsolutePath();
|
||||
srcFilenames[2] = md5File.getAbsolutePath();
|
||||
srcFilenames[3] = md5File.getAbsolutePath();
|
||||
srcFilenames[4] = snapshotVersionFile.getAbsolutePath();
|
||||
List srcFiles = new ArrayList();
|
||||
srcFiles.add(file.getAbsolutePath());
|
||||
srcFiles.add(file.getAbsolutePath());
|
||||
srcFiles.add(md5File.getAbsolutePath());
|
||||
srcFiles.add(md5File.getAbsolutePath());
|
||||
srcFiles.add(snapshotVersionFile.getAbsolutePath());
|
||||
|
||||
String out1 =
|
||||
getRepositoryFile(type, project, MavenConstants.SNAPSHOT_SIGNIFIER);
|
||||
String out2 = getRepositoryFile(type, project, snapshotVersion);
|
||||
getRepositoryPath(type, project, MavenConstants.SNAPSHOT_SIGNIFIER);
|
||||
String out2 = getRepositoryPath(type, project, snapshotVersion);
|
||||
|
||||
String[] destFilenames = new String[5];
|
||||
destFilenames[0] = out1;
|
||||
destFilenames[1] = out2;
|
||||
destFilenames[2] = out1 + ".md5";
|
||||
destFilenames[3] = out2 + ".md5";
|
||||
destFilenames[4] = project.getArtifactId() + "-snapshot-version";
|
||||
doDeploy(srcFilenames, destFilenames, repositoryPath, project);
|
||||
List destFiles = new ArrayList();
|
||||
destFiles.add(out1);
|
||||
destFiles.add(out1 + ".md5");
|
||||
destFiles.add(out2);
|
||||
destFiles.add(out2 + ".md5");
|
||||
destFiles.add(project.getArtifactId() + "-snapshot-version");
|
||||
doDeploy(srcFiles, destFiles, project);
|
||||
|
||||
};
|
||||
|
||||
@@ -213,12 +216,10 @@ public class DefaultArtifactDeployer implements ArtifactDeployer
|
||||
new File(
|
||||
getLocalRepository(project),
|
||||
getRepositoryPath(type, project, version));
|
||||
if (!destFile.exists())
|
||||
if (!destFile.getParentFile().exists())
|
||||
{
|
||||
destFile.mkdirs();
|
||||
destFile.getParentFile().mkdirs();
|
||||
}
|
||||
destFile =
|
||||
new File(destFile, getRepositoryFile(type, project, version));
|
||||
System.out.println(
|
||||
"Copying: from '" + file + "' to: '" + destFile + "'");
|
||||
FileUtils.copyFile(file, destFile);
|
||||
@@ -242,11 +243,7 @@ public class DefaultArtifactDeployer implements ArtifactDeployer
|
||||
* @param project
|
||||
* @param snapshot
|
||||
*/
|
||||
private void doDeploy(
|
||||
String[] srcFilenames,
|
||||
String[] destFilenames,
|
||||
String destPath,
|
||||
Project project)
|
||||
private void doDeploy(List srcFiles, List destFiles, Project project)
|
||||
throws MavenException
|
||||
{
|
||||
|
||||
@@ -257,19 +254,6 @@ public class DefaultArtifactDeployer implements ArtifactDeployer
|
||||
String repos =
|
||||
(String) project.getContext().getVariable("maven.repo.list");
|
||||
|
||||
String distSite = project.getDistributionSite();
|
||||
if (distSite != null && distSite.length() > 0)
|
||||
{
|
||||
project.getContext().setVariable(
|
||||
"maven.repo.central",
|
||||
project.getDistributionSite());
|
||||
project.getContext().setVariable(
|
||||
"maven.central.directory",
|
||||
project.getDistributionDirectory());
|
||||
|
||||
repos = "central, " + repos;
|
||||
}
|
||||
|
||||
if (repos == null || repos.length() == 0)
|
||||
{
|
||||
System.out.println(
|
||||
@@ -280,57 +264,35 @@ public class DefaultArtifactDeployer implements ArtifactDeployer
|
||||
|
||||
System.out.println(
|
||||
"Will deploy to " + repoArray.length + " repo(s): " + repos);
|
||||
|
||||
Deployer deployer = null;
|
||||
for (int i = 0; i < repoArray.length; i++)
|
||||
{
|
||||
|
||||
String repo = repoArray[i].trim();
|
||||
System.out.println("Deploying to repo: " + repo);
|
||||
|
||||
DeployRequest request = null;
|
||||
|
||||
// Will create only one request per repository
|
||||
RepositoryInfo repoInfo = null;
|
||||
try
|
||||
{
|
||||
request = DeployRequestBuilder.getDeployRequest(project, repo);
|
||||
request.setDestDir(destPath);
|
||||
repoInfo =
|
||||
RepositoryInfoBuilder.getRepositoryInfo(
|
||||
project,
|
||||
repo);
|
||||
|
||||
deployTool.deploy(repoInfo, srcFiles, destFiles);
|
||||
}
|
||||
catch (WrongParameterException e)
|
||||
catch (Exception e)
|
||||
{
|
||||
System.out.print(e.getMessage());
|
||||
String msg =
|
||||
"Failed to deploy to: "
|
||||
+ repoInfo.getRepositoryAlias()
|
||||
+ " Reason: "
|
||||
+ e.getMessage();
|
||||
System.out.print(msg);
|
||||
// deploy to next repository
|
||||
e.printStackTrace();
|
||||
continue;
|
||||
}
|
||||
|
||||
for (int j = 0; j < srcFilenames.length; j++)
|
||||
{
|
||||
try
|
||||
{
|
||||
request.setSrcFile(srcFilenames[j]);
|
||||
request.setDestFile(destFilenames[j]);
|
||||
|
||||
System.out.println(
|
||||
"Deploying: '"
|
||||
+ destFilenames[j]
|
||||
+ "' to host: '"
|
||||
+ request.getHost()
|
||||
+ "' remote path: '"
|
||||
+ request.getBaseDir()
|
||||
+ "/"
|
||||
+ request.getDestDir()
|
||||
+ "' remote file: '"
|
||||
+ request.getDestFile());
|
||||
deployTool.performUpload(request);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
String msg =
|
||||
"Cannot deploy to: "
|
||||
+ request.getRepositoryAlias()
|
||||
+ ". Reason:"
|
||||
+ e.getMessage();
|
||||
throw new MavenException(msg, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -363,22 +325,7 @@ public class DefaultArtifactDeployer implements ArtifactDeployer
|
||||
path.append(project.getArtifactDirectory());
|
||||
path.append("/");
|
||||
path.append(type + "s");
|
||||
return path.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param type
|
||||
* @param project
|
||||
* @param version
|
||||
* @return
|
||||
*/
|
||||
private String getRepositoryFile(
|
||||
String type,
|
||||
Project project,
|
||||
String version)
|
||||
{
|
||||
StringBuffer path = new StringBuffer();
|
||||
path.append("/");
|
||||
path.append(project.getArtifactId());
|
||||
path.append("-");
|
||||
path.append(version);
|
||||
@@ -395,7 +342,6 @@ public class DefaultArtifactDeployer implements ArtifactDeployer
|
||||
{
|
||||
Date date = new Date();
|
||||
return SNAPSHOT_MARKER.format(date);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -499,7 +445,7 @@ public class DefaultArtifactDeployer implements ArtifactDeployer
|
||||
|
||||
/**
|
||||
* Return file extension for given type
|
||||
* @todo Dirty hack util Repository Layout Service is used
|
||||
* @todo Dirty hack Repository Layout Service from maven-new should be used
|
||||
* @return extension for given type
|
||||
*/
|
||||
private String extensionForType(String type)
|
||||
|
||||
@@ -56,8 +56,9 @@ package org.apache.maven.artifact.deployer;
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
import org.apache.maven.deploy.DeployRequest;
|
||||
import org.apache.maven.deploy.exceptions.WrongParameterException;
|
||||
import java.net.MalformedURLException;
|
||||
|
||||
import org.apache.maven.deploy.RepositoryInfo;
|
||||
import org.apache.maven.project.Project;
|
||||
|
||||
/**
|
||||
@@ -65,12 +66,11 @@ import org.apache.maven.project.Project;
|
||||
* Perform mapping between project's properties and attributes of DeployRequest class.
|
||||
*
|
||||
* @author <a href="michal.maczka@dimatics.com">Michal Maczka</a>
|
||||
* @version $Id: DeployRequestBuilder.java,v 1.3 2003/07/02 12:42:23 michal Exp $
|
||||
* @version $Id: RepositoryInfoBuilder.java,v 1.1 2003/07/17 11:13:17 michal Exp $
|
||||
*/
|
||||
public class DeployRequestBuilder
|
||||
public class RepositoryInfoBuilder
|
||||
{
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @param project. Will lookup the properties in the context of this project
|
||||
@@ -79,14 +79,14 @@ public class DeployRequestBuilder
|
||||
* @return Deploy request
|
||||
* @throws WrongParameterException
|
||||
*/
|
||||
public static DeployRequest getDeployRequest(
|
||||
public static RepositoryInfo getRepositoryInfo(
|
||||
Project project,
|
||||
String repository)
|
||||
throws WrongParameterException
|
||||
throws MalformedURLException
|
||||
{
|
||||
|
||||
DeployRequest request = new DeployRequest();
|
||||
request.setRepositoryAlias(repository);
|
||||
RepositoryInfo repoInfo = new RepositoryInfo();
|
||||
repoInfo.setRepositoryAlias(repository);
|
||||
String url =
|
||||
(String) project.getContext().getVariable(
|
||||
"maven.repo." + repository);
|
||||
@@ -125,45 +125,46 @@ public class DeployRequestBuilder
|
||||
|
||||
String proxyPort = (String) project.getContext().getProxyPort();
|
||||
|
||||
request.setUserName(username);
|
||||
request.setPassword(password);
|
||||
request.setPassphrase(passphrase);
|
||||
request.setPrivateKey(privateKey);
|
||||
request.setGroup(remoteGroup);
|
||||
request.setUrl(url);
|
||||
request.setProxyHost(proxyHost);
|
||||
request.setProxyUserName(proxyUser);
|
||||
request.setProxyPassword(proxyPassword);
|
||||
repoInfo.setUserName(username);
|
||||
repoInfo.setPassword(password);
|
||||
repoInfo.setPassphrase(passphrase);
|
||||
repoInfo.setPrivateKey(privateKey);
|
||||
repoInfo.setGroup(remoteGroup);
|
||||
repoInfo.setUrl(url);
|
||||
repoInfo.setProxyHost(proxyHost);
|
||||
repoInfo.setProxyUserName(proxyUser);
|
||||
repoInfo.setProxyPassword(proxyPassword);
|
||||
if (port != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
||||
request.setPort(Integer.parseInt(port));
|
||||
repoInfo.setPort(Integer.parseInt(port));
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw new WrongParameterException(
|
||||
"maven.repo." + repository + ".port should be an integer");
|
||||
throw new MalformedURLException(
|
||||
"maven.repo." + repository + ".port should be an integer");
|
||||
}
|
||||
}
|
||||
if (proxyPort != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
request.setProxyPort(Integer.parseInt(proxyPort.trim()));
|
||||
repoInfo.setProxyPort(
|
||||
Integer.parseInt(proxyPort.trim()));
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw new WrongParameterException(
|
||||
throw new MalformedURLException(
|
||||
"maven.repo."
|
||||
+ repository
|
||||
+ ".proxy.port should be an integer");
|
||||
+ ".proxy.port should be an integer");
|
||||
}
|
||||
}
|
||||
|
||||
request.setBaseDir(dir);
|
||||
return request;
|
||||
repoInfo.setBasedir(dir);
|
||||
return repoInfo;
|
||||
|
||||
}
|
||||
|
||||
@@ -62,225 +62,23 @@ package org.apache.maven.deploy;
|
||||
* deploy the file to correct location in remote file system
|
||||
*
|
||||
* @author <a href="michal.maczka@dimatics.com">Michal Maczka</a>
|
||||
* @version $Id: DeployRequest.java,v 1.6 2003/07/02 12:42:23 michal Exp $
|
||||
* @version $Id: DeployRequest.java,v 1.7 2003/07/17 11:13:18 michal Exp $
|
||||
*/
|
||||
public class DeployRequest
|
||||
{
|
||||
|
||||
/** Used to mark */
|
||||
public final static int UNKNOWN_PORT = -1;
|
||||
|
||||
public final static String HEADER_USER_AGENT =
|
||||
"Maven-Deploy-" + DeployTool.VERSION;
|
||||
|
||||
/** The nickname (alias) of the repository*/
|
||||
private String repositoryAlias;
|
||||
|
||||
/** URL of the remote host*/
|
||||
private String url;
|
||||
|
||||
/** Port of remote host */
|
||||
private int port = UNKNOWN_PORT;
|
||||
|
||||
private String baseDir;
|
||||
|
||||
/**
|
||||
* The directory where artifact will be placed
|
||||
* It is relative to base dir
|
||||
*/
|
||||
private String destDir;
|
||||
|
||||
/** The filename of the artifact */
|
||||
/** The filename in target file system */
|
||||
private String destFile;
|
||||
|
||||
/** The artifact file in local file system */
|
||||
/** The file name in local file system */
|
||||
private String srcFile;
|
||||
|
||||
/** The login name of the user in @ remote host*/
|
||||
private String userName;
|
||||
|
||||
/** Password */
|
||||
private String password;
|
||||
|
||||
/** Remote group name */
|
||||
private String group;
|
||||
|
||||
/** The passpharse of the user's private key file */
|
||||
private String passphrase;
|
||||
|
||||
/** The absoluth path to private key file */
|
||||
private String privateKey;
|
||||
|
||||
/** Proxy Server host*/
|
||||
private String proxyHost = null;
|
||||
|
||||
/** the login name of the user @ Proxy Server host*/
|
||||
private String proxyUserName = null;
|
||||
|
||||
/** the password user @ Proxy Server host*/
|
||||
private String proxyPassword = null;
|
||||
|
||||
/** Proxy server port */
|
||||
private int proxyPort = UNKNOWN_PORT;
|
||||
|
||||
/** Indicates if debug mode should be used*/
|
||||
private boolean debugOn = false;
|
||||
|
||||
/**
|
||||
* Set the alias of the repository
|
||||
* @param repositoryAlias
|
||||
*/
|
||||
public void setRepositoryAlias(String repositoryAlias)
|
||||
public DeployRequest(String srcFile, String destFile)
|
||||
{
|
||||
this.repositoryAlias = repositoryAlias;
|
||||
this.srcFile = srcFile;
|
||||
this.destFile = destFile;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the port of the host
|
||||
* @return the port of the remote host where repository resides.
|
||||
*/
|
||||
public int getPort()
|
||||
{
|
||||
return port;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the port of the remote host
|
||||
* @param port
|
||||
*/
|
||||
public void setPort(int port)
|
||||
{
|
||||
this.port = port;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the passphrase of the private key file.
|
||||
* Passphrase is used only when host/protocol supports
|
||||
* authetification via exchange of private/public keys
|
||||
* and private key was provided.
|
||||
*
|
||||
* @return the passphrase of the private key file
|
||||
*/
|
||||
public String getPassphrase()
|
||||
{
|
||||
return passphrase;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the passphrase of the private key file
|
||||
* @param passphrase the passphrase of the private key file
|
||||
*/
|
||||
public void setPassphrase(String passphrase)
|
||||
{
|
||||
this.passphrase = passphrase;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the absoluth path to the private key
|
||||
* @return the path to private key
|
||||
*/
|
||||
public String getPrivateKey()
|
||||
{
|
||||
return privateKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the aboluth path to private key
|
||||
* @param privateKey The path to private key in local file system
|
||||
*/
|
||||
public void setPrivateKey(String privateKey)
|
||||
{
|
||||
this.privateKey = privateKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the remote group to which will belong to
|
||||
* after deployemnt. Not all protolcols support
|
||||
* allow to change the group of the artifact
|
||||
* @return remote group
|
||||
*/
|
||||
public String getGroup()
|
||||
{
|
||||
return group;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the remote group for artifact which is deployed
|
||||
* @param group The remote group to which
|
||||
* artifact which is deployed will belong
|
||||
*/
|
||||
public void setGroup(String group)
|
||||
{
|
||||
this.group = group;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return
|
||||
*/
|
||||
public String getHeaderUserAgent()
|
||||
{
|
||||
return HEADER_USER_AGENT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get base directory
|
||||
* @return base directory
|
||||
*/
|
||||
public String getBaseDir()
|
||||
{
|
||||
return baseDir;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set base directory
|
||||
* @param baseDir
|
||||
*/
|
||||
public void setBaseDir(String baseDir)
|
||||
{
|
||||
this.baseDir = baseDir;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get absolute path to local file = artifact
|
||||
* @return Path to artifact file
|
||||
*/
|
||||
public String getSrcFile()
|
||||
{
|
||||
return srcFile;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the absolute path to artifact file
|
||||
* @param srcFile
|
||||
*/
|
||||
public void setSrcFile(String inputFile)
|
||||
{
|
||||
this.srcFile = inputFile;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get destination directory in remote file system for
|
||||
* the artifact
|
||||
*
|
||||
* @return destination dir for artifact
|
||||
*/
|
||||
public String getDestDir()
|
||||
{
|
||||
return destDir;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set destinatin directory in remote file system
|
||||
*
|
||||
* @param destDir the remote path for the artifact
|
||||
*/
|
||||
public void setDestDir(String outputDir)
|
||||
{
|
||||
this.destDir = outputDir;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get destination file name
|
||||
* @return
|
||||
*/
|
||||
public String getDestFile()
|
||||
@@ -289,183 +87,48 @@ public class DeployRequest
|
||||
}
|
||||
|
||||
/**
|
||||
* Set destination file name
|
||||
* @param destFile
|
||||
*/
|
||||
public void setDestFile(String outputFile)
|
||||
public void setDestFile(String destFile)
|
||||
{
|
||||
this.destFile = outputFile;
|
||||
this.destFile = destFile;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the password to be used when user will be authetificated
|
||||
* while connection to remote host is established
|
||||
* @return the password of user
|
||||
*/
|
||||
public String getPassword()
|
||||
{
|
||||
return password;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @param password
|
||||
*/
|
||||
public void setPassword(String pass)
|
||||
{
|
||||
this.password = pass;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returhn proxy server host name
|
||||
* @return proxy server host name
|
||||
*/
|
||||
public String getProxyHost()
|
||||
{
|
||||
return proxyHost;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set proxy host name
|
||||
* @param proxyHost
|
||||
*/
|
||||
public void setProxyHost(String proxyHost)
|
||||
{
|
||||
this.proxyHost = proxyHost;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get user's password used to login to proxy server
|
||||
* @return the user's password at proxy host
|
||||
*/
|
||||
public String getProxyPassword()
|
||||
{
|
||||
return proxyPassword;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the proxy server password
|
||||
* @param proxyPassword teh epassword to use to login to a proxy server
|
||||
*/
|
||||
public void setProxyPassword(String proxyPass)
|
||||
{
|
||||
this.proxyPassword = proxyPass;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the proxy port
|
||||
* @return Poroxy server port
|
||||
*/
|
||||
public int getProxyPort()
|
||||
{
|
||||
return proxyPort;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the proxy port
|
||||
* @param proxyPort
|
||||
*/
|
||||
public void setProxyPort(int proxyPort)
|
||||
{
|
||||
this.proxyPort = proxyPort;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Get the proxy user name
|
||||
* @return
|
||||
*/
|
||||
public String getProxyUserName()
|
||||
public String getSrcFile()
|
||||
{
|
||||
return proxyUserName;
|
||||
return srcFile;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the proxy user name
|
||||
* @param proxyUserName the proxy user name
|
||||
* @param srcFile
|
||||
*/
|
||||
public void setProxyUserName(String proxyUser)
|
||||
public void setSrcFile(String srcFile)
|
||||
{
|
||||
this.proxyUserName = proxyUser;
|
||||
this.srcFile = srcFile;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get url of remote host
|
||||
* @return URL (with protocol) of remote host
|
||||
* Returns the directory path portion of a file specification string.
|
||||
* Matches the equally named unix command.
|
||||
* @return The directory portion excluding the ending file separator.
|
||||
*/
|
||||
public String getUrl()
|
||||
public String dirname()
|
||||
{
|
||||
return url;
|
||||
int i = destFile.lastIndexOf("/");
|
||||
return (i >= 0 ? destFile.substring(0, i) : "");
|
||||
}
|
||||
|
||||
/**
|
||||
* Set url of remote host
|
||||
* @param url url of remote host
|
||||
* Returns the filename portion of a file specification string.
|
||||
* @return The filename string with extension.
|
||||
*/
|
||||
public void setUrl(String url)
|
||||
public String filename()
|
||||
{
|
||||
this.url = url;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get user login name at remote host
|
||||
* @return user name at remote host
|
||||
*/
|
||||
public String getUserName()
|
||||
{
|
||||
return userName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set user name at remote host
|
||||
* @param userName
|
||||
*/
|
||||
public void setUserName(String user)
|
||||
{
|
||||
this.userName = user;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the host name (Cuts of protocol from the URL)
|
||||
* @return The host name
|
||||
*/
|
||||
public String getHost()
|
||||
{
|
||||
if (url == null)
|
||||
{
|
||||
return "localhost";
|
||||
}
|
||||
return url.substring(url.indexOf("://") + 3).trim();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the name of the repository to which deploy attempt will be made
|
||||
*
|
||||
* @return the name (nickname, alias) of the repository
|
||||
*/
|
||||
public String getRepositoryAlias()
|
||||
{
|
||||
|
||||
return repositoryAlias;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Debug mode
|
||||
* @return the debug mode
|
||||
*/
|
||||
public boolean isDebugOn()
|
||||
{
|
||||
return debugOn;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set deplyer in debug mode - more messages will be wriiten
|
||||
* @param debugOn
|
||||
*/
|
||||
public void setDebugOn(boolean debugOn)
|
||||
{
|
||||
this.debugOn = debugOn;
|
||||
int i = destFile.lastIndexOf("/");
|
||||
return (i >= 0 ? destFile.substring(i + 1) : destFile);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -56,6 +56,9 @@ package org.apache.maven.deploy;
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.maven.deploy.deployers.Deployer;
|
||||
import org.apache.maven.deploy.deployers.ExternalDeployer;
|
||||
import org.apache.maven.deploy.deployers.FileDeployer;
|
||||
@@ -63,16 +66,15 @@ import org.apache.maven.deploy.deployers.FtpDeployer;
|
||||
import org.apache.maven.deploy.deployers.HttpDeployer;
|
||||
import org.apache.maven.deploy.deployers.SFtpDeployer;
|
||||
import org.apache.maven.deploy.deployers.ScpDeployer;
|
||||
import org.apache.maven.deploy.exceptions.NotAuthorizedDeployException;
|
||||
import org.apache.maven.deploy.exceptions.ProxyNotAuthorizedDeployException;
|
||||
import org.apache.maven.deploy.exceptions.AuthenticationException;
|
||||
import org.apache.maven.deploy.exceptions.TransferFailedException;
|
||||
import org.apache.maven.deploy.exceptions.UnsupportedProtocolException;
|
||||
import org.apache.maven.deploy.exceptions.WrongParameterException;
|
||||
|
||||
/**
|
||||
* Delegates
|
||||
* Utility class
|
||||
*
|
||||
* @author <a href="michal.maczka@dimatics.com">Michal Maczka</a>
|
||||
* @version $Id: DeployTool.java,v 1.6 2003/07/02 12:42:23 michal Exp $
|
||||
* @version $Id: DeployTool.java,v 1.7 2003/07/17 11:13:18 michal Exp $
|
||||
*/
|
||||
public class DeployTool
|
||||
{
|
||||
@@ -80,28 +82,22 @@ public class DeployTool
|
||||
public static final String VERSION = "1.0-dev";
|
||||
|
||||
/**
|
||||
* Upload (deploy) artifact to remote repository using
|
||||
* paramerters kepts in <code>DeployReequest</code>
|
||||
* @param request The settings
|
||||
* @throws DeployException When operation fails
|
||||
* Returns deployer which is able to deploy to repository
|
||||
* described by host info.
|
||||
* @param repoInfo
|
||||
* @throws DeployException When no deployer is supporting given protocol
|
||||
*/
|
||||
public void performUpload(DeployRequest request)
|
||||
throws
|
||||
TransferFailedException,
|
||||
NotAuthorizedDeployException,
|
||||
ProxyNotAuthorizedDeployException,
|
||||
TransferFailedException,
|
||||
WrongParameterException,
|
||||
UnsupportedProtocolException
|
||||
public Deployer getDeployer(RepositoryInfo repoInfo)
|
||||
throws IllegalArgumentException, UnsupportedProtocolException
|
||||
{
|
||||
String url = request.getUrl();
|
||||
String url = repoInfo.getUrl();
|
||||
Deployer deployer = null;
|
||||
|
||||
if (url == null || url.length() == 1)
|
||||
{
|
||||
throw new WrongParameterException(
|
||||
"No URL provided for repository: "
|
||||
+ request.getRepositoryAlias());
|
||||
throw new UnsupportedProtocolException(
|
||||
"No URL was provided repository: "
|
||||
+ repoInfo.getRepositoryAlias());
|
||||
}
|
||||
if (url.startsWith(HttpDeployer.PROTOCOL))
|
||||
{
|
||||
@@ -131,8 +127,61 @@ public class DeployTool
|
||||
{
|
||||
throw new UnsupportedProtocolException(url);
|
||||
}
|
||||
|
||||
deployer.deploy(request);
|
||||
|
||||
return deployer;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Deploy given list of files to remote repository
|
||||
* @param repoInfo the
|
||||
* @param srcFiles the list containing local filenames which will be deployed to remote host
|
||||
* @param destFiles the list contating the remote filenames. The size of this list
|
||||
* must match the size of srcFiles list
|
||||
* @throws TransferFailedException when copying operation fails
|
||||
* @throws UnsupportedProtocolException when no deployer is capable to deploy to given host
|
||||
* @throws AuthenticationException when authentication related problem occures
|
||||
*/
|
||||
public void deploy(
|
||||
RepositoryInfo repoInfo,
|
||||
List srcFiles,
|
||||
List destFiles)
|
||||
throws
|
||||
TransferFailedException,
|
||||
UnsupportedProtocolException,
|
||||
AuthenticationException
|
||||
{
|
||||
|
||||
if (srcFiles.size() != destFiles.size())
|
||||
{
|
||||
String msg = "Lenghts of the lists should be the same";
|
||||
throw new IllegalArgumentException(msg);
|
||||
}
|
||||
Deployer deployer = getDeployer(repoInfo);
|
||||
|
||||
try
|
||||
{
|
||||
deployer.init(repoInfo);
|
||||
Iterator srcIterator = srcFiles.iterator();
|
||||
Iterator destIterator = destFiles.iterator();
|
||||
while (srcIterator.hasNext())
|
||||
{
|
||||
String srcFile = (String) srcIterator.next();
|
||||
String destFile = (String) destIterator.next();
|
||||
DeployRequest request = new DeployRequest(srcFile, destFile);
|
||||
System.out.println("Deploying: " + srcFile);
|
||||
deployer.deploy(request);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
try
|
||||
{
|
||||
deployer.release();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
390
artifact/src/main/org/apache/maven/deploy/RepositoryInfo.java
Normal file
390
artifact/src/main/org/apache/maven/deploy/RepositoryInfo.java
Normal file
@@ -0,0 +1,390 @@
|
||||
package org.apache.maven.deploy;
|
||||
|
||||
/* ====================================================================
|
||||
* The Apache Software License, Version 1.1
|
||||
*
|
||||
* Copyright (c) 2003 The Apache Software Foundation. All rights
|
||||
* reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. The end-userName documentation included with the redistribution,
|
||||
* if any, must include the following acknowledgment:
|
||||
* "This product includes software developed by the
|
||||
* Apache Software Foundation (http://www.apache.org/)."
|
||||
* Alternately, this acknowledgment may appear in the software itself,
|
||||
* if and wherever such third-party acknowledgments normally appear.
|
||||
*
|
||||
* 4. The names "Apache" and "Apache Software Foundation" and
|
||||
* "Apache Maven" must not be used to endorse or promote products
|
||||
* derived from this software without prior written permission. For
|
||||
* written permission, please contact apache@apache.org.
|
||||
*
|
||||
* 5. Products derived from this software may not be called "Apache",
|
||||
* "Apache Maven", nor may "Apache" appear in their name, without
|
||||
* prior written permission of the Apache Software Foundation.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
|
||||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
||||
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
* ====================================================================
|
||||
*
|
||||
* This software consists of voluntary contributions made by many
|
||||
* individuals on behalf of the Apache Software Foundation. For more
|
||||
* information on the Apache Software Foundation, please see
|
||||
* <http://www.apache.org/>.
|
||||
*
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
/**
|
||||
* Contatins the set of poperties which are necessery
|
||||
* for esatblishing connection to remote hosts and to
|
||||
* perform a deployment.
|
||||
*
|
||||
* @author <a href="michal.maczka@dimatics.com">Michal Maczka</a>
|
||||
* @version $Id: RepositoryInfo.java,v 1.1 2003/07/17 11:13:18 michal Exp $
|
||||
*/
|
||||
public class RepositoryInfo
|
||||
{
|
||||
|
||||
/** Idicates that port has not been set */
|
||||
public final static int UNKNOWN_PORT = -1;
|
||||
|
||||
/** The nickname (alias) of the repository*/
|
||||
private String repositoryAlias;
|
||||
|
||||
/** URL of the remote host*/
|
||||
private String url;
|
||||
|
||||
/** Port of remote host */
|
||||
private int port = UNKNOWN_PORT;
|
||||
|
||||
/** The login name of the user in @ remote host*/
|
||||
private String userName;
|
||||
|
||||
/** Password */
|
||||
private String password;
|
||||
|
||||
/** Remote group name */
|
||||
private String group;
|
||||
|
||||
/** The passpharse of the user's private key file */
|
||||
private String passphrase;
|
||||
|
||||
/** The absoluth path to private key file */
|
||||
private String privateKey;
|
||||
|
||||
/** Proxy Server host*/
|
||||
private String proxyHost = null;
|
||||
|
||||
/** the login name of the user @ Proxy Server host*/
|
||||
private String proxyUserName = null;
|
||||
|
||||
/** the password user @ Proxy Server host*/
|
||||
private String proxyPassword = null;
|
||||
|
||||
/** Proxy server port */
|
||||
private int proxyPort = UNKNOWN_PORT;
|
||||
|
||||
/** Indicates if debug mode should be used*/
|
||||
private boolean debugOn = true;
|
||||
|
||||
/** basedir */
|
||||
private String basedir;
|
||||
|
||||
/**
|
||||
* @return
|
||||
*/
|
||||
public String getBasedir()
|
||||
{
|
||||
return basedir;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param basedir
|
||||
*/
|
||||
public void setBasedir(String basedir)
|
||||
{
|
||||
this.basedir = basedir;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the alias of the repository
|
||||
* @param repositoryAlias
|
||||
*/
|
||||
public void setRepositoryAlias(String repositoryAlias)
|
||||
{
|
||||
this.repositoryAlias = repositoryAlias;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the port of the host
|
||||
* @return the port of the remote host where repository resides.
|
||||
*/
|
||||
public int getPort()
|
||||
{
|
||||
return port;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the port of the remote host
|
||||
* @param port
|
||||
*/
|
||||
public void setPort(int port)
|
||||
{
|
||||
this.port = port;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the passphrase of the private key file.
|
||||
* Passphrase is used only when host/protocol supports
|
||||
* authetification via exchange of private/public keys
|
||||
* and private key was provided.
|
||||
*
|
||||
* @return the passphrase of the private key file
|
||||
*/
|
||||
public String getPassphrase()
|
||||
{
|
||||
return passphrase;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the passphrase of the private key file
|
||||
* @param passphrase the passphrase of the private key file
|
||||
*/
|
||||
public void setPassphrase(String passphrase)
|
||||
{
|
||||
this.passphrase = passphrase;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the absoluth path to the private key
|
||||
* @return the path to private key
|
||||
*/
|
||||
public String getPrivateKey()
|
||||
{
|
||||
return privateKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the aboluth path to private key
|
||||
* @param privateKey The path to private key in local file system
|
||||
*/
|
||||
public void setPrivateKey(String privateKey)
|
||||
{
|
||||
this.privateKey = privateKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the remote group to which will belong to
|
||||
* after deployemnt. Not all protolcols support
|
||||
* allow to change the group of the artifact
|
||||
* @return remote group
|
||||
*/
|
||||
public String getGroup()
|
||||
{
|
||||
return group;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the remote group for artifact which is deployed
|
||||
* @param group The remote group to which
|
||||
* artifact which is deployed will belong
|
||||
*/
|
||||
public void setGroup(String group)
|
||||
{
|
||||
this.group = group;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the password to be used when user will be authetificated
|
||||
* while connection to remote host is established
|
||||
* @return the password of user
|
||||
*/
|
||||
public String getPassword()
|
||||
{
|
||||
return password;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @param password
|
||||
*/
|
||||
public void setPassword(String pass)
|
||||
{
|
||||
this.password = pass;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returhn proxy server host name
|
||||
* @return proxy server host name
|
||||
*/
|
||||
public String getProxyHost()
|
||||
{
|
||||
return proxyHost;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set proxy host name
|
||||
* @param proxyHost
|
||||
*/
|
||||
public void setProxyHost(String proxyHost)
|
||||
{
|
||||
this.proxyHost = proxyHost;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get user's password used to login to proxy server
|
||||
* @return the user's password at proxy host
|
||||
*/
|
||||
public String getProxyPassword()
|
||||
{
|
||||
return proxyPassword;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the proxy server password
|
||||
* @param proxyPassword teh epassword to use to login to a proxy server
|
||||
*/
|
||||
public void setProxyPassword(String proxyPass)
|
||||
{
|
||||
this.proxyPassword = proxyPass;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the proxy port
|
||||
* @return Poroxy server port
|
||||
*/
|
||||
public int getProxyPort()
|
||||
{
|
||||
return proxyPort;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the proxy port
|
||||
* @param proxyPort
|
||||
*/
|
||||
public void setProxyPort(int proxyPort)
|
||||
{
|
||||
this.proxyPort = proxyPort;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Get the proxy user name
|
||||
* @return
|
||||
*/
|
||||
public String getProxyUserName()
|
||||
{
|
||||
return proxyUserName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the proxy user name
|
||||
* @param proxyUserName the proxy user name
|
||||
*/
|
||||
public void setProxyUserName(String proxyUser)
|
||||
{
|
||||
this.proxyUserName = proxyUser;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get url of remote host
|
||||
* @return URL (with protocol) of remote host
|
||||
*/
|
||||
public String getUrl()
|
||||
{
|
||||
return url;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set url of remote host
|
||||
* @param url url of remote host
|
||||
*/
|
||||
public void setUrl(String url)
|
||||
{
|
||||
this.url = url;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get user login name at remote host
|
||||
* @return user name at remote host
|
||||
*/
|
||||
public String getUserName()
|
||||
{
|
||||
return userName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set user name at remote host
|
||||
* @param userName
|
||||
*/
|
||||
public void setUserName(String user)
|
||||
{
|
||||
this.userName = user;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the host name (Cuts of protocol from the URL)
|
||||
* @return The host name
|
||||
*/
|
||||
public String getHost()
|
||||
{
|
||||
if (url == null)
|
||||
{
|
||||
return "localhost";
|
||||
}
|
||||
return url.substring(url.indexOf("://") + 3).trim();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the name of the repository to which deploy attempt will be made
|
||||
*
|
||||
* @return the name (nickname, alias) of the repository
|
||||
*/
|
||||
public String getRepositoryAlias()
|
||||
{
|
||||
|
||||
return repositoryAlias;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Debug mode
|
||||
* @return the debug mode
|
||||
*/
|
||||
public boolean isDebugOn()
|
||||
{
|
||||
return debugOn;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set deplyer in debug mode - more messages will be wriiten
|
||||
* @param debugOn
|
||||
*/
|
||||
public void setDebugOn(boolean debugOn)
|
||||
{
|
||||
this.debugOn = debugOn;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,10 +1,9 @@
|
||||
package org.apache.maven.deploy.deployers;
|
||||
|
||||
import org.apache.maven.deploy.RepositoryInfo;
|
||||
import org.apache.maven.deploy.DeployRequest;
|
||||
import org.apache.maven.deploy.exceptions.NotAuthorizedDeployException;
|
||||
import org.apache.maven.deploy.exceptions.ProxyNotAuthorizedDeployException;
|
||||
import org.apache.maven.deploy.exceptions.AuthenticationException;
|
||||
import org.apache.maven.deploy.exceptions.TransferFailedException;
|
||||
import org.apache.maven.deploy.exceptions.WrongParameterException;
|
||||
|
||||
/* ====================================================================
|
||||
* The Apache Software License, Version 1.1
|
||||
@@ -63,28 +62,43 @@ import org.apache.maven.deploy.exceptions.WrongParameterException;
|
||||
*/
|
||||
|
||||
/**
|
||||
* Interface for all Maven deployers.
|
||||
*
|
||||
* Deployer which uploads a file to remote host accordingly to paramters
|
||||
* recieved in <i>deploy request</i>
|
||||
* Common interface for classes capable of uploading a file to remote host
|
||||
|
||||
*
|
||||
* @author <a href="mailto:jason@zenplex.com">Jason van Zyl</a>
|
||||
* @version $Id: Deployer.java,v 1.2 2003/06/29 11:57:40 michal Exp $
|
||||
* @author <a href="mailto:michl.maczka@dimatics.com">Michal Maczka</a>
|
||||
* @version $Id: Deployer.java,v 1.3 2003/07/17 11:13:16 michal Exp $
|
||||
*/
|
||||
public interface Deployer
|
||||
{
|
||||
|
||||
/**
|
||||
* Perform an unppload of single file to remote host
|
||||
* Set the information about host to which we will deploy.
|
||||
* In this method deployer can allocate the resources which will
|
||||
* be needed to perform an upload. E.g. connection to remote host
|
||||
* can be opened,
|
||||
* Resources allocated in this metod should
|
||||
* be release when deloyer is not needed any more
|
||||
* @see #release()
|
||||
*
|
||||
* @param repoInfo
|
||||
* @throws AuthenticationException when connection to remote host cannot be established
|
||||
*/
|
||||
public void init(RepositoryInfo repoInfo)
|
||||
throws AuthenticationException;
|
||||
|
||||
/**
|
||||
* Release all resources which were allocated
|
||||
* by this deployer (e.g. a connection to remote host)
|
||||
*
|
||||
*/
|
||||
public void release();
|
||||
|
||||
/**
|
||||
* Perform an upload of single file to remote host
|
||||
* @param request <code>DeployRequest</code> which should contatin all parameters
|
||||
* which are necessery to upload a file
|
||||
* to remote host.
|
||||
*/
|
||||
public void deploy(DeployRequest request)
|
||||
throws
|
||||
TransferFailedException,
|
||||
NotAuthorizedDeployException,
|
||||
ProxyNotAuthorizedDeployException,
|
||||
TransferFailedException,
|
||||
WrongParameterException;
|
||||
public void deploy(DeployRequest request) throws TransferFailedException;
|
||||
}
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
package org.apache.maven.deploy.deployers;
|
||||
|
||||
import org.apache.maven.deploy.RepositoryInfo;
|
||||
import org.apache.maven.deploy.DeployRequest;
|
||||
import org.apache.maven.deploy.exceptions.NotAuthorizedDeployException;
|
||||
import org.apache.maven.deploy.exceptions.ProxyNotAuthorizedDeployException;
|
||||
import org.apache.maven.deploy.exceptions.AuthenticationException;
|
||||
import org.apache.maven.deploy.exceptions.TransferFailedException;
|
||||
import org.apache.maven.deploy.exceptions.WrongParameterException;
|
||||
|
||||
/* ====================================================================
|
||||
* The Apache Software License, Version 1.1
|
||||
@@ -63,9 +62,10 @@ import org.apache.maven.deploy.exceptions.WrongParameterException;
|
||||
*/
|
||||
|
||||
/**
|
||||
* Deployers which runs external script or program as new process.
|
||||
* Deployers which for every deployment request
|
||||
* starts a new external process (e.g batch file, shell script)
|
||||
*
|
||||
* @version $Id: ExternalDeployer.java,v 1.1 2003/07/02 12:42:19 michal Exp $
|
||||
* @version $Id: ExternalDeployer.java,v 1.2 2003/07/17 11:13:17 michal Exp $
|
||||
* @todo still have to account for differing setups for people deploying to
|
||||
* their own sites and to the central repository.
|
||||
* @todo finich
|
||||
@@ -75,42 +75,53 @@ public class ExternalDeployer extends AbstractDeployer
|
||||
|
||||
public final static String PROTOCOL = "external://";
|
||||
|
||||
|
||||
|
||||
private String cmd = null;
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.apache.maven.deploy.deployers.Deployer#init(org.apache.maven.deploy.HostInfo)
|
||||
*/
|
||||
public void init(RepositoryInfo repoInfo)
|
||||
throws AuthenticationException
|
||||
{
|
||||
|
||||
cmd = repoInfo.getHost();
|
||||
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.apache.maven.deploy.deployers.Deployer#release()
|
||||
*/
|
||||
public void release()
|
||||
{
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.apache.maven.deploy.deployers.Deployer#deploy(org.apache.maven.deploy.DeployRequest)
|
||||
*/
|
||||
public void deploy(DeployRequest request)
|
||||
throws
|
||||
TransferFailedException,
|
||||
NotAuthorizedDeployException,
|
||||
ProxyNotAuthorizedDeployException,
|
||||
TransferFailedException,
|
||||
WrongParameterException
|
||||
public void deploy(DeployRequest request) throws TransferFailedException
|
||||
{
|
||||
|
||||
String cmd = request.getHost();
|
||||
|
||||
|
||||
String[] params =
|
||||
{
|
||||
request.getSrcFile(),
|
||||
request.getDestDir(),
|
||||
request.getDestFile(),
|
||||
{
|
||||
request.getSrcFile(),
|
||||
request.getDestFile(),
|
||||
};
|
||||
|
||||
|
||||
try
|
||||
{
|
||||
System.out.println("Staring external process: '" + cmd + "'");
|
||||
Process process = Runtime.getRuntime().exec(cmd,params);
|
||||
Process process = Runtime.getRuntime().exec(cmd, params);
|
||||
process.waitFor();
|
||||
System.out.println("External process finished");
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw new TransferFailedException("Failed to deploy with extrnal program",e);
|
||||
throw new TransferFailedException(
|
||||
"Failed to deploy with extrnal program",
|
||||
e);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -60,6 +60,7 @@ import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.apache.maven.deploy.RepositoryInfo;
|
||||
import org.apache.maven.deploy.DeployRequest;
|
||||
import org.apache.maven.deploy.exceptions.TransferFailedException;
|
||||
|
||||
@@ -68,14 +69,31 @@ import org.apache.maven.deploy.exceptions.TransferFailedException;
|
||||
* file system.
|
||||
*
|
||||
* @author <a href="michal.maczka@dimatics.com">Michal Maczka</a>
|
||||
* @version $Id: FileDeployer.java,v 1.7 2003/07/02 12:42:21 michal Exp $
|
||||
* @version $Id: FileDeployer.java,v 1.8 2003/07/17 11:13:17 michal Exp $
|
||||
*/
|
||||
public class FileDeployer implements Deployer
|
||||
{
|
||||
|
||||
private RepositoryInfo repoInfo;
|
||||
|
||||
/** Protocol understandable by this deployer*/
|
||||
public final static String PROTOCOL = "file://";
|
||||
|
||||
/**
|
||||
* Do nothing
|
||||
*/
|
||||
public void init(RepositoryInfo repoInfo)
|
||||
{
|
||||
this.repoInfo = repoInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Do nothing
|
||||
*/
|
||||
public void release()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.maven.fetch.fetchers.Fetcher#fetchUrl(java.lang.String, java.io.OutputStream)
|
||||
*/
|
||||
@@ -86,18 +104,21 @@ public class FileDeployer implements Deployer
|
||||
File srcFile = new File(request.getSrcFile());
|
||||
|
||||
File destFile =
|
||||
new File(request.getHost(), request.getBaseDir());
|
||||
destFile = new File(destFile, request.getDestDir());
|
||||
if (! destFile.exists())
|
||||
new File(
|
||||
repoInfo.getHost(),
|
||||
repoInfo.getBasedir());
|
||||
destFile = new File(destFile, request.dirname());
|
||||
if (!destFile.exists())
|
||||
{
|
||||
destFile.mkdirs();
|
||||
}
|
||||
destFile = new File( destFile, request.getDestFile());
|
||||
destFile.mkdirs();
|
||||
}
|
||||
destFile = new File(destFile, request.getDestFile());
|
||||
FileUtils.copyFile(srcFile, destFile);
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
throw new TransferFailedException("Cannot copy file: " + e.getMessage());
|
||||
throw new TransferFailedException(
|
||||
"Cannot copy file: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,13 +59,15 @@ import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.apache.commons.net.ProtocolCommandEvent;
|
||||
import org.apache.commons.net.ProtocolCommandListener;
|
||||
import org.apache.commons.net.ftp.FTP;
|
||||
import org.apache.commons.net.ftp.FTPClient;
|
||||
import org.apache.commons.net.ftp.FTPConnectionClosedException;
|
||||
import org.apache.commons.net.ftp.FTPReply;
|
||||
import org.apache.maven.deploy.RepositoryInfo;
|
||||
import org.apache.maven.deploy.DeployRequest;
|
||||
import org.apache.maven.deploy.exceptions.AuthenticationException;
|
||||
import org.apache.maven.deploy.exceptions.TransferFailedException;
|
||||
|
||||
/**
|
||||
@@ -76,7 +78,9 @@ import org.apache.maven.deploy.exceptions.TransferFailedException;
|
||||
*
|
||||
* @author <a href="mailto:jason@zenplex.com">Jason van Zyl</a>
|
||||
* @author <a href="michal.maczka@dimatics.com">Michal Maczka</a>
|
||||
* @version $Id: FtpDeployer.java,v 1.6 2003/07/02 12:42:13 michal Exp $
|
||||
* @version $Id: FtpDeployer.java,v 1.7 2003/07/17 11:13:17 michal Exp $
|
||||
*
|
||||
* @todo review exception handling
|
||||
*
|
||||
*
|
||||
*/
|
||||
@@ -85,20 +89,21 @@ public class FtpDeployer extends AbstractDeployer
|
||||
/** Protocol understandable by this deployer*/
|
||||
public final static String PROTOCOL = "ftp://";
|
||||
|
||||
|
||||
private FTPClient ftp = null;
|
||||
|
||||
/**
|
||||
* @see Deployer#deploy(DeployRequest)
|
||||
/* (non-Javadoc)
|
||||
* @see org.apache.maven.deploy.deployers.Deployer#init(org.apache.maven.deploy.HostInfo)
|
||||
*/
|
||||
public void deploy(DeployRequest request) throws TransferFailedException
|
||||
public void init(RepositoryInfo repoInfo)
|
||||
throws AuthenticationException
|
||||
{
|
||||
String username = request.getUserName();
|
||||
String password = request.getPassword();
|
||||
String host = request.getHost();
|
||||
String username = repoInfo.getUserName();
|
||||
String password = repoInfo.getPassword();
|
||||
String host = repoInfo.getHost();
|
||||
|
||||
FTPClient ftp = new FTPClient();
|
||||
ftp = new FTPClient();
|
||||
|
||||
if (request.isDebugOn())
|
||||
if (repoInfo.isDebugOn())
|
||||
{
|
||||
ftp.addProtocolCommandListener(
|
||||
new PrintCommandListener(new PrintWriter(System.out)));
|
||||
@@ -106,9 +111,10 @@ public class FtpDeployer extends AbstractDeployer
|
||||
try
|
||||
{
|
||||
int reply;
|
||||
if (request.getPort() != DeployRequest.UNKNOWN_PORT)
|
||||
if (repoInfo.getPort()
|
||||
!= RepositoryInfo.UNKNOWN_PORT)
|
||||
{
|
||||
ftp.connect(host, request.getPort());
|
||||
ftp.connect(host, repoInfo.getPort());
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -124,7 +130,7 @@ public class FtpDeployer extends AbstractDeployer
|
||||
{
|
||||
ftp.disconnect();
|
||||
System.err.println();
|
||||
throw new TransferFailedException("FTP server refused connection.");
|
||||
throw new AuthenticationException("FTP server refused connection.");
|
||||
}
|
||||
}
|
||||
catch (IOException e)
|
||||
@@ -140,15 +146,14 @@ public class FtpDeployer extends AbstractDeployer
|
||||
// do nothing
|
||||
}
|
||||
}
|
||||
throw new TransferFailedException("Could not connect to server.");
|
||||
throw new AuthenticationException("Could not connect to server.");
|
||||
}
|
||||
|
||||
__main : try
|
||||
try
|
||||
{
|
||||
if (ftp.login(username.trim(), password.trim()) == false)
|
||||
{
|
||||
ftp.logout();
|
||||
break __main;
|
||||
throw new AuthenticationException("Cannot login to remote system");
|
||||
}
|
||||
|
||||
System.out.println("Remote system is " + ftp.getSystemName());
|
||||
@@ -158,36 +163,64 @@ public class FtpDeployer extends AbstractDeployer
|
||||
// Use passive mode as default because most of us are
|
||||
// behind firewalls these days.
|
||||
ftp.enterLocalPassiveMode();
|
||||
ftp.changeWorkingDirectory(request.getBaseDir());
|
||||
String destDir = request.getDestDir();
|
||||
String filename = request.getDestFile();
|
||||
ftp.makeDirectory(destDir);
|
||||
ftp.changeWorkingDirectory(destDir);
|
||||
ftp.storeFile(filename, new FileInputStream(request.getSrcFile()));
|
||||
ftp.logout();
|
||||
}
|
||||
catch (FTPConnectionClosedException e)
|
||||
{
|
||||
throw new TransferFailedException("Server closed connection.");
|
||||
ftp.changeWorkingDirectory(repoInfo.getBasedir());
|
||||
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
throw new AuthenticationException("Cannot login to remote system");
|
||||
}
|
||||
finally
|
||||
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.apache.maven.deploy.deployers.Deployer#release()
|
||||
*/
|
||||
public void release()
|
||||
{
|
||||
if (ftp.isConnected())
|
||||
{
|
||||
if (ftp.isConnected())
|
||||
try
|
||||
{
|
||||
try
|
||||
{
|
||||
ftp.disconnect();
|
||||
}
|
||||
catch (IOException f)
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
ftp.disconnect();
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @see Deployer#deploy(DeployRequest)
|
||||
*/
|
||||
public void deploy(DeployRequest request) throws TransferFailedException
|
||||
{
|
||||
|
||||
try
|
||||
{
|
||||
String[] dirs = StringUtils.split(request.dirname(), "/");
|
||||
for (int i = 0; i < dirs.length; i++)
|
||||
{
|
||||
ftp.makeDirectory(dirs[i]);
|
||||
ftp.changeWorkingDirectory(dirs[i]);
|
||||
}
|
||||
ftp.storeFile(
|
||||
request.filename(),
|
||||
new FileInputStream(request.getSrcFile()));
|
||||
for (int i = 0; i < dirs.length; i++)
|
||||
{
|
||||
ftp.changeWorkingDirectory("..");
|
||||
}
|
||||
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
throw new TransferFailedException(e.getMessage());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -58,9 +58,8 @@ package org.apache.maven.deploy.deployers;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import org.apache.maven.deploy.DeployRequest;
|
||||
import org.apache.maven.deploy.exceptions.TransferFailedException;
|
||||
import org.apache.maven.deploy.exceptions.WrongParameterException;
|
||||
import org.apache.maven.deploy.RepositoryInfo;
|
||||
import org.apache.maven.deploy.exceptions.AuthenticationException;
|
||||
|
||||
import com.jcraft.jsch.JSch;
|
||||
import com.jcraft.jsch.Proxy;
|
||||
@@ -73,13 +72,14 @@ import com.jcraft.jsch.UserInfo;
|
||||
* A base class for deployers using protocols from SSH2 family
|
||||
* and JSch library for underlining implmenetation
|
||||
*
|
||||
* This class deals with authentification stage of the process.
|
||||
* This is responsible for authentification stage of the process.
|
||||
*
|
||||
* We will first try to
|
||||
* use public keys for authentication and if that doesn't work then we fall back
|
||||
* use public keys for authentication
|
||||
* and if that doesn't work then we fall back
|
||||
* to using the login and password
|
||||
*
|
||||
* @version $Id: GenericSshDeployer.java,v 1.3 2003/06/29 11:57:40 michal Exp $
|
||||
* @version $Id: GenericSshDeployer.java,v 1.4 2003/07/17 11:13:17 michal Exp $
|
||||
* @todo still have to account for differing setups for people deploying to
|
||||
* their own sites and to the central repository.
|
||||
* @todo improve exception handling
|
||||
@@ -87,70 +87,96 @@ import com.jcraft.jsch.UserInfo;
|
||||
public abstract class GenericSshDeployer extends AbstractDeployer
|
||||
{
|
||||
|
||||
private RepositoryInfo repoInfo;
|
||||
|
||||
/** Default port used for SSH protocol */
|
||||
public final static int DEFAULT_SSH_PORT = 22;
|
||||
|
||||
/** Default port used by SOCKS5 proxy server */
|
||||
public final static int SOCKS5_PROXY_PORT = 1080;
|
||||
|
||||
private Session session = null;
|
||||
|
||||
/**
|
||||
* @see Deployer#project
|
||||
*
|
||||
* @todo better way of guessing what kind of proxy server is used
|
||||
* by user. Jsch Supports among others SOCKS and HTTP proxies
|
||||
* @return
|
||||
*/
|
||||
public Session getSession(final DeployRequest request)
|
||||
throws TransferFailedException
|
||||
public Session getSession()
|
||||
{
|
||||
return session;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.apache.maven.deploy.deployers.Deployer#getAuthenticationInfo()
|
||||
*/
|
||||
public RepositoryInfo getAuthenticationInfo()
|
||||
{
|
||||
return repoInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.maven.deploy.deployers.Deployer#release()
|
||||
*/
|
||||
public void release()
|
||||
{
|
||||
session.disconnect();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.apache.maven.deploy.deployers.Deployer#init(org.apache.maven.deploy.HostInfo)
|
||||
*/
|
||||
public void init(RepositoryInfo repoInfo)
|
||||
throws AuthenticationException
|
||||
{
|
||||
|
||||
try
|
||||
{
|
||||
this.repoInfo = repoInfo;
|
||||
JSch jsch = new JSch();
|
||||
|
||||
int port = request.getPort();
|
||||
if (port == DeployRequest.UNKNOWN_PORT)
|
||||
int port = repoInfo.getPort();
|
||||
if (port == RepositoryInfo.UNKNOWN_PORT)
|
||||
{
|
||||
port = DEFAULT_SSH_PORT;
|
||||
}
|
||||
System.out.println("host: '"+ request.getHost() + "'");
|
||||
String host = request.getHost();
|
||||
Session session =
|
||||
jsch.getSession(request.getUserName(), host, port);
|
||||
|
||||
System.out.println("host: '" + repoInfo.getHost() + "'");
|
||||
String host = repoInfo.getHost();
|
||||
session =
|
||||
jsch.getSession(repoInfo.getUserName(), host, port);
|
||||
|
||||
// Look for the private key and use it if available.
|
||||
if (request.getPrivateKey() != null)
|
||||
if (repoInfo.getPrivateKey() != null)
|
||||
{
|
||||
File privateKey = new File(request.getPrivateKey());
|
||||
File privateKey = new File(repoInfo.getPrivateKey());
|
||||
|
||||
if (privateKey.exists())
|
||||
{
|
||||
if (request.getPassphrase() == null)
|
||||
if (repoInfo.getPassphrase() == null)
|
||||
{
|
||||
String msg =
|
||||
"Private key provided "
|
||||
+ "without passpharse for repo: "
|
||||
+ request.getRepositoryAlias();
|
||||
throw new WrongParameterException(msg);
|
||||
+ repoInfo.getRepositoryAlias();
|
||||
throw new AuthenticationException(msg);
|
||||
}
|
||||
|
||||
System.out.println("Using private key: " + privateKey);
|
||||
jsch.addIdentity(
|
||||
privateKey.getAbsolutePath(),
|
||||
request.getPassphrase());
|
||||
repoInfo.getPassphrase());
|
||||
}
|
||||
else
|
||||
{
|
||||
String msg = "Private key: " + privateKey + " not found ";
|
||||
throw new WrongParameterException(msg);
|
||||
throw new AuthenticationException(msg);
|
||||
}
|
||||
}
|
||||
|
||||
String proxyHost = request.getProxyHost();
|
||||
String proxyHost = repoInfo.getProxyHost();
|
||||
|
||||
if (proxyHost != null)
|
||||
{
|
||||
Proxy proxy = null;
|
||||
int proxyPort = request.getProxyPort();
|
||||
int proxyPort = repoInfo.getProxyPort();
|
||||
// HACK:
|
||||
//if port == 1080 we will use SOCKS5 Proxy
|
||||
// otherwise will use HTTP Proxy
|
||||
@@ -159,30 +185,29 @@ public abstract class GenericSshDeployer extends AbstractDeployer
|
||||
{
|
||||
proxy = new ProxySOCKS5(proxyHost);
|
||||
((ProxySOCKS5) proxy).setUserPasswd(
|
||||
request.getProxyUserName(),
|
||||
request.getProxyPassword());
|
||||
repoInfo.getProxyUserName(),
|
||||
repoInfo.getProxyPassword());
|
||||
}
|
||||
else
|
||||
{
|
||||
proxy = new ProxyHTTP(proxyHost, proxyPort);
|
||||
((ProxyHTTP) proxy).setUserPasswd(
|
||||
request.getProxyUserName(),
|
||||
request.getProxyPassword());
|
||||
repoInfo.getProxyUserName(),
|
||||
repoInfo.getProxyPassword());
|
||||
}
|
||||
proxy.connect(session, host, port);
|
||||
|
||||
}
|
||||
}
|
||||
// username and password will be given via UserInfo interface.
|
||||
UserInfo ui = new MavenUserInfo(request);
|
||||
UserInfo ui = new MavenUserInfo(repoInfo);
|
||||
session.setUserInfo(ui);
|
||||
session.connect();
|
||||
return session;
|
||||
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
throw new TransferFailedException(
|
||||
throw new AuthenticationException(
|
||||
"Cannot connect. Reason: " + e.getMessage(),
|
||||
e);
|
||||
}
|
||||
@@ -195,16 +220,16 @@ public abstract class GenericSshDeployer extends AbstractDeployer
|
||||
public class MavenUserInfo implements UserInfo
|
||||
{
|
||||
|
||||
DeployRequest request;
|
||||
RepositoryInfo repoInfo;
|
||||
|
||||
MavenUserInfo(DeployRequest request)
|
||||
MavenUserInfo(RepositoryInfo repoInfo)
|
||||
{
|
||||
this.request = request;
|
||||
this.repoInfo = repoInfo;
|
||||
}
|
||||
|
||||
public String getPassphrase()
|
||||
{
|
||||
return request.getPassphrase();
|
||||
return repoInfo.getPassphrase();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
@@ -212,7 +237,7 @@ public abstract class GenericSshDeployer extends AbstractDeployer
|
||||
*/
|
||||
public String getPassword()
|
||||
{
|
||||
return request.getPassword();
|
||||
return repoInfo.getPassword();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
|
||||
@@ -69,6 +69,7 @@ import org.apache.commons.httpclient.HttpClient;
|
||||
import org.apache.commons.httpclient.HttpException;
|
||||
import org.apache.commons.httpclient.UsernamePasswordCredentials;
|
||||
import org.apache.commons.httpclient.methods.PutMethod;
|
||||
import org.apache.maven.deploy.RepositoryInfo;
|
||||
import org.apache.maven.deploy.DeployRequest;
|
||||
import org.apache.maven.deploy.exceptions.TransferFailedException;
|
||||
|
||||
@@ -76,20 +77,44 @@ import org.apache.maven.deploy.exceptions.TransferFailedException;
|
||||
* An HTTP deployer based the Commons HttpClient library.
|
||||
*
|
||||
* @author <a href="mailto:jason@zenplex.com">Jason van Zyl</a>
|
||||
* @version $Id: HttpDeployer.java,v 1.4 2003/06/29 11:57:39 michal Exp $
|
||||
* @version $Id: HttpDeployer.java,v 1.5 2003/07/17 11:13:16 michal Exp $
|
||||
*
|
||||
* @todo still have to account for differing setups for people deploying to
|
||||
* their own sites and to the central repository.
|
||||
*
|
||||
* @todo deal with proxies
|
||||
* @todo deal with authentication
|
||||
*
|
||||
* @todo this class in not really functional. It should be completly refactored.
|
||||
*/
|
||||
public class HttpDeployer extends AbstractDeployer
|
||||
{
|
||||
private RepositoryInfo repoInfo;
|
||||
|
||||
|
||||
/**Protocol understood by by this deployer*/
|
||||
public final static String PROTOCOL = "http://";
|
||||
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.apache.maven.deploy.deployers.Deployer#init(org.apache.maven.deploy.HostInfo)
|
||||
*/
|
||||
public void init(RepositoryInfo repoInfo)
|
||||
|
||||
{
|
||||
this.repoInfo = repoInfo;
|
||||
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.apache.maven.deploy.deployers.Deployer#release()
|
||||
*/
|
||||
public void release()
|
||||
{
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Description of the Method
|
||||
*/
|
||||
@@ -98,7 +123,7 @@ public class HttpDeployer extends AbstractDeployer
|
||||
URL url = null;
|
||||
try
|
||||
{
|
||||
url = new URL(request.getUrl());
|
||||
url = new URL(repoInfo.getUrl());
|
||||
}
|
||||
catch (MalformedURLException murle)
|
||||
{
|
||||
@@ -106,8 +131,8 @@ public class HttpDeployer extends AbstractDeployer
|
||||
|
||||
Credentials creds =
|
||||
new UsernamePasswordCredentials(
|
||||
request.getUserName(),
|
||||
request.getPassword());
|
||||
repoInfo.getUserName(),
|
||||
repoInfo.getPassword());
|
||||
|
||||
//create a singular HttpClient object
|
||||
HttpClient client = new HttpClient();
|
||||
@@ -124,7 +149,7 @@ public class HttpDeployer extends AbstractDeployer
|
||||
|
||||
//
|
||||
HostConfiguration hc = new HostConfiguration();
|
||||
hc.setHost(request.getHost());
|
||||
hc.setHost(repoInfo.getHost());
|
||||
//start a session with the webserver
|
||||
client.setHostConfiguration(hc);
|
||||
|
||||
|
||||
@@ -57,21 +57,21 @@ package org.apache.maven.deploy.deployers;
|
||||
*/
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.apache.maven.deploy.RepositoryInfo;
|
||||
import org.apache.maven.deploy.DeployRequest;
|
||||
import org.apache.maven.deploy.exceptions.AuthenticationException;
|
||||
import org.apache.maven.deploy.exceptions.TransferFailedException;
|
||||
import org.apache.maven.deploy.exceptions.WrongParameterException;
|
||||
|
||||
import com.jcraft.jsch.ChannelSftp;
|
||||
import com.jcraft.jsch.JSchException;
|
||||
import com.jcraft.jsch.Session;
|
||||
import com.jcraft.jsch.SftpATTRS;
|
||||
import com.jcraft.jsch.SftpException;
|
||||
import com.jcraft.jsch.SftpProgressMonitor;
|
||||
|
||||
/**
|
||||
* An SSH2/SFTP deployer
|
||||
*
|
||||
* @author Michal Maczka
|
||||
* @version $Revision: 1.5 $ $Date: 2003/07/02 12:42:13 $
|
||||
* @version $Revision: 1.6 $ $Date: 2003/07/17 11:13:17 $
|
||||
*/
|
||||
public class SFtpDeployer extends GenericSshDeployer
|
||||
{
|
||||
@@ -80,39 +80,68 @@ public class SFtpDeployer extends GenericSshDeployer
|
||||
|
||||
/** SSH2 Chanel names used to communicate with the server*/
|
||||
private final static String SFTP_CHANNEL = "sftp";
|
||||
|
||||
|
||||
/** artibute of file used in SSH which denotes is given file is a directory*/
|
||||
private static final int S_IFDIR = 0x4000;
|
||||
|
||||
/**
|
||||
* @see Deployer#deploy(DeployRequest)
|
||||
private ChannelSftp channel = null;
|
||||
|
||||
private Integer groupId = null;
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.apache.maven.deploy.deployers.Deployer#init(org.apache.maven.deploy.HostInfo)
|
||||
*/
|
||||
public void deploy(DeployRequest request)
|
||||
throws TransferFailedException, WrongParameterException
|
||||
public void init(RepositoryInfo repoInfo)
|
||||
throws AuthenticationException
|
||||
{
|
||||
Integer groupId = null;
|
||||
|
||||
try
|
||||
{
|
||||
if (request.getGroup() != null)
|
||||
if (repoInfo.getGroup() != null)
|
||||
{
|
||||
groupId = Integer.getInteger(request.getGroup());
|
||||
groupId = Integer.getInteger(repoInfo.getGroup());
|
||||
}
|
||||
}
|
||||
catch (NumberFormatException e)
|
||||
{
|
||||
throw new WrongParameterException("SFTP deployer: remote group should be an integer");
|
||||
throw new AuthenticationException("SFTP deployer: remote group should be an integer");
|
||||
}
|
||||
super.init(repoInfo);
|
||||
|
||||
Session session = getSession(request);
|
||||
ChannelSftp channel = null;
|
||||
channel = null;
|
||||
try
|
||||
{
|
||||
channel = (ChannelSftp) session.openChannel(SFTP_CHANNEL);
|
||||
channel = (ChannelSftp) getSession().openChannel(SFTP_CHANNEL);
|
||||
channel.connect();
|
||||
channel.cd(repoInfo.getBasedir());
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw new AuthenticationException(e.getMessage());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.maven.deploy.deployers.Deployer#release()
|
||||
*/
|
||||
public void release()
|
||||
{
|
||||
channel.disconnect();
|
||||
super.release();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see Deployer#deploy(DeployRequest)
|
||||
*/
|
||||
public void deploy(DeployRequest request) throws TransferFailedException
|
||||
{
|
||||
try
|
||||
{
|
||||
|
||||
// iterate over all directories in the path. try to create
|
||||
// directory
|
||||
String destPath = request.getBaseDir() + "/" + request.getDestDir();
|
||||
String[] dirs = StringUtils.split(destPath, "/");
|
||||
String[] dirs = StringUtils.split(request.dirname(), "/");
|
||||
for (int i = 0; i < dirs.length; i++)
|
||||
{
|
||||
try
|
||||
@@ -120,13 +149,13 @@ public class SFtpDeployer extends GenericSshDeployer
|
||||
SftpATTRS attrs = channel.stat(dirs[i]);
|
||||
if ((attrs.getPermissions() & S_IFDIR) != 0)
|
||||
{
|
||||
// file exists and is dierctory
|
||||
// file exists and is dierctory
|
||||
channel.cd(dirs[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new WrongParameterException(
|
||||
"Incorrect remote path:" + request.getDestDir());
|
||||
throw new TransferFailedException(
|
||||
"Incorrect remote path:" + request.getDestFile());
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
@@ -137,36 +166,72 @@ public class SFtpDeployer extends GenericSshDeployer
|
||||
}
|
||||
|
||||
}
|
||||
if (getAuthenticationInfo().isDebugOn())
|
||||
{
|
||||
channel.put(
|
||||
request.getSrcFile(),
|
||||
request.filename(),
|
||||
new ProgressMonitor());
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
channel.put(request.getSrcFile(), request.getDestFile());
|
||||
channel.put(request.getSrcFile(), request.filename());
|
||||
|
||||
}
|
||||
|
||||
if (groupId != null)
|
||||
{
|
||||
if (getAuthenticationInfo().isDebugOn())
|
||||
{
|
||||
System.out.println("Changing group to: " + groupId);
|
||||
}
|
||||
channel.chgrp(groupId.intValue(), request.getDestFile());
|
||||
}
|
||||
if (getAuthenticationInfo().isDebugOn())
|
||||
{
|
||||
System.out.println("Group successfully changed");
|
||||
}
|
||||
|
||||
}
|
||||
// change back the working directory to repository root
|
||||
for (int i = 0; i < dirs.length; i++)
|
||||
{
|
||||
channel.cd("..");
|
||||
}
|
||||
}
|
||||
catch (SftpException e)
|
||||
{
|
||||
|
||||
String msg =
|
||||
"Error occured while deploying to remote host:"
|
||||
+ request.getHost();
|
||||
+ getAuthenticationInfo().getHost()
|
||||
+ ":"
|
||||
+ e.getMessage();
|
||||
throw new TransferFailedException(msg, e);
|
||||
}
|
||||
|
||||
catch (JSchException e)
|
||||
}
|
||||
|
||||
class ProgressMonitor implements SftpProgressMonitor
|
||||
{
|
||||
|
||||
public boolean count(long count)
|
||||
{
|
||||
String msg =
|
||||
"Error occured while deploying to remote host:"
|
||||
+ request.getHost();
|
||||
throw new TransferFailedException(msg, e);
|
||||
System.out.print("#");
|
||||
return true;
|
||||
}
|
||||
finally
|
||||
|
||||
public void end()
|
||||
{
|
||||
channel.disconnect();
|
||||
session.disconnect();
|
||||
System.out.println();
|
||||
|
||||
}
|
||||
|
||||
public void init(int op, String src, String dest, long max)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -71,14 +71,14 @@ import com.jcraft.jsch.Session;
|
||||
* An SSH2/SCP deployer
|
||||
*
|
||||
* @author Michal Maczka
|
||||
* @version $Revision: 1.4 $ $Date: 2003/07/02 12:42:21 $
|
||||
* @version $Revision: 1.5 $ $Date: 2003/07/17 11:13:17 $
|
||||
*/
|
||||
public class ScpDeployer extends GenericSshDeployer
|
||||
{
|
||||
/**Protocol understood by by this deployer*/
|
||||
/**Protocol understood by this deployer*/
|
||||
public final static String PROTOCOL = "scp://";
|
||||
|
||||
/** SSH2 Chanel names used to communicate with the server*/
|
||||
/** SSH2 Channel name used to communicate with the server*/
|
||||
public final static String EXEC_CHANNEL = "exec";
|
||||
|
||||
/**
|
||||
@@ -86,42 +86,31 @@ public class ScpDeployer extends GenericSshDeployer
|
||||
*
|
||||
*/
|
||||
public void deploy(DeployRequest request) throws TransferFailedException
|
||||
{
|
||||
{
|
||||
Session session = getSession();
|
||||
String mkdirCmd =
|
||||
"mkdir -p "
|
||||
+ getAuthenticationInfo().getBasedir()
|
||||
+ "/"
|
||||
+ request.dirname()
|
||||
+ "\n";
|
||||
executeSimpleCommand(session, mkdirCmd);
|
||||
|
||||
Session session = getSession(request);
|
||||
try
|
||||
doCopy(session, request);
|
||||
if (getAuthenticationInfo().getGroup() != null)
|
||||
{
|
||||
|
||||
String mkdirCmd =
|
||||
"mkdir -p "
|
||||
+ request.getBaseDir()
|
||||
String chgrpCmd =
|
||||
"chgrp "
|
||||
+ getAuthenticationInfo().getGroup()
|
||||
+ " "
|
||||
+ getAuthenticationInfo().getBasedir()
|
||||
+ "/"
|
||||
+ request.getDestDir()
|
||||
+ request.getDestFile()
|
||||
+ "\n";
|
||||
executeSimpleCommand(session, mkdirCmd);
|
||||
|
||||
doCopy(session, request);
|
||||
if (request.getGroup() != null)
|
||||
{
|
||||
|
||||
String chgrpCmd =
|
||||
"chgrp "
|
||||
+ request.getGroup()
|
||||
+ " "
|
||||
+ request.getBaseDir()
|
||||
+ "/"
|
||||
+ request.getDestDir()
|
||||
+ "/"
|
||||
+ request.getDestFile()
|
||||
+ "\n";
|
||||
executeSimpleCommand(session, chgrpCmd);
|
||||
}
|
||||
|
||||
}
|
||||
finally
|
||||
{
|
||||
session.disconnect();
|
||||
executeSimpleCommand(session, chgrpCmd);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -163,17 +152,18 @@ public class ScpDeployer extends GenericSshDeployer
|
||||
throws TransferFailedException
|
||||
{
|
||||
|
||||
ChannelExec channel = null;
|
||||
try
|
||||
{
|
||||
String srcFile = request.getSrcFile();
|
||||
String destFile = request.getDestFile();
|
||||
String destDir =
|
||||
request.getBaseDir() + "/" + request.getDestDir();
|
||||
String destFile =
|
||||
getAuthenticationInfo().getBasedir()
|
||||
+ "/"
|
||||
+ request.getDestFile();
|
||||
// exec 'scp -t rfile' remotely
|
||||
String command = "scp -t " + destDir + "/" + destFile;
|
||||
String command = "scp -t " + destFile;
|
||||
System.out.println("Executing command: " + command);
|
||||
ChannelExec channel =
|
||||
(ChannelExec) session.openChannel(EXEC_CHANNEL);
|
||||
channel = (ChannelExec) session.openChannel(EXEC_CHANNEL);
|
||||
channel.setCommand(command);
|
||||
// get I/O streams for remote scp
|
||||
OutputStream out = channel.getOutputStream();
|
||||
@@ -240,9 +230,16 @@ public class ScpDeployer extends GenericSshDeployer
|
||||
{
|
||||
String msg =
|
||||
"Error occured while deploying to remote host:"
|
||||
+ request.getHost();
|
||||
+ getAuthenticationInfo().getHost();
|
||||
throw new TransferFailedException(msg, e);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (channel != null)
|
||||
{
|
||||
channel.disconnect();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -59,15 +59,15 @@ package org.apache.maven.deploy.exceptions;
|
||||
/**
|
||||
*
|
||||
* @author <a href="michal.maczka@dimatics.com">Michal Maczka</a>
|
||||
* @version $Id: WrongParameterException.java,v 1.1 2003/06/29 11:57:39 michal Exp $
|
||||
* @version $Id: AuthenticationException.java,v 1.1 2003/07/17 11:13:17 michal Exp $
|
||||
*/
|
||||
public class WrongParameterException extends DeployException
|
||||
public class AuthenticationException extends DeployException
|
||||
{
|
||||
|
||||
/**
|
||||
* @param message
|
||||
*/
|
||||
public WrongParameterException(String message)
|
||||
public AuthenticationException(String message)
|
||||
{
|
||||
super(message);
|
||||
}
|
||||
@@ -76,7 +76,7 @@ public class WrongParameterException extends DeployException
|
||||
* @param message
|
||||
* @param cause
|
||||
*/
|
||||
public WrongParameterException(String message, Throwable cause)
|
||||
public AuthenticationException(String message, Throwable cause)
|
||||
{
|
||||
super(message, cause);
|
||||
}
|
||||
@@ -1,84 +0,0 @@
|
||||
package org.apache.maven.deploy.exceptions;
|
||||
|
||||
/* ====================================================================
|
||||
* The Apache Software License, Version 1.1
|
||||
*
|
||||
* Copyright (c) 2003 The Apache Software Foundation. All rights
|
||||
* reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. The end-user documentation included with the redistribution,
|
||||
* if any, must include the following acknowledgment:
|
||||
* "This product includes software developed by the
|
||||
* Apache Software Foundation (http://www.apache.org/)."
|
||||
* Alternately, this acknowledgment may appear in the software itself,
|
||||
* if and wherever such third-party acknowledgments normally appear.
|
||||
*
|
||||
* 4. The names "Apache" and "Apache Software Foundation" and
|
||||
* "Apache Maven" must not be used to endorse or promote products
|
||||
* derived from this software without prior written permission. For
|
||||
* written permission, please contact apache@apache.org.
|
||||
*
|
||||
* 5. Products derived from this software may not be called "Apache",
|
||||
* "Apache Maven", nor may "Apache" appear in their name, without
|
||||
* prior written permission of the Apache Software Foundation.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
|
||||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
||||
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
* ====================================================================
|
||||
*
|
||||
* This software consists of voluntary contributions made by many
|
||||
* individuals on behalf of the Apache Software Foundation. For more
|
||||
* information on the Apache Software Foundation, please see
|
||||
* <http://www.apache.org/>.
|
||||
*
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
/**
|
||||
*
|
||||
* @author <a href="michal.maczka@dimatics.com">Michal Maczka</a>
|
||||
* @version $Id: NotAuthorizedDeployException.java,v 1.1 2003/06/17 22:06:00 michal Exp $
|
||||
*/
|
||||
public class NotAuthorizedDeployException extends DeployException
|
||||
{
|
||||
|
||||
/**
|
||||
* @param message
|
||||
*/
|
||||
public NotAuthorizedDeployException(String message)
|
||||
{
|
||||
super(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param message
|
||||
* @param cause
|
||||
*/
|
||||
public NotAuthorizedDeployException(String message, Throwable cause)
|
||||
{
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,86 +0,0 @@
|
||||
package org.apache.maven.deploy.exceptions;
|
||||
|
||||
/* ====================================================================
|
||||
* The Apache Software License, Version 1.1
|
||||
*
|
||||
* Copyright (c) 2003 The Apache Software Foundation. All rights
|
||||
* reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. The end-user documentation included with the redistribution,
|
||||
* if any, must include the following acknowledgment:
|
||||
* "This product includes software developed by the
|
||||
* Apache Software Foundation (http://www.apache.org/)."
|
||||
* Alternately, this acknowledgment may appear in the software itself,
|
||||
* if and wherever such third-party acknowledgments normally appear.
|
||||
*
|
||||
* 4. The names "Apache" and "Apache Software Foundation" and
|
||||
* "Apache Maven" must not be used to endorse or promote products
|
||||
* derived from this software without prior written permission. For
|
||||
* written permission, please contact apache@apache.org.
|
||||
*
|
||||
* 5. Products derived from this software may not be called "Apache",
|
||||
* "Apache Maven", nor may "Apache" appear in their name, without
|
||||
* prior written permission of the Apache Software Foundation.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
|
||||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
||||
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
* ====================================================================
|
||||
*
|
||||
* This software consists of voluntary contributions made by many
|
||||
* individuals on behalf of the Apache Software Foundation. For more
|
||||
* information on the Apache Software Foundation, please see
|
||||
* <http://www.apache.org/>.
|
||||
*
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @author <a href="michal.maczka@dimatics.com">Michal Maczka</a>
|
||||
* @version $Id: ProxyNotAuthorizedDeployException.java,v 1.1 2003/06/17 22:06:00 michal Exp $
|
||||
*/
|
||||
public class ProxyNotAuthorizedDeployException extends DeployException
|
||||
{
|
||||
|
||||
/**
|
||||
* @param message
|
||||
*/
|
||||
public ProxyNotAuthorizedDeployException(String message)
|
||||
{
|
||||
super(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param message
|
||||
* @param cause
|
||||
*/
|
||||
public ProxyNotAuthorizedDeployException(String message, Throwable cause)
|
||||
{
|
||||
super(message, cause);
|
||||
// TODO Auto-generated constructor stub
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user