org.jboss.arquillian.container.tomcat.CommonTomcatManager.java Source code

Java tutorial

Introduction

Here is the source code for org.jboss.arquillian.container.tomcat.CommonTomcatManager.java

Source

/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 *
 * JBoss, Home of Professional Open Source
 * Copyright 2011, Red Hat Middleware LLC, and individual contributors
 * by the @authors tag. See the copyright.txt in the distribution for a
 * full listing of individual contributors.
 *
 * Copyright 2002, 2004 The Apache Software Foundation.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.jboss.arquillian.container.tomcat;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;
import java.util.logging.Level;
import java.util.logging.Logger;

import org.apache.commons.codec.binary.Base64;
import org.jboss.arquillian.container.spi.ConfigurationException;
import org.jboss.arquillian.container.spi.client.container.DeploymentException;

/**
 * Based on AbstractCatalinaTask, abstract base class for Ant tasks that interact with the <em>Manager</em> web application for
 * dynamically deploying and undeploying applications.
 *
 * @author <a href="mailto:kpiwko@redhat.com">Karel Piwko</a>
 * @author Craig R. McClanahan
 *
 */
public class CommonTomcatManager<C extends CommonTomcatConfiguration> {
    private static Logger log = Logger.getLogger(CommonTomcatManager.class.getName());

    // encoding of manager web app
    protected static final String MANAGER_CHARSET = "utf-8";

    private C configuration;

    /**
     * Creates a Tomcat manager abstraction
     *
     * @param configuration the configuration
     */
    public CommonTomcatManager(C configuration) {
        this.configuration = configuration;
    }

    public void deploy(String name, URL content) throws IOException, DeploymentException {
        final String contentType = "application/octet-stream";
        Validate.notNullOrEmpty(name, "Name must not be null or empty");
        Validate.notNull(content, "Content to be deployed must not be null");

        URLConnection conn = content.openConnection();
        int contentLength = conn.getContentLength();
        InputStream stream = new BufferedInputStream(conn.getInputStream());

        // Building URL
        StringBuilder command = new StringBuilder(getDeployCommand());
        try {
            command.append(URLEncoder.encode(name, configuration.getUrlCharset()));
        } catch (UnsupportedEncodingException e) {
            throw new DeploymentException("Unable to construct path for Tomcat manager", e);
        }

        execute(command.toString(), stream, contentType, contentLength);
    }

    public void undeploy(String name) throws IOException, DeploymentException {
        Validate.notNullOrEmpty(name, "Undeployed name must not be null or empty");

        // Building URL
        StringBuilder command = new StringBuilder(getUndeployCommand());
        try {
            command.append(URLEncoder.encode(name, configuration.getUrlCharset()));
        } catch (UnsupportedEncodingException e) {
            throw new DeploymentException("Unable to construct path for Tomcat manager", e);
        }

        execute(command.toString(), null, null, -1);
    }

    public void list() throws IOException {
        execute(getListCommand(), null, null, -1);
    }

    public boolean isRunning() {
        try {
            list();
            return true;
        } catch (IOException e) {
            return false;
        }
    }

    public String normalizeArchiveName(String name) {
        Validate.notNull(name, "Archive name must not be empty");

        if ("ROOT.war".equals(name)) {
            return "";
        }

        if (name.indexOf('.') != -1) {
            return name.substring(0, name.lastIndexOf("."));
        }

        return name;
    }

    protected String getDeployCommand() {
        return "/deploy?path=";
    }

    protected String getUndeployCommand() {
        return "/undeploy?path=";
    }

    protected String getListCommand() {
        return "/list";
    }

