org.codehaus.mojo.tomcat.TomcatManager.java Source code

Java tutorial

Introduction

Here is the source code for org.codehaus.mojo.tomcat.TomcatManager.java

Source

package org.codehaus.mojo.tomcat;

/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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.
 */

import org.apache.commons.codec.binary.Base64;

import java.io.BufferedOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;

/**
 * A Tomcat manager webapp invocation wrapper.
 * 
 * @author Mark Hobson <markhobson@gmail.com>
 * @version $Id$
 */
public class TomcatManager {
    // ----------------------------------------------------------------------
    // Constants
    // ----------------------------------------------------------------------

    /**
     * The charset to use when decoding Tomcat manager responses.
     */
    private static final String MANAGER_CHARSET = "UTF-8";

    // ----------------------------------------------------------------------
    // Fields
    // ----------------------------------------------------------------------

    /**
     * The full URL of the Tomcat manager instance to use.
     */
    private URL url;

    /**
     * The username to use when authenticating with Tomcat manager.
     */
    private String username;

    /**
     * The password to use when authenticating with Tomcat manager.
     */
    private String password;

    /**
     * The URL encoding charset to use when communicating with Tomcat manager.
     */
    private String charset;

    /**
     * The user agent name to use when communicating with Tomcat manager.
     */
    private String userAgent;

    // ----------------------------------------------------------------------
    // Constructors
    // ----------------------------------------------------------------------

    /**
     * Creates a Tomcat manager wrapper for the specified URL that uses a username of <code>admin</code>, an empty
     * password and ISO-8859-1 URL encoding.
     * 
     * @param url the full URL of the Tomcat manager instance to use
     */
    public TomcatManager(URL url) {
        this(url, "admin");
    }

    /**
     * Creates a Tomcat manager wrapper for the specified URL and username that uses an empty password and ISO-8859-1
     * URL encoding.
     * 
     * @param url the full URL of the Tomcat manager instance to use
     * @param username the username to use when authenticating with Tomcat manager
     */
    public TomcatManager(URL url, String username) {
        this(url, username, "");
    }

    /**
     * Creates a Tomcat manager wrapper for the specified URL, username and password that uses ISO-8859-1 URL encoding.
     * 
     * @param url the full URL of the Tomcat manager instance to use
     * @param username the username to use when authenticating with Tomcat manager
     * @param password the password to use when authenticating with Tomcat manager
     */
    public TomcatManager(URL url, String username, String password) {
        this(url, username, password, "ISO-8859-1");
    }

    /**
     * Creates a Tomcat manager wrapper for the specified URL, username, password and URL encoding.
     * 
     * @param url the full URL of the Tomcat manager instance to use
     * @param username the username to use when authenticating with Tomcat manager
     * @param password the password to use when authenticating with Tomcat manager
     * @param charset the URL encoding charset to use when communicating with Tomcat manager
     */
    public TomcatManager(URL url, String username, String password, String charset) {
        this.url = url;
        this.username = username;
        this.password = password;
        this.charset = charset;
    }

    // ----------------------------------------------------------------------
    // Public Methods
    // ----------------------------------------------------------------------

    /**
     * Gets the full URL of the Tomcat manager instance.
     * 
     * @return the full URL of the Tomcat manager instance
     */
    public URL getURL() {
        return url;
    }

    /**
     * Gets the username to use when authenticating with Tomcat manager.
     * 
     * @return the username to use when authenticating with Tomcat manager
     */
    public String getUserName() {
        return username;
    }

    /**
     * Gets the password to use when authenticating with Tomcat manager.
     * 
     * @return the password to use when authenticating with Tomcat manager
     */
    public String getPassword() {
        return password;
    }

    /**
     * Gets the URL encoding charset to use when communicating with Tomcat manager.
     * 
     * @return the URL encoding charset to use when communicating with Tomcat manager
     */
    public String getCharset() {
        return charset;
    }

    /**
     * Gets the user agent name to use when communicating with Tomcat manager.
     * 
     * @return the user agent name to use when communicating with Tomcat manager
     */
    public String getUserAgent() {
        return userAgent;
    }

