/src/main/java/com/atlassian/bamboo/plugins/tomcat/manager/TomcatApplicationManagerImpl.java
Java | 342 lines | 288 code | 32 blank | 22 comment | 22 complexity | d55f197a4090c509a8fac952af06f91b MD5 | raw file
Possible License(s): Apache-2.0
- package com.atlassian.bamboo.plugins.tomcat.manager;
- import com.atlassian.bamboo.build.logger.BuildLogger;
- import com.atlassian.bamboo.plugins.tomcat.configuration.AbstractTomcatConfigurator;
- import com.atlassian.bamboo.task.CommonTaskContext;
- import com.atlassian.bamboo.task.TaskException;
- import com.atlassian.bamboo.variable.CustomVariableContext;
- import com.google.common.base.Predicate;
- import com.google.common.collect.Iterables;
- import com.google.common.collect.Lists;
- import org.apache.commons.httpclient.DefaultHttpMethodRetryHandler;
- import org.apache.commons.httpclient.HttpClient;
- import org.apache.commons.httpclient.HttpMethod;
- import org.apache.commons.httpclient.UsernamePasswordCredentials;
- import org.apache.commons.httpclient.auth.AuthScope;
- import org.apache.commons.httpclient.methods.GetMethod;
- import org.apache.commons.httpclient.methods.InputStreamRequestEntity;
- import org.apache.commons.httpclient.methods.PutMethod;
- import org.apache.commons.httpclient.params.HttpClientParams;
- import org.apache.commons.httpclient.params.HttpMethodParams;
- import org.apache.commons.io.IOUtils;
- import org.apache.commons.lang.StringUtils;
- import org.apache.log4j.Logger;
- import org.jetbrains.annotations.NotNull;
- import org.jetbrains.annotations.Nullable;
- import javax.servlet.http.HttpServletResponse;
- import java.io.File;
- import java.io.FileInputStream;
- import java.io.IOException;
- import java.io.UnsupportedEncodingException;
- import java.net.MalformedURLException;
- import java.net.URL;
- import java.net.URLEncoder;
- import java.util.List;
- public class TomcatApplicationManagerImpl implements TomcatApplicationManager
- {
- private static final Logger log = Logger.getLogger(TomcatApplicationManagerImpl.class);
- // ------------------------------------------------------------------------------------------------------- Constants
- // ------------------------------------------------------------------------------------------------- Type Properties
- private final String tomcatManagerUrl;
- private final HttpClient client;
- private boolean isTomcat6;
- private String confirmedTomcatVersion;
- @NotNull
- private final CustomVariableContext customVariableContext;
- @NotNull
- private final BuildLogger buildLogger;
- // ---------------------------------------------------------------------------------------------------- Dependencies
- // ---------------------------------------------------------------------------------------------------- Constructors
- public TomcatApplicationManagerImpl(@NotNull TomcatConnection tomcatCredentials, @NotNull CommonTaskContext taskContext, @NotNull final CustomVariableContext customVariableContext, @NotNull BuildLogger buildLogger) throws TaskException
- {
- this.customVariableContext = customVariableContext;
- this.buildLogger = buildLogger;
- try
- {
- this.tomcatManagerUrl = new URL(customVariableContext.substituteString(tomcatCredentials.getURL())).toString();
- }
- catch (MalformedURLException e)
- {
- throw new TaskException("Malformed Tomcat Manager URL, please fix your Tomcat Task configuration.", e);
- }
- HttpClientParams httpClientParams = new HttpClientParams();
- httpClientParams.setAuthenticationPreemptive(true);
- client = new HttpClient(httpClientParams);
- client.getState().setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(customVariableContext.substituteString(tomcatCredentials.getUsername()), customVariableContext.substituteString(tomcatCredentials.getPassword())));
- this.isTomcat6 = taskContext.getConfigurationMap().getAsBoolean(AbstractTomcatConfigurator.TOMCAT_6);
- }
- // ----------------------------------------------------------------------------------------------- Interface Methods
- @NotNull
- @Override
- public List<Application> listApplications() throws IOException
- {
- final List<Application> applications = Lists.newArrayList();
- final String url = new StringBuilder(tomcatManagerUrl).append(getURLPrefix()).append("/list").toString();
- final String result = execute(new GetMethod(url));
- final String[] lines = StringUtils.split(result, '\n');
- if (lines.length > 1)
- {
- for (int i = 1; i < lines.length; i++)
- {
- final String[] appParts = StringUtils.split(lines[i], ":");
- applications.add(new Application(appParts[0], appParts[1], appParts[2], appParts[3]));
- }
- }
- return applications;
- }
- @Override
- public Application getApplicationByContext(@NotNull final String contextPath) throws IOException
- {
- return Iterables.find(listApplications(), new Predicate<Application>()
- {
- @Override
- public boolean apply(final Application application)
- {
- return contextPath.equals(application.getContext());
- }
- }, null);
- }
- @NotNull
- @Override
- public TomcatResult startApplication(@NotNull final String contextPath) throws IOException
- {
- final String url = new StringBuilder(tomcatManagerUrl).append(getURLPrefix()).append("/start?path=").append(encode(customVariableContext.substituteString(contextPath))).toString();
- final String result = execute(new GetMethod(url));
- return TomcatResult.parse(result);
- }
- @NotNull
- @Override
- public TomcatResult reloadApplication(@NotNull final String contextPath) throws IOException
- {
- final String url = new StringBuilder(tomcatManagerUrl).append(getURLPrefix()).append("/reload?path=").append(encode(customVariableContext.substituteString(contextPath))).toString();
- final String result = execute(new GetMethod(url));
- return TomcatResult.parse(result);
- }
- @NotNull
- @Override
- public TomcatResult stopApplication(@NotNull final String contextPath) throws IOException
- {
- final String url = new StringBuilder(tomcatManagerUrl).append(getURLPrefix()).append("/stop?path=").append(encode(customVariableContext.substituteString(contextPath))).toString();
- final String result = execute(new GetMethod(url));
- return TomcatResult.parse(result);
- }
- @NotNull
- @Override
- public TomcatResult undeployApplication(@NotNull final String contextPath) throws IOException
- {
- final String url = new StringBuilder(tomcatManagerUrl).append(getURLPrefix()).append("/undeploy?path=").append(encode(customVariableContext.substituteString(contextPath))).toString();
- final String result = execute(new GetMethod(url));
- return TomcatResult.parse(result);
- }
- @NotNull
- @Override
- public TomcatResult deployApplication(@NotNull final String contextPath, @Nullable final String version, @NotNull final String deploymentTag, @NotNull final File file) throws IOException
- {
- final FileInputStream inputStream = new FileInputStream(file);
- try
- {
- final StringBuilder urlBuilder = new StringBuilder(tomcatManagerUrl)
- .append(getURLPrefix())
- .append("/deploy?path=")
- .append(encode(customVariableContext.substituteString(contextPath)));
- if (version != null)
- {
- urlBuilder.append("&version=")
- .append(encode(customVariableContext.substituteString(version)));
- }
- urlBuilder.append("&update=true&tag=")
- .append(encode(customVariableContext.substituteString(deploymentTag)));
- final PutMethod putMethod = new PutMethod(urlBuilder.toString());
- putMethod.setRequestEntity(new InputStreamRequestEntity(inputStream, file.length()));
- // BAM-14883 InputStreamRequestEntity with length specified cannot be retried.
- putMethod.getParams().setParameter(HttpMethodParams.RETRY_HANDLER, new DefaultHttpMethodRetryHandler(0, false));
- final String result = execute(putMethod);
- return TomcatResult.parse(result);
- }
- finally {
- IOUtils.closeQuietly(inputStream);
- }
- }
- // -------------------------------------------------------------------------------------------------- Action Methods
- // -------------------------------------------------------------------------------------------------- Public Methods
- // -------------------------------------------------------------------------------------- Basic Accessors / Mutators
- @NotNull
- private String execute(HttpMethod httpMethod) throws IOException
- {
- try
- {
- addHeaders(httpMethod);
- client.executeMethod(httpMethod);
- final int status = httpMethod.getStatusCode();
- if (isSuccessfulCode(status))
- {
- return httpMethod.getResponseBodyAsString();
- }
- else
- {
- if (status == HttpServletResponse.SC_FORBIDDEN || status == HttpServletResponse.SC_UNAUTHORIZED)
- {
- throw new IOException("Could not connect to Tomcat manager at '" + httpMethod.getURI() + "' because the username and password provided is not authorized. Status: " + status);
- }
- throw new IOException("Could not connect to Tomcat manager at '" + httpMethod.getURI() + "'. Response code: " + status);
- }
- }
- finally
- {
- httpMethod.releaseConnection();
- }
- }
- private static boolean isSuccessfulCode(int status)
- {
- return status >= HttpServletResponse.SC_OK && status < HttpServletResponse.SC_MULTIPLE_CHOICES;
- }
- private void addHeaders(HttpMethod httpMethod)
- {
- httpMethod.setDoAuthentication(true);
- httpMethod.addRequestHeader("User-Agent", "Atlassian Tomcat API");
- httpMethod.getHostAuthState().isPreemptive();
- }
- private static String encode(String value)
- {
- try
- {
- return URLEncoder.encode(value, "UTF-8");
- }
- catch (UnsupportedEncodingException e)
- {
- throw new IllegalStateException(e);
- }
- }
- private String getURLPrefix()
- {
- if (confirmedTomcatVersion == null)
- {
- confirmTomcatVersionThroughServerInfo();
- }
- return getURLPrefixByTomcatVersion(isTomcat6);
- }
- /**
- * Use server info to confirm that the tomcat version is as configured.
- * Note that if we're unable to detect the Tomcat version automatically, we log that,
- * and then continue, assuming the user's configuration was correct but serverinfo is
- * somehow not available.
- */
- private void confirmTomcatVersionThroughServerInfo()
- {
- buildLogger.addBuildLogEntry("Confirm expected Tomcat manager location.");
- confirmedTomcatVersion = getTomcatVersionFromServerInfo(isTomcat6);
- if (confirmedTomcatVersion != null)
- {
- buildLogger.addBuildLogEntry("Confirmed Tomcat version: " + confirmedTomcatVersion);
- }
- else
- {
- buildLogger.addErrorLogEntry("Try likely variations of Tomcat manager location.");
- confirmedTomcatVersion = getTomcatVersionFromServerInfo(!isTomcat6);
- if (confirmedTomcatVersion != null)
- {
- if (isTomcat6)
- {
- buildLogger.addErrorLogEntry("Detected that Tomcat version is wrongly specified as 6.x but is actually: " + confirmedTomcatVersion);
- }
- else
- {
- buildLogger.addErrorLogEntry("Detected that Tomcat version is wrongly specified as 7.x or greater but is actually " + confirmedTomcatVersion);
- }
- isTomcat6 = !isTomcat6;
- }
- else
- {
- buildLogger.addErrorLogEntry("Could not detect Tomcat version from server info, trusting configuration of " +
- (isTomcat6 ? "Tomcat 6.x" : "Tomcat 7 or greater"));
- }
- }
- }
- /**
- * Look up the serverinfo of the Tomcat server, either at "manager/text/serverinfo" or "manager/serverinfo". Note
- * that while we print out and return the version found, the main thing this method does is confirm that something
- * is returned from the expected path.
- *
- * @return null if a version could not be read from the expected serverinfo path.
- */
- private String getTomcatVersionFromServerInfo(boolean isExpectingTomcat6)
- {
- GetMethod getMethod = new GetMethod(tomcatManagerUrl + getURLPrefixByTomcatVersion(isExpectingTomcat6) + "/serverinfo");
- addHeaders(getMethod);
- try
- {
- buildLogger.addBuildLogEntry("Trying to retrieve Tomcat details from " + getMethod.getURI());
- client.executeMethod(getMethod);
- }
- catch (IOException e)
- {
- buildLogger.addErrorLogEntry("Could not list server info from " + getMethod.getPath(), e);
- return null;
- }
- if (!isSuccessfulCode(getMethod.getStatusCode()))
- {
- buildLogger.addErrorLogEntry("Server info returned status code: " + getMethod.getStatusCode());
- return null;
- }
- String body = null;
- try
- {
- body = getMethod.getResponseBodyAsString();
- }
- catch (IOException e)
- {
- buildLogger.addErrorLogEntry("Error occurred trying to establish Tomcat version", e);
- }
- if (body == null)
- {
- buildLogger.addErrorLogEntry("Empty body occurred trying to establish Tomcat version");
- return null;
- }
- for (String line : StringUtils.split(body, '\n'))
- {
- if (line.startsWith("Tomcat Version: "))
- {
- buildLogger.addBuildLogEntry("Found " + line);
- return line.substring("Tomcat Version: ".length());
- }
- }
- buildLogger.addErrorLogEntry("Unable to find Tomcat Version in server info response: " + body);
- return null;
- }
- @NotNull
- private String getURLPrefixByTomcatVersion(boolean isTomcat6)
- {
- return isTomcat6 ? "" : "/text";
- }
- }