    /**
     * Execute the specified command, based on the configured properties. The input stream will be closed upon completion of
     * this task, whether it was executed successfully or not.
     *
     * @param command Command to be executed
     * @param istream InputStream to include in an HTTP PUT, if any
     * @param contentType Content type to specify for the input, if any
     * @param contentLength Content length to specify for the input, if any
     * @throws IOException
     * @throws MalformedURLException
     * @throws DeploymentException
     */
    protected void execute(String command, InputStream istream, String contentType, int contentLength)
            throws IOException {

        URLConnection conn = null;
        try {
            // Create a connection for this command
            conn = (new URL(configuration.getManagerUrl() + command)).openConnection();
            HttpURLConnection hconn = (HttpURLConnection) conn;

            // Set up standard connection characteristics
            hconn.setAllowUserInteraction(false);
            hconn.setDoInput(true);
            hconn.setUseCaches(false);
            if (istream != null) {
                hconn.setDoOutput(true);
                hconn.setRequestMethod("PUT");
                if (contentType != null) {
                    hconn.setRequestProperty("Content-Type", contentType);
                }
                if (contentLength >= 0) {
                    hconn.setRequestProperty("Content-Length", "" + contentLength);

                    hconn.setFixedLengthStreamingMode(contentLength);
                }
            } else {
                hconn.setDoOutput(false);
                hconn.setRequestMethod("GET");
            }
            hconn.setRequestProperty("User-Agent", "Arquillian-Tomcat-Manager-Util/1.0");
            // add authorization header if password is provided
            if (configuration.getUser() != null && configuration.getUser().length() != 0) {
                hconn.setRequestProperty("Authorization", constructHttpBasicAuthHeader());
            }
            hconn.setRequestProperty("Accept", "text/plain");

            // Establish the connection with the server
            hconn.connect();

            // Send the request data (if any)
            if (istream != null) {
                BufferedOutputStream ostream = new BufferedOutputStream(hconn.getOutputStream(), 1024);
                IOUtil.copy(istream, ostream);
                ostream.flush();
                ostream.close();
                istream.close();
            }

            processResponse(command, hconn);
        } finally {
            IOUtil.closeQuietly(istream);
        }
    }

    protected void processResponse(String command, HttpURLConnection hconn) throws IOException {
        int httpResponseCode = hconn.getResponseCode();
        // Supposes that <= 199 is not bad, but is it? See http://en.wikipedia.org/wiki/List_of_HTTP_status_codes
        if (httpResponseCode >= 400 && httpResponseCode < 500) {
            throw new ConfigurationException("Unable to connect to Tomcat manager. " + "The server command ("
                    + command + ") failed with responseCode (" + httpResponseCode + ") and responseMessage ("
                    + hconn.getResponseMessage() + ").\n\n"
                    + "Please make sure that you provided correct credentials to an user which is able to access Tomcat manager application.\n"
                    + "These credentials can be specified in the Arquillian container configuration as \"user\" and \"pass\" properties.\n"
                    + "The user must have appripriate role specified in tomcat-users.xml file.\n");
        } else if (httpResponseCode >= 300) {
            throw new IllegalStateException("The server command (" + command + ") failed with responseCode ("
                    + httpResponseCode + ") and responseMessage (" + hconn.getResponseMessage() + ").");
        }
        BufferedReader reader = null;
        try {
            // Process the response message
            reader = new BufferedReader(new InputStreamReader(hconn.getInputStream(), MANAGER_CHARSET));
            String line = reader.readLine();
            String contentError = null;
            if (line != null && !line.startsWith("OK -")) {
                contentError = line;
            }
            while (line != null) {
                if (log.isLoggable(Level.FINE)) {
                    log.fine(line);
                }
                line = reader.readLine();
            }
            if (contentError != null) {
                throw new RuntimeException(
                        "The server command (" + command + ") failed with content (" + contentError + ").");
            }
        } finally {
            IOUtil.closeQuietly(reader);
        }
    }

    protected String constructHttpBasicAuthHeader() {
        // Set up an authorization header with our credentials
        String credentials = configuration.getUser() + ":" + configuration.getPass();
        // Encodes the user:password pair as a sequence of ISO-8859-1 bytes.
        // We'll return the Base64 encoded form of this ISO-8859-1 byte sequence.
        try {
            return "Basic " + Base64.encodeBase64String(credentials.getBytes("ISO-8859-1"));
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException(e);
        }
    }

}