    /**
     * Sets the user agent name to use when communicating with Tomcat manager.
     * 
     * @param userAgent the user agent name to use when communicating with Tomcat manager
     */
    public void setUserAgent(String userAgent) {
        this.userAgent = userAgent;
    }

    /**
     * Deploys the specified WAR as a URL to the specified context path.
     * 
     * @param path the webapp context path to deploy to
     * @param war the URL of the WAR to deploy
     * @return the Tomcat manager response
     * @throws TomcatManagerException if the Tomcat manager request fails
     * @throws IOException if an i/o error occurs
     */
    public String deploy(String path, URL war) throws TomcatManagerException, IOException {
        return deploy(path, war, false);
    }

    /**
     * Deploys the specified WAR as a URL to the specified context path, optionally undeploying the webapp if it already
     * exists.
     * 
     * @param path the webapp context path to deploy to
     * @param war the URL of the WAR to deploy
     * @param update whether to first undeploy the webapp if it already exists
     * @return the Tomcat manager response
     * @throws TomcatManagerException if the Tomcat manager request fails
     * @throws IOException if an i/o error occurs
     */
    public String deploy(String path, URL war, boolean update) throws TomcatManagerException, IOException {
        return deploy(path, war, update, null);
    }

    /**
     * Deploys the specified WAR as a URL to the specified context path, optionally undeploying the webapp if it already
     * exists and using the specified tag name.
     * 
     * @param path the webapp context path to deploy to
     * @param war the URL of the WAR to deploy
     * @param update whether to first undeploy the webapp if it already exists
     * @param tag the tag name to use
     * @return the Tomcat manager response
     * @throws TomcatManagerException if the Tomcat manager request fails
     * @throws IOException if an i/o error occurs
     */
    public String deploy(String path, URL war, boolean update, String tag)
            throws TomcatManagerException, IOException {
        return deployImpl(path, null, war, null, update, tag);
    }

    /**
     * Deploys the specified WAR as a HTTP PUT to the specified context path.
     * 
     * @param path the webapp context path to deploy to
     * @param war an input stream to the WAR to deploy
     * @return the Tomcat manager response
     * @throws TomcatManagerException if the Tomcat manager request fails
     * @throws IOException if an i/o error occurs
     */
    public String deploy(String path, InputStream war) throws TomcatManagerException, IOException {
        return deploy(path, war, false);
    }

    /**
     * Deploys the specified WAR as a HTTP PUT to the specified context path, optionally undeploying the webapp if it
     * already exists.
     * 
     * @param path the webapp context path to deploy to
     * @param war an input stream to the WAR to deploy
     * @param update whether to first undeploy the webapp if it already exists
     * @return the Tomcat manager response
     * @throws TomcatManagerException if the Tomcat manager request fails
     * @throws IOException if an i/o error occurs
     */
    public String deploy(String path, InputStream war, boolean update) throws TomcatManagerException, IOException {
        return deploy(path, war, update, null);
    }

    /**
     * Deploys the specified WAR as a HTTP PUT to the specified context path, optionally undeploying the webapp if it
     * already exists and using the specified tag name.
     * 
     * @param path the webapp context path to deploy to
     * @param war an input stream to the WAR to deploy
     * @param update whether to first undeploy the webapp if it already exists
     * @param tag the tag name to use
     * @return the Tomcat manager response
     * @throws TomcatManagerException if the Tomcat manager request fails
     * @throws IOException if an i/o error occurs
     */
    public String deploy(String path, InputStream war, boolean update, String tag)
            throws TomcatManagerException, IOException {
        return deployImpl(path, null, null, war, update, tag);
    }

    /**
     * Deploys the specified context XML configuration to the specified context path.
     * 
     * @param path the webapp context path to deploy to
     * @param config the URL of the context XML configuration to deploy
     * @return the Tomcat manager response
     * @throws TomcatManagerException if the Tomcat manager request fails
     * @throws IOException if an i/o error occurs
     */
    public String deployContext(String path, URL config) throws TomcatManagerException, IOException {
        return deployContext(path, config, false);
    }

