Coverage Report - org.apache.tomcat.maven.common.deployer.TomcatManager
 
Classes in this File Line Coverage Branch Coverage Complexity
TomcatManager
55 %
54/97
41 %
12/29
1,7
TomcatManager$1
N/A
N/A
1,7
TomcatManager$RequestEntityImplementation
74 %
50/67
50 %
13/26
1,7
 
 1  
 package org.apache.tomcat.maven.common.deployer;
 2  
 
 3  
 /*
 4  
  * Licensed to the Apache Software Foundation (ASF) under one
 5  
  * or more contributor license agreements.  See the NOTICE file
 6  
  * distributed with this work for additional information
 7  
  * regarding copyright ownership.  The ASF licenses this file
 8  
  * to you under the Apache License, Version 2.0 (the
 9  
  * "License"); you may not use this file except in compliance
 10  
  * with the License.  You may obtain a copy of the License at
 11  
  *
 12  
  *   http://www.apache.org/licenses/LICENSE-2.0
 13  
  *
 14  
  * Unless required by applicable law or agreed to in writing,
 15  
  * software distributed under the License is distributed on an
 16  
  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 17  
  * KIND, either express or implied.  See the License for the
 18  
  * specific language governing permissions and limitations
 19  
  * under the License.
 20  
  */
 21  
 
 22  
 import org.apache.commons.codec.binary.Base64;
 23  
 import org.apache.commons.io.IOUtils;
 24  
 import org.apache.commons.lang.StringUtils;
 25  
 import org.apache.http.Header;
 26  
 import org.apache.http.HttpHost;
 27  
 import org.apache.http.HttpResponse;
 28  
 import org.apache.http.HttpStatus;
 29  
 import org.apache.http.auth.AuthScope;
 30  
 import org.apache.http.auth.Credentials;
 31  
 import org.apache.http.auth.UsernamePasswordCredentials;
 32  
 import org.apache.http.client.AuthCache;
 33  
 import org.apache.http.client.methods.HttpGet;
 34  
 import org.apache.http.client.methods.HttpPut;
 35  
 import org.apache.http.client.methods.HttpRequestBase;
 36  
 import org.apache.http.client.protocol.ClientContext;
 37  
 import org.apache.http.entity.AbstractHttpEntity;
 38  
 import org.apache.http.impl.auth.BasicScheme;
 39  
 import org.apache.http.impl.client.BasicAuthCache;
 40  
 import org.apache.http.impl.client.DefaultHttpClient;
 41  
 import org.apache.http.impl.conn.PoolingClientConnectionManager;
 42  
 import org.apache.http.protocol.BasicHttpContext;
 43  
 
 44  
 import java.io.File;
 45  
 import java.io.FileInputStream;
 46  
 import java.io.IOException;
 47  
 import java.io.InputStream;
 48  
 import java.io.OutputStream;
 49  
 import java.io.PrintStream;
 50  
 import java.net.URL;
 51  
 import java.net.URLEncoder;
 52  
 import java.text.DecimalFormat;
 53  
 import java.text.DecimalFormatSymbols;
 54  
 import java.util.Locale;
 55  
 
 56  
 /**
 57  
  * FIXME http connection tru a proxy
 58  
  * A Tomcat manager webapp invocation wrapper.
 59  
  *
 60  
  * @author Mark Hobson <markhobson@gmail.com>
 61  
  */
 62  
 public class TomcatManager
 63  
 {
 64  
     // ----------------------------------------------------------------------
 65  
     // Constants
 66  
     // ----------------------------------------------------------------------
 67  
 
 68  
     /**
 69  
      * The charset to use when decoding Tomcat manager responses.
 70  
      */
 71  
     private static final String MANAGER_CHARSET = "UTF-8";
 72  
 
 73  
     // ----------------------------------------------------------------------
 74  
     // Fields
 75  
     // ----------------------------------------------------------------------
 76  
 
 77  
     /**
 78  
      * The full URL of the Tomcat manager instance to use.
 79  
      */
 80  
     private URL url;
 81  
 
 82  
     /**
 83  
      * The username to use when authenticating with Tomcat manager.
 84  
      */
 85  
     private String username;
 86  
 
 87  
     /**
 88  
      * The password to use when authenticating with Tomcat manager.
 89  
      */
 90  
     private String password;
 91  
 
 92  
     /**
 93  
      * The URL encoding charset to use when communicating with Tomcat manager.
 94  
      */
 95  
     private String charset;
 96  
 
 97  
     /**
 98  
      * The user agent name to use when communicating with Tomcat manager.
 99  
      */
 100  
     private String userAgent;
 101  
 
 102  
     /**
 103  
      * @since 2.0
 104  
      */
 105  
     private DefaultHttpClient httpClient;
 106  
 
 107  
     /**
 108  
      * @since 2.0
 109  
      */
 110  
     private BasicHttpContext localContext;
 111  
 
 112  
     // ----------------------------------------------------------------------
 113  
     // Constructors
 114  
     // ----------------------------------------------------------------------
 115  
 
 116  
     /**
 117  
      * Creates a Tomcat manager wrapper for the specified URL that uses a username of <code>admin</code>, an empty
 118  
      * password and ISO-8859-1 URL encoding.
 119  
      *
 120  
      * @param url the full URL of the Tomcat manager instance to use
 121  
      */
 122  
     public TomcatManager( URL url )
 123  
     {
 124  3
         this( url, "admin" );
 125  3
     }
 126  
 
 127  
     /**
 128  
      * Creates a Tomcat manager wrapper for the specified URL and username that uses an empty password and ISO-8859-1
 129  
      * URL encoding.
 130  
      *
 131  
      * @param url      the full URL of the Tomcat manager instance to use
 132  
      * @param username the username to use when authenticating with Tomcat manager
 133  
      */
 134  
     public TomcatManager( URL url, String username )
 135  
     {
 136  3
         this( url, username, "" );
 137  3
     }
 138  
 
 139  
     /**
 140  
      * Creates a Tomcat manager wrapper for the specified URL, username and password that uses ISO-8859-1 URL encoding.
 141  
      *
 142  
      * @param url      the full URL of the Tomcat manager instance to use
 143  
      * @param username the username to use when authenticating with Tomcat manager
 144  
      * @param password the password to use when authenticating with Tomcat manager
 145  
      */
 146  
     public TomcatManager( URL url, String username, String password )
 147  
     {
 148  3
         this( url, username, password, "ISO-8859-1" );
 149  3
     }
 150  
 
 151  
 
 152  
     /**
 153  
      * Creates a Tomcat manager wrapper for the specified URL, username, password and URL encoding.
 154  
      *
 155  
      * @param url      the full URL of the Tomcat manager instance to use
 156  
      * @param username the username to use when authenticating with Tomcat manager
 157  
      * @param password the password to use when authenticating with Tomcat manager
 158  
      * @param charset  the URL encoding charset to use when communicating with Tomcat manager
 159  
      */
 160  
     public TomcatManager( URL url, String username, String password, String charset )
 161  3
     {
 162  3
         this.url = url;
 163  3
         this.username = username;
 164  3
         this.password = password;
 165  3
         this.charset = charset;
 166  
 
 167  3
         PoolingClientConnectionManager poolingClientConnectionManager = new PoolingClientConnectionManager();
 168  3
         poolingClientConnectionManager.setMaxTotal( 5 );
 169  3
         this.httpClient = new DefaultHttpClient( poolingClientConnectionManager );
 170  3
         if ( StringUtils.isNotEmpty( username ) )
 171  
         {
 172  3
             Credentials creds = new UsernamePasswordCredentials( username, password );
 173  
 
 174  3
             String host = url.getHost();
 175  3
             int port = url.getPort() > -1 ? url.getPort() : AuthScope.ANY_PORT;
 176  
 
 177  3
             httpClient.getCredentialsProvider().setCredentials( new AuthScope( host, port ), creds );
 178  
 
 179  3
             AuthCache authCache = new BasicAuthCache();
 180  3
             BasicScheme basicAuth = new BasicScheme();
 181  3
             HttpHost targetHost = new HttpHost( url.getHost(), url.getPort(), url.getProtocol() );
 182  3
             authCache.put( targetHost, basicAuth );
 183  
 
 184  3
             localContext = new BasicHttpContext();
 185  3
             localContext.setAttribute( ClientContext.AUTH_CACHE, authCache );
 186  
         }
 187  3
     }
 188  
 
 189  
     // ----------------------------------------------------------------------
 190  
     // Public Methods
 191  
     // ----------------------------------------------------------------------
 192  
 
 193  
     /**
 194  
      * Gets the full URL of the Tomcat manager instance.
 195  
      *
 196  
      * @return the full URL of the Tomcat manager instance
 197  
      */
 198  
     public URL getURL()
 199  
     {
 200  0
         return url;
 201  
     }
 202  
 
 203  
     /**
 204  
      * Gets the username to use when authenticating with Tomcat manager.
 205  
      *
 206  
      * @return the username to use when authenticating with Tomcat manager
 207  
      */
 208  
     public String getUserName()
 209  
     {
 210  0
         return username;
 211  
     }
 212  
 
 213  
     /**
 214  
      * Gets the password to use when authenticating with Tomcat manager.
 215  
      *
 216  
      * @return the password to use when authenticating with Tomcat manager
 217  
      */
 218  
     public String getPassword()
 219  
     {
 220  0
         return password;
 221  
     }
 222  
 
 223  
     /**
 224  
      * Gets the URL encoding charset to use when communicating with Tomcat manager.
 225  
      *
 226  
      * @return the URL encoding charset to use when communicating with Tomcat manager
 227  
      */
 228  
     public String getCharset()
 229  
     {
 230  0
         return charset;
 231  
     }
 232  
 
 233  
     /**
 234  
      * Gets the user agent name to use when communicating with Tomcat manager.
 235  
      *
 236  
      * @return the user agent name to use when communicating with Tomcat manager
 237  
      */
 238  
     public String getUserAgent()
 239  
     {
 240  0
         return userAgent;
 241  
     }
 242  
 
 243  
     /**
 244  
      * Sets the user agent name to use when communicating with Tomcat manager.
 245  
      *
 246  
      * @param userAgent the user agent name to use when communicating with Tomcat manager
 247  
      */
 248  
     public void setUserAgent( String userAgent )
 249  
     {
 250  0
         this.userAgent = userAgent;
 251  0
     }
 252  
 
 253  
     /**
 254  
      * Deploys the specified WAR as a URL to the specified context path.
 255  
      *
 256  
      * @param path the webapp context path to deploy to
 257  
      * @param war  the URL of the WAR to deploy
 258  
      * @return the Tomcat manager response
 259  
      * @throws TomcatManagerException if the Tomcat manager request fails
 260  
      * @throws IOException            if an i/o error occurs
 261  
      */
 262  
     public TomcatManagerResponse deploy( String path, URL war )
 263  
         throws TomcatManagerException, IOException
 264  
     {
 265  0
         return deploy( path, war, false );
 266  
     }
 267  
 
 268  
     /**
 269  
      * Deploys the specified WAR as a URL to the specified context path, optionally undeploying the webapp if it already
 270  
      * exists.
 271  
      *
 272  
      * @param path   the webapp context path to deploy to
 273  
      * @param war    the URL of the WAR to deploy
 274  
      * @param update whether to first undeploy the webapp if it already exists
 275  
      * @return the Tomcat manager response
 276  
      * @throws TomcatManagerException if the Tomcat manager request fails
 277  
      * @throws IOException            if an i/o error occurs
 278  
      */
 279  
     public TomcatManagerResponse deploy( String path, URL war, boolean update )
 280  
         throws TomcatManagerException, IOException
 281  
     {
 282  0
         return deploy( path, war, update, null );
 283  
     }
 284  
 
 285  
     /**
 286  
      * Deploys the specified WAR as a URL to the specified context path, optionally undeploying the webapp if it already
 287  
      * exists and using the specified tag name.
 288  
      *
 289  
      * @param path   the webapp context path to deploy to
 290  
      * @param war    the URL of the WAR to deploy
 291  
      * @param update whether to first undeploy the webapp if it already exists
 292  
      * @param tag    the tag name to use
 293  
      * @return the Tomcat manager response
 294  
      * @throws TomcatManagerException if the Tomcat manager request fails
 295  
      * @throws IOException            if an i/o error occurs
 296  
      */
 297  
     public TomcatManagerResponse deploy( String path, URL war, boolean update, String tag )
 298  
         throws TomcatManagerException, IOException
 299  
     {
 300  0
         return deployImpl( path, null, war, null, update, tag );
 301  
     }
 302  
 
 303  
     /**
 304  
      * Deploys the specified WAR as a HTTP PUT to the specified context path.
 305  
      *
 306  
      * @param path the webapp context path to deploy to
 307  
      * @param war  an input stream to the WAR to deploy
 308  
      * @return the Tomcat manager response
 309  
      * @throws TomcatManagerException if the Tomcat manager request fails
 310  
      * @throws IOException            if an i/o error occurs
 311  
      */
 312  
     public TomcatManagerResponse deploy( String path, File war )
 313  
         throws TomcatManagerException, IOException
 314  
     {
 315  3
         return deploy( path, war, false );
 316  
     }
 317  
 
 318  
     /**
 319  
      * Deploys the specified WAR as a HTTP PUT to the specified context path, optionally undeploying the webapp if it
 320  
      * already exists.
 321  
      *
 322  
      * @param path   the webapp context path to deploy to
 323  
      * @param war    an input stream to the WAR to deploy
 324  
      * @param update whether to first undeploy the webapp if it already exists
 325  
      * @return the Tomcat manager response
 326  
      * @throws TomcatManagerException if the Tomcat manager request fails
 327  
      * @throws IOException            if an i/o error occurs
 328  
      */
 329  
     public TomcatManagerResponse deploy( String path, File war, boolean update )
 330  
         throws TomcatManagerException, IOException
 331  
     {
 332  3
         return deploy( path, war, update, null );
 333  
     }
 334  
 
 335  
     /**
 336  
      * Deploys the specified WAR as a HTTP PUT to the specified context path, optionally undeploying the webapp if it
 337  
      * already exists and using the specified tag name.
 338  
      *
 339  
      * @param path   the webapp context path to deploy to
 340  
      * @param war    an input stream to the WAR to deploy
 341  
      * @param update whether to first undeploy the webapp if it already exists
 342  
      * @param tag    the tag name to use
 343  
      * @return the Tomcat manager response
 344  
      * @throws TomcatManagerException if the Tomcat manager request fails
 345  
      * @throws IOException            if an i/o error occurs
 346  
      */
 347  
     public TomcatManagerResponse deploy( String path, File war, boolean update, String tag )
 348  
         throws TomcatManagerException, IOException
 349  
     {
 350  3
         return deployImpl( path, null, null, war, update, tag );
 351  
     }
 352  
 
 353  
     /**
 354  
      * @param path
 355  
      * @param war
 356  
      * @param update
 357  
      * @param tag
 358  
      * @param length
 359  
      * @return
 360  
      * @throws TomcatManagerException
 361  
      * @throws IOException
 362  
      * @since 2.0
 363  
      */
 364  
     public TomcatManagerResponse deploy( String path, File war, boolean update, String tag, long length )
 365  
         throws TomcatManagerException, IOException
 366  
     {
 367  0
         return deployImpl( path, null, null, war, update, tag, length );
 368  
     }
 369  
 
 370  
     /**
 371  
      * Deploys the specified context XML configuration to the specified context path.
 372  
      *
 373  
      * @param path   the webapp context path to deploy to
 374  
      * @param config the URL of the context XML configuration to deploy
 375  
      * @return the Tomcat manager response
 376  
      * @throws TomcatManagerException if the Tomcat manager request fails
 377  
      * @throws IOException            if an i/o error occurs
 378  
      */
 379  
     public TomcatManagerResponse deployContext( String path, URL config )
 380  
         throws TomcatManagerException, IOException
 381  
     {
 382  0
         return deployContext( path, config, false );
 383  
     }
 384  
 
 385  
     /**
 386  
      * Deploys the specified context XML configuration to the specified context path, optionally undeploying the webapp
 387  
      * if it already exists.
 388  
      *
 389  
      * @param path   the webapp context path to deploy to
 390  
      * @param config the URL of the context XML configuration to deploy
 391  
      * @param update whether to first undeploy the webapp if it already exists
 392  
      * @return the Tomcat manager response
 393  
      * @throws TomcatManagerException if the Tomcat manager request fails
 394  
      * @throws IOException            if an i/o error occurs
 395  
      */
 396  
     public TomcatManagerResponse deployContext( String path, URL config, boolean update )
 397  
         throws TomcatManagerException, IOException
 398  
     {
 399  0
         return deployContext( path, config, update, null );
 400  
     }
 401  
 
 402  
     /**
 403  
      * Deploys the specified context XML configuration to the specified context path, optionally undeploying the webapp
 404  
      * if it already exists and using the specified tag name.
 405  
      *
 406  
      * @param path   the webapp context path to deploy to
 407  
      * @param config the URL of the context XML configuration to deploy
 408  
      * @param update whether to first undeploy the webapp if it already exists
 409  
      * @param tag    the tag name to use
 410  
      * @return the Tomcat manager response
 411  
      * @throws TomcatManagerException if the Tomcat manager request fails
 412  
      * @throws IOException            if an i/o error occurs
 413  
      */
 414  
     public TomcatManagerResponse deployContext( String path, URL config, boolean update, String tag )
 415  
         throws TomcatManagerException, IOException
 416  
     {
 417  0
         return deployContext( path, config, null, update, tag );
 418  
     }
 419  
 
 420  
     /**
 421  
      * Deploys the specified context XML configuration and WAR as a URL to the specified context path.
 422  
      *
 423  
      * @param path   the webapp context path to deploy to
 424  
      * @param config the URL of the context XML configuration to deploy
 425  
      * @param war    the URL of the WAR to deploy
 426  
      * @return the Tomcat manager response
 427  
      * @throws TomcatManagerException if the Tomcat manager request fails
 428  
      * @throws IOException            if an i/o error occurs
 429  
      */
 430  
     public TomcatManagerResponse deployContext( String path, URL config, URL war )
 431  
         throws TomcatManagerException, IOException
 432  
     {
 433  0
         return deployContext( path, config, war, false );
 434  
     }
 435  
 
 436  
     /**
 437  
      * Deploys the specified context XML configuration and WAR as a URL to the specified context path, optionally
 438  
      * undeploying the webapp if it already exists.
 439  
      *
 440  
      * @param path   the webapp context path to deploy to
 441  
      * @param config the URL of the context XML configuration to deploy
 442  
      * @param war    the URL of the WAR to deploy
 443  
      * @param update whether to first undeploy the webapp if it already exists
 444  
      * @return the Tomcat manager response
 445  
      * @throws TomcatManagerException if the Tomcat manager request fails
 446  
      * @throws IOException            if an i/o error occurs
 447  
      */
 448  
     public TomcatManagerResponse deployContext( String path, URL config, URL war, boolean update )
 449  
         throws TomcatManagerException, IOException
 450  
     {
 451  0
         return deployContext( path, config, war, update, null );
 452  
     }
 453  
 
 454  
     /**
 455  
      * Deploys the specified context XML configuration and WAR as a URL to the specified context path, optionally
 456  
      * undeploying the webapp if it already exists and using the specified tag name.
 457  
      *
 458  
      * @param path   the webapp context path to deploy to
 459  
      * @param config the URL of the context XML configuration to deploy
 460  
      * @param war    the URL of the WAR to deploy
 461  
      * @param update whether to first undeploy the webapp if it already exists
 462  
      * @param tag    the tag name to use
 463  
      * @return the Tomcat manager response
 464  
      * @throws TomcatManagerException if the Tomcat manager request fails
 465  
      * @throws IOException            if an i/o error occurs
 466  
      */
 467  
     public TomcatManagerResponse deployContext( String path, URL config, URL war, boolean update, String tag )
 468  
         throws TomcatManagerException, IOException
 469  
     {
 470  0
         return deployImpl( path, config, war, null, update, tag );
 471  
     }
 472  
 
 473  
     /**
 474  
      * Undeploys the webapp at the specified context path.
 475  
      *
 476  
      * @param path the webapp context path to undeploy
 477  
      * @return the Tomcat manager response
 478  
      * @throws TomcatManagerException if the Tomcat manager request fails
 479  
      * @throws IOException            if an i/o error occurs
 480  
      */
 481  
     public TomcatManagerResponse undeploy( String path )
 482  
         throws TomcatManagerException, IOException
 483  
     {
 484  0
         return invoke( "/undeploy?path=" + URLEncoder.encode( path, charset ) );
 485  
     }
 486  
 
 487  
     /**
 488  
      * Reloads the webapp at the specified context path.
 489  
      *
 490  
      * @param path the webapp context path to reload
 491  
      * @return the Tomcat manager response
 492  
      * @throws TomcatManagerException if the Tomcat manager request fails
 493  
      * @throws IOException            if an i/o error occurs
 494  
      */
 495  
     public TomcatManagerResponse reload( String path )
 496  
         throws TomcatManagerException, IOException
 497  
     {
 498  0
         return invoke( "/reload?path=" + URLEncoder.encode( path, charset ) );
 499  
     }
 500  
 
 501  
     /**
 502  
      * Starts the webapp at the specified context path.
 503  
      *
 504  
      * @param path the webapp context path to start
 505  
      * @return the Tomcat manager response
 506  
      * @throws TomcatManagerException if the Tomcat manager request fails
 507  
      * @throws IOException            if an i/o error occurs
 508  
      */
 509  
     public TomcatManagerResponse start( String path )
 510  
         throws TomcatManagerException, IOException
 511  
     {
 512  0
         return invoke( "/start?path=" + URLEncoder.encode( path, charset ) );
 513  
     }
 514  
 
 515  
     /**
 516  
      * Stops the webapp at the specified context path.
 517  
      *
 518  
      * @param path the webapp context path to stop
 519  
      * @return the Tomcat manager response
 520  
      * @throws TomcatManagerException if the Tomcat manager request fails
 521  
      * @throws IOException            if an i/o error occurs
 522  
      */
 523  
     public TomcatManagerResponse stop( String path )
 524  
         throws TomcatManagerException, IOException
 525  
     {
 526  0
         return invoke( "/stop?path=" + URLEncoder.encode( path, charset ) );
 527  
     }
 528  
 
 529  
     /**
 530  
      * Lists all the currently deployed web applications.
 531  
      *
 532  
      * @return the list of currently deployed applications
 533  
      * @throws TomcatManagerException if the Tomcat manager request fails
 534  
      * @throws IOException            if an i/o error occurs
 535  
      */
 536  
     public TomcatManagerResponse list()
 537  
         throws TomcatManagerException, IOException
 538  
     {
 539  0
         return invoke( "/list" );
 540  
     }
 541  
 
 542  
     /**
 543  
      * Lists information about the Tomcat version, OS, and JVM properties.
 544  
      *
 545  
      * @return the server information
 546  
      * @throws TomcatManagerException if the Tomcat manager request fails
 547  
      * @throws IOException            if an i/o error occurs
 548  
      */
 549  
     public TomcatManagerResponse getServerInfo()
 550  
         throws TomcatManagerException, IOException
 551  
     {
 552  0
         return invoke( "/serverinfo" );
 553  
     }
 554  
 
 555  
     /**
 556  
      * Lists all of the global JNDI resources.
 557  
      *
 558  
      * @return the list of all global JNDI resources
 559  
      * @throws TomcatManagerException if the Tomcat manager request fails
 560  
      * @throws IOException            if an i/o error occurs
 561  
      */
 562  
     public TomcatManagerResponse getResources()
 563  
         throws TomcatManagerException, IOException
 564  
     {
 565  0
         return getResources( null );
 566  
     }
 567  
 
 568  
     /**
 569  
      * Lists the global JNDI resources of the given type.
 570  
      *
 571  
      * @param type the class name of the resources to list, or <code>null</code> for all
 572  
      * @return the list of global JNDI resources of the given type
 573  
      * @throws TomcatManagerException if the Tomcat manager request fails
 574  
      * @throws IOException            if an i/o error occurs
 575  
      */
 576  
     public TomcatManagerResponse getResources( String type )
 577  
         throws TomcatManagerException, IOException
 578  
     {
 579  0
         StringBuffer buffer = new StringBuffer();
 580  0
         buffer.append( "/resources" );
 581  
 
 582  0
         if ( type != null )
 583  
         {
 584  0
             buffer.append( "?type=" + URLEncoder.encode( type, charset ) );
 585  
         }
 586  0
         return invoke( buffer.toString() );
 587  
     }
 588  
 
 589  
     /**
 590  
      * Lists the security role names and corresponding descriptions that are available.
 591  
      *
 592  
      * @return the list of security role names and corresponding descriptions
 593  
      * @throws TomcatManagerException if the Tomcat manager request fails
 594  
      * @throws IOException            if an i/o error occurs
 595  
      */
 596  
     public TomcatManagerResponse getRoles()
 597  
         throws TomcatManagerException, IOException
 598  
     {
 599  0
         return invoke( "/roles" );
 600  
     }
 601  
 
 602  
     /**
 603  
      * Lists the default session timeout and the number of currently active sessions for the given context path.
 604  
      *
 605  
      * @param path the context path to list session information for
 606  
      * @return the default session timeout and the number of currently active sessions
 607  
      * @throws TomcatManagerException if the Tomcat manager request fails
 608  
      * @throws IOException            if an i/o error occurs
 609  
      */
 610  
     public TomcatManagerResponse getSessions( String path )
 611  
         throws TomcatManagerException, IOException
 612  
     {
 613  0
         return invoke( "/sessions?path=" + URLEncoder.encode( path, charset ) );
 614  
     }
 615  
 
 616  
     // ----------------------------------------------------------------------
 617  
     // Protected Methods
 618  
     // ----------------------------------------------------------------------
 619  
 
 620  
     /**
 621  
      * Invokes Tomcat manager with the specified command.
 622  
      *
 623  
      * @param path the Tomcat manager command to invoke
 624  
      * @return the Tomcat manager response
 625  
      * @throws TomcatManagerException if the Tomcat manager request fails
 626  
      * @throws IOException            if an i/o error occurs
 627  
      */
 628  
     protected TomcatManagerResponse invoke( String path )
 629  
         throws TomcatManagerException, IOException
 630  
     {
 631  0
         return invoke( path, null, -1 );
 632  
     }
 633  
 
 634  
     // ----------------------------------------------------------------------
 635  
     // Private Methods
 636  
     // ----------------------------------------------------------------------
 637  
 
 638  
     private TomcatManagerResponse deployImpl( String path, URL config, URL war, File data, boolean update, String tag )
 639  
         throws TomcatManagerException, IOException
 640  
     {
 641  3
         return deployImpl( path, config, war, data, update, tag, -1 );
 642  
     }
 643  
 
 644  
     /**
 645  
      * Deploys the specified WAR.
 646  
      *
 647  
      * @param path   the webapp context path to deploy to
 648  
      * @param config the URL of the context XML configuration to deploy, or null for none
 649  
      * @param war    the URL of the WAR to deploy, or null to use <code>data</code>
 650  
      * @param data   WAR file to deploy, or null to use <code>war</code>
 651  
      * @param update whether to first undeploy the webapp if it already exists
 652  
      * @param tag    the tag name to use
 653  
      * @return the Tomcat manager response
 654  
      * @throws TomcatManagerException if the Tomcat manager request fails
 655  
      * @throws IOException            if an i/o error occurs
 656  
      */
 657  
     private TomcatManagerResponse deployImpl( String path, URL config, URL war, File data, boolean update, String tag,
 658  
                                               long length )
 659  
         throws TomcatManagerException, IOException
 660  
     {
 661  3
         StringBuilder buffer = new StringBuilder( "/deploy" );
 662  3
         buffer.append( "?path=" ).append( URLEncoder.encode( path, charset ) );
 663  
 
 664  3
         if ( config != null )
 665  
         {
 666  0
             buffer.append( "&config=" ).append( URLEncoder.encode( config.toString(), charset ) );
 667  
         }
 668  
 
 669  3
         if ( war != null )
 670  
         {
 671  0
             buffer.append( "&war=" ).append( URLEncoder.encode( war.toString(), charset ) );
 672  
         }
 673  
 
 674  3
         if ( update )
 675  
         {
 676  0
             buffer.append( "&update=true" );
 677  
         }
 678  
 
 679  3
         if ( tag != null )
 680  
         {
 681  0
             buffer.append( "&tag=" ).append( URLEncoder.encode( tag, charset ) );
 682  
         }
 683  
 
 684  3
         return invoke( buffer.toString(), data, length );
 685  
     }
 686  
 
 687  
 
 688  
     /**
 689  
      * Invokes Tomcat manager with the specified command and content data.
 690  
      *
 691  
      * @param path the Tomcat manager command to invoke
 692  
      * @param data file to deploy
 693  
      * @return the Tomcat manager response
 694  
      * @throws TomcatManagerException if the Tomcat manager request fails
 695  
      * @throws IOException            if an i/o error occurs
 696  
      */
 697  
     protected TomcatManagerResponse invoke( String path, File data, long length )
 698  
         throws TomcatManagerException, IOException
 699  
     {
 700  
 
 701  5
         HttpRequestBase httpRequestBase = null;
 702  5
         if ( data == null )
 703  
         {
 704  0
             httpRequestBase = new HttpGet( url + path );
 705  
         }
 706  
         else
 707  
         {
 708  5
             HttpPut httpPut = new HttpPut( url + path );
 709  
 
 710  5
             httpPut.setEntity( new RequestEntityImplementation( data, length, url + path ) );
 711  
 
 712  5
             httpRequestBase = httpPut;
 713  
 
 714  
         }
 715  
 
 716  5
         if ( userAgent != null )
 717  
         {
 718  0
             httpRequestBase.setHeader( "User-Agent", userAgent );
 719  
         }
 720  
 
 721  5
         HttpResponse response = httpClient.execute( httpRequestBase, localContext );
 722  
 
 723  5
         int statusCode = response.getStatusLine().getStatusCode();
 724  
 
 725  5
         switch ( statusCode )
 726  
         {
 727  
             // Success Codes
 728  
             case HttpStatus.SC_OK: // 200
 729  
             case HttpStatus.SC_CREATED: // 201
 730  
             case HttpStatus.SC_ACCEPTED: // 202
 731  3
                 break;
 732  
             // 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"
 733  
             case HttpStatus.SC_MOVED_PERMANENTLY: // 301
 734  
             case HttpStatus.SC_MOVED_TEMPORARILY: // 302
 735  
             case HttpStatus.SC_SEE_OTHER: // 303
 736  2
                 String relocateUrl = calculateRelocatedUrl( response );
 737  2
                 this.url = new URL( relocateUrl );
 738  2
                 return invoke( path, data, length );
 739  
         }
 740  
 
 741  3
         return new TomcatManagerResponse().setStatusCode( response.getStatusLine().getStatusCode() ).setReasonPhrase(
 742  
             response.getStatusLine().getReasonPhrase() ).setHttpResponseBody(
 743  
             IOUtils.toString( response.getEntity().getContent() ) );
 744  
 
 745  
     }
 746  
 
 747  
     protected String calculateRelocatedUrl( HttpResponse response )
 748  
     {
 749  2
         Header locationHeader = response.getFirstHeader( "Location" );
 750  2
         String locationField = locationHeader.getValue();
 751  
         // is it a relative Location or a full ?
 752  2
         return locationField.startsWith( "http" ) ? locationField : url.toString() + '/' + locationField;
 753  
     }
 754  
 
 755  
 
 756  
     /**
 757  
      * Gets the HTTP Basic Authorization header value for the supplied username and password.
 758  
      *
 759  
      * @param username the username to use for authentication
 760  
      * @param password the password to use for authentication
 761  
      * @return the HTTP Basic Authorization header value
 762  
      */
 763  
     private String toAuthorization( String username, String password )
 764  
     {
 765  0
         StringBuffer buffer = new StringBuffer();
 766  0
         buffer.append( username ).append( ':' );
 767  0
         if ( password != null )
 768  
         {
 769  0
             buffer.append( password );
 770  
         }
 771  0
         return "Basic " + new String( Base64.encodeBase64( buffer.toString().getBytes() ) );
 772  
     }
 773  
 
 774  5
     private final class RequestEntityImplementation
 775  
         extends AbstractHttpEntity
 776  
     {
 777  
 
 778  
         private final static int BUFFER_SIZE = 2048;
 779  
 
 780  
         private File file;
 781  
 
 782  5
         PrintStream out = System.out;
 783  
 
 784  5
         private long length = -1;
 785  
 
 786  
         private int lastLength;
 787  
 
 788  
         private String url;
 789  
 
 790  
         private long startTime;
 791  
 
 792  
         private RequestEntityImplementation( final File file, long length, String url )
 793  5
         {
 794  5
             this.file = file;
 795  5
             this.length = length;
 796  5
             this.url = url;
 797  5
         }
 798  
 
 799  
         public long getContentLength()
 800  
         {
 801  15
             return length >= 0 ? length : ( file.length() >= 0 ? file.length() : -1 );
 802  
         }
 803  
 
 804  
 
 805  
         public InputStream getContent()
 806  
             throws IOException, IllegalStateException
 807  
         {
 808  0
             return new FileInputStream( this.file );
 809  
         }
 810  
 
 811  
         public boolean isRepeatable()
 812  
         {
 813  5
             return true;
 814  
         }
 815  
 
 816  
 
 817  
         public void writeTo( final OutputStream outstream )
 818  
             throws IOException
 819  
         {
 820  5
             long completed = 0;
 821  5
             if ( outstream == null )
 822  
             {
 823  0
                 throw new IllegalArgumentException( "Output stream may not be null" );
 824  
             }
 825  5
             FileInputStream stream = new FileInputStream( this.file );
 826  5
             transferInitiated( this.url );
 827  5
             this.startTime = System.currentTimeMillis();
 828  
             try
 829  
             {
 830  5
                 byte[] buffer = new byte[BUFFER_SIZE];
 831  
 
 832  
                 int l;
 833  5
                 if ( this.length < 0 )
 834  
                 {
 835  
                     // until EOF
 836  10
                     while ( ( l = stream.read( buffer ) ) != -1 )
 837  
                     {
 838  5
                         transferProgressed( completed += buffer.length, -1 );
 839  5
                         outstream.write( buffer, 0, l );
 840  
                     }
 841  
                 }
 842  
                 else
 843  
                 {
 844  
                     // no need to consume more than length
 845  0
                     long remaining = this.length;
 846  0
                     while ( remaining > 0 )
 847  
                     {
 848  0
                         int transferSize = (int) Math.min( BUFFER_SIZE, remaining );
 849  0
                         completed += transferSize;
 850  0
                         l = stream.read( buffer, 0, transferSize );
 851  0
                         if ( l == -1 )
 852  
                         {
 853  0
                             break;
 854  
                         }
 855  
 
 856  0
                         outstream.write( buffer, 0, l );
 857  0
                         remaining -= l;
 858  0
                         transferProgressed( completed, this.length );
 859  0
                     }
 860  
                 }
 861  5
                 transferSucceeded( completed );
 862  
             }
 863  
             finally
 864  
             {
 865  5
                 stream.close();
 866  5
                 out.println();
 867  5
             }
 868  
             // end transfer
 869  5
         }
 870  
 
 871  
         public boolean isStreaming()
 872  
         {
 873  0
             return true;
 874  
         }
 875  
 
 876  
 
 877  
         public void transferInitiated( String url )
 878  
         {
 879  5
             String message = "Uploading";
 880  
 
 881  5
             out.println( message + ": " + url );
 882  5
         }
 883  
 
 884  
         public void transferProgressed( long completedSize, long totalSize )
 885  
         {
 886  
 
 887  5
             StringBuilder buffer = new StringBuilder( 64 );
 888  
 
 889  5
             buffer.append( getStatus( completedSize, totalSize ) ).append( "  " );
 890  5
             lastLength = buffer.length();
 891  5
             buffer.append( '\r' );
 892  
 
 893  5
             out.print( buffer );
 894  5
         }
 895  
 
 896  
         public void transferSucceeded( long contentLength )
 897  
         {
 898  
 
 899  5
             if ( contentLength >= 0 )
 900  
             {
 901  5
                 String type = "Uploaded";
 902  5
                 String len = contentLength >= 1024 ? toKB( contentLength ) + " KB" : contentLength + " B";
 903  
 
 904  5
                 String throughput = "";
 905  5
                 long duration = System.currentTimeMillis() - startTime;
 906  5
                 if ( duration > 0 )
 907  
                 {
 908  2
                     DecimalFormat format = new DecimalFormat( "0.0", new DecimalFormatSymbols( Locale.ENGLISH ) );
 909  2
                     double kbPerSec = ( contentLength / 1024.0 ) / ( duration / 1000.0 );
 910  2
                     throughput = " at " + format.format( kbPerSec ) + " KB/sec";
 911  
                 }
 912  
 
 913  5
                 out.println( type + ": " + url + " (" + len + throughput + ")" );
 914  
             }
 915  5
         }
 916  
 
 917  
         private String getStatus( long complete, long total )
 918  
         {
 919  5
             if ( total >= 1024 )
 920  
             {
 921  0
                 return toKB( complete ) + "/" + toKB( total ) + " KB ";
 922  
             }
 923  5
             else if ( total >= 0 )
 924  
             {
 925  0
                 return complete + "/" + total + " B ";
 926  
             }
 927  5
             else if ( complete >= 1024 )
 928  
             {
 929  5
                 return toKB( complete ) + " KB ";
 930  
             }
 931  
             else
 932  
             {
 933  0
                 return complete + " B ";
 934  
             }
 935  
         }
 936  
 
 937  
         private long toKB( long bytes )
 938  
         {
 939  10
             return ( bytes + 1023 ) / 1024;
 940  
         }
 941  
 
 942  
     }
 943  
 }