| package org.apache.tomcat.maven.plugin.tomcat8.run; |
| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| |
| import org.apache.catalina.Context; |
| import org.apache.catalina.Host; |
| import org.apache.catalina.LifecycleException; |
| import org.apache.catalina.WebResource; |
| import org.apache.catalina.WebResourceSet; |
| import org.apache.catalina.Wrapper; |
| import org.apache.catalina.connector.Connector; |
| import org.apache.catalina.core.StandardContext; |
| import org.apache.catalina.loader.WebappLoader; |
| import org.apache.catalina.realm.MemoryRealm; |
| import org.apache.catalina.servlets.DefaultServlet; |
| import org.apache.catalina.startup.Catalina; |
| import org.apache.catalina.startup.CatalinaProperties; |
| import org.apache.catalina.startup.Tomcat; |
| import org.apache.catalina.valves.AccessLogValve; |
| import org.apache.catalina.webresources.FileResource; |
| import org.apache.catalina.webresources.StandardRoot; |
| import org.apache.commons.io.IOUtils; |
| import org.apache.commons.lang.StringUtils; |
| import org.apache.maven.artifact.Artifact; |
| import org.apache.maven.artifact.factory.ArtifactFactory; |
| import org.apache.maven.artifact.repository.ArtifactRepository; |
| import org.apache.maven.artifact.resolver.ArtifactNotFoundException; |
| import org.apache.maven.artifact.resolver.ArtifactResolutionException; |
| import org.apache.maven.artifact.resolver.ArtifactResolver; |
| import org.apache.maven.artifact.resolver.filter.ScopeArtifactFilter; |
| import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException; |
| import org.apache.maven.artifact.versioning.VersionRange; |
| import org.apache.maven.execution.MavenSession; |
| import org.apache.maven.plugin.MojoExecutionException; |
| import org.apache.maven.plugin.MojoFailureException; |
| import org.apache.maven.plugin.logging.Log; |
| import org.apache.maven.plugins.annotations.Component; |
| import org.apache.maven.plugins.annotations.Parameter; |
| import org.apache.maven.project.MavenProject; |
| import org.apache.maven.shared.filtering.MavenFileFilter; |
| import org.apache.maven.shared.filtering.MavenFileFilterRequest; |
| import org.apache.maven.shared.filtering.MavenFilteringException; |
| import org.apache.tomcat.JarScanner; |
| import org.apache.tomcat.maven.common.config.AbstractWebapp; |
| import org.apache.tomcat.maven.common.run.EmbeddedRegistry; |
| import org.apache.tomcat.maven.common.run.ExternalRepositoriesReloadableWebappLoader; |
| import org.apache.tomcat.maven.plugin.tomcat8.AbstractTomcat8Mojo; |
| import org.apache.tomcat.util.scan.StandardJarScanner; |
| import org.codehaus.plexus.archiver.ArchiverException; |
| import org.codehaus.plexus.archiver.UnArchiver; |
| import org.codehaus.plexus.archiver.manager.ArchiverManager; |
| import org.codehaus.plexus.archiver.manager.NoSuchArchiverException; |
| import org.codehaus.plexus.classworlds.ClassWorld; |
| import org.codehaus.plexus.classworlds.realm.ClassRealm; |
| import org.codehaus.plexus.classworlds.realm.DuplicateRealmException; |
| import org.codehaus.plexus.util.DirectoryScanner; |
| import org.codehaus.plexus.util.FileUtils; |
| import org.w3c.dom.Document; |
| import org.w3c.dom.NamedNodeMap; |
| import org.w3c.dom.Node; |
| import org.xml.sax.SAXException; |
| |
| import javax.servlet.ServletException; |
| import javax.xml.parsers.DocumentBuilder; |
| import javax.xml.parsers.DocumentBuilderFactory; |
| import javax.xml.parsers.ParserConfigurationException; |
| import javax.xml.stream.XMLInputFactory; |
| import javax.xml.stream.XMLStreamConstants; |
| import javax.xml.stream.XMLStreamException; |
| import javax.xml.stream.XMLStreamReader; |
| import java.io.File; |
| import java.io.FileInputStream; |
| import java.io.FileNotFoundException; |
| import java.io.FileOutputStream; |
| import java.io.IOException; |
| import java.net.MalformedURLException; |
| import java.net.URL; |
| import java.util.ArrayList; |
| import java.util.Collection; |
| import java.util.Collections; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Properties; |
| import java.util.Set; |
| |
| /** |
| * @author Olivier Lamy |
| * @since 2.0 |
| */ |
| public abstract class AbstractRunMojo |
| extends AbstractTomcat8Mojo |
| { |
| // --------------------------------------------------------------------- |
| // Mojo Components |
| // --------------------------------------------------------------------- |
| |
| /** |
| * Used to look up Artifacts in the remote repository. |
| */ |
| @Component |
| protected ArtifactFactory factory; |
| |
| /** |
| * Location of the local repository. |
| */ |
| @Parameter( defaultValue = "${localRepository}", required = true, readonly = true ) |
| private ArtifactRepository local; |
| |
| /** |
| * Used to look up Artifacts in the remote repository. |
| */ |
| @Component |
| protected ArtifactResolver resolver; |
| |
| // ---------------------------------------------------------------------- |
| // Mojo Parameters |
| // ---------------------------------------------------------------------- |
| |
| /** |
| * The packaging of the Maven project that this goal operates upon. |
| */ |
| @Parameter( defaultValue = "${project.packaging}", required = true, readonly = true ) |
| private String packaging; |
| |
| /** |
| * The directory to create the Tomcat server configuration under. |
| */ |
| @Parameter( defaultValue = "${project.build.directory}/tomcat" ) |
| private File configurationDir; |
| |
| /** |
| * The port to run the Tomcat server on. |
| * Will be exposed as System props and session.executionProperties with key tomcat.maven.http.port |
| */ |
| @Parameter( property = "maven.tomcat.port", defaultValue = "8080" ) |
| private int port; |
| |
| /** |
| * this IP address will be used on all ports |
| * |
| * @since 2.2 |
| */ |
| @Parameter( property = "maven.tomcat.address" ) |
| private String address; |
| |
| /** |
| * The AJP port to run the Tomcat server on. |
| * By default it's 0 this means won't be started. |
| * The ajp connector will be started only for value > 0. |
| * Will be exposed as System props and session.executionProperties with key tomcat.maven.ajp.port |
| * |
| * @since 2.0 |
| */ |
| @Parameter( property = "maven.tomcat.ajp.port", defaultValue = "0" ) |
| private int ajpPort; |
| |
| /** |
| * The AJP protocol to run the Tomcat server on. |
| * By default it's ajp. |
| * NOTE The ajp connector will be started only if {@link #ajpPort} > 0. |
| * possible values are: |
| * <ul> |
| * <li>org.apache.coyote.ajp.AjpProtocol - new blocking Java connector that supports an executor</li> |
| * <li>org.apache.coyote.ajp.AjpAprProtocol - the APR/native connector.</li> |
| * </ul> |
| * |
| * @since 2.0 |
| */ |
| @Parameter( property = "maven.tomcat.ajp.protocol", defaultValue = "org.apache.coyote.ajp.AjpProtocol" ) |
| private String ajpProtocol; |
| |
| /** |
| * The https port to run the Tomcat server on. |
| * By default it's 0 this means won't be started. |
| * The https connector will be started only for value > 0. |
| * Will be exposed as System props and session.executionProperties with key tomcat.maven.https.port |
| * |
| * @since 1.0 |
| */ |
| @Parameter( property = "maven.tomcat.httpsPort", defaultValue = "0" ) |
| private int httpsPort; |
| |
| /** |
| * The max post size to run the Tomcat server on. |
| * By default it's 2097152 bytes. That's the default Tomcat configuration. |
| * Set this value to 0 or less to disable the post size limit. |
| * |
| * @since 2.3 |
| */ |
| @Parameter( property = "maven.tomcat.maxPostSize", defaultValue = "2097152" ) |
| private int maxPostSize; |
| |
| /** |
| * The character encoding to use for decoding URIs. |
| * |
| * @since 1.0 |
| */ |
| @Parameter( property = "maven.tomcat.uriEncoding", defaultValue = "ISO-8859-1" ) |
| private String uriEncoding; |
| |
| /** |
| * List of System properties to pass to the Tomcat Server. |
| * |
| * @since 1.0-alpha-2 |
| */ |
| @Parameter |
| private Map<String, String> systemProperties; |
| |
| /** |
| * The directory contains additional configuration Files that copied in the Tomcat conf Directory. |
| * |
| * @since 1.0-alpha-2 |
| */ |
| @Parameter( property = "maven.tomcat.additionalConfigFilesDir", defaultValue = "${basedir}/src/main/tomcatconf" ) |
| private File additionalConfigFilesDir; |
| |
| /** |
| * server.xml to use <b>Note if you use this you must configure in this file your webapp paths</b>. |
| * |
| * @since 1.0-alpha-2 |
| */ |
| @Parameter( property = "maven.tomcat.serverXml" ) |
| private File serverXml; |
| |
| /** |
| * overriding the providing web.xml to run tomcat |
| * <b>This override the global Tomcat web.xml located in $CATALINA_HOME/conf/</b> |
| * |
| * @since 1.0-alpha-2 |
| */ |
| @Parameter( property = "maven.tomcat.webXml" ) |
| private File tomcatWebXml; |
| |
| /** |
| * Set this to true to allow Maven to continue to execute after invoking |
| * the run goal. |
| * |
| * @since 1.0 |
| */ |
| @Parameter( property = "maven.tomcat.fork", defaultValue = "false" ) |
| private boolean fork; |
| |
| /** |
| * Will create a tomcat context for each dependencies of war type with 'scope' set to 'tomcat'. |
| * In other words, dependencies with: |
| * <pre> |
| * <type>war</type> |
| * <scope>tomcat</scope> |
| * </pre> |
| * To preserve backward compatibility it's false by default. |
| * |
| * @since 1.0 |
| * @deprecated use webapps instead |
| */ |
| @Parameter( property = "maven.tomcat.addContextWarDependencies", defaultValue = "false" ) |
| private boolean addContextWarDependencies; |
| |
| /** |
| * The maven project. |
| * |
| * @since 1.0 |
| */ |
| @Component |
| protected MavenProject project; |
| |
| /** |
| * The archive manager. |
| * |
| * @since 1.0 |
| */ |
| @Component |
| private ArchiverManager archiverManager; |
| |
| /** |
| * if <code>true</code> a new classLoader separated from maven core will be created to start tomcat. |
| * |
| * @since 1.0 |
| */ |
| @Parameter( property = "tomcat.useSeparateTomcatClassLoader", defaultValue = "false" ) |
| protected boolean useSeparateTomcatClassLoader; |
| |
| /** |
| * @since 1.0 |
| */ |
| @Parameter( defaultValue = "${plugin.artifacts}", required = true ) |
| private List<Artifact> pluginArtifacts; |
| |
| /** |
| * If set to true ignore if packaging of project is not 'war'. |
| * |
| * @since 1.0 |
| */ |
| @Parameter( property = "tomcat.ignorePackaging", defaultValue = "false" ) |
| private boolean ignorePackaging; |
| |
| /** |
| * Override the default keystoreFile for the HTTPS connector (if enabled) |
| * |
| * @since 1.1 |
| */ |
| @Parameter |
| private String keystoreFile; |
| |
| /** |
| * Override the default keystorePass for the HTTPS connector (if enabled) |
| * |
| * @since 1.1 |
| */ |
| @Parameter |
| private String keystorePass; |
| |
| /** |
| * Override the type of keystore file to be used for the server certificate. If not specified, the default value is "JKS". |
| * |
| * @since 2.0 |
| */ |
| @Parameter( defaultValue = "JKS" ) |
| private String keystoreType; |
| |
| /** |
| * <p> |
| * Enables or disables naming support for the embedded Tomcat server. |
| * </p> |
| * <p> |
| * <strong>Note:</strong> This setting is ignored if you provide a <code>server.xml</code> for your |
| * Tomcat. Instead please configure naming in the <code>server.xml</code>. |
| * </p> |
| * |
| * @see <a href="http://tomcat.apache.org/tomcat-6.0-doc/api/org/apache/catalina/startup/Embedded.html">org.apache.catalina.startup.Embedded</a> |
| * @see <a href="http://tomcat.apache.org/tomcat-7.0-doc/api/org/apache/catalina/startup/Tomcat.html">org.apache.catalina.startup.Tomcat</a> |
| * @since 2.0 |
| */ |
| @Parameter( property = "maven.tomcat.useNaming", defaultValue = "true" ) |
| private boolean useNaming; |
| |
| /** |
| * Force context scanning if you don't use a context file with reloadable = "true". |
| * The other way to use contextReloadable is to add attribute reloadable = "true" |
| * in your context file. |
| * |
| * @since 2.0 |
| */ |
| @Parameter( property = "maven.tomcat.contextReloadable", defaultValue = "false" ) |
| protected boolean contextReloadable; |
| |
| /** |
| * represents the delay in seconds between each classPathScanning change invocation |
| * |
| * @see <a href="http://tomcat.apache.org/tomcat-7.0-doc/config/context.html">http://tomcat.apache.org/tomcat-7.0-doc/config/context.html</a> |
| */ |
| @Parameter( property = "maven.tomcat.backgroundProcessorDelay", defaultValue = "-1" ) |
| protected int backgroundProcessorDelay = -1; |
| |
| |
| /** |
| * <p>The path of the Tomcat context XML file.</p> |
| * <p>Since release 2.0, the file is filtered as a maven resource so you can use |
| * interpolation tokens ${ }</p> |
| */ |
| @Parameter( property = "maven.tomcat.contextFile" ) |
| protected File contextFile; |
| |
| /** |
| * The default context file to check for if contextFile not configured. |
| * If no contextFile configured and the below default not present, no |
| * contextFile will be sent to Tomcat, resulting in the latter's default |
| * context configuration being used instead. |
| */ |
| @Parameter( defaultValue = "${project.build.directory}/${project.build.finalName}/META-INF/context.xml", |
| readonly = true ) |
| private File defaultContextFile; |
| |
| /** |
| * The protocol to run the Tomcat server on. |
| * By default it's HTTP/1.1. |
| * See possible values <a href="http://tomcat.apache.org/tomcat-7.0-doc/config/http.html">HTTP Connector</a> |
| * protocol attribute |
| * |
| * @since 2.0 |
| */ |
| @Parameter( property = "maven.tomcat.protocol", defaultValue = "HTTP/1.1" ) |
| private String protocol; |
| |
| /** |
| * The path of the Tomcat users XML file. |
| * |
| * @since 2.0 |
| */ |
| @Parameter( property = "maven.tomcat.tomcatUsers.file" ) |
| private File tomcatUsers; |
| |
| /** |
| * The path of the Tomcat logging configuration. |
| * |
| * @since 2.0 |
| */ |
| @Parameter( property = "maven.tomcat.tomcatLogging.file" ) |
| private File tomcatLoggingFile; |
| |
| /** |
| * Skip execution |
| * |
| * @since 2.0 |
| */ |
| @Parameter( property = "maven.tomcat.skip", defaultValue = "false" ) |
| protected boolean skip; |
| |
| /** |
| * Collection of webapp artifacts to be deployed. Elements are <webapp> and contain |
| * usual GAVC plus contextPath and/or contextFile elements.<p> |
| * |
| * @see {@link Webapp} |
| * @since 2.0 |
| */ |
| @Parameter |
| private List<Webapp> webapps; |
| |
| /** |
| * The static context |
| * |
| * @since 2.0 |
| */ |
| @Parameter( property = "maven.tomcat.staticContextPath", defaultValue = "/" ) |
| private String staticContextPath; |
| |
| /** |
| * The static context docroot base fully qualified path |
| * if <code>null</code> static context won't be added |
| * |
| * @since 2.0 |
| */ |
| @Parameter( property = "maven.tomcat.staticContextDocbase" ) |
| private String staticContextDocbase; |
| |
| /** |
| * Class loader class to set. |
| * |
| * @since 2.0 |
| */ |
| @Parameter |
| protected String classLoaderClass; |
| |
| @Parameter( defaultValue = "${session}", readonly = true, required = true ) |
| protected MavenSession session; |
| |
| /** |
| * Will dump port in a properties file (see ports for property names). |
| * If empty no file generated |
| */ |
| @Parameter( property = "maven.tomcat.propertiesPortFilePath" ) |
| protected String propertiesPortFilePath; |
| |
| /** |
| * configure host name |
| * |
| * @since 2.0 |
| */ |
| @Parameter( property = "maven.tomcat.hostName", defaultValue = "localhost" ) |
| protected String hostName; |
| |
| /** |
| * configure aliases |
| * see <a href="http://tomcat.apache.org/tomcat-7.0-doc/config/host.html#Host_Name_Aliases">Host Name aliases</a> |
| * |
| * @since 2.0 |
| */ |
| @Parameter |
| protected String[] aliases; |
| |
| /** |
| * enable client authentication for https (if configured) |
| * see <a href="http://tomcat.apache.org/tomcat-7.0-doc/config/http.html#SSL_Support_-_BIO_and_NIO">http://tomcat.apache.org/tomcat-7.0-doc/config/http.html#SSL_Support_-_BIO_and_NIO</a> |
| * |
| * @since 2.1 |
| */ |
| @Parameter( property = "maven.tomcat.https.clientAuth", defaultValue = "false" ) |
| protected String clientAuth = "false"; |
| |
| @Component( role = MavenFileFilter.class, hint = "default" ) |
| protected MavenFileFilter mavenFileFilter; |
| |
| |
| /** |
| * In case a module in your reactors has some web-fragments they will be read. |
| * If you don't need that for performance reasons, you can deactivate it. |
| * |
| * @since 2.2 |
| */ |
| @Parameter( property = "maven.tomcat.jarScan.allDirectories", defaultValue = "true" ) |
| protected boolean jarScanAllDirectories = true; |
| |
| /** |
| * @since 2.2 |
| */ |
| @Parameter( property = "maven.tomcat.useBodyEncodingForURI", defaultValue = "false" ) |
| protected boolean useBodyEncodingForURI; |
| |
| /** |
| * @since 2.2 |
| */ |
| @Parameter |
| protected String trustManagerClassName; |
| |
| /** |
| * @since 2.2 |
| */ |
| @Parameter |
| protected String trustMaxCertLength; |
| |
| /** |
| * @since 2.2 |
| */ |
| @Parameter |
| protected String truststoreAlgorithm; |
| |
| /** |
| * @since 2.2 |
| */ |
| @Parameter |
| protected String truststoreFile; |
| |
| /** |
| * @since 2.2 |
| */ |
| @Parameter |
| protected String truststorePass; |
| |
| /** |
| * @since 2.2 |
| */ |
| @Parameter |
| protected String truststoreProvider; |
| |
| /** |
| * @since 2.2 |
| */ |
| @Parameter |
| protected String truststoreType; |
| |
| // ---------------------------------------------------------------------- |
| // Fields |
| // ---------------------------------------------------------------------- |
| |
| /** |
| * @since 1.0 |
| */ |
| private ClassRealm tomcatRealm; |
| |
| // ---------------------------------------------------------------------- |
| // Mojo Implementation |
| // ---------------------------------------------------------------------- |
| |
| /** |
| * {@inheritDoc} |
| */ |
| public void execute() |
| throws MojoExecutionException, MojoFailureException |
| { |
| if ( skip ) |
| { |
| getLog().info( "skip execution" ); |
| return; |
| } |
| // ensure project is a web application |
| if ( !isWar() && !addContextWarDependencies && getAdditionalWebapps().isEmpty() ) |
| { |
| getLog().info( messagesProvider.getMessage( "AbstractRunMojo.nonWar" ) ); |
| return; |
| } |
| ClassLoader originalClassLoader = null; |
| if ( useSeparateTomcatClassLoader ) |
| { |
| originalClassLoader = Thread.currentThread().getContextClassLoader(); |
| } |
| try |
| { |
| getLog().info( messagesProvider.getMessage( "AbstractRunMojo.runningWar", getWebappUrl() ) ); |
| |
| initConfiguration(); |
| startContainer(); |
| if ( !fork ) |
| { |
| waitIndefinitely(); |
| } |
| } |
| catch ( LifecycleException exception ) |
| { |
| throw new MojoExecutionException( messagesProvider.getMessage( "AbstractRunMojo.cannotStart" ), exception ); |
| } |
| catch ( IOException exception ) |
| { |
| throw new MojoExecutionException( |
| messagesProvider.getMessage( "AbstractRunMojo.cannotCreateConfiguration" ), exception ); |
| } |
| catch ( ServletException e ) |
| { |
| throw new MojoExecutionException( e.getMessage(), e ); |
| } |
| catch ( MavenFilteringException e ) |
| { |
| throw new MojoExecutionException( "filtering issue: " + e.getMessage(), e ); |
| } |
| finally |
| { |
| if ( useSeparateTomcatClassLoader ) |
| { |
| Thread.currentThread().setContextClassLoader( originalClassLoader ); |
| } |
| } |
| } |
| |
| // ---------------------------------------------------------------------- |
| // Protected Methods |
| // ---------------------------------------------------------------------- |
| |
| /** |
| * Gets the webapp context path to use for the web application being run. |
| * |
| * @return the webapp context path |
| */ |
| protected String getPath() |
| { |
| return path; |
| } |
| |
| protected void enhanceContext( final Context context ) |
| throws MojoExecutionException |
| { |
| // no op |
| } |
| |
| |
| /** |
| * Gets the context to run this web application under for the specified embedded Tomcat. |
| * |
| * @param container the embedded Tomcat container being used |
| * @return the context to run this web application under |
| * @throws IOException if the context could not be created |
| * @throws MojoExecutionException in case of an error creating the context |
| */ |
| protected Context createContext( Tomcat container ) |
| throws IOException, MojoExecutionException, ServletException |
| { |
| String contextPath = getPath(); |
| |
| String baseDir = getDocBase().getAbsolutePath(); |
| |
| File overriddenContextFile = getContextFile(); |
| |
| StandardContext standardContext = null; |
| |
| if ( overriddenContextFile != null && overriddenContextFile.exists() ) |
| { |
| standardContext = parseContextFile( overriddenContextFile ); |
| } |
| else if ( defaultContextFile.exists() ) |
| { |
| standardContext = parseContextFile( defaultContextFile ); |
| } |
| |
| if ( standardContext != null ) |
| { |
| if ( standardContext.getPath() != null ) |
| { |
| contextPath = standardContext.getPath(); |
| } |
| if ( standardContext.getDocBase() != null ) |
| { |
| baseDir = standardContext.getDocBase(); |
| } |
| } |
| |
| contextPath = "/".equals( contextPath ) ? "" : contextPath; |
| |
| getLog().info( "create webapp with contextPath: " + contextPath ); |
| |
| Context context = container.addWebapp( contextPath, baseDir ); |
| |
| context.setResources( |
| new MyDirContext( new File( project.getBuild().getOutputDirectory() ).getAbsolutePath(), // |
| getPath(), // |
| getLog() ) ); |
| |
| if ( useSeparateTomcatClassLoader ) |
| { |
| context.setParentClassLoader( getTomcatClassLoader() ); |
| } |
| |
| enhanceContext( context ); |
| |
| final WebappLoader loader = createWebappLoader(); |
| |
| context.setLoader( loader ); |
| |
| if ( overriddenContextFile != null ) |
| { |
| // here, send file to Tomcat for it to complain if missing |
| context.setConfigFile( overriddenContextFile.toURI().toURL() ); |
| } |
| else if ( defaultContextFile.exists() ) |
| { |
| // here, only sending default file if it indeed exists |
| // otherwise Tomcat will create a default context |
| context.setConfigFile( defaultContextFile.toURI().toURL() ); |
| } |
| |
| if ( classLoaderClass != null ) |
| { |
| loader.setLoaderClass( classLoaderClass ); |
| } |
| |
| // https://issues.apache.org/jira/browse/MTOMCAT-239 |
| // get the jar scanner to configure scanning directories as we can run a jar or a reactor project with a jar so |
| // the entries is a directory (target/classes) |
| JarScanner jarScanner = context.getJarScanner(); |
| |
| // normally this one only but just in case ... |
| if ( jarScanner instanceof StandardJarScanner ) |
| { |
| ( (StandardJarScanner) jarScanner ).setScanAllDirectories( jarScanAllDirectories ); |
| } |
| |
| return context; |
| |
| } |
| |
| protected StandardContext parseContextFile( File file ) |
| throws MojoExecutionException |
| { |
| try |
| { |
| StandardContext standardContext = new StandardContext(); |
| XMLStreamReader reader = XMLInputFactory.newFactory().createXMLStreamReader( new FileInputStream( file ) ); |
| |
| int tag = reader.next(); |
| |
| while ( true ) |
| { |
| if ( tag == XMLStreamConstants.START_ELEMENT && StringUtils.equals( "Context", reader.getLocalName() ) ) |
| { |
| String path = reader.getAttributeValue( null, "path" ); |
| if ( StringUtils.isNotBlank( path ) ) |
| { |
| standardContext.setPath( path ); |
| } |
| |
| String docBase = reader.getAttributeValue( null, "docBase" ); |
| if ( StringUtils.isNotBlank( docBase ) ) |
| { |
| standardContext.setDocBase( docBase ); |
| } |
| } |
| if ( !reader.hasNext() ) |
| { |
| break; |
| } |
| tag = reader.next(); |
| } |
| |
| return standardContext; |
| } |
| catch ( XMLStreamException e ) |
| { |
| throw new MojoExecutionException( e.getMessage(), e ); |
| } |
| catch ( FileNotFoundException e ) |
| { |
| throw new MojoExecutionException( e.getMessage(), e ); |
| } |
| } |
| |
| |
| protected static class MyDirContext |
| extends StandardRoot |
| { |
| String buildOutputDirectory; |
| |
| String webAppPath; |
| |
| WebResourceSet webResourceSet; |
| |
| Log log; |
| |
| MyDirContext( String buildOutputDirectory, String webAppPath, Log log ) |
| { |
| |
| this.buildOutputDirectory = buildOutputDirectory; |
| this.webAppPath = webAppPath; |
| this.log = log; |
| } |
| |
| @Override |
| public WebResource getResource( String path ) |
| { |
| |
| log.debug( "MyDirContext#getResource: " + path ); |
| if ( "/WEB-INF/classes".equals( path ) ) |
| { |
| return new FileResource( this, this.webAppPath, new File( this.buildOutputDirectory ), true ); |
| } |
| |
| File file = new File( path ); |
| if ( file.exists() ) |
| { |
| return new FileResource( this, this.webAppPath, file, true ); |
| } |
| WebResource webResource = super.getResource( path ); |
| return webResource; |
| } |
| |
| |
| @Override |
| public WebResource getClassLoaderResource( String path ) |
| { |
| log.debug( "MyDirContext#getClassLoaderResource: " + path ); |
| // here get resources from various paths |
| return super.getClassLoaderResource( path ); |
| } |
| |
| |
| @Override |
| public WebResource[] listResources( String path ) |
| { |
| log.debug( "MyDirContext#listResources: " + path ); |
| return super.listResources( path ); |
| } |
| |
| @Override |
| public WebResource[] getClassLoaderResources( String path ) |
| { |
| log.debug( "MyDirContext#getClassLoaderResources: " + path ); |
| return super.getClassLoaderResources( path ); |
| } |
| |
| @Override |
| public WebResource[] getResources( String path ) |
| { |
| log.debug( "MyDirContext#getResources: " + path ); |
| return super.getResources( path ); |
| } |
| |
| @Override |
| protected WebResource[] getResourcesInternal( String path, boolean useClassLoaderResources ) |
| { |
| log.debug( "MyDirContext#getResourcesInternal: " + path ); |
| return super.getResourcesInternal( path, useClassLoaderResources ); |
| } |
| |
| |
| } |
| |
| /** |
| * Gets the webapp loader to run this web application under. |
| * |
| * @return the webapp loader to use |
| * @throws IOException if the webapp loader could not be created |
| * @throws MojoExecutionException in case of an error creating the webapp loader |
| */ |
| protected WebappLoader createWebappLoader() |
| throws IOException, MojoExecutionException |
| { |
| WebappLoader webappLoader = null; |
| if ( useSeparateTomcatClassLoader ) |
| { |
| if ( isContextReloadable() ) |
| { |
| webappLoader = new ExternalRepositoriesReloadableWebappLoader( getTomcatClassLoader(), getLog() ); |
| } |
| else |
| { |
| webappLoader = new WebappLoader( getTomcatClassLoader() ); |
| } |
| } |
| else |
| { |
| if ( isContextReloadable() ) |
| { |
| webappLoader = |
| new ExternalRepositoriesReloadableWebappLoader( Thread.currentThread().getContextClassLoader(), |
| getLog() ); |
| } |
| else |
| { |
| webappLoader = new WebappLoader( Thread.currentThread().getContextClassLoader() ); |
| } |
| } |
| return webappLoader; |
| } |
| |
| /** |
| * Determine whether the passed context.xml file declares the context as reloadable or not. |
| * |
| * @return false by default, true if reloadable="true" in context.xml. |
| */ |
| protected boolean isContextReloadable() |
| throws MojoExecutionException |
| { |
| if ( contextReloadable || backgroundProcessorDelay > 0 ) |
| { |
| return true; |
| } |
| // determine whether to use a reloadable Loader or not (default is false). |
| boolean reloadable = false; |
| try |
| { |
| if ( contextFile != null && contextFile.exists() ) |
| { |
| DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance(); |
| DocumentBuilder builder = builderFactory.newDocumentBuilder(); |
| Document contextDoc = builder.parse( contextFile ); |
| contextDoc.getDocumentElement().normalize(); |
| |
| NamedNodeMap nodeMap = contextDoc.getDocumentElement().getAttributes(); |
| Node reloadableAttribute = nodeMap.getNamedItem( "reloadable" ); |
| |
| reloadable = |
| ( reloadableAttribute != null ) ? Boolean.valueOf( reloadableAttribute.getNodeValue() ) : false; |
| } |
| getLog().debug( "context reloadable: " + reloadable ); |
| } |
| catch ( IOException ioe ) |
| { |
| getLog().error( "Could not parse file: [" + contextFile.getAbsolutePath() + "]", ioe ); |
| } |
| catch ( ParserConfigurationException pce ) |
| { |
| getLog().error( "Could not configure XML parser", pce ); |
| } |
| catch ( SAXException se ) |
| { |
| getLog().error( "Could not parse file: [" + contextFile.getAbsolutePath() + "]", se ); |
| } |
| |
| return reloadable; |
| } |
| |
| |
| /** |
| * Gets the webapp directory to run. |
| * |
| * @return the webapp directory |
| */ |
| protected abstract File getDocBase() |
| throws IOException; |
| |
| /** |
| * Gets the Tomcat context XML file to use. |
| * |
| * @return the context XML file |
| */ |
| protected abstract File getContextFile() |
| throws MojoExecutionException; |
| |
| // ---------------------------------------------------------------------- |
| // Private Methods |
| // ---------------------------------------------------------------------- |
| |
| /** |
| * Gets whether this project uses WAR packaging. |
| * |
| * @return whether this project uses WAR packaging |
| */ |
| protected boolean isWar() |
| { |
| return "war".equals( packaging ) || ignorePackaging; |
| } |
| |
| /** |
| * Gets the URL of the running webapp. |
| * |
| * @return the URL of the running webapp |
| * @throws java.net.MalformedURLException if the running webapp URL is invalid |
| */ |
| private URL getWebappUrl() |
| throws MalformedURLException |
| { |
| return new URL( "http", "localhost", port, getPath() ); |
| } |
| |
| /** |
| * FIXME not sure we need all of those files with tomcat8 |
| * Creates the Tomcat configuration directory with the necessary resources. |
| * |
| * @throws IOException if the Tomcat configuration could not be created |
| * @throws MojoExecutionException if the Tomcat configuration could not be created |
| */ |
| private void initConfiguration() |
| throws IOException, MojoExecutionException, MavenFilteringException |
| { |
| if ( configurationDir.exists() ) |
| { |
| getLog().info( messagesProvider.getMessage( "AbstractRunMojo.usingConfiguration", configurationDir ) ); |
| } |
| else |
| { |
| getLog().info( messagesProvider.getMessage( "AbstractRunMojo.creatingConfiguration", configurationDir ) ); |
| |
| configurationDir.mkdirs(); |
| |
| File confDir = new File( configurationDir, "conf" ); |
| confDir.mkdir(); |
| |
| if ( tomcatLoggingFile != null ) |
| { |
| FileUtils.copyFile( tomcatLoggingFile, new File( confDir, "logging.properties" ) ); |
| } |
| else |
| { |
| copyFile( "/conf/logging.properties", new File( confDir, "logging.properties" ) ); |
| } |
| |
| copyFile( "/conf/tomcat-users.xml", new File( confDir, "tomcat-users.xml" ) ); |
| if ( tomcatWebXml != null ) |
| { |
| if ( !tomcatWebXml.exists() ) |
| { |
| throw new MojoExecutionException( " tomcatWebXml " + tomcatWebXml.getPath() + " not exists" ); |
| } |
| //MTOMCAT-42 here it's a real file resources not a one coming with the mojo |
| //MTOMCAT-128 apply filtering |
| MavenFileFilterRequest mavenFileFilterRequest = new MavenFileFilterRequest(); |
| mavenFileFilterRequest.setFrom( tomcatWebXml ); |
| mavenFileFilterRequest.setTo( new File( confDir, "web.xml" ) ); |
| mavenFileFilterRequest.setMavenProject( project ); |
| mavenFileFilterRequest.setMavenSession( session ); |
| mavenFileFilterRequest.setFiltering( true ); |
| |
| mavenFileFilter.copyFile( mavenFileFilterRequest ); |
| |
| } |
| else |
| { |
| copyFile( "/conf/web.xml", new File( confDir, "web.xml" ) ); |
| } |
| |
| File logDir = new File( configurationDir, "logs" ); |
| logDir.mkdir(); |
| |
| File webappsDir = new File( configurationDir, "webapps" ); |
| webappsDir.mkdir(); |
| |
| if ( additionalConfigFilesDir != null && additionalConfigFilesDir.exists() ) |
| { |
| DirectoryScanner scanner = new DirectoryScanner(); |
| scanner.addDefaultExcludes(); |
| scanner.setBasedir( additionalConfigFilesDir.getPath() ); |
| scanner.scan(); |
| |
| String[] files = scanner.getIncludedFiles(); |
| |
| if ( files != null && files.length > 0 ) |
| { |
| getLog().info( "Coping additional tomcat config files" ); |
| |
| for ( int i = 0; i < files.length; i++ ) |
| { |
| File file = new File( additionalConfigFilesDir, files[i] ); |
| |
| getLog().info( " copy " + file.getName() ); |
| |
| FileUtils.copyFileToDirectory( file, confDir ); |
| } |
| } |
| } |
| } |
| } |
| |
| /** |
| * Copies the specified class resource to the specified file. |
| * |
| * @param fromPath the path of the class resource to copy |
| * @param toFile the file to copy to |
| * @throws IOException if the file could not be copied |
| */ |
| private void copyFile( String fromPath, File toFile ) |
| throws IOException |
| { |
| URL fromURL = getClass().getResource( fromPath ); |
| |
| if ( fromURL == null ) |
| { |
| throw new FileNotFoundException( fromPath ); |
| } |
| |
| FileUtils.copyURLToFile( fromURL, toFile ); |
| } |
| |
| /** |
| * Starts the embedded Tomcat server. |
| * |
| * @throws IOException if the server could not be configured |
| * @throws LifecycleException if the server could not be started |
| * @throws MojoExecutionException if the server could not be configured |
| */ |
| private void startContainer() |
| throws IOException, LifecycleException, MojoExecutionException, ServletException |
| { |
| String previousCatalinaBase = System.getProperty( "catalina.base" ); |
| |
| try |
| { |
| |
| // Set the system properties |
| setupSystemProperties(); |
| |
| System.setProperty( "catalina.base", configurationDir.getAbsolutePath() ); |
| |
| if ( serverXml != null ) |
| { |
| if ( !serverXml.exists() ) |
| { |
| throw new MojoExecutionException( serverXml.getPath() + " not exists" ); |
| } |
| |
| Catalina container = new Catalina(); |
| |
| if ( useSeparateTomcatClassLoader ) |
| { |
| Thread.currentThread().setContextClassLoader( getTomcatClassLoader() ); |
| container.setParentClassLoader( getTomcatClassLoader() ); |
| } |
| |
| container.setUseNaming( this.useNaming ); |
| container.setConfigFile( serverXml.getAbsolutePath() ); |
| container.start(); |
| EmbeddedRegistry.getInstance().register( container ); |
| } |
| else |
| { |
| |
| System.setProperty( "java.util.logging.manager", "org.apache.juli.ClassLoaderLogManager" ); |
| System.setProperty( "java.util.logging.config.file", |
| new File( configurationDir, "conf/logging.properties" ).toString() ); |
| |
| // Trigger loading of catalina.properties |
| CatalinaProperties.getProperty( "foo" ); |
| |
| Tomcat embeddedTomcat = new ExtendedTomcat( configurationDir ); |
| |
| embeddedTomcat.setBaseDir( configurationDir.getAbsolutePath() ); |
| MemoryRealm memoryRealm = new MemoryRealm(); |
| |
| if ( tomcatUsers != null ) |
| { |
| if ( !tomcatUsers.exists() ) |
| { |
| throw new MojoExecutionException( " tomcatUsers " + tomcatUsers.getPath() + " not exists" ); |
| } |
| getLog().info( "use tomcat-users.xml from " + tomcatUsers.getAbsolutePath() ); |
| memoryRealm.setPathname( tomcatUsers.getAbsolutePath() ); |
| } |
| |
| embeddedTomcat.getEngine().setRealm( memoryRealm ); |
| |
| Context ctx = createContext( embeddedTomcat ); |
| |
| if ( useNaming ) |
| { |
| embeddedTomcat.enableNaming(); |
| } |
| |
| embeddedTomcat.getHost().setAppBase( new File( configurationDir, "webapps" ).getAbsolutePath() ); |
| |
| if ( hostName != null ) |
| { |
| embeddedTomcat.getHost().setName( hostName ); |
| } |
| if ( aliases != null ) |
| { |
| for ( String alias : aliases ) |
| { |
| embeddedTomcat.getHost().addAlias( alias ); |
| } |
| |
| } |
| createStaticContext( embeddedTomcat, ctx, embeddedTomcat.getHost() ); |
| |
| Connector connector = new Connector( protocol ); |
| connector.setPort( port ); |
| connector.setMaxPostSize( maxPostSize ); |
| |
| if ( httpsPort > 0 ) |
| { |
| connector.setRedirectPort( httpsPort ); |
| } |
| |
| if ( address != null ) |
| { |
| connector.setAttribute( "address", address ); |
| } |
| |
| connector.setURIEncoding( uriEncoding ); |
| |
| connector.setUseBodyEncodingForURI( this.useBodyEncodingForURI ); |
| |
| embeddedTomcat.getService().addConnector( connector ); |
| |
| embeddedTomcat.setConnector( connector ); |
| |
| AccessLogValve alv = new AccessLogValve(); |
| alv.setDirectory( new File( configurationDir, "logs" ).getAbsolutePath() ); |
| alv.setPattern( "%h %l %u %t \"%r\" %s %b %I %D" ); |
| embeddedTomcat.getHost().getPipeline().addValve( alv ); |
| |
| // create https connector |
| Connector httpsConnector = null; |
| if ( httpsPort > 0 ) |
| { |
| httpsConnector = new Connector( protocol ); |
| httpsConnector.setPort( httpsPort ); |
| httpsConnector.setMaxPostSize( maxPostSize ); |
| httpsConnector.setSecure( true ); |
| httpsConnector.setProperty( "SSLEnabled", "true" ); |
| // should be default but configure it anyway |
| httpsConnector.setProperty( "sslProtocol", "TLS" ); |
| if ( keystoreFile != null ) |
| { |
| httpsConnector.setAttribute( "keystoreFile", keystoreFile ); |
| } |
| if ( keystorePass != null ) |
| { |
| httpsConnector.setAttribute( "keystorePass", keystorePass ); |
| } |
| if ( keystoreType != null ) |
| { |
| httpsConnector.setAttribute( "keystoreType", keystoreType ); |
| } |
| |
| if ( trustManagerClassName != null ) |
| { |
| httpsConnector.setAttribute( "trustManagerClassName", trustManagerClassName ); |
| } |
| |
| if ( trustMaxCertLength != null ) |
| { |
| httpsConnector.setAttribute( "trustMaxCertLength", trustMaxCertLength ); |
| } |
| |
| if ( truststoreAlgorithm != null ) |
| { |
| httpsConnector.setAttribute( "truststoreAlgorithm", truststoreAlgorithm ); |
| } |
| |
| if ( truststoreFile != null ) |
| { |
| httpsConnector.setAttribute( "truststoreFile", truststoreFile ); |
| } |
| |
| if ( truststorePass != null ) |
| { |
| httpsConnector.setAttribute( "truststorePass", truststorePass ); |
| } |
| |
| if ( truststoreProvider != null ) |
| { |
| httpsConnector.setAttribute( "truststoreProvider", truststoreProvider ); |
| } |
| |
| if ( truststoreType != null ) |
| { |
| httpsConnector.setAttribute( "truststoreType", truststoreType ); |
| } |
| |
| httpsConnector.setAttribute( "clientAuth", clientAuth ); |
| |
| httpsConnector.setUseBodyEncodingForURI( this.useBodyEncodingForURI ); |
| |
| if ( address != null ) |
| { |
| httpsConnector.setAttribute( "address", address ); |
| } |
| |
| embeddedTomcat.getEngine().getService().addConnector( httpsConnector ); |
| |
| } |
| |
| // create ajp connector |
| Connector ajpConnector = null; |
| if ( ajpPort > 0 ) |
| { |
| ajpConnector = new Connector( ajpProtocol ); |
| ajpConnector.setPort( ajpPort ); |
| ajpConnector.setURIEncoding( uriEncoding ); |
| ajpConnector.setUseBodyEncodingForURI( this.useBodyEncodingForURI ); |
| if ( address != null ) |
| { |
| ajpConnector.setAttribute( "address", address ); |
| } |
| embeddedTomcat.getEngine().getService().addConnector( ajpConnector ); |
| } |
| |
| if ( addContextWarDependencies || !getAdditionalWebapps().isEmpty() ) |
| { |
| createDependencyContexts( embeddedTomcat ); |
| } |
| |
| if ( useSeparateTomcatClassLoader ) |
| { |
| Thread.currentThread().setContextClassLoader( getTomcatClassLoader() ); |
| embeddedTomcat.getEngine().setParentClassLoader( getTomcatClassLoader() ); |
| } |
| |
| embeddedTomcat.start(); |
| |
| Properties portProperties = new Properties(); |
| |
| portProperties.put( "tomcat.maven.http.port", Integer.toString( connector.getLocalPort() ) ); |
| |
| session.getExecutionProperties().put( "tomcat.maven.http.port", |
| Integer.toString( connector.getLocalPort() ) ); |
| System.setProperty( "tomcat.maven.http.port", Integer.toString( connector.getLocalPort() ) ); |
| |
| if ( httpsConnector != null ) |
| { |
| session.getExecutionProperties().put( "tomcat.maven.https.port", |
| Integer.toString( httpsConnector.getLocalPort() ) ); |
| portProperties.put( "tomcat.maven.https.port", Integer.toString( httpsConnector.getLocalPort() ) ); |
| System.setProperty( "tomcat.maven.https.port", Integer.toString( httpsConnector.getLocalPort() ) ); |
| } |
| |
| if ( ajpConnector != null ) |
| { |
| session.getExecutionProperties().put( "tomcat.maven.ajp.port", |
| Integer.toString( ajpConnector.getLocalPort() ) ); |
| portProperties.put( "tomcat.maven.ajp.port", Integer.toString( ajpConnector.getLocalPort() ) ); |
| System.setProperty( "tomcat.maven.ajp.port", Integer.toString( ajpConnector.getLocalPort() ) ); |
| } |
| if ( propertiesPortFilePath != null ) |
| { |
| File propertiesPortsFile = new File( propertiesPortFilePath ); |
| if ( propertiesPortsFile.exists() ) |
| { |
| propertiesPortsFile.delete(); |
| } |
| FileOutputStream fileOutputStream = new FileOutputStream( propertiesPortsFile ); |
| try |
| { |
| portProperties.store( fileOutputStream, "Apache Tomcat Maven plugin port used" ); |
| } |
| finally |
| { |
| IOUtils.closeQuietly( fileOutputStream ); |
| } |
| } |
| |
| EmbeddedRegistry.getInstance().register( embeddedTomcat ); |
| |
| } |
| |
| |
| } |
| finally |
| { |
| if ( previousCatalinaBase != null ) |
| { |
| System.setProperty( "catalina.base", previousCatalinaBase ); |
| } |
| } |
| } |
| |
| private List<Webapp> getAdditionalWebapps() |
| { |
| if ( webapps == null ) |
| { |
| return Collections.emptyList(); |
| } |
| return webapps; |
| } |
| |
| protected ClassRealm getTomcatClassLoader() |
| throws MojoExecutionException |
| { |
| if ( this.tomcatRealm != null ) |
| { |
| return tomcatRealm; |
| } |
| try |
| { |
| ClassWorld world = new ClassWorld(); |
| ClassRealm root = world.newRealm( "tomcat", Thread.currentThread().getContextClassLoader() ); |
| |
| for ( Iterator<Artifact> i = pluginArtifacts.iterator(); i.hasNext(); ) |
| { |
| Artifact pluginArtifact = i.next(); |
| // add all plugin artifacts see https://issues.apache.org/jira/browse/MTOMCAT-122 |
| if ( pluginArtifact.getFile() != null ) |
| { |
| root.addURL( pluginArtifact.getFile().toURI().toURL() ); |
| } |
| |
| } |
| tomcatRealm = root; |
| return root; |
| } |
| catch ( DuplicateRealmException e ) |
| { |
| throw new MojoExecutionException( e.getMessage(), e ); |
| } |
| catch ( MalformedURLException e ) |
| { |
| throw new MojoExecutionException( e.getMessage(), e ); |
| } |
| } |
| |
| @SuppressWarnings( "unchecked" ) |
| public Set<Artifact> getProjectArtifacts() |
| { |
| return project.getArtifacts(); |
| } |
| |
| /** |
| * Causes the current thread to wait indefinitely. This method does not return. |
| */ |
| private void waitIndefinitely() |
| { |
| Object lock = new Object(); |
| |
| synchronized ( lock ) |
| { |
| try |
| { |
| lock.wait(); |
| } |
| catch ( InterruptedException exception ) |
| { |
| getLog().warn( messagesProvider.getMessage( "AbstractRunMojo.interrupted" ), exception ); |
| } |
| } |
| } |
| |
| |
| /** |
| * Set the SystemProperties from the configuration. |
| */ |
| private void setupSystemProperties() |
| { |
| if ( systemProperties != null && !systemProperties.isEmpty() ) |
| { |
| getLog().info( "setting SystemProperties:" ); |
| |
| for ( String key : systemProperties.keySet() ) |
| { |
| String value = systemProperties.get( key ); |
| |
| if ( value != null ) |
| { |
| getLog().info( " " + key + "=" + value ); |
| System.setProperty( key, value ); |
| } |
| else |
| { |
| getLog().info( "skip sysProps " + key + " with empty value" ); |
| } |
| } |
| } |
| } |
| |
| |
| /** |
| * Allows the startup of additional webapps in the tomcat container by declaration with scope |
| * "tomcat". |
| * |
| * @param container tomcat |
| * @return dependency tomcat contexts of warfiles in scope "tomcat" |
| */ |
| private Collection<Context> createDependencyContexts( Tomcat container ) |
| throws MojoExecutionException, MalformedURLException, ServletException, IOException |
| { |
| getLog().info( "Deploying dependency wars" ); |
| // Let's add other modules |
| List<Context> contexts = new ArrayList<Context>(); |
| |
| ScopeArtifactFilter filter = new ScopeArtifactFilter( "tomcat" ); |
| @SuppressWarnings( "unchecked" ) Set<Artifact> artifacts = project.getArtifacts(); |
| for ( Artifact artifact : artifacts ) |
| { |
| |
| // Artifact is not yet registered and it has neither test, nor a |
| // provided scope, not is it optional |
| if ( "war".equals( artifact.getType() ) && !artifact.isOptional() && filter.include( artifact ) ) |
| { |
| addContextFromArtifact( container, contexts, artifact, "/" + artifact.getArtifactId(), null, false ); |
| } |
| } |
| |
| for ( AbstractWebapp additionalWebapp : getAdditionalWebapps() ) |
| { |
| String contextPath = additionalWebapp.getContextPath(); |
| if ( !contextPath.startsWith( "/" ) ) |
| { |
| contextPath = "/" + contextPath; |
| } |
| addContextFromArtifact( container, contexts, getArtifact( additionalWebapp ), contextPath, |
| additionalWebapp.getContextFile(), additionalWebapp.isAsWebapp() ); |
| } |
| return contexts; |
| } |
| |
| |
| private void addContextFromArtifact( Tomcat container, List<Context> contexts, Artifact artifact, |
| String contextPath, File contextXml, boolean asWebApp ) |
| throws MojoExecutionException, ServletException, IOException |
| { |
| getLog().info( "Deploy warfile: " + String.valueOf( artifact.getFile() ) + " to contextPath: " + contextPath ); |
| File webapps = new File( configurationDir, "webapps" ); |
| File artifactWarDir = new File( webapps, artifact.getArtifactId() ); |
| if ( !artifactWarDir.exists() ) |
| { |
| //dont extract if exists |
| artifactWarDir.mkdir(); |
| try |
| { |
| UnArchiver unArchiver = archiverManager.getUnArchiver( "zip" ); |
| unArchiver.setSourceFile( artifact.getFile() ); |
| unArchiver.setDestDirectory( artifactWarDir ); |
| |
| // Extract the module |
| unArchiver.extract(); |
| } |
| catch ( NoSuchArchiverException e ) |
| { |
| getLog().error( e ); |
| return; |
| } |
| catch ( ArchiverException e ) |
| { |
| getLog().error( e ); |
| return; |
| } |
| } |
| // TODO make that configurable ? |
| //WebappLoader webappLoader = new WebappLoader( Thread.currentThread().getContextClassLoader() ); |
| WebappLoader webappLoader = createWebappLoader(); |
| Context context = null; |
| if ( asWebApp ) |
| { |
| context = container.addWebapp( contextPath, artifactWarDir.getAbsolutePath() ); |
| } |
| else |
| { |
| context = container.addContext( contextPath, artifactWarDir.getAbsolutePath() ); |
| } |
| context.setLoader( webappLoader ); |
| |
| File contextFile = contextXml != null ? contextXml : getContextFile(); |
| if ( contextFile != null ) |
| { |
| context.setConfigFile( contextFile.toURI().toURL() ); |
| } |
| |
| contexts.add( context ); |
| // container.getHost().addChild(context); |
| } |
| |
| private void createStaticContext( final Tomcat container, Context context, Host host ) |
| { |
| if ( staticContextDocbase != null ) |
| { |
| Context staticContext = container.addContext( staticContextPath, staticContextDocbase ); |
| staticContext.setPrivileged( true ); |
| Wrapper servlet = context.createWrapper(); |
| servlet.setServletClass( DefaultServlet.class.getName() ); |
| servlet.setName( "staticContent" ); |
| staticContext.addChild( servlet ); |
| staticContext.addServletMapping( "/", "staticContent" ); |
| // see https://issues.apache.org/jira/browse/MTOMCAT-238 |
| //host.addChild( staticContext ); |
| } |
| } |
| |
| |
| /** |
| * Resolves the Artifact from the remote repository if necessary. If no version is specified, it will be retrieved |
| * from the dependency list or from the DependencyManagement section of the pom. |
| * |
| * @param additionalWebapp containing information about artifact from plugin configuration. |
| * @return Artifact object representing the specified file. |
| * @throws MojoExecutionException with a message if the version can't be found in DependencyManagement. |
| */ |
| protected Artifact getArtifact( AbstractWebapp additionalWebapp ) |
| throws MojoExecutionException |
| { |
| |
| Artifact artifact; |
| VersionRange vr; |
| try |
| { |
| vr = VersionRange.createFromVersionSpec( additionalWebapp.getVersion() ); |
| } |
| catch ( InvalidVersionSpecificationException e ) |
| { |
| getLog().warn( "fail to create versionRange from version: " + additionalWebapp.getVersion(), e ); |
| vr = VersionRange.createFromVersion( additionalWebapp.getVersion() ); |
| } |
| |
| if ( StringUtils.isEmpty( additionalWebapp.getClassifier() ) ) |
| { |
| artifact = |
| factory.createDependencyArtifact( additionalWebapp.getGroupId(), additionalWebapp.getArtifactId(), vr, |
| additionalWebapp.getType(), null, Artifact.SCOPE_COMPILE ); |
| } |
| else |
| { |
| artifact = |
| factory.createDependencyArtifact( additionalWebapp.getGroupId(), additionalWebapp.getArtifactId(), vr, |
| additionalWebapp.getType(), additionalWebapp.getClassifier(), |
| Artifact.SCOPE_COMPILE ); |
| } |
| |
| try |
| { |
| resolver.resolve( artifact, project.getRemoteArtifactRepositories(), this.local ); |
| } |
| catch ( ArtifactResolutionException e ) |
| { |
| throw new MojoExecutionException( "Unable to resolve artifact.", e ); |
| } |
| catch ( ArtifactNotFoundException e ) |
| { |
| throw new MojoExecutionException( "Unable to find artifact.", e ); |
| } |
| |
| return artifact; |
| } |
| } |