    /**
     * Deploys the specified context XML configuration to the specified context path, optionally undeploying the webapp
     * if it already exists.
     * 
     * @param path the webapp context path to deploy to
     * @param config the URL of the context XML configuration to deploy
     * @param update whether to first undeploy the webapp if it already exists
     * @return the Tomcat manager response
     * @throws TomcatManagerException if the Tomcat manager request fails
     * @throws IOException if an i/o error occurs
     */
    public String deployContext(String path, URL config, boolean update)
            throws TomcatManagerException, IOException {
        return deployContext(path, config, update, null);
    }

    /**
     * Deploys the specified context XML configuration to the specified context path, optionally undeploying the webapp
     * if it already exists and using the specified tag name.
     * 
     * @param path the webapp context path to deploy to
     * @param config the URL of the context XML configuration to deploy
     * @param update whether to first undeploy the webapp if it already exists
     * @param tag the tag name to use
     * @return the Tomcat manager response
     * @throws TomcatManagerException if the Tomcat manager request fails
     * @throws IOException if an i/o error occurs
     */
    public String deployContext(String path, URL config, boolean update, String tag)
            throws TomcatManagerException, IOException {
        return deployContext(path, config, null, update, tag);
    }

    /**
     * Deploys the specified context XML configuration and WAR as a URL to the specified context path.
     * 
     * @param path the webapp context path to deploy to
     * @param config the URL of the context XML configuration to deploy
     * @param war the URL of the WAR to deploy
     * @return the Tomcat manager response
     * @throws TomcatManagerException if the Tomcat manager request fails
     * @throws IOException if an i/o error occurs
     */
    public String deployContext(String path, URL config, URL war) throws TomcatManagerException, IOException {
        return deployContext(path, config, war, false);
    }

    /**
     * Deploys the specified context XML configuration and WAR as a URL to the specified context path, optionally
     * undeploying the webapp if it already exists.
     * 
     * @param path the webapp context path to deploy to
     * @param config the URL of the context XML configuration to deploy
     * @param war the URL of the WAR to deploy
     * @param update whether to first undeploy the webapp if it already exists
     * @return the Tomcat manager response
     * @throws TomcatManagerException if the Tomcat manager request fails
     * @throws IOException if an i/o error occurs
     */
    public String deployContext(String path, URL config, URL war, boolean update)
            throws TomcatManagerException, IOException {
        return deployContext(path, config, war, update, null);
    }

    /**
     * Deploys the specified context XML configuration and WAR as a URL to the specified context path, optionally
     * undeploying the webapp if it already exists and using the specified tag name.
     * 
     * @param path the webapp context path to deploy to
     * @param config the URL of the context XML configuration to deploy
     * @param war the URL of the WAR to deploy
     * @param update whether to first undeploy the webapp if it already exists
     * @param tag the tag name to use
     * @return the Tomcat manager response
     * @throws TomcatManagerException if the Tomcat manager request fails
     * @throws IOException if an i/o error occurs
     */
    public String deployContext(String path, URL config, URL war, boolean update, String tag)
            throws TomcatManagerException, IOException {
        return deployImpl(path, config, war, null, update, tag);
    }

    /**
     * Undeploys the webapp at the specified context path.
     * 
     * @param path the webapp context path to undeploy
     * @return the Tomcat manager response
     * @throws TomcatManagerException if the Tomcat manager request fails
     * @throws IOException if an i/o error occurs
     */
    public String undeploy(String path) throws TomcatManagerException, IOException {
        return invoke("/undeploy?path=" + URLEncoder.encode(path, charset));
    }

    /**
     * Reloads the webapp at the specified context path.
     * 
     * @param path the webapp context path to reload
     * @return the Tomcat manager response
     * @throws TomcatManagerException if the Tomcat manager request fails
     * @throws IOException if an i/o error occurs
     */
    public String reload(String path) throws TomcatManagerException, IOException {
        return invoke("/reload?path=" + URLEncoder.encode(path, charset));
    }

