Coverage Report - org.apache.tomcat.maven.plugin.tomcat6.AbstractRunMojo
 
Classes in this File Line Coverage Branch Coverage Complexity
AbstractRunMojo
0 %
0/265
0 %
0/132
5,619
 
 1  
 package org.apache.tomcat.maven.plugin.tomcat6;
 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  
 
 23  
 import org.apache.catalina.Context;
 24  
 import org.apache.catalina.Engine;
 25  
 import org.apache.catalina.Host;
 26  
 import org.apache.catalina.LifecycleException;
 27  
 import org.apache.catalina.Wrapper;
 28  
 import org.apache.catalina.connector.Connector;
 29  
 import org.apache.catalina.loader.WebappLoader;
 30  
 import org.apache.catalina.realm.MemoryRealm;
 31  
 import org.apache.catalina.servlets.DefaultServlet;
 32  
 import org.apache.catalina.startup.Catalina;
 33  
 import org.apache.catalina.startup.Embedded;
 34  
 import org.apache.maven.artifact.Artifact;
 35  
 import org.apache.maven.artifact.factory.ArtifactFactory;
 36  
 import org.apache.maven.artifact.repository.ArtifactRepository;
 37  
 import org.apache.maven.artifact.resolver.ArtifactNotFoundException;
 38  
 import org.apache.maven.artifact.resolver.ArtifactResolutionException;
 39  
 import org.apache.maven.artifact.resolver.ArtifactResolver;
 40  
 import org.apache.maven.artifact.resolver.filter.ScopeArtifactFilter;
 41  
 import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException;
 42  
 import org.apache.maven.artifact.versioning.VersionRange;
 43  
 import org.apache.maven.plugin.MojoExecutionException;
 44  
 import org.apache.maven.plugin.MojoFailureException;
 45  
 import org.apache.maven.plugins.annotations.Component;
 46  
 import org.apache.maven.plugins.annotations.Parameter;
 47  
 import org.apache.maven.project.MavenProject;
 48  
 import org.apache.tomcat.maven.common.config.AbstractWebapp;
 49  
 import org.apache.tomcat.maven.common.run.EmbeddedRegistry;
 50  
 import org.codehaus.plexus.archiver.ArchiverException;
 51  
 import org.codehaus.plexus.archiver.UnArchiver;
 52  
 import org.codehaus.plexus.archiver.manager.ArchiverManager;
 53  
 import org.codehaus.plexus.archiver.manager.NoSuchArchiverException;
 54  
 import org.codehaus.plexus.classworlds.ClassWorld;
 55  
 import org.codehaus.plexus.classworlds.realm.ClassRealm;
 56  
 import org.codehaus.plexus.classworlds.realm.DuplicateRealmException;
 57  
 import org.codehaus.plexus.util.DirectoryScanner;
 58  
 import org.codehaus.plexus.util.FileUtils;
 59  
 import org.codehaus.plexus.util.StringUtils;
 60  
 import org.w3c.dom.Document;
 61  
 import org.w3c.dom.NamedNodeMap;
 62  
 import org.w3c.dom.Node;
 63  
 import org.xml.sax.SAXException;
 64  
 
 65  
 import javax.xml.parsers.DocumentBuilder;
 66  
 import javax.xml.parsers.DocumentBuilderFactory;
 67  
 import javax.xml.parsers.ParserConfigurationException;
 68  
 import java.io.File;
 69  
 import java.io.FileNotFoundException;
 70  
 import java.io.IOException;
 71  
 import java.net.InetAddress;
 72  
 import java.net.MalformedURLException;
 73  
 import java.net.URL;
 74  
 import java.util.ArrayList;
 75  
 import java.util.Collection;
 76  
 import java.util.Collections;
 77  
 import java.util.List;
 78  
 import java.util.Map;
 79  
 import java.util.Set;
 80  
 
 81  
 /**
 82  
  * Abstract goal that provides common configuration for embedded Tomcat goals.
 83  
  *
 84  
  * @author Jurgen Lust
 85  
  * @author Mark Hobson <markhobson@gmail.com>
 86  
  */
 87  0
 public abstract class AbstractRunMojo
 88  
     extends AbstractI18NTomcat6Mojo
 89  
 {
 90  
     // ---------------------------------------------------------------------
 91  
     // Mojo Components
 92  
     // ---------------------------------------------------------------------
 93  
 
 94  
     /**
 95  
      * Used to look up Artifacts in the remote repository.
 96  
      */
 97  
     @Component( role = ArtifactFactory.class )
 98  
     protected ArtifactFactory artifactFactory;
 99  
 
 100  
     /**
 101  
      * Location of the local repository.
 102  
      */
 103  
     @Parameter( defaultValue = "${localRepository}", required = true, readonly = true )
 104  
     private ArtifactRepository artifactRepository;
 105  
 
 106  
     /**
 107  
      * Used to look up Artifacts in the remote repository.
 108  
      */
 109  
     @Component( role = ArtifactResolver.class )
 110  
     protected ArtifactResolver artifactResolver;
 111  
 
 112  
     // ----------------------------------------------------------------------
 113  
     // Mojo Parameters
 114  
     // ----------------------------------------------------------------------
 115  
 
 116  
     /**
 117  
      * The packaging of the Maven project that this goal operates upon.
 118  
      */
 119  
     @Parameter( defaultValue = "${project.packaging}", required = true, readonly = true )
 120  
     private String packaging;
 121  
 
 122  
     /**
 123  
      * The directory to create the Tomcat server configuration under.
 124  
      */
 125  
     @Parameter( defaultValue = "${project.build.directory}/tomcat" )
 126  
     private File configurationDir;
 127  
 
 128  
     /**
 129  
      * The port to run the Tomcat server on.
 130  
      */
 131  
     @Parameter( property = "maven.tomcat.port", defaultValue = "8080" )
 132  
     private int port;
 133  
 
 134  
     /**
 135  
      * The AJP port to run the Tomcat server on.
 136  
      * By default it's 0 this means won't be started.
 137  
      * The ajp connector will be started only for value > 0.
 138  
      *
 139  
      * @since 2.0
 140  
      */
 141  
     @Parameter( property = "maven.tomcat.ajp.port", defaultValue = "0" )
 142  
     private int ajpPort;
 143  
 
 144  
     /**
 145  
      * The AJP protocol to run the Tomcat server on.
 146  
      * By default it's ajp.
 147  
      * NOTE The ajp connector will be started only if {@link #ajpPort} > 0.
 148  
      *
 149  
      * @since 2.0
 150  
      */
 151  
     @Parameter( property = "maven.tomcat.ajp.protocol", defaultValue = "ajp" )
 152  
     private String ajpProtocol;
 153  
 
 154  
     /**
 155  
      * The https port to run the Tomcat server on.
 156  
      * By default it's 0 this means won't be started.
 157  
      * The https connector will be started only for value > 0.
 158  
      *
 159  
      * @since 1.0
 160  
      */
 161  
     @Parameter( property = "maven.tomcat.httpsPort", defaultValue = "0" )
 162  
     private int httpsPort;
 163  
 
 164  
     /**
 165  
      * The character encoding to use for decoding URIs.
 166  
      *
 167  
      * @since 1.0
 168  
      */
 169  
     @Parameter( property = "maven.tomcat.uriEncoding", defaultValue = "ISO-8859-1" )
 170  
     private String uriEncoding;
 171  
 
 172  
     /**
 173  
      * List of System properties to pass to the Tomcat Server.
 174  
      *
 175  
      * @since 1.0-alpha-2
 176  
      */
 177  
     @Parameter
 178  
     private Map<String, String> systemProperties;
 179  
 
 180  
     /**
 181  
      * The directory contains additional configuration Files that copied in the Tomcat conf Directory.
 182  
      *
 183  
      * @since 1.0-alpha-2
 184  
      */
 185  
     @Parameter( property = "maven.tomcat.additionalConfigFilesDir", defaultValue = "${basedir}/src/main/tomcatconf" )
 186  
     private File additionalConfigFilesDir;
 187  
 
 188  
     /**
 189  
      * server.xml to use <b>Note if you use this you must configure in this file your webapp paths</b>.
 190  
      *
 191  
      * @since 1.0-alpha-2
 192  
      */
 193  
     @Parameter( property = "maven.tomcat.serverXml" )
 194  
     private File serverXml;
 195  
 
 196  
     /**
 197  
      * overriding the providing web.xml to run tomcat
 198  
      *
 199  
      * @since 1.0-alpha-2
 200  
      */
 201  
     @Parameter( property = "maven.tomcat.webXml" )
 202  
     private File tomcatWebXml;
 203  
 
 204  
     /**
 205  
      * Set this to true to allow Maven to continue to execute after invoking
 206  
      * the run goal.
 207  
      *
 208  
      * @since 1.0
 209  
      */
 210  
     @Parameter( property = "maven.tomcat.fork", defaultValue = "false" )
 211  
     private boolean fork;
 212  
 
 213  
     /**
 214  
      * Will create a tomcat context for each dependencies of war type with 'scope' set to 'tomcat'.
 215  
      * In other words, dependencies with:
 216  
      * <pre>
 217  
      *    &lt;type&gt;war&lt;/type&gt;
 218  
      *    &lt;scope&gt;tomcat&lt;/scope&gt;
 219  
      * </pre>
 220  
      * To preserve backward compatibility it's false by default.
 221  
      *
 222  
      * @since 1.0
 223  
      * @deprecated use webapps instead
 224  
      */
 225  
     @Parameter( property = "maven.tomcat.addContextWarDependencies", defaultValue = "false" )
 226  
     private boolean addContextWarDependencies;
 227  
 
 228  
     /**
 229  
      * The maven project.
 230  
      *
 231  
      * @since 1.0
 232  
      */
 233  
     @Component
 234  
     protected MavenProject project;
 235  
 
 236  
     /**
 237  
      * The archive manager.
 238  
      *
 239  
      * @since 1.0
 240  
      */
 241  
     @Component( role = ArchiverManager.class )
 242  
     private ArchiverManager archiverManager;
 243  
 
 244  
     /**
 245  
      * if <code>true</code> a new classLoader separated from maven core will be created to start tomcat.
 246  
      *
 247  
      * @since 1.0
 248  
      */
 249  
     @Parameter( property = "tomcat.useSeparateTomcatClassLoader", defaultValue = "false" )
 250  
     protected boolean useSeparateTomcatClassLoader;
 251  
 
 252  
     /**
 253  
      * @since 1.0
 254  
      */
 255  
     @Parameter( defaultValue = "${plugin.artifacts}", required = true )
 256  
     private List<Artifact> pluginArtifacts;
 257  
 
 258  
     /**
 259  
      * If set to true ignore if packaging of project is not 'war'.
 260  
      *
 261  
      * @since 1.0
 262  
      */
 263  
     @Parameter( property = "tomcat.ignorePackaging", defaultValue = "false" )
 264  
     private boolean ignorePackaging;
 265  
 
 266  
     /**
 267  
      * Override the default keystoreFile for the HTTPS connector (if enabled)
 268  
      *
 269  
      * @since 1.1
 270  
      */
 271  
     @Parameter
 272  
     private String keystoreFile;
 273  
 
 274  
     /**
 275  
      * Override the default keystorePass for the HTTPS connector (if enabled)
 276  
      *
 277  
      * @since 1.1
 278  
      */
 279  
     @Parameter
 280  
     private String keystorePass;
 281  
 
 282  
     /**
 283  
      * Override the type of keystore file to be used for the server certificate. If not specified, the default value is "JKS".
 284  
      *
 285  
      * @since 2.0
 286  
      */
 287  
     @Parameter( defaultValue = "JKS" )
 288  
     private String keystoreType;
 289  
 
 290  
     /**
 291  
      * <p>
 292  
      * Enables or disables naming support for the embedded Tomcat server. By default the embedded Tomcat
 293  
      * in Tomcat 6 comes with naming enabled. In contrast to this the embedded Tomcat 7 comes with
 294  
      * naming disabled by default.
 295  
      * </p>
 296  
      * <p>
 297  
      * <strong>Note:</strong> This setting is ignored if you provide a <code>server.xml</code> for your
 298  
      * Tomcat. Instead please configure naming in the <code>server.xml</code>.
 299  
      * </p>
 300  
      *
 301  
      * @see <a href="http://tomcat.apache.org/tomcat-6.0-doc/api/org/apache/catalina/startup/Embedded.html">org.apache.catalina.startup.Embedded</a>
 302  
      * @since 2.0
 303  
      */
 304  
     @Parameter( property = "maven.tomcat.useNaming", defaultValue = "true" )
 305  
     private boolean useNaming;
 306  
 
 307  
     /**
 308  
      * Force context scanning if you don't use a context file with reloadable = "true".
 309  
      * The other way to use contextReloadable is to add attribute reloadable = "true"
 310  
      * in your context file.
 311  
      *
 312  
      * @since 2.0
 313  
      */
 314  
     @Parameter( property = "maven.tomcat.contextReloadable", defaultValue = "false" )
 315  
     protected boolean contextReloadable;
 316  
 
 317  
 
 318  
     /**
 319  
      * The path of the Tomcat context XML file.
 320  
      */
 321  
     @Parameter( defaultValue = "src/main/webapp/META-INF/context.xml" )
 322  
     protected File contextFile;
 323  
 
 324  
     /**
 325  
      * The protocol to run the Tomcat server on.
 326  
      * By default it's HTTP/1.1.
 327  
      *
 328  
      * @since 2.0
 329  
      */
 330  
     @Parameter( property = "maven.tomcat.protocol", defaultValue = "HTTP/1.1" )
 331  
     private String protocol;
 332  
 
 333  
     /**
 334  
      * The path of the Tomcat users XML file.
 335  
      */
 336  
     @Parameter( property = "maven.tomcat.tomcatUsers.file" )
 337  
     private File tomcatUsers;
 338  
 
 339  
     /**
 340  
      * to install a manager in your embeded tomcat
 341  
      *
 342  
      * @since 2.0
 343  
      */
 344  
     @Parameter
 345  
     private File managerWarPath;
 346  
 
 347  
 
 348  
     /**
 349  
      * Skip execution
 350  
      *
 351  
      * @since 2.0
 352  
      */
 353  
     @Parameter( property = "maven.tomcat.skip", defaultValue = "false" )
 354  
     protected boolean skip;
 355  
 
 356  
     /**
 357  
      * @see {@link Webapp}
 358  
      * @since 2.0
 359  
      */
 360  
     @Parameter
 361  
     private List<Webapp> webapps;
 362  
 
 363  
     // ----------------------------------------------------------------------
 364  
     // Fields
 365  
     // ----------------------------------------------------------------------
 366  
 
 367  
     /**
 368  
      * @since 1.0
 369  
      */
 370  
     private ClassRealm tomcatRealm;
 371  
 
 372  
     /**
 373  
      * The static context
 374  
      *
 375  
      * @since 2.0
 376  
      */
 377  
     @Parameter( property = "maven.tomcat.staticContextPath", defaultValue = "/" )
 378  
     private String staticContextPath;
 379  
 
 380  
     /**
 381  
      * The static context docroot base fully qualified path.
 382  
      * if <code>null</code> static context won't be added
 383  
      *
 384  
      * @since 2.0
 385  
      */
 386  
     @Parameter( property = "maven.tomcat.staticContextDocbase" )
 387  
     private String staticContextDocbase;
 388  
 
 389  
     /**
 390  
      * Class loader class to set.
 391  
      *
 392  
      * @since 2.0
 393  
      */
 394  
     @Parameter
 395  
     protected String classLoaderClass;
 396  
 
 397  
     // ----------------------------------------------------------------------
 398  
     // Mojo Implementation
 399  
     // ----------------------------------------------------------------------
 400  
 
 401  
     /**
 402  
      * {@inheritDoc}
 403  
      */
 404  
     public void execute()
 405  
         throws MojoExecutionException, MojoFailureException
 406  
     {
 407  0
         if ( skip )
 408  
         {
 409  0
             getLog().info( "skip execution" );
 410  0
             return;
 411  
         }
 412  
         // ensure project is a web application and we have at least additionnal webapps to run
 413  0
         if ( !isWar() && !addContextWarDependencies && getAdditionalWebapps().isEmpty() )
 414  
         {
 415  0
             getLog().info( messagesProvider.getMessage( "AbstractRunMojo.nonWar" ) );
 416  0
             return;
 417  
         }
 418  0
         ClassLoader originalClassLoader = null;
 419  
         try
 420  
         {
 421  
 
 422  0
             if ( useSeparateTomcatClassLoader )
 423  
             {
 424  0
                 originalClassLoader = Thread.currentThread().getContextClassLoader();
 425  
             }
 426  0
             getLog().info( messagesProvider.getMessage( "AbstractRunMojo.runningWar", getWebappUrl() ) );
 427  
 
 428  0
             initConfiguration();
 429  0
             startContainer();
 430  0
             if ( !fork )
 431  
             {
 432  0
                 waitIndefinitely();
 433  
             }
 434  
         }
 435  0
         catch ( LifecycleException exception )
 436  
         {
 437  0
             throw new MojoExecutionException( messagesProvider.getMessage( "AbstractRunMojo.cannotStart" ), exception );
 438  
         }
 439  0
         catch ( IOException exception )
 440  
         {
 441  0
             throw new MojoExecutionException(
 442  
                 messagesProvider.getMessage( "AbstractRunMojo.cannotCreateConfiguration" ), exception );
 443  
         }
 444  
         finally
 445  
         {
 446  0
             if ( useSeparateTomcatClassLoader )
 447  
             {
 448  0
                 Thread.currentThread().setContextClassLoader( originalClassLoader );
 449  
             }
 450  
         }
 451  0
     }
 452  
 
 453  
     // ----------------------------------------------------------------------
 454  
     // Protected Methods
 455  
     // ----------------------------------------------------------------------
 456  
 
 457  
     /**
 458  
      * Gets the webapp context path to use for the web application being run.
 459  
      *
 460  
      * @return the webapp context path
 461  
      */
 462  
     protected String getPath()
 463  
     {
 464  0
         return path;
 465  
     }
 466  
 
 467  
     /**
 468  
      * Gets the context to run this web application under for the specified embedded Tomcat.
 469  
      *
 470  
      * @param container the embedded Tomcat container being used
 471  
      * @return the context to run this web application under
 472  
      * @throws IOException            if the context could not be created
 473  
      * @throws MojoExecutionException in case of an error creating the context
 474  
      */
 475  
     protected Context createContext( Embedded container )
 476  
         throws IOException, MojoExecutionException
 477  
     {
 478  0
         String contextPath = getPath();
 479  0
         Context context =
 480  
             container.createContext( "/".equals( contextPath ) ? "" : contextPath, getDocBase().getAbsolutePath() );
 481  
 
 482  0
         if ( useSeparateTomcatClassLoader )
 483  
         {
 484  0
             context.setParentClassLoader( getTomcatClassLoader() );
 485  
         }
 486  
 
 487  0
         final WebappLoader webappLoader = createWebappLoader();
 488  
 
 489  0
         if ( classLoaderClass != null )
 490  
         {
 491  0
             webappLoader.setLoaderClass( classLoaderClass );
 492  
         }
 493  
 
 494  0
         context.setLoader( webappLoader );
 495  0
         File contextFile = getContextFile();
 496  0
         if ( contextFile != null )
 497  
         {
 498  0
             context.setConfigFile( getContextFile().getAbsolutePath() );
 499  
         }
 500  0
         return context;
 501  
     }
 502  
 
 503  
     /**
 504  
      * Gets the webapp loader to run this web application under.
 505  
      *
 506  
      * @return the webapp loader to use
 507  
      * @throws IOException            if the webapp loader could not be created
 508  
      * @throws MojoExecutionException in case of an error creating the webapp loader
 509  
      */
 510  
     protected WebappLoader createWebappLoader()
 511  
         throws IOException, MojoExecutionException
 512  
     {
 513  0
         if ( useSeparateTomcatClassLoader )
 514  
         {
 515  0
             return ( isContextReloadable() )
 516  
                 ? new ExternalRepositoriesReloadableWebappLoader( getTomcatClassLoader(), getLog() )
 517  
                 : new WebappLoader( getTomcatClassLoader() );
 518  
         }
 519  
 
 520  0
         return ( isContextReloadable() )
 521  
             ? new ExternalRepositoriesReloadableWebappLoader( Thread.currentThread().getContextClassLoader(), getLog() )
 522  
             : new WebappLoader( Thread.currentThread().getContextClassLoader() );
 523  
     }
 524  
 
 525  
     /**
 526  
      * Determine whether the passed context.xml file declares the context as reloadable or not.
 527  
      *
 528  
      * @return false by default, true if  reloadable="true" in context.xml.
 529  
      */
 530  
     protected boolean isContextReloadable()
 531  
         throws MojoExecutionException
 532  
     {
 533  0
         if ( contextReloadable )
 534  
         {
 535  0
             return true;
 536  
         }
 537  
         // determine whether to use a reloadable Loader or not (default is false).
 538  0
         boolean reloadable = false;
 539  
         try
 540  
         {
 541  0
             if ( contextFile != null && contextFile.exists() )
 542  
             {
 543  0
                 DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
 544  0
                 DocumentBuilder builder = builderFactory.newDocumentBuilder();
 545  0
                 Document contextDoc = builder.parse( contextFile );
 546  0
                 contextDoc.getDocumentElement().normalize();
 547  
 
 548  0
                 NamedNodeMap nodeMap = contextDoc.getDocumentElement().getAttributes();
 549  0
                 Node reloadableAttribute = nodeMap.getNamedItem( "reloadable" );
 550  
 
 551  0
                 reloadable =
 552  
                     ( reloadableAttribute != null ) ? Boolean.valueOf( reloadableAttribute.getNodeValue() ) : false;
 553  
             }
 554  0
             getLog().debug( "context reloadable: " + reloadable );
 555  
         }
 556  0
         catch ( IOException ioe )
 557  
         {
 558  0
             getLog().error( "Could not parse file: [" + contextFile.getAbsolutePath() + "]", ioe );
 559  
         }
 560  0
         catch ( ParserConfigurationException pce )
 561  
         {
 562  0
             getLog().error( "Could not configure XML parser", pce );
 563  
         }
 564  0
         catch ( SAXException se )
 565  
         {
 566  0
             getLog().error( "Could not parse file: [" + contextFile.getAbsolutePath() + "]", se );
 567  0
         }
 568  
 
 569  0
         return reloadable;
 570  
     }
 571  
 
 572  
 
 573  
     /**
 574  
      * Gets the webapp directory to run.
 575  
      *
 576  
      * @return the webapp directory
 577  
      */
 578  
     protected abstract File getDocBase();
 579  
 
 580  
     /**
 581  
      * Gets the Tomcat context XML file to use.
 582  
      *
 583  
      * @return the context XML file
 584  
      */
 585  
     protected abstract File getContextFile()
 586  
         throws MojoExecutionException;
 587  
 
 588  
     // ----------------------------------------------------------------------
 589  
     // Private Methods
 590  
     // ----------------------------------------------------------------------
 591  
 
 592  
     /**
 593  
      * Gets whether this project uses WAR packaging.
 594  
      *
 595  
      * @return whether this project uses WAR packaging
 596  
      */
 597  
     protected boolean isWar()
 598  
     {
 599  0
         return "war".equals( packaging ) || ignorePackaging;
 600  
     }
 601  
 
 602  
     /**
 603  
      * Gets the URL of the running webapp.
 604  
      *
 605  
      * @return the URL of the running webapp
 606  
      * @throws MalformedURLException if the running webapp URL is invalid
 607  
      */
 608  
     private URL getWebappUrl()
 609  
         throws MalformedURLException
 610  
     {
 611  0
         return new URL( "http", "localhost", port, getPath() );
 612  
     }
 613  
 
 614  
     /**
 615  
      * Creates the Tomcat configuration directory with the necessary resources.
 616  
      *
 617  
      * @throws IOException            if the Tomcat configuration could not be created
 618  
      * @throws MojoExecutionException if the Tomcat configuration could not be created
 619  
      */
 620  
     private void initConfiguration()
 621  
         throws IOException, MojoExecutionException
 622  
     {
 623  0
         if ( configurationDir.exists() )
 624  
         {
 625  0
             getLog().info( messagesProvider.getMessage( "AbstractRunMojo.usingConfiguration", configurationDir ) );
 626  
         }
 627  
         else
 628  
         {
 629  0
             getLog().info( messagesProvider.getMessage( "AbstractRunMojo.creatingConfiguration", configurationDir ) );
 630  
 
 631  0
             configurationDir.mkdirs();
 632  
 
 633  0
             File confDir = new File( configurationDir, "conf" );
 634  0
             confDir.mkdir();
 635  
 
 636  0
             copyFile( "/conf/tomcat-users.xml", new File( confDir, "tomcat-users.xml" ) );
 637  
 
 638  0
             if ( tomcatWebXml != null )
 639  
             {
 640  0
                 if ( !tomcatWebXml.exists() )
 641  
                 {
 642  0
                     throw new MojoExecutionException( " tomcatWebXml " + tomcatWebXml.getPath() + " not exists" );
 643  
                 }
 644  
                 //MTOMCAT-42  here it's a real file resources not a one coming with the mojo 
 645  0
                 FileUtils.copyFile( tomcatWebXml, new File( confDir, "web.xml" ) );
 646  
                 //copyFile( tomcatWebXml.getPath(), new File( confDir, "web.xml" ) );
 647  
             }
 648  
             else
 649  
             {
 650  0
                 copyFile( "/conf/web.xml", new File( confDir, "web.xml" ) );
 651  
             }
 652  
 
 653  0
             File logDir = new File( configurationDir, "logs" );
 654  0
             logDir.mkdir();
 655  
 
 656  0
             File webappsDir = new File( configurationDir, "webapps" );
 657  0
             webappsDir.mkdir();
 658  0
             if ( managerWarPath != null && managerWarPath.exists() )
 659  
             {
 660  0
                 FileUtils.copyFileToDirectory( managerWarPath, webappsDir );
 661  
             }
 662  
 
 663  0
             if ( additionalConfigFilesDir != null && additionalConfigFilesDir.exists() )
 664  
             {
 665  0
                 DirectoryScanner scanner = new DirectoryScanner();
 666  0
                 scanner.addDefaultExcludes();
 667  0
                 scanner.setBasedir( additionalConfigFilesDir.getPath() );
 668  0
                 scanner.scan();
 669  
 
 670  0
                 String[] files = scanner.getIncludedFiles();
 671  
 
 672  0
                 if ( files != null && files.length > 0 )
 673  
                 {
 674  0
                     getLog().info( "Coping additional tomcat config files" );
 675  
 
 676  0
                     for ( int i = 0; i < files.length; i++ )
 677  
                     {
 678  0
                         File file = new File( additionalConfigFilesDir, files[i] );
 679  
 
 680  0
                         getLog().info( " copy " + file.getName() );
 681  
 
 682  0
                         FileUtils.copyFileToDirectory( file, confDir );
 683  
                     }
 684  
                 }
 685  
             }
 686  
         }
 687  0
     }
 688  
 
 689  
     /**
 690  
      * Copies the specified class resource to the specified file.
 691  
      *
 692  
      * @param fromPath the path of the class resource to copy
 693  
      * @param toFile   the file to copy to
 694  
      * @throws IOException if the file could not be copied
 695  
      */
 696  
     private void copyFile( String fromPath, File toFile )
 697  
         throws IOException
 698  
     {
 699  0
         URL fromURL = getClass().getResource( fromPath );
 700  
 
 701  0
         if ( fromURL == null )
 702  
         {
 703  0
             throw new FileNotFoundException( fromPath );
 704  
         }
 705  
 
 706  0
         FileUtils.copyURLToFile( fromURL, toFile );
 707  0
     }
 708  
 
 709  
     /**
 710  
      * Starts the embedded Tomcat server.
 711  
      *
 712  
      * @throws IOException            if the server could not be configured
 713  
      * @throws LifecycleException     if the server could not be started
 714  
      * @throws MojoExecutionException if the server could not be configured
 715  
      */
 716  
     private void startContainer()
 717  
         throws IOException, LifecycleException, MojoExecutionException
 718  
     {
 719  0
         String previousCatalinaBase = System.getProperty( "catalina.base" );
 720  
 
 721  
         try
 722  
         {
 723  
 
 724  
             // Set the system properties
 725  0
             setupSystemProperties();
 726  
 
 727  0
             System.setProperty( "catalina.base", configurationDir.getAbsolutePath() );
 728  0
             System.setProperty( "catalina.home", configurationDir.getAbsolutePath() );
 729  
 
 730  0
             File catalinaPolicy = new File( configurationDir, "conf/catalina.policy" );
 731  
 
 732  0
             if ( catalinaPolicy.exists() )
 733  
             {
 734  
                 // FIXME restore previous value ?
 735  0
                 System.setProperty( "java.security.policy", catalinaPolicy.getAbsolutePath() );
 736  
             }
 737  
 
 738  
             final Embedded container;
 739  0
             if ( serverXml != null )
 740  
             {
 741  0
                 if ( !serverXml.exists() )
 742  
                 {
 743  0
                     throw new MojoExecutionException( serverXml.getPath() + " not exists" );
 744  
                 }
 745  
 
 746  0
                 container = new Catalina();
 747  0
                 container.setCatalinaHome( configurationDir.getAbsolutePath() );
 748  0
                 container.setCatalinaBase( configurationDir.getAbsolutePath() );
 749  0
                 ( (Catalina) container ).setConfigFile( serverXml.getPath() );
 750  0
                 ( (Catalina) container ).setRedirectStreams( true );
 751  0
                 ( (Catalina) container ).setUseNaming( this.useNaming );
 752  
 
 753  0
                 container.start();
 754  
             }
 755  
             else
 756  
             {
 757  
                 // create server
 758  0
                 container = new Embedded();
 759  0
                 container.setCatalinaHome( configurationDir.getAbsolutePath() );
 760  0
                 MemoryRealm memoryRealm = new MemoryRealm();
 761  
 
 762  0
                 if ( tomcatUsers != null )
 763  
                 {
 764  0
                     if ( !tomcatUsers.exists() )
 765  
                     {
 766  0
                         throw new MojoExecutionException( " tomcatUsers " + tomcatUsers.getPath() + " not exists" );
 767  
                     }
 768  0
                     getLog().info( "use tomcat-users.xml from " + tomcatUsers.getAbsolutePath() );
 769  0
                     memoryRealm.setPathname( tomcatUsers.getAbsolutePath() );
 770  
 
 771  
                 }
 772  
 
 773  0
                 container.setRealm( memoryRealm );
 774  0
                 container.setUseNaming( useNaming );
 775  
 
 776  
                 //container.createLoader( getTomcatClassLoader() ).
 777  
 
 778  
                 // create context
 779  0
                 Context context = createContext( container );
 780  
 
 781  
                 // create host
 782  0
                 String appBase = new File( configurationDir, "webapps" ).getAbsolutePath();
 783  0
                 Host host = container.createHost( "localHost", appBase );
 784  
 
 785  0
                 host.addChild( context );
 786  0
                 createStaticContext( container, context, host );
 787  0
                 if ( addContextWarDependencies || !getAdditionalWebapps().isEmpty() )
 788  
                 {
 789  0
                     Collection<Context> dependencyContexts = createDependencyContexts( container );
 790  0
                     for ( Context extraContext : dependencyContexts )
 791  
                     {
 792  0
                         host.addChild( extraContext );
 793  
                     }
 794  
                 }
 795  
 
 796  
                 // create engine
 797  0
                 Engine engine = container.createEngine();
 798  0
                 engine.setName( "localEngine-" + port );
 799  0
                 engine.addChild( host );
 800  0
                 engine.setDefaultHost( host.getName() );
 801  0
                 container.addEngine( engine );
 802  
 
 803  0
                 getLog().debug( "start tomcat instance on http port:" + port + " and protocol: " + protocol );
 804  
 
 805  
                 // create http connector
 806  0
                 Connector httpConnector = container.createConnector( (InetAddress) null, port, protocol );
 807  0
                 if ( httpsPort > 0 )
 808  
                 {
 809  0
                     httpConnector.setRedirectPort( httpsPort );
 810  
                 }
 811  0
                 httpConnector.setURIEncoding( uriEncoding );
 812  0
                 container.addConnector( httpConnector );
 813  
 
 814  
                 // create https connector
 815  0
                 if ( httpsPort > 0 )
 816  
                 {
 817  0
                     Connector httpsConnector = container.createConnector( (InetAddress) null, httpsPort, true );
 818  0
                     httpsConnector.setSecure( true );
 819  0
                     httpsConnector.setProperty( "SSLEnabled", "true" );
 820  
                     // should be default but configure it anyway
 821  0
                     httpsConnector.setProperty( "sslProtocol", "TLS" );
 822  0
                     if ( keystoreFile != null )
 823  
                     {
 824  0
                         httpsConnector.setAttribute( "keystoreFile", keystoreFile );
 825  
                     }
 826  0
                     if ( keystorePass != null )
 827  
                     {
 828  0
                         httpsConnector.setAttribute( "keystorePass", keystorePass );
 829  
                     }
 830  0
                     if ( keystoreType != null )
 831  
                     {
 832  0
                         httpsConnector.setAttribute( "keystoreType", keystoreType );
 833  
                     }
 834  0
                     container.addConnector( httpsConnector );
 835  
 
 836  
                 }
 837  
 
 838  
                 // create ajp connector
 839  0
                 if ( ajpPort > 0 )
 840  
                 {
 841  0
                     Connector ajpConnector = container.createConnector( (InetAddress) null, ajpPort, ajpProtocol );
 842  0
                     ajpConnector.setURIEncoding( uriEncoding );
 843  0
                     container.addConnector( ajpConnector );
 844  
                 }
 845  0
                 if ( useSeparateTomcatClassLoader )
 846  
                 {
 847  0
                     Thread.currentThread().setContextClassLoader( getTomcatClassLoader() );
 848  0
                     engine.setParentClassLoader( getTomcatClassLoader() );
 849  
                 }
 850  0
                 container.start();
 851  
             }
 852  
 
 853  0
             EmbeddedRegistry.getInstance().register( container );
 854  
         }
 855  
         finally
 856  
         {
 857  0
             if ( previousCatalinaBase != null )
 858  
             {
 859  0
                 System.setProperty( "catalina.base", previousCatalinaBase );
 860  
             }
 861  
         }
 862  0
     }
 863  
 
 864  
     private List<Webapp> getAdditionalWebapps()
 865  
     {
 866  0
         if ( webapps == null )
 867  
         {
 868  0
             return Collections.emptyList();
 869  
         }
 870  0
         return webapps;
 871  
     }
 872  
 
 873  
     protected ClassRealm getTomcatClassLoader()
 874  
         throws MojoExecutionException
 875  
     {
 876  0
         if ( this.tomcatRealm != null )
 877  
         {
 878  0
             return tomcatRealm;
 879  
         }
 880  
         try
 881  
         {
 882  0
             ClassWorld world = new ClassWorld();
 883  0
             ClassRealm root = world.newRealm( "tomcat", Thread.currentThread().getContextClassLoader() );
 884  
 
 885  0
             for ( Artifact pluginArtifact : pluginArtifacts )
 886  
             {
 887  
                 // add all plugin artifacts see https://issues.apache.org/jira/browse/MTOMCAT-122
 888  0
                 if ( pluginArtifact.getFile() != null )
 889  
                 {
 890  0
                     root.addURL( pluginArtifact.getFile().toURI().toURL() );
 891  
                 }
 892  
 
 893  
             }
 894  0
             tomcatRealm = root;
 895  0
             return root;
 896  
         }
 897  0
         catch ( DuplicateRealmException e )
 898  
         {
 899  0
             throw new MojoExecutionException( e.getMessage(), e );
 900  
         }
 901  0
         catch ( MalformedURLException e )
 902  
         {
 903  0
             throw new MojoExecutionException( e.getMessage(), e );
 904  
         }
 905  
     }
 906  
 
 907  
     @SuppressWarnings( "unchecked" )
 908  
     public Set<Artifact> getProjectArtifacts()
 909  
     {
 910  0
         return project.getArtifacts();
 911  
     }
 912  
 
 913  
     /**
 914  
      * Causes the current thread to wait indefinitely. This method does not return.
 915  
      */
 916  
     private void waitIndefinitely()
 917  
     {
 918  0
         Object lock = new Object();
 919  
 
 920  0
         synchronized ( lock )
 921  
         {
 922  
             try
 923  
             {
 924  0
                 lock.wait();
 925  
             }
 926  0
             catch ( InterruptedException exception )
 927  
             {
 928  0
                 getLog().warn( messagesProvider.getMessage( "AbstractRunMojo.interrupted" ), exception );
 929  0
             }
 930  0
         }
 931  0
     }
 932  
 
 933  
 
 934  
     /**
 935  
      * Set the SystemProperties from the configuration.
 936  
      */
 937  
     private void setupSystemProperties()
 938  
     {
 939  0
         if ( systemProperties != null && !systemProperties.isEmpty() )
 940  
         {
 941  0
             getLog().info( "setting SystemProperties:" );
 942  
 
 943  0
             for ( String key : systemProperties.keySet() )
 944  
             {
 945  0
                 String value = systemProperties.get( key );
 946  
 
 947  0
                 if ( value != null )
 948  
                 {
 949  0
                     getLog().info( " " + key + "=" + value );
 950  0
                     System.setProperty( key, value );
 951  
                 }
 952  
                 else
 953  
                 {
 954  0
                     getLog().info( "skip sysProps " + key + " with empty value" );
 955  
                 }
 956  0
             }
 957  
         }
 958  0
     }
 959  
 
 960  
 
 961  
     /**
 962  
      * Allows the startup of additional webapps in the tomcat container by declaration with scope
 963  
      * "tomcat".
 964  
      *
 965  
      * @param container tomcat
 966  
      * @return dependency tomcat contexts of warfiles in scope "tomcat" and those from webapps
 967  
      */
 968  
     private Collection<Context> createDependencyContexts( Embedded container )
 969  
         throws MojoExecutionException
 970  
     {
 971  0
         getLog().info( "Deploying dependency wars" );
 972  
         // Let's add other modules
 973  0
         List<Context> contexts = new ArrayList<Context>();
 974  
 
 975  0
         ScopeArtifactFilter filter = new ScopeArtifactFilter( "tomcat" );
 976  0
         @SuppressWarnings( "unchecked" ) Set<Artifact> artifacts = project.getArtifacts();
 977  0
         for ( Artifact artifact : artifacts )
 978  
         {
 979  
             // Artifact is not yet registered and it has neither test, nor a
 980  
             // provided scope, not is it optional
 981  0
             if ( "war".equals( artifact.getType() ) && !artifact.isOptional() && filter.include( artifact ) )
 982  
             {
 983  0
                 addContextFromArtifact( container, contexts, artifact, "/" + artifact.getArtifactId(), null );
 984  
             }
 985  
         }
 986  
 
 987  0
         for ( AbstractWebapp additionalWebapp : getAdditionalWebapps() )
 988  
         {
 989  0
             String contextPath = additionalWebapp.getContextPath();
 990  0
             if ( !contextPath.startsWith( "/" ) )
 991  
             {
 992  0
                 contextPath = "/" + contextPath;
 993  
             }
 994  0
             addContextFromArtifact( container, contexts, getArtifact( additionalWebapp ), contextPath,
 995  
                                     additionalWebapp.getContextFile() );
 996  0
         }
 997  0
         return contexts;
 998  
     }
 999  
 
 1000  
 
 1001  
     private void addContextFromArtifact( Embedded container, List<Context> contexts, Artifact artifact,
 1002  
                                          String contextPath, File contextXml )
 1003  
         throws MojoExecutionException
 1004  
     {
 1005  0
         getLog().info( "Deploy warfile: " + String.valueOf( artifact.getFile() ) + " to contextPath: " + contextPath );
 1006  0
         File webapps = new File( configurationDir, "webapps" );
 1007  0
         File artifactWarDir = new File( webapps, artifact.getArtifactId() );
 1008  0
         if ( !artifactWarDir.exists() )
 1009  
         {
 1010  
             //dont extract if exists
 1011  0
             artifactWarDir.mkdir();
 1012  
             try
 1013  
             {
 1014  0
                 UnArchiver unArchiver = archiverManager.getUnArchiver( "zip" );
 1015  0
                 unArchiver.setSourceFile( artifact.getFile() );
 1016  0
                 unArchiver.setDestDirectory( artifactWarDir );
 1017  
 
 1018  
                 // Extract the module
 1019  0
                 unArchiver.extract();
 1020  
             }
 1021  0
             catch ( NoSuchArchiverException e )
 1022  
             {
 1023  0
                 getLog().error( e );
 1024  0
                 return;
 1025  
             }
 1026  0
             catch ( ArchiverException e )
 1027  
             {
 1028  0
                 getLog().error( e );
 1029  0
                 return;
 1030  0
             }
 1031  
         }
 1032  0
         WebappLoader webappLoader = new WebappLoader( Thread.currentThread().getContextClassLoader() );
 1033  0
         Context context = container.createContext( contextPath, artifactWarDir.getAbsolutePath() );
 1034  0
         context.setLoader( webappLoader );
 1035  
 
 1036  0
         File contextFile = contextXml != null ? contextXml : getContextFile();
 1037  0
         if ( contextFile != null )
 1038  
         {
 1039  0
             context.setConfigFile( contextFile.getAbsolutePath() );
 1040  
         }
 1041  0
         contexts.add( context );
 1042  0
     }
 1043  
 
 1044  
 
 1045  
     private void createStaticContext( final Embedded container, Context context, Host host )
 1046  
     {
 1047  0
         if ( staticContextDocbase != null )
 1048  
         {
 1049  0
             Context staticContext = container.createContext( staticContextPath, staticContextDocbase );
 1050  0
             staticContext.setPrivileged( true );
 1051  0
             Wrapper servlet = context.createWrapper();
 1052  0
             servlet.setServletClass( DefaultServlet.class.getName() );
 1053  0
             servlet.setName( "staticContent" );
 1054  0
             staticContext.addChild( servlet );
 1055  0
             staticContext.addServletMapping( "/", "staticContent" );
 1056  0
             host.addChild( staticContext );
 1057  
         }
 1058  0
     }
 1059  
 
 1060  
 
 1061  
     /**
 1062  
      * Resolves the Artifact from the remote repository if necessary. If no version is specified, it will be retrieved
 1063  
      * from the dependency list or from the DependencyManagement section of the pom.
 1064  
      *
 1065  
      * @param additionalWebapp containing information about artifact from plugin configuration.
 1066  
      * @return Artifact object representing the specified file.
 1067  
      * @throws MojoExecutionException with a message if the version can't be found in DependencyManagement.
 1068  
      */
 1069  
     protected Artifact getArtifact( AbstractWebapp additionalWebapp )
 1070  
         throws MojoExecutionException
 1071  
     {
 1072  
 
 1073  
         Artifact artifact;
 1074  
         VersionRange vr;
 1075  
         try
 1076  
         {
 1077  0
             vr = VersionRange.createFromVersionSpec( additionalWebapp.getVersion() );
 1078  
         }
 1079  0
         catch ( InvalidVersionSpecificationException e )
 1080  
         {
 1081  0
             getLog().warn( "fail to create versionRange from version: " + additionalWebapp.getVersion(), e );
 1082  0
             vr = VersionRange.createFromVersion( additionalWebapp.getVersion() );
 1083  0
         }
 1084  
 
 1085  0
         if ( StringUtils.isEmpty( additionalWebapp.getClassifier() ) )
 1086  
         {
 1087  0
             artifact = artifactFactory.createDependencyArtifact( additionalWebapp.getGroupId(),
 1088  
                                                                  additionalWebapp.getArtifactId(), vr,
 1089  
                                                                  additionalWebapp.getType(), null,
 1090  
                                                                  Artifact.SCOPE_COMPILE );
 1091  
         }
 1092  
         else
 1093  
         {
 1094  0
             artifact = artifactFactory.createDependencyArtifact( additionalWebapp.getGroupId(),
 1095  
                                                                  additionalWebapp.getArtifactId(), vr,
 1096  
                                                                  additionalWebapp.getType(),
 1097  
                                                                  additionalWebapp.getClassifier(),
 1098  
                                                                  Artifact.SCOPE_COMPILE );
 1099  
         }
 1100  
 
 1101  
         try
 1102  
         {
 1103  0
             artifactResolver.resolve( artifact, project.getRemoteArtifactRepositories(), this.artifactRepository );
 1104  
         }
 1105  0
         catch ( ArtifactResolutionException e )
 1106  
         {
 1107  0
             throw new MojoExecutionException( "Unable to resolve artifact.", e );
 1108  
         }
 1109  0
         catch ( ArtifactNotFoundException e )
 1110  
         {
 1111  0
             throw new MojoExecutionException( "Unable to find artifact.", e );
 1112  0
         }
 1113  
 
 1114  0
         return artifact;
 1115  
     }
 1116  
 }