Coverage Report - org.apache.tomcat.maven.plugin.tomcat7.run.AbstractRunMojo
 
Classes in this File Line Coverage Branch Coverage Complexity
AbstractRunMojo
0 %
0/326
0 %
0/162
0
AbstractRunMojo$MyDirContext
0 %
0/11
0 %
0/4
0
 
 1  
 package org.apache.tomcat.maven.plugin.tomcat7.run;
 2  
 /*
 3  
  * Licensed to the Apache Software Foundation (ASF) under one
 4  
  * or more contributor license agreements.  See the NOTICE file
 5  
  * distributed with this work for additional information
 6  
  * regarding copyright ownership.  The ASF licenses this file
 7  
  * to you under the Apache License, Version 2.0 (the
 8  
  * "License"); you may not use this file except in compliance
 9  
  * with the License.  You may obtain a copy of the License at
 10  
  *
 11  
  *   http://www.apache.org/licenses/LICENSE-2.0
 12  
  *
 13  
  * Unless required by applicable law or agreed to in writing,
 14  
  * software distributed under the License is distributed on an
 15  
  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 16  
  * KIND, either express or implied.  See the License for the
 17  
  * specific language governing permissions and limitations
 18  
  * under the License.
 19  
  */
 20  
 
 21  
 import org.apache.catalina.Context;
 22  
 import org.apache.catalina.Host;
 23  
 import org.apache.catalina.LifecycleException;
 24  
 import org.apache.catalina.Wrapper;
 25  
 import org.apache.catalina.connector.Connector;
 26  
 import org.apache.catalina.core.StandardContext;
 27  
 import org.apache.catalina.loader.WebappLoader;
 28  
 import org.apache.catalina.realm.MemoryRealm;
 29  
 import org.apache.catalina.servlets.DefaultServlet;
 30  
 import org.apache.catalina.startup.Catalina;
 31  
 import org.apache.catalina.startup.CatalinaProperties;
 32  
 import org.apache.catalina.startup.Tomcat;
 33  
 import org.apache.catalina.valves.AccessLogValve;
 34  
 import org.apache.commons.io.IOUtils;
 35  
 import org.apache.commons.lang.StringUtils;
 36  
 import org.apache.maven.artifact.Artifact;
 37  
 import org.apache.maven.artifact.factory.ArtifactFactory;
 38  
 import org.apache.maven.artifact.repository.ArtifactRepository;
 39  
 import org.apache.maven.artifact.resolver.ArtifactNotFoundException;
 40  
 import org.apache.maven.artifact.resolver.ArtifactResolutionException;
 41  
 import org.apache.maven.artifact.resolver.ArtifactResolver;
 42  
 import org.apache.maven.artifact.resolver.filter.ScopeArtifactFilter;
 43  
 import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException;
 44  
 import org.apache.maven.artifact.versioning.VersionRange;
 45  
 import org.apache.maven.execution.MavenSession;
 46  
 import org.apache.maven.plugin.MojoExecutionException;
 47  
 import org.apache.maven.plugin.MojoFailureException;
 48  
 import org.apache.maven.plugins.annotations.Component;
 49  
 import org.apache.maven.plugins.annotations.Parameter;
 50  
 import org.apache.maven.project.MavenProject;
 51  
 import org.apache.naming.NamingEntry;
 52  
 import org.apache.naming.resources.FileDirContext;
 53  
 import org.apache.tomcat.maven.common.config.AbstractWebapp;
 54  
 import org.apache.tomcat.maven.common.run.EmbeddedRegistry;
 55  
 import org.apache.tomcat.maven.common.run.ExternalRepositoriesReloadableWebappLoader;
 56  
 import org.apache.tomcat.maven.plugin.tomcat7.AbstractTomcat7Mojo;
 57  
 import org.codehaus.plexus.archiver.ArchiverException;
 58  
 import org.codehaus.plexus.archiver.UnArchiver;
 59  
 import org.codehaus.plexus.archiver.manager.ArchiverManager;
 60  
 import org.codehaus.plexus.archiver.manager.NoSuchArchiverException;
 61  
 import org.codehaus.plexus.classworlds.ClassWorld;
 62  
 import org.codehaus.plexus.classworlds.realm.ClassRealm;
 63  
 import org.codehaus.plexus.classworlds.realm.DuplicateRealmException;
 64  
 import org.codehaus.plexus.util.DirectoryScanner;
 65  
 import org.codehaus.plexus.util.FileUtils;
 66  
 import org.w3c.dom.Document;
 67  
 import org.w3c.dom.NamedNodeMap;
 68  
 import org.w3c.dom.Node;
 69  
 import org.xml.sax.SAXException;
 70  
 
 71  
 import javax.naming.NamingException;
 72  
 import javax.servlet.ServletException;
 73  
 import javax.xml.parsers.DocumentBuilder;
 74  
 import javax.xml.parsers.DocumentBuilderFactory;
 75  
 import javax.xml.parsers.ParserConfigurationException;
 76  
 import javax.xml.stream.XMLInputFactory;
 77  
 import javax.xml.stream.XMLStreamConstants;
 78  
 import javax.xml.stream.XMLStreamException;
 79  
 import javax.xml.stream.XMLStreamReader;
 80  
 import java.io.File;
 81  
 import java.io.FileInputStream;
 82  
 import java.io.FileNotFoundException;
 83  
 import java.io.FileOutputStream;
 84  
 import java.io.IOException;
 85  
 import java.net.MalformedURLException;
 86  
 import java.net.URL;
 87  
 import java.util.ArrayList;
 88  
 import java.util.Collection;
 89  
 import java.util.Collections;
 90  
 import java.util.Iterator;
 91  
 import java.util.List;
 92  
 import java.util.Map;
 93  
 import java.util.Properties;
 94  
 import java.util.Set;
 95  
 
 96  
 /**
 97  
  * @author Olivier Lamy
 98  
  * @since 2.0
 99  
  */
 100  0
 public abstract class AbstractRunMojo
 101  
     extends AbstractTomcat7Mojo
 102  
 {
 103  
     // ---------------------------------------------------------------------
 104  
     // Mojo Components
 105  
     // ---------------------------------------------------------------------
 106  
 
 107  
     /**
 108  
      * Used to look up Artifacts in the remote repository.
 109  
      */
 110  
     @Component
 111  
     protected ArtifactFactory factory;
 112  
 
 113  
     /**
 114  
      * Location of the local repository.
 115  
      */
 116  
     @Parameter( defaultValue = "${localRepository}", required = true, readonly = true )
 117  
     private ArtifactRepository local;
 118  
 
 119  
     /**
 120  
      * Used to look up Artifacts in the remote repository.
 121  
      */
 122  
     @Component
 123  
     protected ArtifactResolver resolver;
 124  
 
 125  
     // ----------------------------------------------------------------------
 126  
     // Mojo Parameters
 127  
     // ----------------------------------------------------------------------
 128  
 
 129  
     /**
 130  
      * The packaging of the Maven project that this goal operates upon.
 131  
      */
 132  
     @Parameter( defaultValue = "${project.packaging}", required = true, readonly = true )
 133  
     private String packaging;
 134  
 
 135  
     /**
 136  
      * The directory to create the Tomcat server configuration under.
 137  
      */
 138  
     @Parameter( defaultValue = "${project.build.directory}/tomcat" )
 139  
     private File configurationDir;
 140  
 
 141  
     /**
 142  
      * The port to run the Tomcat server on.
 143  
      * Will be exposed as System props and session.executionProperties with key tomcat.maven.http.port
 144  
      */
 145  
     @Parameter( property = "maven.tomcat.port", defaultValue = "8080" )
 146  
     private int port;
 147  
 
 148  
     /**
 149  
      * The AJP port to run the Tomcat server on.
 150  
      * By default it's 0 this means won't be started.
 151  
      * The ajp connector will be started only for value > 0.
 152  
      * Will be exposed as System props and session.executionProperties with key tomcat.maven.ajp.port
 153  
      *
 154  
      * @since 2.0
 155  
      */
 156  
     @Parameter( property = "maven.tomcat.ajp.port", defaultValue = "0" )
 157  
     private int ajpPort;
 158  
 
 159  
     /**
 160  
      * The AJP protocol to run the Tomcat server on.
 161  
      * By default it's ajp.
 162  
      * NOTE The ajp connector will be started only if {@link #ajpPort} > 0.
 163  
      * possible values are:
 164  
      * <ul>
 165  
      * <li>org.apache.coyote.ajp.AjpProtocol - new blocking Java connector that supports an executor</li>
 166  
      * <li>org.apache.coyote.ajp.AjpAprProtocol - the APR/native connector.</li>
 167  
      * </ul>
 168  
      *
 169  
      * @since 2.0
 170  
      */
 171  
     @Parameter( property = "maven.tomcat.ajp.protocol", defaultValue = "org.apache.coyote.ajp.AjpProtocol" )
 172  
     private String ajpProtocol;
 173  
 
 174  
     /**
 175  
      * The https port to run the Tomcat server on.
 176  
      * By default it's 0 this means won't be started.
 177  
      * The https connector will be started only for value > 0.
 178  
      * Will be exposed as System props and session.executionProperties with key tomcat.maven.https.port
 179  
      *
 180  
      * @since 1.0
 181  
      */
 182  
     @Parameter( property = "maven.tomcat.httpsPort", defaultValue = "0" )
 183  
     private int httpsPort;
 184  
 
 185  
     /**
 186  
      * The character encoding to use for decoding URIs.
 187  
      *
 188  
      * @since 1.0
 189  
      */
 190  
     @Parameter( property = "maven.tomcat.uriEncoding", defaultValue = "ISO-8859-1" )
 191  
     private String uriEncoding;
 192  
 
 193  
     /**
 194  
      * List of System properties to pass to the Tomcat Server.
 195  
      *
 196  
      * @since 1.0-alpha-2
 197  
      */
 198  
     @Parameter
 199  
     private Map<String, String> systemProperties;
 200  
 
 201  
     /**
 202  
      * The directory contains additional configuration Files that copied in the Tomcat conf Directory.
 203  
      *
 204  
      * @since 1.0-alpha-2
 205  
      */
 206  
     @Parameter( property = "maven.tomcat.additionalConfigFilesDir", defaultValue = "${basedir}/src/main/tomcatconf" )
 207  
     private File additionalConfigFilesDir;
 208  
 
 209  
     /**
 210  
      * server.xml to use <b>Note if you use this you must configure in this file your webapp paths</b>.
 211  
      *
 212  
      * @since 1.0-alpha-2
 213  
      */
 214  
     @Parameter( property = "maven.tomcat.serverXml" )
 215  
     private File serverXml;
 216  
 
 217  
     /**
 218  
      * overriding the providing web.xml to run tomcat
 219  
      *
 220  
      * @since 1.0-alpha-2
 221  
      */
 222  
     @Parameter( property = "maven.tomcat.webXml" )
 223  
     private File tomcatWebXml;
 224  
 
 225  
     /**
 226  
      * Set this to true to allow Maven to continue to execute after invoking
 227  
      * the run goal.
 228  
      *
 229  
      * @since 1.0
 230  
      */
 231  
     @Parameter( property = "maven.tomcat.fork", defaultValue = "false" )
 232  
     private boolean fork;
 233  
 
 234  
     /**
 235  
      * Will create a tomcat context for each dependencies of war type with 'scope' set to 'tomcat'.
 236  
      * In other words, dependencies with:
 237  
      * <pre>
 238  
      *    &lt;type&gt;war&lt;/type&gt;
 239  
      *    &lt;scope&gt;tomcat&lt;/scope&gt;
 240  
      * </pre>
 241  
      * To preserve backward compatibility it's false by default.
 242  
      *
 243  
      * @since 1.0
 244  
      * @deprecated use webapps instead
 245  
      */
 246  
     @Parameter( property = "maven.tomcat.addContextWarDependencies", defaultValue = "false" )
 247  
     private boolean addContextWarDependencies;
 248  
 
 249  
     /**
 250  
      * The maven project.
 251  
      *
 252  
      * @since 1.0
 253  
      */
 254  
     @Component
 255  
     protected MavenProject project;
 256  
 
 257  
     /**
 258  
      * The archive manager.
 259  
      *
 260  
      * @since 1.0
 261  
      */
 262  
     @Component
 263  
     private ArchiverManager archiverManager;
 264  
 
 265  
     /**
 266  
      * if <code>true</code> a new classLoader separated from maven core will be created to start tomcat.
 267  
      *
 268  
      * @since 1.0
 269  
      */
 270  
     @Parameter( property = "tomcat.useSeparateTomcatClassLoader", defaultValue = "false" )
 271  
     protected boolean useSeparateTomcatClassLoader;
 272  
 
 273  
     /**
 274  
      * @since 1.0
 275  
      */
 276  
     @Parameter( defaultValue = "${plugin.artifacts}", required = true )
 277  
     private List<Artifact> pluginArtifacts;
 278  
 
 279  
     /**
 280  
      * If set to true ignore if packaging of project is not 'war'.
 281  
      *
 282  
      * @since 1.0
 283  
      */
 284  
     @Parameter( property = "tomcat.ignorePackaging", defaultValue = "false" )
 285  
     private boolean ignorePackaging;
 286  
 
 287  
     /**
 288  
      * Override the default keystoreFile for the HTTPS connector (if enabled)
 289  
      *
 290  
      * @since 1.1
 291  
      */
 292  
     @Parameter
 293  
     private String keystoreFile;
 294  
 
 295  
     /**
 296  
      * Override the default keystorePass for the HTTPS connector (if enabled)
 297  
      *
 298  
      * @since 1.1
 299  
      */
 300  
     @Parameter
 301  
     private String keystorePass;
 302  
 
 303  
     /**
 304  
      * Override the type of keystore file to be used for the server certificate. If not specified, the default value is "JKS".
 305  
      *
 306  
      * @since 2.0
 307  
      */
 308  
     @Parameter( defaultValue = "JKS" )
 309  
     private String keystoreType;
 310  
 
 311  
     /**
 312  
      * <p>
 313  
      * Enables or disables naming support for the embedded Tomcat server.
 314  
      * </p>
 315  
      * <p>
 316  
      * <strong>Note:</strong> This setting is ignored if you provide a <code>server.xml</code> for your
 317  
      * Tomcat. Instead please configure naming in the <code>server.xml</code>.
 318  
      * </p>
 319  
      *
 320  
      * @see <a href="http://tomcat.apache.org/tomcat-6.0-doc/api/org/apache/catalina/startup/Embedded.html">org.apache.catalina.startup.Embedded</a>
 321  
      * @see <a href="http://tomcat.apache.org/tomcat-7.0-doc/api/org/apache/catalina/startup/Tomcat.html">org.apache.catalina.startup.Tomcat</a>
 322  
      * @since 2.0
 323  
      */
 324  
     @Parameter( property = "maven.tomcat.useNaming", defaultValue = "true" )
 325  
     private boolean useNaming;
 326  
 
 327  
     /**
 328  
      * Force context scanning if you don't use a context file with reloadable = "true".
 329  
      * The other way to use contextReloadable is to add attribute reloadable = "true"
 330  
      * in your context file.
 331  
      *
 332  
      * @since 2.0
 333  
      */
 334  
     @Parameter( property = "maven.tomcat.contextReloadable", defaultValue = "false" )
 335  
     protected boolean contextReloadable;
 336  
 
 337  
 
 338  
     /**
 339  
      * <p>The path of the Tomcat context XML file.</p>
 340  
      * <p>Since release 2.0, the file is filtered as a maven resource so you can use
 341  
      * interpolation tokens ${ }</p>
 342  
      */
 343  
     @Parameter( property = "maven.tomcat.contextFile" )
 344  
     protected File contextFile;
 345  
 
 346  
     /**
 347  
      * The protocol to run the Tomcat server on.
 348  
      * By default it's HTTP/1.1.
 349  
      *
 350  
      * @since 2.0
 351  
      */
 352  
     @Parameter( property = "maven.tomcat.protocol", defaultValue = "HTTP/1.1" )
 353  
     private String protocol;
 354  
 
 355  
     /**
 356  
      * The path of the Tomcat users XML file.
 357  
      *
 358  
      * @since 2.0
 359  
      */
 360  
     @Parameter( property = "maven.tomcat.tomcatUsers.file" )
 361  
     private File tomcatUsers;
 362  
 
 363  
     /**
 364  
      * The path of the Tomcat logging configuration.
 365  
      *
 366  
      * @since 2.0
 367  
      */
 368  
     @Parameter( property = "maven.tomcat.tomcatLogging.file" )
 369  
     private File tomcatLoggingFile;
 370  
 
 371  
     /**
 372  
      * Skip execution
 373  
      *
 374  
      * @since 2.0
 375  
      */
 376  
     @Parameter( property = "maven.tomcat.skip", defaultValue = "false" )
 377  
     protected boolean skip;
 378  
 
 379  
     /**
 380  
      * @see {@link Webapp}
 381  
      * @since 2.0
 382  
      */
 383  
     @Parameter
 384  
     private List<Webapp> webapps;
 385  
 
 386  
     /**
 387  
      * The static context
 388  
      *
 389  
      * @since 2.0
 390  
      */
 391  
     @Parameter( property = "maven.tomcat.staticContextPath", defaultValue = "/" )
 392  
     private String staticContextPath;
 393  
 
 394  
     /**
 395  
      * The static context docroot base fully qualified path
 396  
      * if <code>null</code> static context won't be added
 397  
      *
 398  
      * @since 2.0
 399  
      */
 400  
     @Parameter( property = "maven.tomcat.staticContextDocbase" )
 401  
     private String staticContextDocbase;
 402  
 
 403  
     /**
 404  
      * Class loader class to set.
 405  
      *
 406  
      * @since 2.0
 407  
      */
 408  
     @Parameter
 409  
     protected String classLoaderClass;
 410  
 
 411  
     @Parameter( defaultValue = "${session}", readonly = true, required = true )
 412  
     protected MavenSession session;
 413  
 
 414  
     /**
 415  
      * Will dump port in a properties file (see ports for property names).
 416  
      * If empty no file generated
 417  
      */
 418  
     @Parameter( property = "maven.tomcat.propertiesPortFilePath" )
 419  
     protected String propertiesPortFilePath;
 420  
 
 421  
     /**
 422  
      * configure host name
 423  
      *
 424  
      * @since 2.0
 425  
      */
 426  
     @Parameter( property = "maven.tomcat.hostName", defaultValue = "localhost" )
 427  
     protected String hostName;
 428  
 
 429  
     /**
 430  
      * configure aliases
 431  
      * see <a href="http://tomcat.apache.org/tomcat-7.0-doc/config/host.html#Host_Name_Aliases">Host Name aliases</a>
 432  
      *
 433  
      * @since 2.0
 434  
      */
 435  
     @Parameter
 436  
     protected String[] aliases;
 437  
 
 438  
     // ----------------------------------------------------------------------
 439  
     // Fields
 440  
     // ----------------------------------------------------------------------
 441  
 
 442  
     /**
 443  
      * @since 1.0
 444  
      */
 445  
     private ClassRealm tomcatRealm;
 446  
 
 447  
     // ----------------------------------------------------------------------
 448  
     // Mojo Implementation
 449  
     // ----------------------------------------------------------------------
 450  
 
 451  
     /**
 452  
      * {@inheritDoc}
 453  
      */
 454  
     public void execute()
 455  
         throws MojoExecutionException, MojoFailureException
 456  
     {
 457  0
         if ( skip )
 458  
         {
 459  0
             getLog().info( "skip execution" );
 460  0
             return;
 461  
         }
 462  
         // ensure project is a web application
 463  0
         if ( !isWar() && !addContextWarDependencies && getAdditionalWebapps().isEmpty() )
 464  
         {
 465  0
             getLog().info( messagesProvider.getMessage( "AbstractRunMojo.nonWar" ) );
 466  0
             return;
 467  
         }
 468  0
         ClassLoader originalClassLoader = null;
 469  0
         if ( useSeparateTomcatClassLoader )
 470  
         {
 471  0
             originalClassLoader = Thread.currentThread().getContextClassLoader();
 472  
         }
 473  
         try
 474  
         {
 475  0
             getLog().info( messagesProvider.getMessage( "AbstractRunMojo.runningWar", getWebappUrl() ) );
 476  
 
 477  0
             initConfiguration();
 478  0
             startContainer();
 479  0
             if ( !fork )
 480  
             {
 481  0
                 waitIndefinitely();
 482  
             }
 483  
         }
 484  0
         catch ( LifecycleException exception )
 485  
         {
 486  0
             throw new MojoExecutionException( messagesProvider.getMessage( "AbstractRunMojo.cannotStart" ), exception );
 487  
         }
 488  0
         catch ( IOException exception )
 489  
         {
 490  0
             throw new MojoExecutionException(
 491  
                 messagesProvider.getMessage( "AbstractRunMojo.cannotCreateConfiguration" ), exception );
 492  
         }
 493  0
         catch ( ServletException e )
 494  
         {
 495  0
             throw new MojoExecutionException( e.getMessage(), e );
 496  
         }
 497  
         finally
 498  
         {
 499  0
             if ( useSeparateTomcatClassLoader )
 500  
             {
 501  0
                 Thread.currentThread().setContextClassLoader( originalClassLoader );
 502  
             }
 503  
         }
 504  0
     }
 505  
 
 506  
     // ----------------------------------------------------------------------
 507  
     // Protected Methods
 508  
     // ----------------------------------------------------------------------
 509  
 
 510  
     /**
 511  
      * Gets the webapp context path to use for the web application being run.
 512  
      *
 513  
      * @return the webapp context path
 514  
      */
 515  
     protected String getPath()
 516  
     {
 517  0
         return path;
 518  
     }
 519  
 
 520  
     /**
 521  
      * Gets the context to run this web application under for the specified embedded Tomcat.
 522  
      *
 523  
      * @param container the embedded Tomcat container being used
 524  
      * @return the context to run this web application under
 525  
      * @throws IOException            if the context could not be created
 526  
      * @throws MojoExecutionException in case of an error creating the context
 527  
      */
 528  
     protected Context createContext( Tomcat container )
 529  
         throws IOException, MojoExecutionException, ServletException
 530  
     {
 531  0
         String contextPath = getPath();
 532  
 
 533  0
         String baseDir = getDocBase().getAbsolutePath();
 534  
 
 535  0
         File overridedContextFile = getContextFile();
 536  
 
 537  0
         if ( overridedContextFile != null && overridedContextFile.exists() )
 538  
         {
 539  0
             StandardContext standardContext = parseContextFile( overridedContextFile );
 540  
 
 541  0
             if ( standardContext.getPath() != null )
 542  
             {
 543  0
                 contextPath = standardContext.getPath();
 544  
             }
 545  0
             if ( standardContext.getDocBase() != null )
 546  
             {
 547  0
                 baseDir = standardContext.getDocBase();
 548  
             }
 549  
         }
 550  
 
 551  0
         contextPath = "/".equals( contextPath ) ? "" : contextPath;
 552  
 
 553  0
         getLog().info( "create webapp with contextPath: " + contextPath );
 554  
 
 555  0
         Context context = container.addWebapp( contextPath, baseDir );
 556  
 
 557  0
         context.setResources(
 558  
             new MyDirContext( new File( project.getBuild().getOutputDirectory() ).getAbsolutePath() ) );
 559  
 
 560  0
         if ( useSeparateTomcatClassLoader )
 561  
         {
 562  0
             context.setParentClassLoader( getTomcatClassLoader() );
 563  
         }
 564  
 
 565  0
         final WebappLoader loader = createWebappLoader();
 566  
 
 567  0
         context.setLoader( loader );
 568  
 
 569  0
         if ( overridedContextFile != null )
 570  
         {
 571  0
             context.setConfigFile( overridedContextFile.toURI().toURL() );
 572  
         }
 573  
 
 574  0
         if ( classLoaderClass != null )
 575  
         {
 576  0
             loader.setLoaderClass( classLoaderClass );
 577  
         }
 578  
 
 579  0
         return context;
 580  
 
 581  
     }
 582  
 
 583  
     protected StandardContext parseContextFile( File file )
 584  
         throws MojoExecutionException
 585  
     {
 586  
         try
 587  
         {
 588  0
             StandardContext standardContext = new StandardContext();
 589  0
             XMLStreamReader reader = XMLInputFactory.newFactory().createXMLStreamReader( new FileInputStream( file ) );
 590  
 
 591  0
             int tag = reader.next();
 592  
 
 593  
             while ( true )
 594  
             {
 595  0
                 if ( tag == XMLStreamConstants.START_ELEMENT && StringUtils.equals( "Context", reader.getLocalName() ) )
 596  
                 {
 597  0
                     String path = reader.getAttributeValue( null, "path" );
 598  0
                     if ( StringUtils.isNotBlank( path ) )
 599  
                     {
 600  0
                         standardContext.setPath( path );
 601  
                     }
 602  
 
 603  0
                     String docBase = reader.getAttributeValue( null, "docBase" );
 604  0
                     if ( StringUtils.isNotBlank( docBase ) )
 605  
                     {
 606  0
                         standardContext.setDocBase( docBase );
 607  
                     }
 608  
                 }
 609  0
                 if ( !reader.hasNext() )
 610  
                 {
 611  0
                     break;
 612  
                 }
 613  0
                 tag = reader.next();
 614  
             }
 615  
 
 616  0
             return standardContext;
 617  
         }
 618  0
         catch ( XMLStreamException e )
 619  
         {
 620  0
             throw new MojoExecutionException( e.getMessage(), e );
 621  
         }
 622  0
         catch ( FileNotFoundException e )
 623  
         {
 624  0
             throw new MojoExecutionException( e.getMessage(), e );
 625  
         }
 626  
     }
 627  
 
 628  
 
 629  0
     private static class MyDirContext
 630  
         extends FileDirContext
 631  
     {
 632  
         String buildOutputDirectory;
 633  
 
 634  
         MyDirContext( String buildOutputDirectory )
 635  0
         {
 636  0
             this.buildOutputDirectory = buildOutputDirectory;
 637  0
         }
 638  
 
 639  
         @Override
 640  
         protected List<NamingEntry> doListBindings( String name )
 641  
             throws NamingException
 642  
         {
 643  0
             if ( "/WEB-INF/classes".equals( name ) )
 644  
             {
 645  0
                 if ( !new File( buildOutputDirectory ).exists() )
 646  
                 {
 647  0
                     return Collections.emptyList();
 648  
                 }
 649  0
                 FileDirContext fileDirContext = new FileDirContext();
 650  0
                 fileDirContext.setDocBase( buildOutputDirectory );
 651  0
                 NamingEntry namingEntry = new NamingEntry( "/WEB-INF/classes", fileDirContext, -1 );
 652  0
                 return Collections.singletonList( namingEntry );
 653  
             }
 654  
 
 655  0
             return super.doListBindings( name );
 656  
         }
 657  
     }
 658  
 
 659  
     /**
 660  
      * Gets the webapp loader to run this web application under.
 661  
      *
 662  
      * @return the webapp loader to use
 663  
      * @throws IOException            if the webapp loader could not be created
 664  
      * @throws MojoExecutionException in case of an error creating the webapp loader
 665  
      */
 666  
     protected WebappLoader createWebappLoader()
 667  
         throws IOException, MojoExecutionException
 668  
     {
 669  0
         if ( useSeparateTomcatClassLoader )
 670  
         {
 671  0
             return ( isContextReloadable() )
 672  
                 ? new ExternalRepositoriesReloadableWebappLoader( getTomcatClassLoader(), getLog() )
 673  
                 : new WebappLoader( getTomcatClassLoader() );
 674  
         }
 675  
 
 676  0
         return ( isContextReloadable() )
 677  
             ? new ExternalRepositoriesReloadableWebappLoader( Thread.currentThread().getContextClassLoader(), getLog() )
 678  
             : new WebappLoader( Thread.currentThread().getContextClassLoader() );
 679  
     }
 680  
 
 681  
     /**
 682  
      * Determine whether the passed context.xml file declares the context as reloadable or not.
 683  
      *
 684  
      * @return false by default, true if  reloadable="true" in context.xml.
 685  
      */
 686  
     protected boolean isContextReloadable()
 687  
         throws MojoExecutionException
 688  
     {
 689  0
         if ( contextReloadable )
 690  
         {
 691  0
             return true;
 692  
         }
 693  
         // determine whether to use a reloadable Loader or not (default is false).
 694  0
         boolean reloadable = false;
 695  
         try
 696  
         {
 697  0
             if ( contextFile != null && contextFile.exists() )
 698  
             {
 699  0
                 DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
 700  0
                 DocumentBuilder builder = builderFactory.newDocumentBuilder();
 701  0
                 Document contextDoc = builder.parse( contextFile );
 702  0
                 contextDoc.getDocumentElement().normalize();
 703  
 
 704  0
                 NamedNodeMap nodeMap = contextDoc.getDocumentElement().getAttributes();
 705  0
                 Node reloadableAttribute = nodeMap.getNamedItem( "reloadable" );
 706  
 
 707  0
                 reloadable =
 708  
                     ( reloadableAttribute != null ) ? Boolean.valueOf( reloadableAttribute.getNodeValue() ) : false;
 709  
             }
 710  0
             getLog().debug( "context reloadable: " + reloadable );
 711  
         }
 712  0
         catch ( IOException ioe )
 713  
         {
 714  0
             getLog().error( "Could not parse file: [" + contextFile.getAbsolutePath() + "]", ioe );
 715  
         }
 716  0
         catch ( ParserConfigurationException pce )
 717  
         {
 718  0
             getLog().error( "Could not configure XML parser", pce );
 719  
         }
 720  0
         catch ( SAXException se )
 721  
         {
 722  0
             getLog().error( "Could not parse file: [" + contextFile.getAbsolutePath() + "]", se );
 723  0
         }
 724  
 
 725  0
         return reloadable;
 726  
     }
 727  
 
 728  
 
 729  
     /**
 730  
      * Gets the webapp directory to run.
 731  
      *
 732  
      * @return the webapp directory
 733  
      */
 734  
     protected abstract File getDocBase();
 735  
 
 736  
     /**
 737  
      * Gets the Tomcat context XML file to use.
 738  
      *
 739  
      * @return the context XML file
 740  
      */
 741  
     protected abstract File getContextFile()
 742  
         throws MojoExecutionException;
 743  
 
 744  
     // ----------------------------------------------------------------------
 745  
     // Private Methods
 746  
     // ----------------------------------------------------------------------
 747  
 
 748  
     /**
 749  
      * Gets whether this project uses WAR packaging.
 750  
      *
 751  
      * @return whether this project uses WAR packaging
 752  
      */
 753  
     protected boolean isWar()
 754  
     {
 755  0
         return "war".equals( packaging ) || ignorePackaging;
 756  
     }
 757  
 
 758  
     /**
 759  
      * Gets the URL of the running webapp.
 760  
      *
 761  
      * @return the URL of the running webapp
 762  
      * @throws java.net.MalformedURLException if the running webapp URL is invalid
 763  
      */
 764  
     private URL getWebappUrl()
 765  
         throws MalformedURLException
 766  
     {
 767  0
         return new URL( "http", "localhost", port, getPath() );
 768  
     }
 769  
 
 770  
     /**
 771  
      * FIXME not sure we need all of those files with tomcat7
 772  
      * Creates the Tomcat configuration directory with the necessary resources.
 773  
      *
 774  
      * @throws IOException            if the Tomcat configuration could not be created
 775  
      * @throws MojoExecutionException if the Tomcat configuration could not be created
 776  
      */
 777  
     private void initConfiguration()
 778  
         throws IOException, MojoExecutionException
 779  
     {
 780  0
         if ( configurationDir.exists() )
 781  
         {
 782  0
             getLog().info( messagesProvider.getMessage( "AbstractRunMojo.usingConfiguration", configurationDir ) );
 783  
         }
 784  
         else
 785  
         {
 786  0
             getLog().info( messagesProvider.getMessage( "AbstractRunMojo.creatingConfiguration", configurationDir ) );
 787  
 
 788  0
             configurationDir.mkdirs();
 789  
 
 790  0
             File confDir = new File( configurationDir, "conf" );
 791  0
             confDir.mkdir();
 792  
 
 793  0
             if ( tomcatLoggingFile != null )
 794  
             {
 795  0
                 FileUtils.copyFile( tomcatLoggingFile, new File( confDir, "logging.properties" ) );
 796  
             }
 797  
             else
 798  
             {
 799  0
                 copyFile( "/conf/logging.properties", new File( confDir, "logging.properties" ) );
 800  
             }
 801  
 
 802  0
             copyFile( "/conf/tomcat-users.xml", new File( confDir, "tomcat-users.xml" ) );
 803  0
             if ( tomcatWebXml != null )
 804  
             {
 805  0
                 if ( !tomcatWebXml.exists() )
 806  
                 {
 807  0
                     throw new MojoExecutionException( " tomcatWebXml " + tomcatWebXml.getPath() + " not exists" );
 808  
                 }
 809  
                 //MTOMCAT-42  here it's a real file resources not a one coming with the mojo
 810  0
                 FileUtils.copyFile( tomcatWebXml, new File( confDir, "web.xml" ) );
 811  
             }
 812  
             else
 813  
             {
 814  0
                 copyFile( "/conf/web.xml", new File( confDir, "web.xml" ) );
 815  
             }
 816  
 
 817  0
             File logDir = new File( configurationDir, "logs" );
 818  0
             logDir.mkdir();
 819  
 
 820  0
             File webappsDir = new File( configurationDir, "webapps" );
 821  0
             webappsDir.mkdir();
 822  
 
 823  0
             if ( additionalConfigFilesDir != null && additionalConfigFilesDir.exists() )
 824  
             {
 825  0
                 DirectoryScanner scanner = new DirectoryScanner();
 826  0
                 scanner.addDefaultExcludes();
 827  0
                 scanner.setBasedir( additionalConfigFilesDir.getPath() );
 828  0
                 scanner.scan();
 829  
 
 830  0
                 String[] files = scanner.getIncludedFiles();
 831  
 
 832  0
                 if ( files != null && files.length > 0 )
 833  
                 {
 834  0
                     getLog().info( "Coping additional tomcat config files" );
 835  
 
 836  0
                     for ( int i = 0; i < files.length; i++ )
 837  
                     {
 838  0
                         File file = new File( additionalConfigFilesDir, files[i] );
 839  
 
 840  0
                         getLog().info( " copy " + file.getName() );
 841  
 
 842  0
                         FileUtils.copyFileToDirectory( file, confDir );
 843  
                     }
 844  
                 }
 845  
             }
 846  
         }
 847  0
     }
 848  
 
 849  
     /**
 850  
      * Copies the specified class resource to the specified file.
 851  
      *
 852  
      * @param fromPath the path of the class resource to copy
 853  
      * @param toFile   the file to copy to
 854  
      * @throws IOException if the file could not be copied
 855  
      */
 856  
     private void copyFile( String fromPath, File toFile )
 857  
         throws IOException
 858  
     {
 859  0
         URL fromURL = getClass().getResource( fromPath );
 860  
 
 861  0
         if ( fromURL == null )
 862  
         {
 863  0
             throw new FileNotFoundException( fromPath );
 864  
         }
 865  
 
 866  0
         FileUtils.copyURLToFile( fromURL, toFile );
 867  0
     }
 868  
 
 869  
     /**
 870  
      * Starts the embedded Tomcat server.
 871  
      *
 872  
      * @throws IOException            if the server could not be configured
 873  
      * @throws LifecycleException     if the server could not be started
 874  
      * @throws MojoExecutionException if the server could not be configured
 875  
      */
 876  
     private void startContainer()
 877  
         throws IOException, LifecycleException, MojoExecutionException, ServletException
 878  
     {
 879  0
         String previousCatalinaBase = System.getProperty( "catalina.base" );
 880  
 
 881  
         try
 882  
         {
 883  
 
 884  
             // Set the system properties
 885  0
             setupSystemProperties();
 886  
 
 887  0
             System.setProperty( "catalina.base", configurationDir.getAbsolutePath() );
 888  
 
 889  0
             if ( serverXml != null )
 890  
             {
 891  0
                 if ( !serverXml.exists() )
 892  
                 {
 893  0
                     throw new MojoExecutionException( serverXml.getPath() + " not exists" );
 894  
                 }
 895  
 
 896  0
                 Catalina container = new Catalina();
 897  0
                 container.setUseNaming( this.useNaming );
 898  0
                 container.setConfig( serverXml.getAbsolutePath() );
 899  0
                 container.start();
 900  0
                 EmbeddedRegistry.getInstance().register( container );
 901  0
             }
 902  
             else
 903  
             {
 904  
 
 905  0
                 System.setProperty( "java.util.logging.manager", "org.apache.juli.ClassLoaderLogManager" );
 906  0
                 System.setProperty( "java.util.logging.config.file",
 907  
                                     new File( configurationDir, "conf/logging.properties" ).toString() );
 908  
 
 909  
                 // Trigger loading of catalina.properties
 910  0
                 CatalinaProperties.getProperty( "foo" );
 911  
 
 912  0
                 Tomcat embeddedTomcat = new ExtendedTomcat( configurationDir );
 913  
 
 914  0
                 embeddedTomcat.setBaseDir( configurationDir.getAbsolutePath() );
 915  0
                 MemoryRealm memoryRealm = new MemoryRealm();
 916  
 
 917  0
                 if ( tomcatUsers != null )
 918  
                 {
 919  0
                     if ( !tomcatUsers.exists() )
 920  
                     {
 921  0
                         throw new MojoExecutionException( " tomcatUsers " + tomcatUsers.getPath() + " not exists" );
 922  
                     }
 923  0
                     getLog().info( "use tomcat-users.xml from " + tomcatUsers.getAbsolutePath() );
 924  0
                     memoryRealm.setPathname( tomcatUsers.getAbsolutePath() );
 925  
                 }
 926  
 
 927  0
                 embeddedTomcat.setDefaultRealm( memoryRealm );
 928  
 
 929  0
                 Context ctx = createContext( embeddedTomcat );
 930  
 
 931  0
                 if ( useNaming )
 932  
                 {
 933  0
                     embeddedTomcat.enableNaming();
 934  
                 }
 935  
 
 936  0
                 embeddedTomcat.getHost().setAppBase( new File( configurationDir, "webapps" ).getAbsolutePath() );
 937  
 
 938  0
                 if ( hostName != null )
 939  
                 {
 940  0
                     embeddedTomcat.getHost().setName( hostName );
 941  
                 }
 942  0
                 if ( aliases != null )
 943  
                 {
 944  0
                     for ( String alias : aliases )
 945  
                     {
 946  0
                         embeddedTomcat.getHost().addAlias( alias );
 947  
                     }
 948  
 
 949  
                 }
 950  0
                 createStaticContext( embeddedTomcat, ctx, embeddedTomcat.getHost() );
 951  
 
 952  0
                 Connector connector = new Connector( protocol );
 953  0
                 connector.setPort( port );
 954  
 
 955  0
                 if ( httpsPort > 0 )
 956  
                 {
 957  0
                     connector.setRedirectPort( httpsPort );
 958  
                 }
 959  
 
 960  0
                 connector.setURIEncoding( uriEncoding );
 961  
 
 962  0
                 embeddedTomcat.getService().addConnector( connector );
 963  
 
 964  0
                 embeddedTomcat.setConnector( connector );
 965  
 
 966  0
                 AccessLogValve alv = new AccessLogValve();
 967  0
                 alv.setDirectory( new File( configurationDir, "logs" ).getAbsolutePath() );
 968  0
                 alv.setPattern( "%h %l %u %t \"%r\" %s %b %I %D" );
 969  0
                 embeddedTomcat.getHost().getPipeline().addValve( alv );
 970  
 
 971  
                 // create https connector
 972  0
                 Connector httpsConnector = null;
 973  0
                 if ( httpsPort > 0 )
 974  
                 {
 975  0
                     httpsConnector = new Connector( protocol );
 976  0
                     httpsConnector.setPort( httpsPort );
 977  0
                     httpsConnector.setSecure( true );
 978  0
                     httpsConnector.setProperty( "SSLEnabled", "true" );
 979  
                     // should be default but configure it anyway
 980  0
                     httpsConnector.setProperty( "sslProtocol", "TLS" );
 981  0
                     if ( keystoreFile != null )
 982  
                     {
 983  0
                         httpsConnector.setAttribute( "keystoreFile", keystoreFile );
 984  
                     }
 985  0
                     if ( keystorePass != null )
 986  
                     {
 987  0
                         httpsConnector.setAttribute( "keystorePass", keystorePass );
 988  
                     }
 989  0
                     if ( keystoreType != null )
 990  
                     {
 991  0
                         httpsConnector.setAttribute( "keystoreType", keystoreType );
 992  
                     }
 993  0
                     embeddedTomcat.getEngine().getService().addConnector( httpsConnector );
 994  
 
 995  
                 }
 996  
 
 997  
                 // create ajp connector
 998  0
                 Connector ajpConnector = null;
 999  0
                 if ( ajpPort > 0 )
 1000  
                 {
 1001  0
                     ajpConnector = new Connector( ajpProtocol );
 1002  0
                     ajpConnector.setPort( ajpPort );
 1003  0
                     ajpConnector.setURIEncoding( uriEncoding );
 1004  0
                     embeddedTomcat.getEngine().getService().addConnector( ajpConnector );
 1005  
                 }
 1006  
 
 1007  0
                 if ( addContextWarDependencies || !getAdditionalWebapps().isEmpty() )
 1008  
                 {
 1009  0
                     createDependencyContexts( embeddedTomcat );
 1010  
                 }
 1011  
 
 1012  0
                 if ( useSeparateTomcatClassLoader )
 1013  
                 {
 1014  0
                     Thread.currentThread().setContextClassLoader( getTomcatClassLoader() );
 1015  0
                     embeddedTomcat.getEngine().setParentClassLoader( getTomcatClassLoader() );
 1016  
                 }
 1017  
 
 1018  0
                 embeddedTomcat.start();
 1019  
 
 1020  0
                 Properties portProperties = new Properties();
 1021  
 
 1022  0
                 portProperties.put( "tomcat.maven.http.port", Integer.toString( connector.getLocalPort() ) );
 1023  
 
 1024  0
                 session.getExecutionProperties().put( "tomcat.maven.http.port",
 1025  
                                                       Integer.toString( connector.getLocalPort() ) );
 1026  0
                 System.setProperty( "tomcat.maven.http.port", Integer.toString( connector.getLocalPort() ) );
 1027  
 
 1028  0
                 if ( httpsConnector != null )
 1029  
                 {
 1030  0
                     session.getExecutionProperties().put( "tomcat.maven.https.port",
 1031  
                                                           Integer.toString( httpsConnector.getLocalPort() ) );
 1032  0
                     portProperties.put( "tomcat.maven.https.port", Integer.toString( httpsConnector.getLocalPort() ) );
 1033  0
                     System.setProperty( "tomcat.maven.https.port", Integer.toString( httpsConnector.getLocalPort() ) );
 1034  
                 }
 1035  
 
 1036  0
                 if ( ajpConnector != null )
 1037  
                 {
 1038  0
                     session.getExecutionProperties().put( "tomcat.maven.ajp.port",
 1039  
                                                           Integer.toString( ajpConnector.getLocalPort() ) );
 1040  0
                     portProperties.put( "tomcat.maven.ajp.port", Integer.toString( ajpConnector.getLocalPort() ) );
 1041  0
                     System.setProperty( "tomcat.maven.ajp.port", Integer.toString( ajpConnector.getLocalPort() ) );
 1042  
                 }
 1043  0
                 if ( propertiesPortFilePath != null )
 1044  
                 {
 1045  0
                     File propertiesPortsFile = new File( propertiesPortFilePath );
 1046  0
                     if ( propertiesPortsFile.exists() )
 1047  
                     {
 1048  0
                         propertiesPortsFile.delete();
 1049  
                     }
 1050  0
                     FileOutputStream fileOutputStream = new FileOutputStream( propertiesPortsFile );
 1051  
                     try
 1052  
                     {
 1053  0
                         portProperties.store( fileOutputStream, "Apache Tomcat Maven plugin port used" );
 1054  
                     }
 1055  
                     finally
 1056  
                     {
 1057  0
                         IOUtils.closeQuietly( fileOutputStream );
 1058  0
                     }
 1059  
                 }
 1060  
 
 1061  0
                 EmbeddedRegistry.getInstance().register( embeddedTomcat );
 1062  
 
 1063  
             }
 1064  
 
 1065  
 
 1066  
         }
 1067  
         finally
 1068  
         {
 1069  0
             if ( previousCatalinaBase != null )
 1070  
             {
 1071  0
                 System.setProperty( "catalina.base", previousCatalinaBase );
 1072  
             }
 1073  
         }
 1074  0
     }
 1075  
 
 1076  
     private List<Webapp> getAdditionalWebapps()
 1077  
     {
 1078  0
         if ( webapps == null )
 1079  
         {
 1080  0
             return Collections.emptyList();
 1081  
         }
 1082  0
         return webapps;
 1083  
     }
 1084  
 
 1085  
     protected ClassRealm getTomcatClassLoader()
 1086  
         throws MojoExecutionException
 1087  
     {
 1088  0
         if ( this.tomcatRealm != null )
 1089  
         {
 1090  0
             return tomcatRealm;
 1091  
         }
 1092  
         try
 1093  
         {
 1094  0
             ClassWorld world = new ClassWorld();
 1095  0
             ClassRealm root = world.newRealm( "tomcat", Thread.currentThread().getContextClassLoader() );
 1096  
 
 1097  0
             for ( @SuppressWarnings( "rawtypes" ) Iterator i = pluginArtifacts.iterator(); i.hasNext(); )
 1098  
             {
 1099  0
                 Artifact pluginArtifact = (Artifact) i.next();
 1100  
                 // add all plugin artifacts see https://issues.apache.org/jira/browse/MTOMCAT-122
 1101  0
                 if ( pluginArtifact.getFile() != null )
 1102  
                 {
 1103  0
                     root.addURL( pluginArtifact.getFile().toURI().toURL() );
 1104  
                 }
 1105  
 
 1106  0
             }
 1107  0
             tomcatRealm = root;
 1108  0
             return root;
 1109  
         }
 1110  0
         catch ( DuplicateRealmException e )
 1111  
         {
 1112  0
             throw new MojoExecutionException( e.getMessage(), e );
 1113  
         }
 1114  0
         catch ( MalformedURLException e )
 1115  
         {
 1116  0
             throw new MojoExecutionException( e.getMessage(), e );
 1117  
         }
 1118  
     }
 1119  
 
 1120  
     @SuppressWarnings( "unchecked" )
 1121  
     public Set<Artifact> getProjectArtifacts()
 1122  
     {
 1123  0
         return project.getArtifacts();
 1124  
     }
 1125  
 
 1126  
     /**
 1127  
      * Causes the current thread to wait indefinitely. This method does not return.
 1128  
      */
 1129  
     private void waitIndefinitely()
 1130  
     {
 1131  0
         Object lock = new Object();
 1132  
 
 1133  0
         synchronized ( lock )
 1134  
         {
 1135  
             try
 1136  
             {
 1137  0
                 lock.wait();
 1138  
             }
 1139  0
             catch ( InterruptedException exception )
 1140  
             {
 1141  0
                 getLog().warn( messagesProvider.getMessage( "AbstractRunMojo.interrupted" ), exception );
 1142  0
             }
 1143  0
         }
 1144  0
     }
 1145  
 
 1146  
 
 1147  
     /**
 1148  
      * Set the SystemProperties from the configuration.
 1149  
      */
 1150  
     private void setupSystemProperties()
 1151  
     {
 1152  0
         if ( systemProperties != null && !systemProperties.isEmpty() )
 1153  
         {
 1154  0
             getLog().info( "setting SystemProperties:" );
 1155  
 
 1156  0
             for ( String key : systemProperties.keySet() )
 1157  
             {
 1158  0
                 String value = systemProperties.get( key );
 1159  
 
 1160  0
                 if ( value != null )
 1161  
                 {
 1162  0
                     getLog().info( " " + key + "=" + value );
 1163  0
                     System.setProperty( key, value );
 1164  
                 }
 1165  
                 else
 1166  
                 {
 1167  0
                     getLog().info( "skip sysProps " + key + " with empty value" );
 1168  
                 }
 1169  0
             }
 1170  
         }
 1171  0
     }
 1172  
 
 1173  
 
 1174  
     /**
 1175  
      * Allows the startup of additional webapps in the tomcat container by declaration with scope
 1176  
      * "tomcat".
 1177  
      *
 1178  
      * @param container tomcat
 1179  
      * @return dependency tomcat contexts of warfiles in scope "tomcat"
 1180  
      */
 1181  
     private Collection<Context> createDependencyContexts( Tomcat container )
 1182  
         throws MojoExecutionException, MalformedURLException, ServletException, IOException
 1183  
     {
 1184  0
         getLog().info( "Deploying dependency wars" );
 1185  
         // Let's add other modules
 1186  0
         List<Context> contexts = new ArrayList<Context>();
 1187  
 
 1188  0
         ScopeArtifactFilter filter = new ScopeArtifactFilter( "tomcat" );
 1189  0
         @SuppressWarnings( "unchecked" ) Set<Artifact> artifacts = project.getArtifacts();
 1190  0
         for ( Artifact artifact : artifacts )
 1191  
         {
 1192  
 
 1193  
             // Artifact is not yet registered and it has neither test, nor a
 1194  
             // provided scope, not is it optional
 1195  0
             if ( "war".equals( artifact.getType() ) && !artifact.isOptional() && filter.include( artifact ) )
 1196  
             {
 1197  0
                 addContextFromArtifact( container, contexts, artifact, "/" + artifact.getArtifactId(), null, false );
 1198  
             }
 1199  
         }
 1200  
 
 1201  0
         for ( AbstractWebapp additionalWebapp : getAdditionalWebapps() )
 1202  
         {
 1203  0
             String contextPath = additionalWebapp.getContextPath();
 1204  0
             if ( !contextPath.startsWith( "/" ) )
 1205  
             {
 1206  0
                 contextPath = "/" + contextPath;
 1207  
             }
 1208  0
             addContextFromArtifact( container, contexts, getArtifact( additionalWebapp ), contextPath,
 1209  
                                     additionalWebapp.getContextFile(), additionalWebapp.isAsWebapp() );
 1210  0
         }
 1211  0
         return contexts;
 1212  
     }
 1213  
 
 1214  
 
 1215  
     private void addContextFromArtifact( Tomcat container, List<Context> contexts, Artifact artifact,
 1216  
                                          String contextPath, File contextXml, boolean asWebApp )
 1217  
         throws MojoExecutionException, MalformedURLException, ServletException, IOException
 1218  
     {
 1219  0
         getLog().info( "Deploy warfile: " + String.valueOf( artifact.getFile() ) + " to contextPath: " + contextPath );
 1220  0
         File webapps = new File( configurationDir, "webapps" );
 1221  0
         File artifactWarDir = new File( webapps, artifact.getArtifactId() );
 1222  0
         if ( !artifactWarDir.exists() )
 1223  
         {
 1224  
             //dont extract if exists
 1225  0
             artifactWarDir.mkdir();
 1226  
             try
 1227  
             {
 1228  0
                 UnArchiver unArchiver = archiverManager.getUnArchiver( "zip" );
 1229  0
                 unArchiver.setSourceFile( artifact.getFile() );
 1230  0
                 unArchiver.setDestDirectory( artifactWarDir );
 1231  
 
 1232  
                 // Extract the module
 1233  0
                 unArchiver.extract();
 1234  
             }
 1235  0
             catch ( NoSuchArchiverException e )
 1236  
             {
 1237  0
                 getLog().error( e );
 1238  0
                 return;
 1239  
             }
 1240  0
             catch ( ArchiverException e )
 1241  
             {
 1242  0
                 getLog().error( e );
 1243  0
                 return;
 1244  0
             }
 1245  
         }
 1246  
         // TODO make that configurable ?
 1247  
         //WebappLoader webappLoader = new WebappLoader( Thread.currentThread().getContextClassLoader() );
 1248  0
         WebappLoader webappLoader = createWebappLoader();
 1249  0
         Context context = null;
 1250  0
         if ( asWebApp )
 1251  
         {
 1252  0
             context = container.addWebapp( contextPath, artifactWarDir.getAbsolutePath() );
 1253  
         }
 1254  
         else
 1255  
         {
 1256  0
             context = container.addContext( contextPath, artifactWarDir.getAbsolutePath() );
 1257  
         }
 1258  0
         context.setLoader( webappLoader );
 1259  
 
 1260  0
         File contextFile = contextXml != null ? contextXml : getContextFile();
 1261  0
         if ( contextFile != null )
 1262  
         {
 1263  0
             context.setConfigFile( contextFile.toURI().toURL() );
 1264  
         }
 1265  
 
 1266  0
         contexts.add( context );
 1267  
 //        container.getHost().addChild(context);
 1268  0
     }
 1269  
 
 1270  
     private void createStaticContext( final Tomcat container, Context context, Host host )
 1271  
     {
 1272  0
         if ( staticContextDocbase != null )
 1273  
         {
 1274  0
             Context staticContext = container.addContext( staticContextPath, staticContextDocbase );
 1275  0
             staticContext.setPrivileged( true );
 1276  0
             Wrapper servlet = context.createWrapper();
 1277  0
             servlet.setServletClass( DefaultServlet.class.getName() );
 1278  0
             servlet.setName( "staticContent" );
 1279  0
             staticContext.addChild( servlet );
 1280  0
             staticContext.addServletMapping( "/", "staticContent" );
 1281  0
             host.addChild( staticContext );
 1282  
         }
 1283  0
     }
 1284  
 
 1285  
 
 1286  
     /**
 1287  
      * Resolves the Artifact from the remote repository if necessary. If no version is specified, it will be retrieved
 1288  
      * from the dependency list or from the DependencyManagement section of the pom.
 1289  
      *
 1290  
      * @param additionalWebapp containing information about artifact from plugin configuration.
 1291  
      * @return Artifact object representing the specified file.
 1292  
      * @throws MojoExecutionException with a message if the version can't be found in DependencyManagement.
 1293  
      */
 1294  
     protected Artifact getArtifact( AbstractWebapp additionalWebapp )
 1295  
         throws MojoExecutionException
 1296  
     {
 1297  
 
 1298  
         Artifact artifact;
 1299  
         VersionRange vr;
 1300  
         try
 1301  
         {
 1302  0
             vr = VersionRange.createFromVersionSpec( additionalWebapp.getVersion() );
 1303  
         }
 1304  0
         catch ( InvalidVersionSpecificationException e )
 1305  
         {
 1306  0
             getLog().warn( "fail to create versionRange from version: " + additionalWebapp.getVersion(), e );
 1307  0
             vr = VersionRange.createFromVersion( additionalWebapp.getVersion() );
 1308  0
         }
 1309  
 
 1310  0
         if ( StringUtils.isEmpty( additionalWebapp.getClassifier() ) )
 1311  
         {
 1312  0
             artifact =
 1313  
                 factory.createDependencyArtifact( additionalWebapp.getGroupId(), additionalWebapp.getArtifactId(), vr,
 1314  
                                                   additionalWebapp.getType(), null, Artifact.SCOPE_COMPILE );
 1315  
         }
 1316  
         else
 1317  
         {
 1318  0
             artifact =
 1319  
                 factory.createDependencyArtifact( additionalWebapp.getGroupId(), additionalWebapp.getArtifactId(), vr,
 1320  
                                                   additionalWebapp.getType(), additionalWebapp.getClassifier(),
 1321  
                                                   Artifact.SCOPE_COMPILE );
 1322  
         }
 1323  
 
 1324  
         try
 1325  
         {
 1326  0
             resolver.resolve( artifact, project.getRemoteArtifactRepositories(), this.local );
 1327  
         }
 1328  0
         catch ( ArtifactResolutionException e )
 1329  
         {
 1330  0
             throw new MojoExecutionException( "Unable to resolve artifact.", e );
 1331  
         }
 1332  0
         catch ( ArtifactNotFoundException e )
 1333  
         {
 1334  0
             throw new MojoExecutionException( "Unable to find artifact.", e );
 1335  0
         }
 1336  
 
 1337  0
         return artifact;
 1338  
     }
 1339  
 }