    /**
     * Starts the webapp at the specified context path.
     * 
     * @param path the webapp context path to start
     * @return the Tomcat manager response
     * @throws TomcatManagerException if the Tomcat manager request fails
     * @throws IOException if an i/o error occurs
     */
    public String start(String path) throws TomcatManagerException, IOException {
        return invoke("/start?path=" + URLEncoder.encode(path, charset));
    }

    /**
     * Stops the webapp at the specified context path.
     * 
     * @param path the webapp context path to stop
     * @return the Tomcat manager response
     * @throws TomcatManagerException if the Tomcat manager request fails
     * @throws IOException if an i/o error occurs
     */
    public String stop(String path) throws TomcatManagerException, IOException {
        return invoke("/stop?path=" + URLEncoder.encode(path, charset));
    }

    /**
     * Lists all the currently deployed web applications.
     * 
     * @return the list of currently deployed applications
     * @throws TomcatManagerException if the Tomcat manager request fails
     * @throws IOException if an i/o error occurs
     */
    public String list() throws TomcatManagerException, IOException {
        return invoke("/list");
    }

    /**
     * Lists information about the Tomcat version, OS, and JVM properties.
     * 
     * @return the server information
     * @throws TomcatManagerException if the Tomcat manager request fails
     * @throws IOException if an i/o error occurs
     */
    public String getServerInfo() throws TomcatManagerException, IOException {
        return invoke("/serverinfo");
    }

    /**
     * Lists all of the global JNDI resources.
     * 
     * @return the list of all global JNDI resources
     * @throws TomcatManagerException if the Tomcat manager request fails
     * @throws IOException if an i/o error occurs
     */
    public String getResources() throws TomcatManagerException, IOException {
        return getResources(null);
    }

    /**
     * Lists the global JNDI resources of the given type.
     * 
     * @param type the class name of the resources to list, or <code>null</code> for all
     * @return the list of global JNDI resources of the given type
     * @throws TomcatManagerException if the Tomcat manager request fails
     * @throws IOException if an i/o error occurs
     */
    public String getResources(String type) throws TomcatManagerException, IOException {
        StringBuffer buffer = new StringBuffer();
        buffer.append("/resources");

        if (type != null) {
            buffer.append("?type=" + URLEncoder.encode(type, charset));
        }
        return invoke(buffer.toString());
    }

    /**
     * Lists the security role names and corresponding descriptions that are available.
     * 
     * @return the list of security role names and corresponding descriptions
     * @throws TomcatManagerException if the Tomcat manager request fails
     * @throws IOException if an i/o error occurs
     */
    public String getRoles() throws TomcatManagerException, IOException {
        return invoke("/roles");
    }

    /**
     * Lists the default session timeout and the number of currently active sessions for the given context path.
     * 
     * @param path the context path to list session information for
     * @return the default session timeout and the number of currently active sessions
     * @throws TomcatManagerException if the Tomcat manager request fails
     * @throws IOException if an i/o error occurs
     */
    public String getSessions(String path) throws TomcatManagerException, IOException {
        return invoke("/sessions?path=" + URLEncoder.encode(path, charset));
    }

    // ----------------------------------------------------------------------
    // Protected Methods
    // ----------------------------------------------------------------------

    /**
     * Invokes Tomcat manager with the specified command.
     * 
     * @param path the Tomcat manager command to invoke
     * @return the Tomcat manager response
     * @throws TomcatManagerException if the Tomcat manager request fails
     * @throws IOException if an i/o error occurs
     */
    protected String invoke(String path) throws TomcatManagerException, IOException {
        return invoke(path, null);
    }

