| package org.apache.tomcat.maven.common.deployer; |
| |
| /* |
| * 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 org.apache.commons.io.IOUtils; |
| import org.apache.commons.lang.StringUtils; |
| import org.apache.http.Header; |
| import org.apache.http.HttpHost; |
| import org.apache.http.HttpResponse; |
| import org.apache.http.HttpStatus; |
| import org.apache.http.auth.AuthScope; |
| import org.apache.http.auth.Credentials; |
| import org.apache.http.auth.UsernamePasswordCredentials; |
| import org.apache.http.client.AuthCache; |
| import org.apache.http.client.methods.HttpGet; |
| import org.apache.http.client.methods.HttpPut; |
| import org.apache.http.client.methods.HttpRequestBase; |
| import org.apache.http.client.protocol.ClientContext; |
| import org.apache.http.conn.params.ConnRoutePNames; |
| import org.apache.http.entity.AbstractHttpEntity; |
| import org.apache.http.impl.auth.BasicScheme; |
| import org.apache.http.impl.client.BasicAuthCache; |
| import org.apache.http.impl.client.DefaultHttpClient; |
| import org.apache.http.impl.conn.PoolingClientConnectionManager; |
| import org.apache.http.protocol.BasicHttpContext; |
| import org.apache.maven.settings.Proxy; |
| |
| import java.io.File; |
| import java.io.FileInputStream; |
| import java.io.IOException; |
| import java.io.InputStream; |
| import java.io.OutputStream; |
| import java.io.PrintStream; |
| import java.net.URL; |
| import java.net.URLEncoder; |
| import java.text.DecimalFormat; |
| import java.text.DecimalFormatSymbols; |
| import java.util.Locale; |
| |
| /** |
| * FIXME http connection tru a proxy |
| * A Tomcat manager webapp invocation wrapper. |
| * |
| * @author Mark Hobson <markhobson@gmail.com> |
| */ |
| 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; |
| |
| /** |
| * @since 2.0 |
| */ |
| private DefaultHttpClient httpClient; |
| |
| /** |
| * @since 2.0 |
| */ |
| private BasicHttpContext localContext; |
| |
| private Proxy proxy; |
| |
| /** |
| * @since 2.2 |
| */ |
| private boolean verbose; |
| |
| // ---------------------------------------------------------------------- |
| // 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, username, password, charset, true ); |
| } |
| |
| /** |
| * 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 |
| * @param verbose if the build is in verbose mode (quiet mode otherwise) |
| * @since 2.2 |
| */ |
| public TomcatManager( URL url, String username, String password, String charset, boolean verbose ) |
| { |
| this.url = url; |
| this.username = username; |
| this.password = password; |
| this.charset = charset; |
| this.verbose = verbose; |
| |
| PoolingClientConnectionManager poolingClientConnectionManager = new PoolingClientConnectionManager(); |
| poolingClientConnectionManager.setMaxTotal( 5 ); |
| this.httpClient = new DefaultHttpClient( poolingClientConnectionManager ); |
| |
| if ( StringUtils.isNotEmpty( username ) ) |
| { |
| Credentials creds = new UsernamePasswordCredentials( username, password ); |
| |
| String host = url.getHost(); |
| int port = url.getPort() > -1 ? url.getPort() : AuthScope.ANY_PORT; |
| httpClient.getCredentialsProvider().setCredentials( new AuthScope( host, port ), creds ); |
| |
| AuthCache authCache = new BasicAuthCache(); |
| BasicScheme basicAuth = new BasicScheme(); |
| HttpHost targetHost = new HttpHost( url.getHost(), url.getPort(), url.getProtocol() ); |
| authCache.put( targetHost, basicAuth ); |
| |
| localContext = new BasicHttpContext(); |
| localContext.setAttribute( ClientContext.AUTH_CACHE, authCache ); |
| } |
| } |
| |
| // ---------------------------------------------------------------------- |
| // 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; |
| } |
| |
| /** |
| * @param proxy |
| */ |
| public void setProxy(Proxy proxy) { |
| if( this.proxy != proxy ) { |
| this.proxy = proxy; |
| if( httpClient != null ) { |
| applyProxy(); |
| } |
| } |
| } |
| |
| /** |
| * {@link #setProxy(Proxy)} is called by {@link AbstractCatinalMojo#getManager()} after the constructor |
| */ |
| private void applyProxy() { |
| if( this.proxy != null ) { |
| HttpHost proxy = new HttpHost(this.proxy.getHost(), this.proxy.getPort(), this.proxy.getProtocol()); |
| httpClient.getParams().setParameter( ConnRoutePNames.DEFAULT_PROXY, proxy ); |
| if( this.proxy.getUsername() != null ) { |
| httpClient.getCredentialsProvider().setCredentials( new AuthScope(this.proxy.getHost(), this.proxy.getPort()), |
| new UsernamePasswordCredentials(this.proxy.getUsername(), |
| this.proxy.getPassword()) ); |
| } |
| } else { |
| httpClient.getParams().removeParameter( ConnRoutePNames.DEFAULT_PROXY ); |
| } |
| } |
| |
| |
| /** |
| * 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 TomcatManagerResponse 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 TomcatManagerResponse 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 TomcatManagerResponse 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 TomcatManagerResponse deploy( String path, File 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 TomcatManagerResponse deploy( String path, File 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 TomcatManagerResponse deploy( String path, File war, boolean update, String tag ) |
| throws TomcatManagerException, IOException |
| { |
| return deployImpl( path, null, null, war, update, tag ); |
| } |
| |
| /** |
| * @param path |
| * @param war |
| * @param update |
| * @param tag |
| * @param length |
| * @return |
| * @throws TomcatManagerException |
| * @throws IOException |
| * @since 2.0 |
| */ |
| public TomcatManagerResponse deploy( String path, File war, boolean update, String tag, long length ) |
| throws TomcatManagerException, IOException |
| { |
| return deployImpl( path, null, null, war, update, tag, length ); |
| } |
| |
| /** |
| * 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 TomcatManagerResponse 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 TomcatManagerResponse 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 TomcatManagerResponse 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 TomcatManagerResponse 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 TomcatManagerResponse 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 TomcatManagerResponse 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 TomcatManagerResponse 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 TomcatManagerResponse 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 TomcatManagerResponse 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 TomcatManagerResponse 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 TomcatManagerResponse 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 TomcatManagerResponse 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 TomcatManagerResponse 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 TomcatManagerResponse 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 TomcatManagerResponse 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 TomcatManagerResponse 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 TomcatManagerResponse invoke( String path ) |
| throws TomcatManagerException, IOException |
| { |
| return invoke( path, null, -1 ); |
| } |
| |
| // ---------------------------------------------------------------------- |
| // Private Methods |
| // ---------------------------------------------------------------------- |
| |
| private TomcatManagerResponse deployImpl( String path, URL config, URL war, File data, boolean update, String tag ) |
| throws TomcatManagerException, IOException |
| { |
| return deployImpl( path, config, war, data, update, tag, -1 ); |
| } |
| |
| /** |
| * 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 WAR file 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 TomcatManagerResponse deployImpl( String path, URL config, URL war, File data, boolean update, String tag, |
| long length ) |
| throws TomcatManagerException, IOException |
| { |
| StringBuilder buffer = new StringBuilder( "/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 ) ); |
| } |
| |
| if ( update ) |
| { |
| buffer.append( "&update=true" ); |
| } |
| |
| if ( tag != null ) |
| { |
| buffer.append( "&tag=" ).append( URLEncoder.encode( tag, charset ) ); |
| } |
| |
| return invoke( buffer.toString(), data, length ); |
| } |
| |
| |
| /** |
| * Invokes Tomcat manager with the specified command and content data. |
| * |
| * @param path the Tomcat manager command to invoke |
| * @param data file to deploy |
| * @return the Tomcat manager response |
| * @throws TomcatManagerException if the Tomcat manager request fails |
| * @throws IOException if an i/o error occurs |
| */ |
| protected TomcatManagerResponse invoke( String path, File data, long length ) |
| throws TomcatManagerException, IOException |
| { |
| |
| HttpRequestBase httpRequestBase = null; |
| if ( data == null ) |
| { |
| httpRequestBase = new HttpGet( url + path ); |
| } |
| else |
| { |
| HttpPut httpPut = new HttpPut( url + path ); |
| |
| httpPut.setEntity( new RequestEntityImplementation( data, length, url + path, verbose ) ); |
| |
| httpRequestBase = httpPut; |
| |
| } |
| |
| if ( userAgent != null ) |
| { |
| httpRequestBase.setHeader( "User-Agent", userAgent ); |
| } |
| |
| HttpResponse response = httpClient.execute( httpRequestBase, localContext ); |
| |
| int statusCode = response.getStatusLine().getStatusCode(); |
| |
| switch ( statusCode ) |
| { |
| // Success Codes |
| case HttpStatus.SC_OK: // 200 |
| case HttpStatus.SC_CREATED: // 201 |
| case HttpStatus.SC_ACCEPTED: // 202 |
| break; |
| // handle all redirect even if http specs says " the user agent MUST NOT automatically redirect the request unless it can be confirmed by the user" |
| case HttpStatus.SC_MOVED_PERMANENTLY: // 301 |
| case HttpStatus.SC_MOVED_TEMPORARILY: // 302 |
| case HttpStatus.SC_SEE_OTHER: // 303 |
| String relocateUrl = calculateRelocatedUrl( response ); |
| this.url = new URL( relocateUrl ); |
| return invoke( path, data, length ); |
| } |
| |
| return new TomcatManagerResponse().setStatusCode( response.getStatusLine().getStatusCode() ).setReasonPhrase( |
| response.getStatusLine().getReasonPhrase() ).setHttpResponseBody( |
| IOUtils.toString( response.getEntity().getContent() ) ); |
| |
| } |
| |
| protected String calculateRelocatedUrl( HttpResponse response ) |
| { |
| Header locationHeader = response.getFirstHeader( "Location" ); |
| String locationField = locationHeader.getValue(); |
| // is it a relative Location or a full ? |
| return locationField.startsWith( "http" ) ? locationField : url.toString() + '/' + locationField; |
| } |
| |
| |
| /** |
| * 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() ) ); |
| } |
| |
| private final class RequestEntityImplementation |
| extends AbstractHttpEntity |
| { |
| |
| private final static int BUFFER_SIZE = 2048; |
| |
| private File file; |
| |
| PrintStream out = System.out; |
| |
| private long length = -1; |
| |
| private int lastLength; |
| |
| private String url; |
| |
| private long startTime; |
| |
| private boolean verbose; |
| |
| private RequestEntityImplementation( final File file, long length, String url, boolean verbose ) |
| { |
| this.file = file; |
| this.length = length; |
| this.url = url; |
| this.verbose = verbose; |
| } |
| |
| public long getContentLength() |
| { |
| return length >= 0 ? length : ( file.length() >= 0 ? file.length() : -1 ); |
| } |
| |
| |
| public InputStream getContent() |
| throws IOException, IllegalStateException |
| { |
| return new FileInputStream( this.file ); |
| } |
| |
| public boolean isRepeatable() |
| { |
| return true; |
| } |
| |
| |
| public void writeTo( final OutputStream outstream ) |
| throws IOException |
| { |
| long completed = 0; |
| if ( outstream == null ) |
| { |
| throw new IllegalArgumentException( "Output stream may not be null" ); |
| } |
| FileInputStream stream = new FileInputStream( this.file ); |
| transferInitiated( this.url ); |
| this.startTime = System.currentTimeMillis(); |
| try |
| { |
| byte[] buffer = new byte[BUFFER_SIZE]; |
| |
| int l; |
| if ( this.length < 0 ) |
| { |
| // until EOF |
| while ( ( l = stream.read( buffer ) ) != -1 ) |
| { |
| transferProgressed( completed += buffer.length, -1 ); |
| outstream.write( buffer, 0, l ); |
| } |
| } |
| else |
| { |
| // no need to consume more than length |
| long remaining = this.length; |
| while ( remaining > 0 ) |
| { |
| int transferSize = (int) Math.min( BUFFER_SIZE, remaining ); |
| completed += transferSize; |
| l = stream.read( buffer, 0, transferSize ); |
| if ( l == -1 ) |
| { |
| break; |
| } |
| |
| outstream.write( buffer, 0, l ); |
| remaining -= l; |
| transferProgressed( completed, this.length ); |
| } |
| } |
| transferSucceeded( completed ); |
| } |
| finally |
| { |
| stream.close(); |
| out.println(); |
| } |
| // end transfer |
| } |
| |
| public boolean isStreaming() |
| { |
| return true; |
| } |
| |
| |
| public void transferInitiated( String url ) |
| { |
| String message = "Uploading"; |
| |
| out.println( message + ": " + url ); |
| } |
| |
| public void transferProgressed( long completedSize, long totalSize ) |
| { |
| if ( !verbose ) |
| { |
| return; |
| } |
| |
| StringBuilder buffer = new StringBuilder( 64 ); |
| |
| buffer.append( getStatus( completedSize, totalSize ) ).append( " " ); |
| lastLength = buffer.length(); |
| buffer.append( '\r' ); |
| |
| out.print( buffer ); |
| } |
| |
| public void transferSucceeded( long contentLength ) |
| { |
| |
| if ( contentLength >= 0 ) |
| { |
| String type = "Uploaded"; |
| String len = contentLength >= 1024 ? toKB( contentLength ) + " KB" : contentLength + " B"; |
| |
| String throughput = ""; |
| long duration = System.currentTimeMillis() - startTime; |
| if ( duration > 0 ) |
| { |
| DecimalFormat format = new DecimalFormat( "0.0", new DecimalFormatSymbols( Locale.ENGLISH ) ); |
| double kbPerSec = ( contentLength / 1024.0 ) / ( duration / 1000.0 ); |
| throughput = " at " + format.format( kbPerSec ) + " KB/sec"; |
| } |
| |
| out.println( type + ": " + url + " (" + len + throughput + ")" ); |
| } |
| } |
| |
| private String getStatus( long complete, long total ) |
| { |
| if ( total >= 1024 ) |
| { |
| return toKB( complete ) + "/" + toKB( total ) + " KB "; |
| } |
| else if ( total >= 0 ) |
| { |
| return complete + "/" + total + " B "; |
| } |
| else if ( complete >= 1024 ) |
| { |
| return toKB( complete ) + " KB "; |
| } |
| else |
| { |
| return complete + " B "; |
| } |
| } |
| |
| private long toKB( long bytes ) |
| { |
| return ( bytes + 1023 ) / 1024; |
| } |
| |
| } |
| } |