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 java.io.File; 22 import java.io.FileInputStream; 23 import java.io.FileOutputStream; 24 import java.io.IOException; 25 import java.io.PrintWriter; 26 import java.util.Properties; 27 import java.util.jar.JarFile; 28 29 import org.apache.commons.compress.archivers.ArchiveException; 30 import org.apache.commons.compress.archivers.ArchiveOutputStream; 31 import org.apache.commons.compress.archivers.ArchiveStreamFactory; 32 import org.apache.commons.compress.archivers.jar.JarArchiveEntry; 33 import org.apache.commons.io.IOUtils; 34 import org.apache.commons.lang.StringUtils; 35 import org.apache.maven.artifact.Artifact; 36 import org.apache.maven.artifact.resolver.ArtifactNotFoundException; 37 import org.apache.maven.artifact.resolver.ArtifactResolutionException; 38 import org.apache.maven.model.Dependency; 39 import org.apache.maven.plugin.MojoExecutionException; 40 import org.apache.maven.plugin.MojoFailureException; 41 import org.apache.maven.plugins.annotations.Parameter; 42 import org.apache.tomcat.maven.runner.Tomcat7Runner; 43 import org.apache.tomcat.maven.runner.Tomcat7RunnerCli; 44 import org.codehaus.plexus.archiver.jar.Manifest; 45 import org.codehaus.plexus.archiver.jar.ManifestException; 46 import org.codehaus.plexus.util.DirectoryScanner; 47 48 /** 49 * Abstract Mojo for building deployable and executable war files 50 * 51 * @since 2.1 52 */ 53 public abstract class AbstractStandaloneWarMojo 54 extends AbstractExecWarMojo 55 { 56 57 /** 58 * Name of the generated WAR. 59 */ 60 @Parameter(property = "tomcat.jar.finalName", 61 defaultValue = "${project.artifactId}-${project.version}-standalone.war", required = true) 62 protected String finalName; 63 64 /** 65 * the classifier to use for the attached/generated artifact 66 */ 67 @Parameter(property = "maven.tomcat.exec.war.attachArtifactClassifier", defaultValue = "standalone", 68 required = true) 69 protected String attachArtifactClassifier; 70 71 public void execute() 72 throws MojoExecutionException, MojoFailureException 73 { 74 if ( !"war".equals( project.getPackaging() ) ) 75 { 76 throw new MojoFailureException( "Pacakaging must be of type war for standalone-war goal." ); 77 } 78 79 File warExecFile = new File( buildDirectory, finalName ); 80 if ( warExecFile.exists() ) 81 { 82 warExecFile.delete(); 83 } 84 85 File execWarJar = new File( buildDirectory, finalName ); 86 87 FileOutputStream execWarJarOutputStream = null; 88 ArchiveOutputStream os = null; 89 File tmpPropertiesFile = null; 90 File tmpManifestFile = null; 91 FileOutputStream tmpPropertiesFileOutputStream = null; 92 PrintWriter tmpManifestWriter = null; 93 94 try 95 { 96 tmpPropertiesFile = new File( buildDirectory, "war-exec.properties" ); 97 if ( tmpPropertiesFile.exists() ) 98 { 99 tmpPropertiesFile.delete(); 100 } 101 tmpPropertiesFile.getParentFile().mkdirs(); 102 103 tmpManifestFile = new File( buildDirectory, "war-exec.manifest" ); 104 if ( tmpManifestFile.exists() ) 105 { 106 tmpManifestFile.delete(); 107 } 108 tmpPropertiesFileOutputStream = new FileOutputStream( tmpPropertiesFile ); 109 execWarJar.getParentFile().mkdirs(); 110 execWarJar.createNewFile(); 111 execWarJarOutputStream = new FileOutputStream( execWarJar ); 112 113 tmpManifestWriter = new PrintWriter( tmpManifestFile ); 114 115 // store : 116 //* wars in the root: foo.war 117 //* tomcat jars 118 //* file tomcat.standalone.properties with possible values : 119 // * useServerXml=true/false to use directly the one provided 120 // * enableNaming=true/false 121 // * wars=foo.war|contextpath;bar.war ( |contextpath is optionnal if empty use the war name ) 122 // * accessLogValveFormat= 123 // * connectorhttpProtocol: HTTP/1.1 or org.apache.coyote.http11.Http11NioProtocol 124 // * codeSourceContextPath=path parameter, default is project.artifactId 125 //* optionnal: conf/ with usual tomcat configuration files 126 //* MANIFEST with Main-Class 127 128 Properties properties = new Properties(); 129 130 properties.put( Tomcat7Runner.ARCHIVE_GENERATION_TIMESTAMP_KEY, 131 Long.toString( System.currentTimeMillis() ) ); 132 properties.put( Tomcat7Runner.ENABLE_NAMING_KEY, Boolean.toString( enableNaming ) ); 133 properties.put( Tomcat7Runner.ACCESS_LOG_VALVE_FORMAT_KEY, accessLogValveFormat ); 134 properties.put( Tomcat7Runner.HTTP_PROTOCOL_KEY, connectorHttpProtocol ); 135 properties.put( Tomcat7Runner.CODE_SOURCE_CONTEXT_PATH, path ); 136 137 os = new ArchiveStreamFactory().createArchiveOutputStream( ArchiveStreamFactory.JAR, 138 execWarJarOutputStream ); 139 140 extractJarToArchive( new JarFile( projectArtifact.getFile() ), os ); 141 142 if ( serverXml != null && serverXml.exists() ) 143 { 144 os.putArchiveEntry( new JarArchiveEntry( "conf/server.xml" ) ); 145 IOUtils.copy( new FileInputStream( serverXml ), os ); 146 os.closeArchiveEntry(); 147 properties.put( Tomcat7Runner.USE_SERVER_XML_KEY, Boolean.TRUE.toString() ); 148 } 149 else 150 { 151 properties.put( Tomcat7Runner.USE_SERVER_XML_KEY, Boolean.FALSE.toString() ); 152 } 153 154 os.putArchiveEntry( new JarArchiveEntry( "conf/web.xml" ) ); 155 IOUtils.copy( getClass().getResourceAsStream( "/conf/web.xml" ), os ); 156 os.closeArchiveEntry(); 157 158 properties.store( tmpPropertiesFileOutputStream, "created by Apache Tomcat Maven plugin" ); 159 160 tmpPropertiesFileOutputStream.flush(); 161 tmpPropertiesFileOutputStream.close(); 162 163 os.putArchiveEntry( new JarArchiveEntry( Tomcat7RunnerCli.STAND_ALONE_PROPERTIES_FILENAME ) ); 164 IOUtils.copy( new FileInputStream( tmpPropertiesFile ), os ); 165 os.closeArchiveEntry(); 166 167 // add tomcat classes 168 for ( Artifact pluginArtifact : pluginArtifacts ) 169 { 170 if ( StringUtils.equals( "org.apache.tomcat", pluginArtifact.getGroupId() ) || StringUtils.equals( 171 "org.apache.tomcat.embed", pluginArtifact.getGroupId() ) || StringUtils.equals( 172 "org.eclipse.jdt.core.compiler", pluginArtifact.getGroupId() ) || StringUtils.equals( "commons-cli", 173 pluginArtifact.getArtifactId() ) 174 || StringUtils.equals( "tomcat7-war-runner", pluginArtifact.getArtifactId() ) ) 175 { 176 JarFile jarFile = new JarFile( pluginArtifact.getFile() ); 177 extractJarToArchive( jarFile, os ); 178 } 179 } 180 181 // add extra dependencies 182 if ( extraDependencies != null && !extraDependencies.isEmpty() ) 183 { 184 for ( Dependency dependency : extraDependencies ) 185 { 186 // String groupId, String artifactId, String version, String scope, String type 187 Artifact artifact = 188 artifactFactory.createArtifact( dependency.getGroupId(), dependency.getArtifactId(), 189 dependency.getVersion(), dependency.getScope(), 190 dependency.getType() ); 191 192 artifactResolver.resolve( artifact, this.remoteRepos, this.local ); 193 JarFile jarFile = new JarFile( artifact.getFile() ); 194 extractJarToArchive( jarFile, os ); 195 } 196 } 197 198 Manifest manifest = new Manifest(); 199 200 Manifest.Attribute mainClassAtt = new Manifest.Attribute(); 201 mainClassAtt.setName( "Main-Class" ); 202 mainClassAtt.setValue( mainClass ); 203 manifest.addConfiguredAttribute( mainClassAtt ); 204 205 manifest.write( tmpManifestWriter ); 206 tmpManifestWriter.flush(); 207 tmpManifestWriter.close(); 208 209 os.putArchiveEntry( new JarArchiveEntry( "META-INF/MANIFEST.MF" ) ); 210 IOUtils.copy( new FileInputStream( tmpManifestFile ), os ); 211 os.closeArchiveEntry(); 212 213 if ( attachArtifact ) 214 { 215 //MavenProject project, String artifactType, String artifactClassifier, File artifactFile 216 projectHelper.attachArtifact( project, attachArtifactClassifierType, attachArtifactClassifier, 217 execWarJar ); 218 } 219 220 if ( extraResources != null ) 221 { 222 for ( ExtraResource extraResource : extraResources ) 223 { 224 225 DirectoryScanner directoryScanner = new DirectoryScanner(); 226 directoryScanner.setBasedir( extraResource.getDirectory() ); 227 directoryScanner.addDefaultExcludes(); 228 directoryScanner.setExcludes( toStringArray( extraResource.getExcludes() ) ); 229 directoryScanner.setIncludes( toStringArray( extraResource.getIncludes() ) ); 230 directoryScanner.scan(); 231 for ( String includeFile : directoryScanner.getIncludedFiles() ) 232 { 233 getLog().debug( "include file:" + includeFile ); 234 os.putArchiveEntry( new JarArchiveEntry( includeFile ) ); 235 IOUtils.copy( new FileInputStream( new File( extraResource.getDirectory(), includeFile ) ), 236 os ); 237 os.closeArchiveEntry(); 238 } 239 } 240 } 241 242 if ( tomcatConfigurationFilesDirectory != null && tomcatConfigurationFilesDirectory.exists() ) 243 { 244 // Because its the tomcat default dir for configs 245 String aConfigOutputDir = "conf/"; 246 copyDirectoryContentIntoArchive( tomcatConfigurationFilesDirectory, aConfigOutputDir, os ); 247 } 248 } 249 catch ( ManifestException e ) 250 { 251 throw new MojoExecutionException( e.getMessage(), e ); 252 } 253 catch ( IOException e ) 254 { 255 throw new MojoExecutionException( e.getMessage(), e ); 256 } 257 catch ( ArchiveException e ) 258 { 259 throw new MojoExecutionException( e.getMessage(), e ); 260 } 261 catch ( ArtifactNotFoundException e ) 262 { 263 throw new MojoExecutionException( e.getMessage(), e ); 264 } 265 catch ( ArtifactResolutionException e ) 266 { 267 throw new MojoExecutionException( e.getMessage(), e ); 268 } 269 finally 270 { 271 IOUtils.closeQuietly( os ); 272 IOUtils.closeQuietly( tmpManifestWriter ); 273 IOUtils.closeQuietly( execWarJarOutputStream ); 274 IOUtils.closeQuietly( tmpPropertiesFileOutputStream ); 275 } 276 277 } 278 }