    /**
     * Invokes Tomcat manager with the specified command and content data.
     * 
     * @param path the Tomcat manager command to invoke
     * @param data an input stream to the content data
     * @return the Tomcat manager response
     * @throws TomcatManagerException if the Tomcat manager request fails
     * @throws IOException if an i/o error occurs
     */
    protected String invoke(String path, InputStream data) throws TomcatManagerException, IOException {
        HttpURLConnection connection = (HttpURLConnection) new URL(url + path).openConnection();
        connection.setAllowUserInteraction(false);
        connection.setDoInput(true);
        connection.setUseCaches(false);

        if (data == null) {
            connection.setDoOutput(false);
            connection.setRequestMethod("GET");
        } else {
            connection.setDoOutput(true);
            connection.setRequestMethod("PUT");
            connection.setRequestProperty("Content-Type", "application/octet-stream");
        }

        if (userAgent != null) {
            connection.setRequestProperty("User-Agent", userAgent);
        }
        connection.setRequestProperty("Authorization", toAuthorization(username, password));

        connection.connect();

        if (data != null) {
            pipe(data, connection.getOutputStream());
        }

        String response = toString(connection.getInputStream(), MANAGER_CHARSET);

        if (!response.startsWith("OK -")) {
            throw new TomcatManagerException(response);
        }

        return response;
    }

    // ----------------------------------------------------------------------
    // Private Methods
    // ----------------------------------------------------------------------

    /**
     * Deploys the specified WAR.
     * 
     * @param path the webapp context path to deploy to
     * @param config the URL of the context XML configuration to deploy, or null for none
     * @param war the URL of the WAR to deploy, or null to use <code>data</code>
     * @param data an input stream to the WAR to deploy, or null to use <code>war</code>
     * @param update whether to first undeploy the webapp if it already exists
     * @param tag the tag name to use
     * @return the Tomcat manager response
     * @throws TomcatManagerException if the Tomcat manager request fails
     * @throws IOException if an i/o error occurs
     */
    private String deployImpl(String path, URL config, URL war, InputStream data, boolean update, String tag)
            throws TomcatManagerException, IOException {
        StringBuffer buffer = new StringBuffer("/deploy");
        buffer.append("?path=").append(URLEncoder.encode(path, charset));

        if (config != null) {
            buffer.append("&config=").append(URLEncoder.encode(config.toString(), charset));
        }

        if (war != null) {
            buffer.append("&war=").append(URLEncoder.encode(war.toString(), charset));
        } else {
            // for Tomcat 5.0.27
            buffer.append("&war=");
        }

        if (update) {
            buffer.append("&update=true");
        }

        if (tag != null) {
            buffer.append("&tag=").append(URLEncoder.encode(tag, charset));
        }

        return invoke(buffer.toString(), data);
    }

    /**
     * Gets the HTTP Basic Authorization header value for the supplied username and password.
     * 
     * @param username the username to use for authentication
     * @param password the password to use for authentication
     * @return the HTTP Basic Authorization header value
     */
    private String toAuthorization(String username, String password) {
        StringBuffer buffer = new StringBuffer();
        buffer.append(username).append(':');
        if (password != null) {
            buffer.append(password);
        }
        return "Basic " + new String(Base64.encodeBase64(buffer.toString().getBytes()));
    }

    /**
     * Reads all the data from the specified input stream and writes it to the specified output stream. Both streams are
     * also closed.
     * 
     * @param in the input stream to read from
     * @param out the output stream to write to
     * @throws IOException if an i/o error occurs
     */
    private void pipe(InputStream in, OutputStream out) throws IOException {
        out = new BufferedOutputStream(out);
        int n;
        byte[] bytes = new byte[1024 * 4];
        while ((n = in.read(bytes)) != -1) {
            out.write(bytes, 0, n);
        }
        out.flush();
        out.close();
        in.close();
    }

    /**
     * Gets the data from the specified input stream as a string using the specified charset.
     * 
     * @param in the input stream to read from
     * @param charset the charset to use when constructing the string
     * @return a string representation of the data read from the input stream
     * @throws IOException if an i/o error occurs
     */
    private String toString(InputStream in, String charset) throws IOException {
        InputStreamReader reader = new InputStreamReader(in, charset);

        StringBuffer buffer = new StringBuffer();
        char[] chars = new char[1024];
        int n;
        while ((n = reader.read(chars, 0, chars.length)) != -1) {
            buffer.append(chars, 0, n);
        }

        return buffer.toString();
    }
}