/** * Copyright (c) 2010 Perforce Software. All rights reserved. */ package com.perforce.maven.scm.provider.p4.command; import java.io.File; import java.io.IOException; import java.net.InetAddress; import java.net.UnknownHostException; import java.util.List; import java.util.Properties; import org.apache.maven.scm.ScmException; import org.apache.maven.scm.ScmFileSet; import org.apache.maven.scm.log.ScmLogger; import com.perforce.maven.scm.provider.p4.repository.P4ScmProviderRepository; import com.perforce.p4java.client.IClient; import com.perforce.p4java.core.IChangelist; import com.perforce.p4java.core.file.FileSpecBuilder; import com.perforce.p4java.core.file.IFileSpec; import com.perforce.p4java.exception.P4JavaException; import com.perforce.p4java.impl.generic.client.ClientView.ClientViewMapping; import com.perforce.p4java.option.UsageOptions; import com.perforce.p4java.option.server.LoginOptions; import com.perforce.p4java.server.IOptionsServer; /** * Base class for Perforce server and client commands. It defines some common * properties and methods shared by most Perforce commands. This class is further * extended by a base server and a base client classes. </p> */ public abstract class P4Executor { /** The Constant P4_PORT_PROPERTY. */ public static final String P4_PORT_PROPERTY = "maven.scm.p4.port"; /** The Constant P4_USER_PROPERTY. */ public static final String P4_USER_PROPERTY = "maven.scm.p4.user"; /** The Constant P4_PASSWD_PROPERTY. */ public static final String P4_PASSWD_PROPERTY = "maven.scm.p4.password"; /** The Constant P4_CHARSET_PROPERTY. */ public static final String P4_CHARSET_PROPERTY = "maven.scm.p4.charset"; /** The Constant P4_CLIENT_PROPERTY. */ public static final String P4_CLIENT_PROPERTY = "maven.scm.perforce.clientspec.name"; /** The Constant P4_JOBS_PROPERTY. */ public static final String P4_JOBS_PROPERTY = "maven.scm.jobs"; /** The Constant P4_CHANGELIST_PROPERTY. */ public static final String P4_CHANGELIST_PROPERTY = "maven.scm.p4.changelist"; /** The Constant P4_CHANGELIST_PROPERTY. */ public static final String P4_CHANGELIST_DESCRIPTION_PROPERTY = "maven.scm.p4.changelist.description"; /** The Constant P4_FROM_CHANGELIST_PROPERTY. */ public static final String P4_FROM_CHANGELIST_PROPERTY = "maven.scm.p4.fromchangelist"; /** The Constant P4_TO_CHANGELIST_PROPERTY. */ public static final String P4_TO_CHANGELIST_PROPERTY = "maven.scm.p4.tochangelist"; /** The Constant P4_LOCK_TAG_PROPERTY. */ public static final String P4_LOCK_TAG_PROPERTY = "maven.scm.locktag"; /** Perforce server. */ protected IOptionsServer server; /** Perforce client. */ protected IClient client; /** Perforce server properties. */ protected Properties p4ServerProperties; /** Perforce server options. */ protected UsageOptions p4ServerOptions; /** The p4 login options. */ protected LoginOptions p4LoginOptions; /** SCM logger. */ protected ScmLogger logger; /** P4 SCM provider repository. */ protected P4ScmProviderRepository repository; /** SCM file set. */ protected ScmFileSet fileSet; /** Perforce client. */ protected String p4Client; /** * Character set used for translation of unicode files. P4CHARSET only * affects files of type unicode and utf16; non-unicode files are never * translated. For servers operating in the default (non-Unicode mode), * P4CHARSET must be left unset on client machines. If P4CHARSET is set, but * the server is not operating in internationalized mode, the server returns * the following error message: "Unicode clients require a unicode enabled * server". For servers operating in Unicode mode, P4CHARSET must be set on * client machines. If P4CHARSET is unset, but the server is operating in * Unicode mode, client programs return the following error message: * "Unicode server permits only unicode enabled clients". Note that the * names below are not actually the standard name for the charset in some * cases: e.g. UTF-8 should be "utf-8" not "utf8", but we follow the * Perforce server's rules here. </p> * * "none", "utf8", "iso8859-1", "shiftjis", "eucjp", "winansi", "cp949", * "macosroman", "iso8859-15", "iso8859-5", "koi8-r", "cp1251", "utf16le", * "utf16be", "utf16" */ protected String p4Charset; /** Perforce port. */ protected String p4Port; /** Perforce user. */ protected String p4User; /** Perforce password. */ protected String p4Passwd; /** Perforce client created. */ protected boolean p4ClientCreated; /** * Gets the server. * * @return the server */ public IOptionsServer getServer() { return server; } /** * Sets the server. * * @param server * the new server */ public void setServer(IOptionsServer server) { this.server = server; } /** * Gets the client. * * @return the client */ public IClient getClient() { return client; } /** * Sets the client. * * @param client * the new client */ public void setClient(IClient client) { this.client = client; } /** * Gets the p4 server properties. * * @return the p4 server properties */ public Properties getP4ServerProperties() { return p4ServerProperties; } /** * Sets the p4 server properties. * * @param p4ServerProperties * the new p4 server properties */ public void setP4ServerProperties(Properties p4ServerProperties) { this.p4ServerProperties = p4ServerProperties; } /** * Gets the p4 server options. * * @return the p4 server options */ public UsageOptions getP4ServerOptions() { return p4ServerOptions; } /** * Sets the p4 server options. * * @param p4ServerOptions * the new p4 server options */ public void setP4ServerOptions(UsageOptions p4ServerOptions) { this.p4ServerOptions = p4ServerOptions; } /** * Gets the p4 login options. * * @return the p4 login options */ public LoginOptions getP4LoginOptions() { return p4LoginOptions; } /** * Sets the p4 login options. * * @param p4LoginOptions * the new p4 login options */ public void setP4LoginOptions(LoginOptions p4LoginOptions) { this.p4LoginOptions = p4LoginOptions; } /** * Gets the logger. * * @return the logger */ public ScmLogger getLogger() { return logger; } /** * Sets the logger. * * @param logger * the new logger */ public void setLogger(ScmLogger logger) { this.logger = logger; } /** * Gets the repository. * * @return the repository */ public P4ScmProviderRepository getRepository() { return repository; } /** * Sets the repository. * * @param repository * the new repository */ public void setRepository(P4ScmProviderRepository repository) { this.repository = repository; } /** * Gets the file set. * * @return the file set */ public ScmFileSet getFileSet() { return fileSet; } /** * Sets the file set. * * @param fileSet * the new file set */ public void setFileSet(ScmFileSet fileSet) { this.fileSet = fileSet; } /** * Gets the p4 client. * * @return the p4 client */ public String getP4Client() { return p4Client; } /** * Sets the p4 client. * * @param p4Client * the new p4 client */ public void setP4Client(String p4Client) { this.p4Client = p4Client; } /** * Gets the p4 charset. * * @return the p4 charset */ public String getP4Charset() { return p4Charset; } /** * Sets the p4 charset. * * @param p4Charset * the new p4 charset */ public void setP4Charset(String p4Charset) { this.p4Charset = p4Charset; } /** * Gets the p4 port. * * @return the p4 port */ public String getP4Port() { return p4Port; } /** * Sets the p4 port. * * @param p4Port * the new p4 port */ public void setP4Port(String p4Port) { this.p4Port = p4Port; } /** * Gets the p4 user. * * @return the p4 user */ public String getP4User() { return p4User; } /** * Sets the p4 user. * * @param p4User * the new p4 user */ public void setP4User(String p4User) { this.p4User = p4User; } /** * Gets the p4 passwd. * * @return the p4 passwd */ public String getP4Passwd() { return p4Passwd; } /** * Sets the p4 passwd. * * @param p4Passwd * the new p4 passwd */ public void setP4Passwd(String p4Passwd) { this.p4Passwd = p4Passwd; } /** * Checks if is p4 client created. * * @return true, if is p4 client created */ public boolean isP4ClientCreated() { return p4ClientCreated; } /** * Sets the p4 client created. * * @param p4ClientCreated * the new p4 client created */ public void setP4ClientCreated(boolean p4ClientCreated) { this.p4ClientCreated = p4ClientCreated; } /* * Hide default constructor */ /** * Instantiates a new p4 executor. */ @SuppressWarnings("unused") private P4Executor() { } /** * Instantiates a new p4 command helper. * * @param repository * the repository * @param fileSet * the file set * @param logger * the logger * @throws ScmException * the scm exception */ public P4Executor(P4ScmProviderRepository repository, ScmFileSet fileSet, ScmLogger logger) throws ScmException { if (repository == null) { throw new ScmException("Scm provider repository cannot be null."); } if (fileSet == null) { throw new ScmException("Scm file set cannot be null."); } if (logger == null) { throw new ScmException("Scm logger cannot be null."); } this.repository = repository; this.fileSet = fileSet; this.logger = logger; initEnv(); initP4(); } /** * Initialize Perforce server and client instances. This should be * implemented in the Perforce server and client subclasses. * * @throws ScmException * the scm exception */ protected abstract void initP4() throws ScmException; /** * Cleanup Perforce server and client instances; logout, disconnect, etc. * This should be implemented by the Perforce server and client subclasses. * * @throws ScmException * the scm exception */ protected abstract void cleanP4() throws ScmException; /** * Initialize Perforce environment variables from system properties or * system environment, respectively. */ private void initEnv() { if (isEmpty(p4Port)) { p4Port = System.getProperty(P4_PORT_PROPERTY); if (isEmpty(p4Port)) { if (repository != null) { StringBuilder sb = new StringBuilder(); if (repository.getHost() != null) { sb.append(repository.getHost()); if (repository.getPort() != 0) { sb.append(":").append(repository.getPort()); } } p4Port = sb.toString(); } } if (isEmpty(p4Port)) { p4Port = System.getenv("P4PORT"); } } if (isEmpty(p4User)) { p4User = System.getProperty(P4_USER_PROPERTY); if (isEmpty(p4User)) { if (repository != null) { p4User = repository.getUser(); } } if (isEmpty(p4User)) { p4User = System.getenv("P4USER"); } if (isEmpty(p4User)) { // Get user name from OS p4User = System.getProperty("user.name"); } if (isEmpty(p4User)) { p4User = "nouser"; } } if (isEmpty(p4Passwd)) { p4Passwd = System.getProperty(P4_PASSWD_PROPERTY); if (isEmpty(p4Passwd)) { if (repository != null) { p4Passwd = repository.getPassword(); } } if (isEmpty(p4Passwd)) { p4Passwd = System.getenv("P4PASSWD"); } } if (isEmpty(p4Client)) { p4Client = System.getProperty(P4_CLIENT_PROPERTY); if (isEmpty(p4Client)) { p4Client = System.getenv("P4CLIENT"); } if (isEmpty(p4Client)) { p4Client = "noclient"; } } if (isEmpty(p4Charset)) { p4Charset = System.getProperty(P4_CHARSET_PROPERTY); if (isEmpty(p4Charset)) { p4Charset = System.getenv("P4CHARSET"); } } } /** * Generate a Perforce client workspace name. * * @return the string */ protected String generateClientName() { File workDir = fileSet != null ? new File(fileSet.getBasedir() .getAbsolutePath()) : null; String username = isEmpty(p4User) ? "nouser" : p4User; String hostname = "nohost"; String path = "nopath"; try { hostname = InetAddress.getLocalHost().getHostName(); if (workDir != null) { path = encodeWildcards(workDir.getCanonicalPath() .replaceAll("[/ ~]", "-").replaceAll(",", "")); } } catch (UnknownHostException e) { if (getLogger().isErrorEnabled()) { getLogger().error(e); } } catch (IOException e) { if (getLogger().isErrorEnabled()) { getLogger().error(e); } } return username + "-" + hostname + "-MavenSCM-" + path; } /** * Checks if is client name generated. * * @return true, if is client name generated */ public boolean isClientNameGenerated() { boolean generated = false; File workDir = fileSet != null ? new File(fileSet.getBasedir() .getAbsolutePath()) : null; if (!isEmpty(p4Client)) { if (workDir != null) { if (p4Client.contentEquals(generateClientName())) { generated = true; } } } return generated; } /** * Creates the client view mapping. * * @param repo * the repo * @param basedir * the basedir * @return the client view mapping */ protected ClientViewMapping createClientViewMapping( P4ScmProviderRepository repo, File basedir) { // Create a new client String repoPath = getRepoPath(repo, basedir); String viewPath = getCanonicalRepoPath(repoPath); ClientViewMapping clientViewMapping = new ClientViewMapping(0, viewPath, "//" + p4Client + "/..."); return clientViewMapping; } /** * Gets the repo location. * * @param path * the path * @return the repo location */ public String getRepoLocation(String path) { String location = null; if (!isEmpty(path)) { if (client != null) { try { List<IFileSpec> fileSpecs = client.where(FileSpecBuilder .makeFileSpecList(path)); if (fileSpecs != null) { for (IFileSpec fileSpec : fileSpecs) { if (fileSpec != null) { if (!isEmpty(fileSpec.getDepotPathString())) { location = fileSpec.getDepotPathString(); break; } } } } } catch (P4JavaException e) { if (getLogger().isErrorEnabled()) { getLogger().error(e); } } } } return location; } /** * Gets the repo path. Handles cases where repo.getPath() is not a valid * Perforce depot location. This might be an error due to branches and * directory naming where dir name != artifactId. * * @param repo * the repo * @param basedir * the basedir * @return the repo path */ public String getRepoPath(P4ScmProviderRepository repo, File basedir) { // Handles a case where executing release:prepare on a module with an // invalid SCM location. The release.properties contains the invalid URL // for checkout during release:perform and the basedir is not the module // root. So, the trailing target/checkout directory must be removed. if (basedir.toString().replace('\\', '/').endsWith("/target/checkout")) { String dir = basedir.toString(); basedir = new File(dir.substring(0, dir.length() - "/target/checkout".length())); if (getLogger().isDebugEnabled()) { logger.debug("Fixing checkout URL: " + basedir); } } File pom = new File(basedir, "pom.xml"); String location = repo.getPath(); if (getLogger().isDebugEnabled()) { logger.debug("SCM path in pom: " + location); } if (pom.exists()) { location = getRepoLocation(encodeWildcards(pom.getAbsolutePath())); if (location == null) { location = repo.getPath(); if (getLogger().isDebugEnabled()) { logger.debug("cannot find depot => using " + location); } } else if (location.endsWith("/pom.xml")) { location = location.substring(0, location.length() - "/pom.xml".length()); if (getLogger().isDebugEnabled()) { logger.debug("Actual POM location: " + location); } if (!repo.getPath().equals(location)) { if (getLogger().isInfoEnabled()) { logger.info("The SCM location in your pom.xml (" + repo.getPath() + ") is not equal to the depot location (" + location + "). This happens frequently with branches. " + "Ignoring the SCM location."); } } } } return location; } /** * Gets the canonical repo path. * * @param repoPath * the repo path * @return the canonical repo path */ public static String getCanonicalRepoPath(String repoPath) { if (repoPath == null) { return null; } if (repoPath.endsWith("/...")) { return repoPath; } else if (repoPath.endsWith("/")) { return repoPath + "..."; } else { return repoPath + "/..."; } } /** * Parse the changelist string to a changelist number. Convert the "default" * changelist string to the default changelist number. If it is negative * return unknown changelist. Otherwise, return the converted changelist * number. * * @param changelist * the changelist * @return the int */ public static int parseChangelist(String changelist) { if (!isEmpty(changelist)) { if (changelist.trim().equalsIgnoreCase("default")) { return IChangelist.DEFAULT; } try { int changelistId = Integer.parseInt(changelist); if (changelistId < 0) { return IChangelist.UNKNOWN; } return changelistId; } catch (NumberFormatException e) { // Suppress error } } return IChangelist.UNKNOWN; } /** * Perforce wildcards expansion. * * @param filePath the file path * @return the string */ public static String encodeWildcards(String filePath) { String path = new String(); if (filePath != null) { path = filePath.replaceAll("%", "%25").replaceAll("\\*", "%2A") .replaceAll("#", "%23").replaceAll("@", "%40"); } return path; } /** * Checks if is empty. * * @param value * the value * @return true, if is empty */ public static boolean isEmpty(String value) { if (value == null || value.trim().length() == 0) { return true; } return false; } }
# | Change | User | Description | Committed | |
---|---|---|---|---|---|
#3 | 10055 | Matt Attaway | Pull over numerous changes from @dantran's branch. | ||
#2 | 9014 | Matt Attaway |
Add SSL support to P4Maven (committed on behalf of Dan Tran) USer visible change |
||
#1 | 8496 | Matt Attaway | Move P4Ant and P4Maven into their proper homes | ||
//public/perforce/p4maven/main/com.perforce.maven/src/main/java/com/perforce/maven/scm/provider/p4/command/P4Executor.java | |||||
#1 | 8270 | Matt Attaway | Initial add of P4Maven source code |