maven-war-plugin-2.1.1/0000755000175000017500000000000011641142610014636 5ustar twernertwernermaven-war-plugin-2.1.1/pom.xml0000644000175000017500000001440411463101427016161 0ustar twernertwerner 4.0.0 maven-plugins org.apache.maven.plugins 18 maven-war-plugin 2.1.1 maven-plugin Maven WAR Plugin Builds a Web Application Archive (WAR) file from the project output and its dependencies. ${mavenVersion} scm:svn:http://svn.apache.org/repos/asf/maven/plugins/tags/maven-war-plugin-2.1.1 scm:svn:https://svn.apache.org/repos/asf/maven/plugins/tags/maven-war-plugin-2.1.1 http://svn.apache.org/viewvc/maven/plugins/tags/maven-war-plugin-2.1.1 JIRA http://jira.codehaus.org/browse/MWAR 2.0.6 2.4.1 org.apache.maven maven-plugin-api ${mavenVersion} org.apache.maven maven-artifact ${mavenVersion} org.apache.maven maven-model ${mavenVersion} org.apache.maven maven-project ${mavenVersion} org.apache.maven maven-core ${mavenVersion} org.apache.maven maven-settings ${mavenVersion} org.apache.maven maven-monitor ${mavenVersion} org.apache.maven maven-archiver ${mavenArchiverVersion} org.codehaus.plexus plexus-archiver 1.2 org.codehaus.plexus plexus-container-default org.codehaus.plexus plexus-component-api org.codehaus.plexus plexus-interpolation 1.13 org.codehaus.plexus plexus-container-default 1.0-alpha-9-stable-1 com.thoughtworks.xstream xstream 1.3.1 org.codehaus.plexus plexus-utils 2.0.5 org.apache.maven.shared maven-filtering 1.0-beta-2 junit junit 3.8.1 test org.apache.maven.plugin-testing maven-plugin-testing-harness 1.2 test run-its org.apache.maven.plugins maven-invoker-plugin 1.4 src/it */pom.xml verify ${project.build.directory}/local-repo clean package src/it/settings.xml ${project.build.directory}/it integration-test install run maven-war-plugin-2.1.1/src/0000755000175000017500000000000011641142610015425 5ustar twernertwernermaven-war-plugin-2.1.1/src/test/0000755000175000017500000000000011641142606016411 5ustar twernertwernermaven-war-plugin-2.1.1/src/test/resources/0000755000175000017500000000000011641142606020423 5ustar twernertwernermaven-war-plugin-2.1.1/src/test/resources/unit/0000755000175000017500000000000011641142606021402 5ustar twernertwernermaven-war-plugin-2.1.1/src/test/resources/unit/warexplodedinplacemojo/0000755000175000017500000000000011641142606026141 5ustar twernertwernermaven-war-plugin-2.1.1/src/test/resources/unit/warexplodedinplacemojo/plugin-config.xml0000644000175000017500000000174710533420321031425 0ustar twernertwerner war-plugin-test maven-war-plugin maven-war-plugin-2.1.1/src/test/resources/unit/warexplodedmojo/0000755000175000017500000000000011641142606024605 5ustar twernertwernermaven-war-plugin-2.1.1/src/test/resources/unit/warexplodedmojo/plugin-config.xml0000644000175000017500000000174710533420321030071 0ustar twernertwerner war-plugin-test maven-war-plugin maven-war-plugin-2.1.1/src/test/resources/unit/manifest/0000755000175000017500000000000011641142606023210 5ustar twernertwernermaven-war-plugin-2.1.1/src/test/resources/unit/manifest/basic-manifest-test/0000755000175000017500000000000011641142606027052 5ustar twernertwernermaven-war-plugin-2.1.1/src/test/resources/unit/manifest/basic-manifest-test/plugin-config.xml0000644000175000017500000000230211431607526032336 0ustar twernertwerner war-plugin-test maven-war-plugin ${basedir}/target/test-classes/unit/manifest/basic-manifest-test/src/main maven-war-plugin-2.1.1/src/test/resources/unit/manifest/manifest-with-classpath/0000755000175000017500000000000011641142606027747 5ustar twernertwernermaven-war-plugin-2.1.1/src/test/resources/unit/manifest/manifest-with-classpath/sample-artifacts/0000755000175000017500000000000011641142606033206 5ustar twernertwernermaven-war-plugin-2.1.1/src/test/resources/unit/manifest/manifest-with-classpath/plugin-config.xml0000644000175000017500000000253610772000266033237 0ustar twernertwerner war-plugin-test maven-war-plugin ${basedir}/target/test-classes/unit/manifest/manifest-with-classpath/src/main true maven-war-plugin-2.1.1/src/test/resources/unit/manifest/manifest-with-main-class/0000755000175000017500000000000011641142606030014 5ustar twernertwernermaven-war-plugin-2.1.1/src/test/resources/unit/manifest/manifest-with-main-class/plugin-config.xml0000644000175000017500000000254111431607526033305 0ustar twernertwerner war-plugin-test maven-war-plugin ${basedir}/target/test-classes/unit/manifest/manifest-with-main-class/src/main org.dummy.test.SomeClass maven-war-plugin-2.1.1/src/test/resources/unit/manifest/manifest-with-other-attrs/0000755000175000017500000000000011641142606030241 5ustar twernertwernermaven-war-plugin-2.1.1/src/test/resources/unit/manifest/manifest-with-other-attrs/plugin-config.xml0000644000175000017500000000301010772000266033515 0ustar twernertwerner war-plugin-test maven-war-plugin ${basedir}/target/test-classes/unit/manifest/manifest-with-other-attrs/src/main true true true maven-war-plugin-2.1.1/src/test/resources/unit/manifest/manifest-with-custom-attrs/0000755000175000017500000000000011641142606030432 5ustar twernertwerner././@LongLink0000000000000000000000000000014500000000000011565 Lustar rootrootmaven-war-plugin-2.1.1/src/test/resources/unit/manifest/manifest-with-custom-attrs/plugin-config.xmlmaven-war-plugin-2.1.1/src/test/resources/unit/manifest/manifest-with-custom-attrs/plugin-config.xml0000644000175000017500000000317111431607526033723 0ustar twernertwerner war-plugin-test maven-war-plugin ${basedir}/target/test-classes/unit/manifest/manifest-with-custom-attrs/src/main true true true 2.0 maven-war-plugin-2.1.1/src/test/resources/unit/dependencies/0000755000175000017500000000000011641142606024030 5ustar twernertwernermaven-war-plugin-2.1.1/src/test/resources/unit/dependencies/default.xml0000644000175000017500000000201410772000266026172 0ustar twernertwerner war-plugin-test maven-war-plugin true maven-war-plugin-2.1.1/src/test/resources/unit/warmojotest/0000755000175000017500000000000011641142606023760 5ustar twernertwernermaven-war-plugin-2.1.1/src/test/resources/unit/warmojotest/plugin-config-primary-artifact.xml0000644000175000017500000000203111431607526032517 0ustar twernertwerner war-plugin-test maven-war-plugin true maven-war-plugin-2.1.1/src/test/resources/unit/warmojotest/not-primary-artifact.xml0000644000175000017500000000203211431607526030557 0ustar twernertwerner war-plugin-test maven-war-plugin false maven-war-plugin-2.1.1/src/test/resources/unit/warziptest/0000755000175000017500000000000011641142606023616 5ustar twernertwernermaven-war-plugin-2.1.1/src/test/resources/unit/warziptest/war-with-zip.xml0000644000175000017500000000175010772000266026704 0ustar twernertwerner war-with-one-zip maven-war-plugin maven-war-plugin-2.1.1/src/test/resources/unit/warziptest/foobar.zip0000755000175000017500000000070510702264475025625 0ustar twernertwernerPK +6!esfoo.txtfooPK 66(Documents and Settings/olamy/Bureau/bar/PK 46 bar/bar.txtPK 66bar/PK +6!es foo.txtPK 66((Documents and Settings/olamy/Bureau/bar/PK 46  nbar/bar.txtPK 66bar/PKmaven-war-plugin-2.1.1/src/test/resources/unit/sample_wars/0000755000175000017500000000000011641142606023717 5ustar twernertwernermaven-war-plugin-2.1.1/src/test/resources/unit/sample_wars/simple.aar0000644000175000017500000000171111045075464025702 0ustar twernertwernerPKn4 META-INF/PKPKn4META-INF/MANIFEST.MFMLK-. K-*ϳR03r.JM,IMu *h)f&W+x%irrPKGGPK n4WEB-INF/PK n4WEB-INF/web.xmlPK n4org/PK n4 org/sample/PK n4org/sample/company/PK n4org/sample/company/test.jspPKn4 META-INF/PKn4GG=META-INF/MANIFEST.MFPK n4WEB-INF/PK n4WEB-INF/web.xmlPK n4org/PK n4 ;org/sample/PK n4dorg/sample/company/PK n4org/sample/company/test.jspPKmaven-war-plugin-2.1.1/src/test/resources/unit/sample_wars/simple.war0000644000175000017500000000171110430006224025711 0ustar twernertwernerPKn4 META-INF/PKPKn4META-INF/MANIFEST.MFMLK-. K-*ϳR03r.JM,IMu *h)f&W+x%irrPKGGPK n4WEB-INF/PK n4WEB-INF/web.xmlPK n4org/PK n4 org/sample/PK n4org/sample/company/PK n4org/sample/company/test.jspPKn4 META-INF/PKn4GG=META-INF/MANIFEST.MFPK n4WEB-INF/PK n4WEB-INF/web.xmlPK n4org/PK n4 ;org/sample/PK n4dorg/sample/company/PK n4org/sample/company/test.jspPKmaven-war-plugin-2.1.1/src/test/resources/unit/sample_wars/simple.mar0000644000175000017500000000000011453733464025710 0ustar twernertwernermaven-war-plugin-2.1.1/src/test/resources/unit/sample_wars/simple-updated.war0000644000175000017500000000174311045075464027361 0ustar twernertwernerPKn4 META-INF/PKPKn4META-INF/MANIFEST.MFMLK-. K-*ϳR03r.JM,IMu *h)f&W+x%irrPKGGPK n4WEB-INF/PK n4WEB-INF/web.xmlPK n4org/PK n4 org/sample/PK 4org/sample/company/PK4org/sample/company/test.jsp+-HI,IMPK PKn4 META-INF/PKn4GG=META-INF/MANIFEST.MFPK n4WEB-INF/PK n4WEB-INF/web.xmlPK n4org/PK n4 ;org/sample/PK 4dorg/sample/company/PK4 org/sample/company/test.jspPKmaven-war-plugin-2.1.1/src/test/resources/unit/sample_wars/sample.par0000644000175000017500000000000011045075464025677 0ustar twernertwernermaven-war-plugin-2.1.1/src/test/resources/unit/sample_wars/include-exclude.war0000644000175000017500000000234710430006224027500 0ustar twernertwernerPKu4 META-INF/PKPKu4META-INF/MANIFEST.MFMLK-. K-*ϳR03r.JM,IMu *h)f&W+x%irrPKGGPK n4WEB-INF/PK n4WEB-INF/web.xmlPK n4org/PK u4 org/sample/PK u4org/sample/company/PK n4"org/sample/company/testInclude.jspPK u4org/sample/companyExclude/PK u4"org/sample/companyExclude/test.jspPKu4 META-INF/PKu4GG=META-INF/MANIFEST.MFPK n4WEB-INF/PK n4WEB-INF/web.xmlPK n4org/PK u4 ;org/sample/PK u4dorg/sample/company/PK n4"org/sample/company/testInclude.jspPK u4org/sample/companyExclude/PK u4" org/sample/companyExclude/test.jspPK Mmaven-war-plugin-2.1.1/src/test/resources/unit/waroverlays/0000755000175000017500000000000011641142606023760 5ustar twernertwernermaven-war-plugin-2.1.1/src/test/resources/unit/waroverlays/default.xml0000644000175000017500000000204010772000266026121 0ustar twernertwerner war-plugin-test maven-war-plugin maven-war-plugin-2.1.1/src/test/resources/overlays/0000755000175000017500000000000011641142606022267 5ustar twernertwernermaven-war-plugin-2.1.1/src/test/resources/overlays/overlay-two/0000755000175000017500000000000011641142606024557 5ustar twernertwernermaven-war-plugin-2.1.1/src/test/resources/overlays/overlay-two/admin.jsp0000644000175000017500000000001711045075710026362 0ustar twernertwerner maven-war-plugin-2.1.1/src/test/resources/overlays/overlay-two/WEB-INF/0000755000175000017500000000000011641142606025606 5ustar twernertwernermaven-war-plugin-2.1.1/src/test/resources/overlays/overlay-two/WEB-INF/web.xml0000644000175000017500000000010710772000266027102 0ustar twernertwerner Sample two overlay maven-war-plugin-2.1.1/src/test/resources/overlays/overlay-two/index.jsp0000644000175000017500000000011211045075710026375 0ustar twernertwerner

Hello World, this is overlay-two!

maven-war-plugin-2.1.1/src/test/resources/overlays/overlay-one/0000755000175000017500000000000011641142606024527 5ustar twernertwernermaven-war-plugin-2.1.1/src/test/resources/overlays/overlay-one/login.jsp0000644000175000017500000000001711045075710026352 0ustar twernertwerner maven-war-plugin-2.1.1/src/test/resources/overlays/overlay-one/WEB-INF/0000755000175000017500000000000011641142606025556 5ustar twernertwernermaven-war-plugin-2.1.1/src/test/resources/overlays/overlay-one/WEB-INF/web.xml0000644000175000017500000000010710772000266027052 0ustar twernertwerner Sample one overlay maven-war-plugin-2.1.1/src/test/resources/overlays/overlay-one/index.jsp0000644000175000017500000000011211045075710026345 0ustar twernertwerner

Hello World, this is overlay-one!

maven-war-plugin-2.1.1/src/test/java/0000755000175000017500000000000011641142606017332 5ustar twernertwernermaven-war-plugin-2.1.1/src/test/java/org/0000755000175000017500000000000011641142606020121 5ustar twernertwernermaven-war-plugin-2.1.1/src/test/java/org/apache/0000755000175000017500000000000011641142606021342 5ustar twernertwernermaven-war-plugin-2.1.1/src/test/java/org/apache/maven/0000755000175000017500000000000011641142606022450 5ustar twernertwernermaven-war-plugin-2.1.1/src/test/java/org/apache/maven/plugin/0000755000175000017500000000000011641142606023746 5ustar twernertwernermaven-war-plugin-2.1.1/src/test/java/org/apache/maven/plugin/war/0000755000175000017500000000000011641142606024537 5ustar twernertwernermaven-war-plugin-2.1.1/src/test/java/org/apache/maven/plugin/war/WarExplodedMojoFilteringTest.java0000644000175000017500000002452511123544663033165 0ustar twernertwernerpackage org.apache.maven.plugin.war; /* * 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 java.io.BufferedReader; import java.io.File; import java.io.StringReader; import java.util.LinkedList; import java.util.List; import org.apache.maven.plugin.war.stub.MavenProjectBasicStub; import org.apache.maven.plugin.war.stub.ResourceStub; import org.codehaus.plexus.util.FileUtils; /** * @author olamy * @since 21 juil. 2008 * @version $Id: WarExplodedMojoFilteringTest.java 728546 2008-12-21 22:56:51Z bentmann $ */ public class WarExplodedMojoFilteringTest extends AbstractWarExplodedMojoTest { protected File getPomFile() { return new File( getBasedir(), "/target/test-classes/unit/warexplodedmojo/plugin-config.xml" ); } protected File getTestDirectory() { return new File( getBasedir(), "target/test-classes/unit/warexplodedmojo/test-dir" ); } /** * @throws Exception */ public void testExplodedWar_WithResourceFiltering() throws Exception { // setup test data String testId = "ExplodedWar_WithResourceFiltering"; MavenProjectBasicStub project = new MavenProjectBasicStub(); File webAppDirectory = new File( getTestDirectory(), testId ); File webAppSource = createWebAppSource( testId ); File classesDir = createClassesDir( testId, false ); File webAppResource = new File( getTestDirectory(), testId + "-test-data/resources" ); File sampleResource = new File( webAppResource, "custom-setting.cfg" ); File sampleResourceWDir = new File( webAppResource, "custom-config/custom-setting.cfg" ); List filterList = new LinkedList(); ResourceStub[] resources = new ResourceStub[]{new ResourceStub()}; createFile( sampleResource ); createFile( sampleResourceWDir ); String ls = System.getProperty( "line.separator" ); final String comment = "# this is comment created by author@somewhere@"; // prepare web resources String content = comment + ls; content += "system_key_1=${user.dir}" + ls; content += "system_key_2=@user.dir@" + ls; content += "project_key_1=${is_this_simple}" + ls; content += "project_key_2=@is_this_simple@" + ls; content += "project_name_1=${project.name}" + ls; content += "project_name_2=@project.name@" + ls; content += "system_property_1=${system.property}" + ls; content += "system_property_2=@system.property@" + ls; FileUtils.fileWrite( sampleResourceWDir.getAbsolutePath(), content ); FileUtils.fileWrite( sampleResource.getAbsolutePath(), content ); System.setProperty( "system.property", "system-property-value" ); // configure mojo project.addProperty( "is_this_simple", "i_think_so" ); resources[0].setDirectory( webAppResource.getAbsolutePath() ); resources[0].setFiltering( true ); this.configureMojo( mojo, filterList, classesDir, webAppSource, webAppDirectory, project ); setVariableValueToObject( mojo, "webResources", resources ); mojo.execute(); // validate operation File expectedWebSourceFile = new File( webAppDirectory, "pansit.jsp" ); File expectedWebSource2File = new File( webAppDirectory, "org/web/app/last-exile.jsp" ); File expectedResourceFile = new File( webAppDirectory, "custom-setting.cfg" ); File expectedResourceWDirFile = new File( webAppDirectory, "custom-config/custom-setting.cfg" ); assertTrue( "source files not found: " + expectedWebSourceFile.toString(), expectedWebSourceFile.exists() ); assertTrue( "source files not found: " + expectedWebSource2File.toString(), expectedWebSource2File.exists() ); assertTrue( "resource file not found:" + expectedResourceFile.toString(), expectedResourceFile.exists() ); assertTrue( "resource file with dir not found:" + expectedResourceWDirFile.toString(), expectedResourceWDirFile.exists() ); // validate filtered file content = FileUtils.fileRead( expectedResourceWDirFile ); BufferedReader reader = new BufferedReader( new StringReader( content ) ); assertEquals( "error in filtering using System Properties", comment, reader.readLine() ); String line = reader.readLine(); System.out.println( " line " + line ); System.out.println( " need " + System.getProperty( "user.dir" ) ); assertEquals( "error in filtering using System properties", "system_key_1=" + System.getProperty( "user.dir" ), line ); line = reader.readLine(); System.out.println(" line " + line ); assertEquals( "error in filtering using System properties", "system_key_2=" + System.getProperty( "user.dir" ), line ); assertEquals( "error in filtering using project properties", "project_key_1=i_think_so", reader.readLine() ); assertEquals( "error in filtering using project properties", "project_key_2=i_think_so", reader.readLine() ); assertEquals( "error in filtering using project properties", "project_name_1=Test Project ", reader.readLine() ); assertEquals( "error in filtering using project properties", "project_name_2=Test Project ", reader.readLine() ); assertEquals( "error in filtering using System properties", "system_property_1=system-property-value", reader.readLine() ); assertEquals( "error in filtering using System properties", "system_property_2=system-property-value", reader.readLine() ); // update property, and generate again System.setProperty( "system.property", "new-system-property-value" ); mojo.execute(); // validate filtered file content = FileUtils.fileRead( expectedResourceWDirFile ); reader = new BufferedReader( new StringReader( content ) ); assertEquals( "error in filtering using System Properties", comment, reader.readLine() ); assertEquals( "error in filtering using System properties", "system_key_1=" + System.getProperty( "user.dir" ), reader.readLine() ); assertEquals( "error in filtering using System properties", "system_key_2=" + System.getProperty( "user.dir" ), reader.readLine() ); assertEquals( "error in filtering using project properties", "project_key_1=i_think_so", reader.readLine() ); assertEquals( "error in filtering using project properties", "project_key_2=i_think_so", reader.readLine() ); assertEquals( "error in filtering using project properties", "project_name_1=Test Project ", reader.readLine() ); assertEquals( "error in filtering using project properties", "project_name_2=Test Project ", reader.readLine() ); assertEquals( "error in filtering using System properties", "system_property_1=new-system-property-value", reader.readLine() ); assertEquals( "error in filtering using System properties", "system_property_2=new-system-property-value", reader.readLine() ); // update property, and generate again File filterFile = new File( getTestDirectory(), testId + "-test-data/filters/filter.properties" ); createFile( filterFile ); filterList.add( filterFile.getAbsolutePath() ); content += "resource_key_1=${resource_value_1}\n"; content += "resource_key_2=@resource_value_2@\n" + content; FileUtils.fileWrite( sampleResourceWDir.getAbsolutePath(), content ); FileUtils.fileWrite( sampleResource.getAbsolutePath(), content ); String filterContent = "resource_value_1=this_is_filtered\n"; filterContent += "resource_value_2=this_is_filtered"; FileUtils.fileWrite( filterFile.getAbsolutePath(), filterContent ); mojo.execute(); // validate filtered file content = FileUtils.fileRead( expectedResourceWDirFile ); reader = new BufferedReader( new StringReader( content ) ); assertEquals( "error in filtering using System Properties", comment, reader.readLine() ); assertEquals( "error in filtering using System properties", "system_key_1=" + System.getProperty( "user.dir" ), reader.readLine() ); assertEquals( "error in filtering using System properties", "system_key_2=" + System.getProperty( "user.dir" ), reader.readLine() ); assertEquals( "error in filtering using project properties", "project_key_1=i_think_so", reader.readLine() ); assertEquals( "error in filtering using project properties", "project_key_2=i_think_so", reader.readLine() ); assertEquals( "error in filtering using project properties", "project_name_1=Test Project ", reader.readLine() ); assertEquals( "error in filtering using project properties", "project_name_2=Test Project ", reader.readLine() ); assertEquals( "error in filtering using System properties", "system_property_1=new-system-property-value", reader.readLine() ); assertEquals( "error in filtering using System properties", "system_property_2=new-system-property-value", reader.readLine() ); assertEquals( "error in filtering using filter files", "resource_key_1=this_is_filtered", reader.readLine() ); assertEquals( "error in filtering using filter files", "resource_key_2=this_is_filtered", reader.readLine() ); // house keeping expectedWebSourceFile.delete(); expectedWebSource2File.delete(); expectedResourceFile.delete(); expectedResourceWDirFile.delete(); } } maven-war-plugin-2.1.1/src/test/java/org/apache/maven/plugin/war/WarDependenciesAnalysisTest.java0000644000175000017500000001653011432027106033006 0ustar twernertwernerpackage org.apache.maven.plugin.war; /* * 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.maven.artifact.Artifact; import org.apache.maven.artifact.handler.ArtifactHandler; import org.apache.maven.plugin.testing.stubs.ArtifactStub; import org.apache.maven.plugin.war.stub.JarArtifactStub; import java.io.File; import java.io.FileFilter; import java.util.ArrayList; import java.util.List; /** * * * @author Stephane Nicoll */ public class WarDependenciesAnalysisTest extends AbstractWarExplodedMojoTest { protected File getPomFile() { return new File( getBasedir(), "/target/test-classes/unit/dependencies/default.xml" ); } protected File getTestDirectory() { return new File( getBasedir(), "target/test-classes/unit/dependenciesanalysis/test-dir" ); } public void testNoChange() throws Exception { // setup test data final String testId = "no-change"; final ArtifactHandler artifactHandler = (ArtifactHandler) lookup( ArtifactHandler.ROLE, "jar" ); ArtifactStub jarArtifact = new JarArtifactStub( getBasedir(), artifactHandler ); jarArtifact.setArtifactId( "lib-test" ); jarArtifact.setVersion( "1.0" ); doTestTwiceWithUpdatedDependency( testId, new ArtifactStub[]{jarArtifact}, new ArtifactStub[]{jarArtifact}, new String[]{"WEB-INF/lib/lib-test-1.0.jar"}, new String[]{"WEB-INF/lib/lib-test-1.0.jar"} ); } public void testRemovedDependency() throws Exception { // setup test data final String testId = "remove-dependency"; final ArtifactHandler artifactHandler = (ArtifactHandler) lookup( ArtifactHandler.ROLE, "jar" ); ArtifactStub jarArtifact = new JarArtifactStub( getBasedir(), artifactHandler ); jarArtifact.setArtifactId( "lib-test" ); jarArtifact.setVersion( "1.0" ); doTestTwiceWithUpdatedDependency( testId, new ArtifactStub[]{jarArtifact}, null, new String[]{"WEB-INF/lib/lib-test-1.0.jar"}, null ); } public void testDependencyWithUpdatedVersion() throws Exception { // setup test data final String testId = "dependency-update-version"; final ArtifactHandler artifactHandler = (ArtifactHandler) lookup( ArtifactHandler.ROLE, "jar" ); ArtifactStub jarArtifact = new JarArtifactStub( getBasedir(), artifactHandler ); jarArtifact.setArtifactId( "lib-test" ); jarArtifact.setVersion( "1.0" ); ArtifactStub jarArtifact2 = new JarArtifactStub( getBasedir(), artifactHandler ); jarArtifact2.setArtifactId( "lib-test" ); jarArtifact2.setVersion( "2.0" ); doTestTwiceWithUpdatedDependency( testId, new ArtifactStub[]{jarArtifact}, new ArtifactStub[]{jarArtifact2}, new String[]{"WEB-INF/lib/lib-test-1.0.jar"}, new String[]{"WEB-INF/lib/lib-test-2.0.jar"} ); } public void testDependencyNowProvided() throws Exception { // setup test data final String testId = "dependency-now-provided"; final ArtifactHandler artifactHandler = (ArtifactHandler) lookup( ArtifactHandler.ROLE, "jar" ); ArtifactStub jarArtifact = new JarArtifactStub( getBasedir(), artifactHandler ); jarArtifact.setArtifactId( "lib-test" ); jarArtifact.setVersion( "1.0" ); ArtifactStub jarArtifact2 = new JarArtifactStub( getBasedir(), artifactHandler ); jarArtifact2.setArtifactId( "lib-test" ); jarArtifact2.setVersion( "1.0" ); jarArtifact2.setScope( Artifact.SCOPE_PROVIDED ); doTestTwiceWithUpdatedDependency( testId, new ArtifactStub[]{jarArtifact}, new ArtifactStub[]{jarArtifact2}, new String[]{"WEB-INF/lib/lib-test-1.0.jar"}, null ); } protected void doTestTwiceWithUpdatedDependency( String testId, ArtifactStub[] firstStubs, ArtifactStub[] secondStubs, String[] firstCustomContent, String[] secondCustomContent ) throws Exception { // setup test data final File xmlSource = createXMLConfigDir( testId, new String[]{"web.xml"} ); final File webAppDirectory = setUpMojoWithCache( testId, firstStubs ); try { mojo.setWebXml( new File( xmlSource, "web.xml" ) ); mojo.execute(); final List assertedFiles = new ArrayList(); assertedFiles.addAll( assertDefaultContent( webAppDirectory ) ); assertedFiles.addAll( assertWebXml( webAppDirectory ) ); assertedFiles.addAll( assertCustomContent( webAppDirectory, firstCustomContent, "library not found" ) ); // Ok now check that there is no more files/directories final FileFilter filter = new FileFilterImpl( webAppDirectory, new String[]{MANIFEST_PATH} ); assertWebAppContent( webAppDirectory, assertedFiles, filter ); // Run the thing again and check it's ok setUpMojoWithCache( testId, secondStubs ); mojo.execute(); final List assertedFiles2 = new ArrayList(); assertedFiles2.addAll( assertDefaultContent( webAppDirectory ) ); assertedFiles2.addAll( assertWebXml( webAppDirectory ) ); if ( secondCustomContent != null ) { assertedFiles2.addAll( assertCustomContent( webAppDirectory, secondCustomContent, "library not found" ) ); } assertWebAppContent( webAppDirectory, assertedFiles2, filter ); } finally { cleanDirectory( webAppDirectory ); cleanDirectory( mojo.getWorkDirectory() ); } } /** * Configures the exploded mojo for the specified test. * * @param testId the id of the test * @param artifactStubs the dependencies (may be null) * @return the webapp directory * @throws Exception if an error occurs while configuring the mojo */ protected File setUpMojoWithCache( final String testId, ArtifactStub[] artifactStubs ) throws Exception { final File webappDir = setUpMojo( testId, artifactStubs, null ); setVariableValueToObject( mojo, "useCache", Boolean.TRUE ); final File cacheFile = new File( mojo.getWorkDirectory(), "webapp-cache.xml" ); setVariableValueToObject( mojo, "cacheFile", cacheFile ); return webappDir; } } maven-war-plugin-2.1.1/src/test/java/org/apache/maven/plugin/war/stub/0000755000175000017500000000000011641142606025514 5ustar twernertwernermaven-war-plugin-2.1.1/src/test/java/org/apache/maven/plugin/war/stub/EJBClientArtifactStub.java0000644000175000017500000000376711015344504032443 0ustar twernertwernerpackage org.apache.maven.plugin.war.stub; /* * 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.maven.artifact.handler.ArtifactHandler; import org.apache.maven.artifact.handler.DefaultArtifactHandler; import java.io.File; public class EJBClientArtifactStub extends AbstractArtifactStub { protected String groupId; public EJBClientArtifactStub( String _basedir ) { super( _basedir ); } public void setGroupId( String id ) { groupId = id; } public String getGroupId() { if ( groupId != null ) { return groupId; } else { return "org.sample.ejb"; } } public String getType() { return "ejb-client"; } public String getClassifier() { return "client"; } public String getArtifactId() { return "ejbclientartifact"; } public File getFile() { return new File( basedir, "/target/test-classes/unit/sample_wars/ejbclient.jar" ); } public ArtifactHandler getArtifactHandler() { return new DefaultArtifactHandler() { public String getExtension() { return "jar"; } }; } } ././@LongLink0000000000000000000000000000015100000000000011562 Lustar rootrootmaven-war-plugin-2.1.1/src/test/java/org/apache/maven/plugin/war/stub/EJBArtifactStubWithClassifier.javamaven-war-plugin-2.1.1/src/test/java/org/apache/maven/plugin/war/stub/EJBArtifactStubWithClassifier.0000644000175000017500000000417511015344504033275 0ustar twernertwernerpackage org.apache.maven.plugin.war.stub; /* * 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.maven.artifact.handler.ArtifactHandler; import org.apache.maven.artifact.handler.DefaultArtifactHandler; import java.io.File; public class EJBArtifactStubWithClassifier extends AbstractArtifactStub { protected String groupId; protected String classifier; public EJBArtifactStubWithClassifier( String _basedir ) { super( _basedir ); } public void setGroupId( String id ) { groupId = id; } public String getGroupId() { if ( groupId != null ) { return groupId; } else { return "org.sample.ejb"; } } public String getType() { return "ejb"; } public String getArtifactId() { return "ejbartifact"; } public void setClassifier( String classifier ) { this.classifier = classifier; } public String getClassifier() { return classifier; } public File getFile() { return new File( basedir, "/target/test-classes/unit/sample_wars/ejb.jar" ); } public ArtifactHandler getArtifactHandler() { return new DefaultArtifactHandler() { public String getExtension() { return "jar"; } }; } } ././@LongLink0000000000000000000000000000015000000000000011561 Lustar rootrootmaven-war-plugin-2.1.1/src/test/java/org/apache/maven/plugin/war/stub/MavenProject4CopyConstructor.javamaven-war-plugin-2.1.1/src/test/java/org/apache/maven/plugin/war/stub/MavenProject4CopyConstructor.j0000644000175000017500000000406111015344504033446 0ustar twernertwernerpackage org.apache.maven.plugin.war.stub; /* * 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 java.io.File; import java.util.HashSet; import java.util.LinkedList; import java.util.List; public class MavenProject4CopyConstructor extends MavenProjectBasicStub { protected ModelStub model; public MavenProject4CopyConstructor() throws Exception { initializeParentFields(); } public List getAttachedArtifacts() { return new LinkedList(); } // to prevent the MavenProject copy constructor from blowing up private void initializeParentFields() { // the pom should be located in the isolated dummy root super.setFile( new File( getBasedir(), "pom.xml" ) ); super.setDependencyArtifacts( new HashSet() ); super.setArtifacts( new HashSet() ); super.setPluginArtifacts( new HashSet() ); super.setReportArtifacts( new HashSet() ); super.setExtensionArtifacts( new HashSet() ); super.setRemoteArtifactRepositories( new LinkedList() ); super.setPluginArtifactRepositories( new LinkedList() ); super.setCollectedProjects( new LinkedList() ); super.setActiveProfiles( new LinkedList() ); super.setOriginalModel( null ); super.setExecutionProject( this ); } } maven-war-plugin-2.1.1/src/test/java/org/apache/maven/plugin/war/stub/ZipArtifactStub.java0000644000175000017500000000406511432027106031435 0ustar twernertwernerpackage org.apache.maven.plugin.war.stub; /* * 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 java.io.File; import org.apache.maven.artifact.handler.ArtifactHandler; /** * @author olamy * @since 8 juin 07 * @version $Id: ZipArtifactStub.java 985726 2010-08-15 18:13:26Z bentmann $ */ public class ZipArtifactStub extends AbstractArtifactStub { private ArtifactHandler artifactHandler; private File zip; public ZipArtifactStub( String basedir, ArtifactHandler artifactHandler, File zipFile ) { super( basedir ); this.artifactHandler = artifactHandler; this.zip = zipFile; } public String getId() { return null; } public ArtifactHandler getArtifactHandler() { return super.getArtifactHandler(); } public String getScope() { return super.getScope(); } public String getVersion() { return "1.0"; } public boolean isOptional() { return super.isOptional(); } public File getFile() { return this.zip; } public String getType() { return "zip"; } public String getArtifactId() { return "zipId"; } public String getGroupId() { return "zipGroupId"; } } maven-war-plugin-2.1.1/src/test/java/org/apache/maven/plugin/war/stub/PARArtifactStub.java0000644000175000017500000000241311015344504031311 0ustar twernertwernerpackage org.apache.maven.plugin.war.stub; /* * 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 java.io.File; public class PARArtifactStub extends AbstractArtifactStub { public PARArtifactStub( String _basedir ) { super( _basedir ); } public String getType() { return "par"; } public String getArtifactId() { return "parartifact"; } public File getFile() { return new File( basedir, "/target/test-classes/unit/sample_wars/sample.par" ); } } maven-war-plugin-2.1.1/src/test/java/org/apache/maven/plugin/war/stub/ResourceStub.java0000644000175000017500000000246711015344504031011 0ustar twernertwernerpackage org.apache.maven.plugin.war.stub; /* * 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 java.util.ArrayList; import java.util.List; import org.apache.maven.model.Resource; public class ResourceStub extends Resource { String directory; public List getIncludes() { return new ArrayList(); } public List getExcludes() { return new ArrayList(); } public void setDirectory( String _directory ) { directory = _directory; } public String getDirectory() { return directory; } } maven-war-plugin-2.1.1/src/test/java/org/apache/maven/plugin/war/stub/MarArtifactStub.java0000644000175000017500000000355611453733464031434 0ustar twernertwerner/* * 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. */ package org.apache.maven.plugin.war.stub; import org.apache.maven.artifact.handler.ArtifactHandler; import java.io.File; /** * @author Stephane Nicoll */ public class MarArtifactStub extends AbstractArtifactStub { protected String groupId; private ArtifactHandler artifactHandler; public MarArtifactStub( String basedir, ArtifactHandler artifactHandler ) { super( basedir ); this.artifactHandler = artifactHandler; } public void setGroupId( String id ) { groupId = id; } public String getGroupId() { if ( groupId != null ) { return groupId; } else { return "org.sample.mar"; } } public String getType() { return "mar"; } public String getArtifactId() { return "marartifact"; } public File getFile() { return new File( basedir, "/target/test-classes/unit/sample_wars/simple.mar" ); } public ArtifactHandler getArtifactHandler() { return artifactHandler; } } maven-war-plugin-2.1.1/src/test/java/org/apache/maven/plugin/war/stub/ProjectHelperStub.java0000644000175000017500000000415411015344504031763 0ustar twernertwernerpackage org.apache.maven.plugin.war.stub; /* * 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 java.io.File; import java.util.List; import org.apache.maven.project.MavenProject; import org.apache.maven.project.MavenProjectHelper; public class ProjectHelperStub implements MavenProjectHelper { File artifactFile; String artifactType; String artifactClassifier; public File getArtifactFile() { return artifactFile; } public String getArtifactType() { return artifactType; } public String getArtifactClassifier() { return artifactClassifier; } public void attachArtifact( MavenProject project, File artifactFile, String artifactClassifier ) { } public void attachArtifact( MavenProject project, String artifactType, File artifactFile ) { } public void attachArtifact( MavenProject project, String _artifactType, String _artifactClassifier, File _artifactFile ) { artifactType = _artifactType; artifactClassifier = _artifactClassifier; artifactFile = _artifactFile; } public void addResource( MavenProject project, String resourceDirectory, List includes, List excludes ) { } public void addTestResource( MavenProject project, String resourceDirectory, List includes, List excludes ) { } } maven-war-plugin-2.1.1/src/test/java/org/apache/maven/plugin/war/stub/EJBArtifactStub.java0000644000175000017500000000362011015344504031270 0ustar twernertwernerpackage org.apache.maven.plugin.war.stub; /* * 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.maven.artifact.handler.ArtifactHandler; import org.apache.maven.artifact.handler.DefaultArtifactHandler; import java.io.File; public class EJBArtifactStub extends AbstractArtifactStub { protected String groupId; public EJBArtifactStub( String _basedir ) { super( _basedir ); } public void setGroupId( String id ) { groupId = id; } public String getGroupId() { if ( groupId != null ) { return groupId; } else { return "org.sample.ejb"; } } public String getType() { return "ejb"; } public String getArtifactId() { return "ejbartifact"; } public File getFile() { return new File( basedir, "/target/test-classes/unit/sample_wars/ejb.jar" ); } public ArtifactHandler getArtifactHandler() { return new DefaultArtifactHandler() { public String getExtension() { return "jar"; } }; } } maven-war-plugin-2.1.1/src/test/java/org/apache/maven/plugin/war/stub/WarOverlayStub.java0000644000175000017500000000356111015344504031311 0ustar twernertwernerpackage org.apache.maven.plugin.war.stub; /* * 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 java.io.File; /** * @author Stephane Nicoll */ public class WarOverlayStub extends AbstractArtifactStub { private final String artifactId; private File file; public WarOverlayStub( String _basedir, String artifactId, File warFile ) { super( _basedir ); if ( artifactId == null ) { throw new NullPointerException( "Id could not be null." ); } if ( warFile == null ) { throw new NullPointerException( "warFile could not be null." ); } else if ( !warFile.exists() ) { throw new IllegalStateException( "warFile[" + file.getAbsolutePath() + "] should exist." ); } this.artifactId = artifactId; this.file = warFile; } public String getType() { return "war"; } public String getArtifactId() { return artifactId; } public String getGroupId() { return "wartests"; } public File getFile() { return file; } } maven-war-plugin-2.1.1/src/test/java/org/apache/maven/plugin/war/stub/WarArtifactStub.java0000644000175000017500000000447111015344504031426 0ustar twernertwernerpackage org.apache.maven.plugin.war.stub; /* * 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 java.io.File; /** * Stub */ public class WarArtifactStub extends AbstractArtifactStub { private String groupId; private String artifactId; private String classifier; private File file; public WarArtifactStub( String _basedir ) { super( _basedir ); } public String getType() { return "war"; } public String getArtifactId() { if ( artifactId == null ) { return "simple"; } else { return artifactId; } } public void setArtifactId( String _artifactId ) { artifactId = _artifactId; } public String getGroupId() { if ( groupId == null ) { return "wartests"; } else { return groupId; } } public void setGroupId( String groupId ) { this.groupId = groupId; } public File getFile() { if ( file == null ) { return new File( basedir, "/target/test-classes/unit/sample_wars/simple.war" ); } else { return file; } } public void setFile( File _file ) { file = _file; } public String getClassifier() { return classifier; } public void setClassifier( String classifier ) { this.classifier = classifier; } public boolean hasClassifier() { return classifier != null; } } maven-war-plugin-2.1.1/src/test/java/org/apache/maven/plugin/war/stub/AbstractArtifactStub.java0000644000175000017500000001143011377545522032447 0ustar twernertwernerpackage org.apache.maven.plugin.war.stub; /* * 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.maven.artifact.Artifact; import org.apache.maven.artifact.handler.ArtifactHandler; import org.apache.maven.artifact.handler.DefaultArtifactHandler; import org.apache.maven.artifact.versioning.ArtifactVersion; import org.apache.maven.artifact.versioning.DefaultArtifactVersion; import org.apache.maven.artifact.versioning.VersionRange; import org.apache.maven.plugin.testing.stubs.ArtifactStub; import java.util.ArrayList; public abstract class AbstractArtifactStub extends ArtifactStub { protected String basedir; public AbstractArtifactStub( String _basedir ) { basedir = _basedir; } public String getVersion() { return "0.0-Test"; } public String getScope() { return Artifact.SCOPE_RUNTIME; } public VersionRange getVersionRange() { return VersionRange.createFromVersion( getVersion()); } public boolean isOptional() { return false; } public ArtifactHandler getArtifactHandler() { return new DefaultArtifactHandler( getType() ); } /* * TODO: Coppied from org/apache/maven/artifact/DefaultArtifact.java; Consider merging... */ public int compareTo( Object o ) { Artifact a = (Artifact) o; /* -- We need to support groupId=null (it is missing in DefaultArtifact.java) */ int result; if ( a.getGroupId() != null ) { result = getGroupId().compareTo( a.getGroupId() ); } else { result = ( getGroupId() == null ? 0 : -1 ); } /* -- */ if ( result == 0 ) { result = getArtifactId().compareTo( a.getArtifactId() ); if ( result == 0 ) { result = getType().compareTo( a.getType() ); if ( result == 0 ) { if ( getClassifier() == null ) { if ( a.getClassifier() != null ) { result = 1; } } else { if ( a.getClassifier() != null ) { result = getClassifier().compareTo( a.getClassifier() ); } else { result = -1; } } if ( result == 0 ) { // We don't consider the version range in the comparison, just the resolved version result = getVersion().compareTo( a.getVersion() ); } } } } return result; } /* * TODO: Coppied from org/apache/maven/artifact/DefaultArtifact.java; Consider merging... */ public boolean equals( Object o ) { if ( o == this ) { return true; } if ( !( o instanceof Artifact ) ) { return false; } Artifact a = (Artifact) o; /* -- We need to support groupId=null (it is missing in DefaultArtifact.java) */ if ( a.getGroupId() == null ? ( getGroupId() != null ) : a.getGroupId().equals( getGroupId() ) ) { return false; } else if ( !a.getArtifactId().equals( getArtifactId() ) ) { return false; } else if ( !a.getVersion().equals( getVersion() ) ) { return false; } else if ( !a.getType().equals( getType() ) ) { return false; } else if ( a.getClassifier() == null ? getClassifier() != null : !a.getClassifier().equals( getClassifier() ) ) { return false; } // We don't consider the version range in the comparison, just the resolved version return true; } } ././@LongLink0000000000000000000000000000015100000000000011562 Lustar rootrootmaven-war-plugin-2.1.1/src/test/java/org/apache/maven/plugin/war/stub/IncludeExcludeWarArtifactStub.javamaven-war-plugin-2.1.1/src/test/java/org/apache/maven/plugin/war/stub/IncludeExcludeWarArtifactStub.0000644000175000017500000000241211015344504033373 0ustar twernertwernerpackage org.apache.maven.plugin.war.stub; /* * 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 java.io.File; public class IncludeExcludeWarArtifactStub extends WarArtifactStub { public IncludeExcludeWarArtifactStub( String id ) { super( id ); setGroupId( "wartests" ); } public String getArtifactId() { return "war-include-exclude"; } public File getFile() { return new File( basedir, "/target/test-classes/unit/sample_wars/include-exclude.war" ); } } maven-war-plugin-2.1.1/src/test/java/org/apache/maven/plugin/war/stub/ModelStub.java0000644000175000017500000000362511015344504030257 0ustar twernertwernerpackage org.apache.maven.plugin.war.stub; /* * 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 java.util.LinkedList; import java.util.List; import java.util.Properties; import org.apache.maven.model.Model; import org.apache.maven.model.Parent; /** * Stub */ public class ModelStub extends Model { public ModelStub() { } public String getVersion() { return "0.0-TEST"; } public String getModelVersion() { return "0.0-TEST"; } public String getName() { return "Test Model"; } public String getGroupId() { return "org.apache.maven.test"; } public String getPackaging() { return "jar"; } public Parent getParent() { return new Parent(); } public String getArtifactId() { return "maven-test-plugin"; } public Properties getProperties() { return new Properties(); } public List getPackages() { return new LinkedList(); } public List getProfiles() { return new LinkedList(); } public List getModules() { return new LinkedList(); } } ././@LongLink0000000000000000000000000000014500000000000011565 Lustar rootrootmaven-war-plugin-2.1.1/src/test/java/org/apache/maven/plugin/war/stub/MavenProjectArtifactsStub.javamaven-war-plugin-2.1.1/src/test/java/org/apache/maven/plugin/war/stub/MavenProjectArtifactsStub.java0000644000175000017500000000523211015344504033451 0ustar twernertwernerpackage org.apache.maven.plugin.war.stub; /* * 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.maven.artifact.Artifact; import org.apache.maven.model.Dependency; import org.apache.maven.plugin.testing.stubs.ArtifactStub; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Set; import java.util.TreeSet; public class MavenProjectArtifactsStub extends MavenProjectBasicStub { TreeSet artifacts; public MavenProjectArtifactsStub() throws Exception { artifacts = new TreeSet(); } public void addArtifact( ArtifactStub stub ) { artifacts.add( stub ); } public Set getArtifacts() { return artifacts; } public List getDependencies() { if ( getArtifacts() == null ) { return new ArrayList(); } final List dependencies = new ArrayList(); final Iterator it = getArtifacts().iterator(); while ( it.hasNext() ) { Artifact a = (Artifact) it.next(); Dependency dependency = new Dependency(); dependency.setArtifactId( a.getArtifactId() ); dependency.setGroupId( a.getGroupId() ); dependency.setVersion( a.getVersion() ); dependency.setScope( a.getScope() ); dependency.setType( a.getType() ); dependency.setClassifier( a.getClassifier() ); dependencies.add( dependency ); } return dependencies; } public List getRuntimeClasspathElements() { List artifacts = new ArrayList(); artifacts.add( "src/test/resources/unit/manifest/manifest-with-classpath/sample-artifacts/maven-artifact1-1.0-SNAPSHOT.jar" ); artifacts.add( "src/test/resources/unit/manifest/manifest-with-classpath/sample-artifacts/maven-artifact2-1.0-SNAPSHOT.jar" ); return artifacts; } } maven-war-plugin-2.1.1/src/test/java/org/apache/maven/plugin/war/stub/AarArtifactStub.java0000644000175000017500000000367111015345234031402 0ustar twernertwernerpackage org.apache.maven.plugin.war.stub; /* * 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.maven.artifact.handler.ArtifactHandler; import java.io.File; /** * @author Stephane Nicoll * @version $Id: AarArtifactStub.java 659222 2008-05-22 19:33:48Z olamy $ */ public class AarArtifactStub extends AbstractArtifactStub { protected String groupId; private ArtifactHandler artifactHandler; public AarArtifactStub( String basedir, ArtifactHandler artifactHandler ) { super( basedir ); this.artifactHandler = artifactHandler; } public void setGroupId( String id ) { groupId = id; } public String getGroupId() { if ( groupId != null ) { return groupId; } else { return "org.sample.aar"; } } public String getType() { return "aar"; } public String getArtifactId() { return "aarartifact"; } public File getFile() { return new File( basedir, "/target/test-classes/unit/sample_wars/simple.aar" ); } public ArtifactHandler getArtifactHandler() { return artifactHandler; } } maven-war-plugin-2.1.1/src/test/java/org/apache/maven/plugin/war/stub/MavenProjectBasicStub.java0000644000175000017500000000465411015344504032561 0ustar twernertwernerpackage org.apache.maven.plugin.war.stub; /* * 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.maven.model.Organization; import org.apache.maven.project.MavenProject; import java.io.File; import java.util.HashSet; import java.util.Properties; import java.util.Set; /** * Stub */ public class MavenProjectBasicStub extends MavenProject { protected String testRootDir; protected Properties properties; public MavenProjectBasicStub() throws Exception { super( new ModelStub() ); properties = new Properties(); } public Set getArtifacts() { return new HashSet(); } public String getName() { return "Test Project "; } public File getBasedir() { // create an isolated environment // see setupTestEnvironment for details //return new File( testRootDir ); return null; } public String getGroupId() { return "org.apache.maven.plugin.test"; } public String getArtifactId() { return "maven-war-plugin-test"; } public String getPackaging() { return "jar"; } public String getVersion() { return "0.0-Test"; } public void addProperty( String key, String value ) { properties.put( key, value ); } public Properties getProperties() { return properties; } public String getDescription() { return "Test Description"; } public Organization getOrganization() { return new Organization() { public String getName() { return "Test Name"; } }; } } maven-war-plugin-2.1.1/src/test/java/org/apache/maven/plugin/war/stub/JarArtifactStub.java0000644000175000017500000000560310733561373031422 0ustar twernertwernerpackage org.apache.maven.plugin.war.stub; /* * 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.maven.artifact.handler.ArtifactHandler; import java.io.File; public class JarArtifactStub extends AbstractArtifactStub { protected String groupId; protected String artifactId; protected String version; protected boolean optional = false; protected String scope; private ArtifactHandler artifactHandler; public JarArtifactStub( String basedir, ArtifactHandler artifactHandler ) { super( basedir ); this.artifactHandler = artifactHandler; } public void setGroupId( String id ) { groupId = id; } public String getGroupId() { if ( groupId != null ) { return groupId; } else { return "org.sample.jar"; } } public String getType() { return "jar"; } public void setArtifactId( String artifactId ) { this.artifactId = artifactId; } public String getArtifactId() { if ( artifactId != null ) { return artifactId; } else { return "jarartifact"; } } public String getVersion() { if ( version != null ) { return version; } else { return super.getVersion(); } } public void setVersion( String version ) { this.version = version; } public boolean isOptional() { return optional; } public void setOptional( boolean optional ) { this.optional = optional; } public String getScope() { if ( scope != null ) { return scope; } else { return super.getScope(); } } public void setScope( String scope ) { this.scope = scope; } public File getFile() { return new File( basedir, "/target/test-classes/unit/sample_wars/simple.jar" ); } public ArtifactHandler getArtifactHandler() { return artifactHandler; } } maven-war-plugin-2.1.1/src/test/java/org/apache/maven/plugin/war/stub/WarArtifact4CCStub.java0000644000175000017500000000317211015344504031715 0ustar twernertwernerpackage org.apache.maven.plugin.war.stub; /* * 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.maven.artifact.handler.ArtifactHandler; import org.apache.maven.artifact.handler.DefaultArtifactHandler; import org.apache.maven.artifact.versioning.VersionRange; /** * stub for copy constructor * to preven the copy constructor frow blowing up */ public class WarArtifact4CCStub extends WarArtifactStub { public WarArtifact4CCStub( String basedir ) { super( basedir ); } public VersionRange getVersionRange() { return VersionRange.createFromVersion( getVersion() ); } public String getGroupId() { return "org.maven.plugin.test"; } public String getClassifier() { return "testclassifier"; } public ArtifactHandler getArtifactHandler() { return new DefaultArtifactHandler(); } } maven-war-plugin-2.1.1/src/test/java/org/apache/maven/plugin/war/stub/MavenZipProject.java0000644000175000017500000000307211432027106031434 0ustar twernertwernerpackage org.apache.maven.plugin.war.stub; /* * 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 java.util.HashSet; import java.util.Set; import org.apache.maven.artifact.Artifact; /** * @author olamy * @since 9 juin 07 * @version $Id: MavenZipProject.java 985726 2010-08-15 18:13:26Z bentmann $ */ public class MavenZipProject extends MavenProject4CopyConstructor { private Set artifacts; public MavenZipProject() throws Exception { super(); this.artifacts = new HashSet(); } public Set getArtifacts() { return this.artifacts; } public Set getDependencyArtifacts() { return this.artifacts; } public void addArtifact( Artifact artifact ) { this.artifacts.add( artifact ); } } maven-war-plugin-2.1.1/src/test/java/org/apache/maven/plugin/war/stub/TLDArtifactStub.java0000644000175000017500000000241011015344504031307 0ustar twernertwernerpackage org.apache.maven.plugin.war.stub; /* * 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 java.io.File; public class TLDArtifactStub extends AbstractArtifactStub { public TLDArtifactStub( String _basedir ) { super( _basedir ); } public String getType() { return "tld"; } public String getArtifactId() { return "tldartifact"; } public File getFile() { return new File( basedir, "/target/test-classes/unit/sample_wars/tld.jar" ); } } maven-war-plugin-2.1.1/src/test/java/org/apache/maven/plugin/war/util/0000755000175000017500000000000011641142606025514 5ustar twernertwernermaven-war-plugin-2.1.1/src/test/java/org/apache/maven/plugin/war/util/MappingUtilsTest.java0000644000175000017500000001346711376451113031647 0ustar twernertwernerpackage org.apache.maven.plugin.war.util; /* * 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 junit.framework.TestCase; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.war.AbstractWarMojo; import org.apache.maven.plugin.war.stub.AbstractArtifactStub; import org.codehaus.plexus.interpolation.InterpolationException; /** * Tests the mapping of file names. * * @author Stephane Nicoll */ public class MappingUtilsTest extends TestCase { public void testCompleteMapping() throws MojoExecutionException, InterpolationException { TestArtifactStub jar = new TestArtifactStub(); jar.setGroupId( "org.apache.sample" ); jar.setArtifactId( "maven-test-lib" ); jar.setVersion( "1.0" ); assertEquals( "maven-test-lib-1.0.jar", MappingUtils.evaluateFileNameMapping( "@{artifactId}@-@{version}@.@{extension}@", jar ) ); } public void testNoVersionMapping() throws MojoExecutionException, InterpolationException { TestArtifactStub jar = new TestArtifactStub(); jar.setGroupId( "org.apache.sample" ); jar.setArtifactId( "maven-test-lib" ); jar.setVersion( "1.0" ); assertEquals( "maven-test-lib.jar", MappingUtils.evaluateFileNameMapping( "@{artifactId}@.@{extension}@", jar ) ); } public void testMappingWithGroupId() throws MojoExecutionException, InterpolationException { TestArtifactStub jar = new TestArtifactStub(); jar.setGroupId( "org.apache.sample" ); jar.setArtifactId( "maven-test-lib" ); jar.setVersion( "1.0" ); assertEquals( "org.apache.sample-maven-test-lib-1.0.jar", MappingUtils.evaluateFileNameMapping( "@{groupId}@-@{artifactId}@-@{version}@.@{extension}@", jar ) ); } public void testMappingWithClassifier() throws MojoExecutionException, InterpolationException { TestArtifactStub jar = new TestArtifactStub(); jar.setGroupId( "org.apache.sample" ); jar.setArtifactId( "maven-test-lib" ); jar.setVersion( "1.0" ); jar.setClassifier( "classifier" ); assertEquals( "maven-test-lib-1.0-classifier.jar", MappingUtils.evaluateFileNameMapping( AbstractWarMojo.DEFAULT_FILE_NAME_MAPPING_CLASSIFIER, jar ) ); } /** * Test for MWAR-212. */ public void testMappingWithOptionalClassifier() throws MojoExecutionException, InterpolationException { final String MAPPING_WITH_OPTIONAL_CLASSIFIER_1 = "@{artifactId}@-@{version}@@{dashClassifier}@.@{extension}@"; final String MAPPING_WITH_OPTIONAL_CLASSIFIER_2 = "@{artifactId}@-@{version}@@{dashClassifier?}@.@{extension}@"; TestArtifactStub jar = new TestArtifactStub(); jar.setGroupId( "org.apache.sample" ); jar.setArtifactId( "maven-test-lib" ); jar.setVersion( "1.0" ); assertEquals( "maven-test-lib-1.0.jar", MappingUtils.evaluateFileNameMapping( MAPPING_WITH_OPTIONAL_CLASSIFIER_1, jar ) ); assertEquals( "maven-test-lib-1.0.jar", MappingUtils.evaluateFileNameMapping( MAPPING_WITH_OPTIONAL_CLASSIFIER_2, jar ) ); jar = new TestArtifactStub(); jar.setGroupId( "org.apache.sample" ); jar.setArtifactId( "maven-test-lib" ); jar.setVersion( "1.0" ); jar.setClassifier( "classifier" ); assertEquals( "maven-test-lib-1.0-classifier.jar", MappingUtils.evaluateFileNameMapping( MAPPING_WITH_OPTIONAL_CLASSIFIER_1, jar ) ); assertEquals( "maven-test-lib-1.0-classifier.jar", MappingUtils.evaluateFileNameMapping( MAPPING_WITH_OPTIONAL_CLASSIFIER_2, jar ) ); } // A very dumb stub used to test the mappings class TestArtifactStub extends AbstractArtifactStub { protected String groupId; protected String artifactId; protected String version; protected String classifier; protected String type = "jar"; public TestArtifactStub() { super( null ); } public String getGroupId() { return groupId; } public void setGroupId( String groupId ) { this.groupId = groupId; } public String getArtifactId() { return artifactId; } public void setArtifactId( String artifactId ) { this.artifactId = artifactId; } public String getVersion() { return version; } public void setVersion( String version ) { this.version = version; } public String getClassifier() { return classifier; } public void setClassifier( String classifier ) { this.classifier = classifier; } public String getType() { return type; } public void setType( String type ) { this.type = type; } } } maven-war-plugin-2.1.1/src/test/java/org/apache/maven/plugin/war/util/WebappStructureTest.java0000644000175000017500000002437311432027106032362 0ustar twernertwernerpackage org.apache.maven.plugin.war.util; /* * 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 junit.framework.TestCase; import org.apache.maven.artifact.Artifact; import org.apache.maven.model.Dependency; import java.util.ArrayList; import java.util.List; /** * @author Stephane Nicoll */ public class WebappStructureTest extends TestCase { public void testDependencyAnalysisNoChange() { final List dependencies = new ArrayList(); dependencies.add( createDependency( "groupTest", "artifactTest", "1.0" ) ); final WebappStructure cache = new WebappStructure( dependencies ); final WebappStructure webappStructure = new WebappStructure( dependencies, cache ); webappStructure.analyseDependencies( new WebappStructure.DependenciesAnalysisCallback() { int count = 0; public void unchangedDependency( Dependency dependency ) { if ( count == 0 ) { count++; } else { fail( "Should have called unchanged dependency only once" ); } } public void newDependency( Dependency dependency ) { fail( "Should have failed to trigger this callback" ); } public void removedDependency( Dependency dependency ) { fail( "Should have failed to trigger this callback" ); } public void updatedVersion( Dependency dependency, String previousVersion ) { fail( "Should have failed to trigger this callback" ); } public void updatedScope( Dependency dependency, String previousScope ) { fail( "Should have failed to trigger this callback" ); } public void updatedOptionalFlag( Dependency dependency, boolean previousOptional ) { fail( "Should have failed to trigger this callback" ); } public void updatedUnknown( Dependency dependency, Dependency previousDep ) { fail( "Should have failed to trigger this callback" ); } } ); } public void testDependencyAnalysisWithNewDependency() { final List dependencies = new ArrayList(); dependencies.add( createDependency( "groupTest", "artifactTest", "1.0" ) ); final WebappStructure cache = new WebappStructure( dependencies ); final List newDependencies = new ArrayList( dependencies ); final Dependency newDependency = createDependency( "groupTest", "nexArtifact", "2.0" ); newDependencies.add( newDependency ); final WebappStructure webappStructure = new WebappStructure( newDependencies, cache ); webappStructure.analyseDependencies( new WebappStructure.DependenciesAnalysisCallback() { int count = 0; public void unchangedDependency( Dependency dependency ) { if ( count == 0 ) { count++; } else { fail( "Should have called unchanged dependency only once" ); } } public void newDependency( Dependency dependency ) { if ( !newDependency.equals( dependency ) ) { fail( "Called new dependency with an unexpected dependency " + dependency ); } } public void removedDependency( Dependency dependency ) { fail( "Should have failed to trigger this callback" ); } public void updatedVersion( Dependency dependency, String previousVersion ) { fail( "Should have failed to trigger this callback" ); } public void updatedScope( Dependency dependency, String previousScope ) { fail( "Should have failed to trigger this callback" ); } public void updatedOptionalFlag( Dependency dependency, boolean previousOptional ) { fail( "Should have failed to trigger this callback" ); } public void updatedUnknown( Dependency dependency, Dependency previousDep ) { fail( "Should have failed to trigger this callback" ); } } ); } public void testDependencyAnalysisWithRemovedDependency() { final List dependencies = new ArrayList(); dependencies.add( createDependency( "groupTest", "artifactTest", "1.0" ) ); final Dependency removedDependency = createDependency( "groupTest", "removedDep", "5.2" ); dependencies.add( removedDependency ); final WebappStructure cache = new WebappStructure( dependencies ); final List newDependencies = new ArrayList( dependencies ); newDependencies.remove( removedDependency ); final WebappStructure webappStructure = new WebappStructure( newDependencies, cache ); webappStructure.analyseDependencies( new WebappStructure.DependenciesAnalysisCallback() { int count = 0; public void unchangedDependency( Dependency dependency ) { if ( count == 0 ) { count++; } else { fail( "Should have called unchanged dependency only once" ); } } public void newDependency( Dependency dependency ) { fail( "Should have failed to trigger this callback" ); } public void removedDependency( Dependency dependency ) { if ( !removedDependency.equals( dependency ) ) { fail( "Called removed dependency with an unexpected dependency " + dependency ); } } public void updatedVersion( Dependency dependency, String previousVersion ) { fail( "Should have failed to trigger this callback" ); } public void updatedScope( Dependency dependency, String previousScope ) { fail( "Should have failed to trigger this callback" ); } public void updatedOptionalFlag( Dependency dependency, boolean previousOptional ) { fail( "Should have failed to trigger this callback" ); } public void updatedUnknown( Dependency dependency, Dependency previousDep ) { fail( "Should have failed to trigger this callback" ); } } ); } public void testUnknownFileNotAvailable() { final WebappStructure structure = new WebappStructure( new ArrayList() ); assertFalse( structure.isRegistered( "/foo/bar.txt" ) ); } public void testRegisterSamePathTwice() { final WebappStructure structure = new WebappStructure( new ArrayList() ); structure.registerFile( "overlay1", "WEB-INF/web.xml" ); assertFalse( structure.registerFile( "currentBuild", "WEB-INF/web.xml" ) ); } public void testRegisterForced() { final String path = "WEB-INF/web.xml"; final WebappStructure structure = new WebappStructure( new ArrayList() ); assertFalse("New file should return false", structure.registerFileForced( "overlay1", path )); assertEquals( "overlay1", structure.getOwner( path ) ); } public void testRegisterSamePathTwiceForced() { final String path = "WEB-INF/web.xml"; final WebappStructure structure = new WebappStructure( new ArrayList() ); structure.registerFile( "overlay1", path ); assertEquals( "overlay1", structure.getOwner( path ) ); assertTrue("owner replacement should have returned true", structure.registerFileForced( "currentBuild", path )); assertEquals("currentBuild", structure.getOwner( path )); } protected Dependency createDependency( String groupId, String artifactId, String version, String type, String scope, String classifier ) { final Dependency dep = new Dependency(); dep.setGroupId( groupId ); dep.setArtifactId( artifactId ); dep.setVersion( version ); if ( type == null ) { dep.setType( "jar" ); } else { dep.setType( type ); } if ( scope != null ) { dep.setScope( scope ); } else { dep.setScope( Artifact.SCOPE_COMPILE ); } if ( classifier != null ) { dep.setClassifier( classifier ); } return dep; } protected Dependency createDependency( String groupId, String artifactId, String version, String type, String scope ) { return createDependency( groupId, artifactId, version, type, scope, null ); } protected Dependency createDependency( String groupId, String artifactId, String version, String type ) { return createDependency( groupId, artifactId, version, type, null ); } protected Dependency createDependency( String groupId, String artifactId, String version ) { return createDependency( groupId, artifactId, version, null ); } } maven-war-plugin-2.1.1/src/test/java/org/apache/maven/plugin/war/util/PathSetTest.java0000644000175000017500000002634411046132465030601 0ustar twernertwernerpackage org.apache.maven.plugin.war.util; /* * 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 junit.framework.TestCase; import org.codehaus.plexus.util.StringUtils; import java.io.File; import java.io.IOException; import java.util.HashSet; import java.util.Iterator; import java.util.Set; public class PathSetTest extends TestCase { /* --------------- Normalization tests --------------*/ /** * Test method for 'org.apache.maven.plugin.war.PathSet.normalizeFilePathStatic(String)' */ public void testNormalizeFilePathStatic() { assertEquals( "Normalized path error", "", PathSet.normalizeFilePathStatic( "" ) ); assertEquals( "Normalized path error", "", PathSet.normalizeFilePathStatic( "/" ) ); assertEquals( "Normalized path error", "", PathSet.normalizeFilePathStatic( "////" ) ); assertEquals( "Normalized path error", "", PathSet.normalizeFilePathStatic( "\\" ) ); assertEquals( "Normalized path error", "", PathSet.normalizeFilePathStatic( "\\\\\\\\" ) ); assertEquals( "Normalized path error", "abc", PathSet.normalizeFilePathStatic( "abc" ) ); assertEquals( "Normalized path error", "abc", PathSet.normalizeFilePathStatic( "/abc" ) ); assertEquals( "Normalized path error", "abc", PathSet.normalizeFilePathStatic( "////abc" ) ); assertEquals( "Normalized path error", "abc", PathSet.normalizeFilePathStatic( "\\abc" ) ); assertEquals( "Normalized path error", "abc", PathSet.normalizeFilePathStatic( "\\\\\\\\abc" ) ); assertEquals( "Normalized path error", "abc/def/xyz/", PathSet.normalizeFilePathStatic( "abc/def\\xyz\\" ) ); assertEquals( "Normalized path error", "abc/def/xyz/", PathSet.normalizeFilePathStatic( "/abc/def/xyz/" ) ); assertEquals( "Normalized path error", "abc/def/xyz/", PathSet.normalizeFilePathStatic( "////abc/def/xyz/" ) ); assertEquals( "Normalized path error", "abc/def/xyz/", PathSet.normalizeFilePathStatic( "\\abc/def/xyz/" ) ); assertEquals( "Normalized path error", "abc/def/xyz/", PathSet.normalizeFilePathStatic( "\\\\\\\\abc/def/xyz/" ) ); } /** * Test method for 'org.apache.maven.plugin.war.PathSet.trimTrailingSlashes(String)' */ public void testTrimTrailingSlashes() { assertEquals( "Trimed path error", "", PathSet.trimTrailingSlashes( "" ) ); assertEquals( "Trimed path error", "", PathSet.trimTrailingSlashes( "/" ) ); assertEquals( "Trimed path error", "", PathSet.trimTrailingSlashes( "//" ) ); assertEquals( "Trimed path error", "\\", PathSet.trimTrailingSlashes( "\\" ) ); assertEquals( "Trimed path error", "abc/def\\xyz\\", PathSet.trimTrailingSlashes( "abc/def\\xyz\\" ) ); assertEquals( "Trimed path error", "abc/def/xyz/", PathSet.trimTrailingSlashes( "/abc/def/xyz/" ) ); assertEquals( "Trimed path error", "abc/def/xyz/", PathSet.trimTrailingSlashes( "////abc/def/xyz/" ) ); assertEquals( "Trimed path error", "\\abc/def/xyz\\", PathSet.trimTrailingSlashes( "\\abc/def/xyz\\" ) ); assertEquals( "Trimed path error", "\\\\\\\\abc/def/xyz", PathSet.trimTrailingSlashes( "\\\\\\\\abc/def/xyz" ) ); } /* -------------- Operations tests ------------------*/ /** * Test method for: * */ public void testPathsSetBasic() { PathSet ps = new PathSet(); assertEquals( "Unexpected PathSet size", ps.size(), 0 ); Iterator iter = ps.iterator(); assertNotNull( "Iterator is null", iter ); assertFalse( "Can iterate on empty set", iter.hasNext() ); ps.add( "abc" ); assertEquals( "Unexpected PathSet size", ps.size(), 1 ); ps.add( "abc" ); assertEquals( "Unexpected PathSet size", ps.size(), 1 ); ps.add( "xyz/abc" ); assertEquals( "Unexpected PathSet size", ps.size(), 2 ); ps.add( "///abc" ); assertEquals( "Unexpected PathSet size", ps.size(), 2 ); ps.add( "///xyz\\abc" ); assertEquals( "Unexpected PathSet size", ps.size(), 2 ); ps.addAll( ps ); assertEquals( "Unexpected PathSet size", ps.size(), 2 ); int i = 0; for ( Iterator iter2 = ps.iterator(); iter2.hasNext(); ) { i++; String pathstr = (String) iter2.next(); assertTrue( ps.contains( pathstr ) ); assertTrue( ps.contains( "/" + pathstr ) ); assertTrue( ps.contains( "/" + StringUtils.replace( pathstr, '/', '\\' ) ) ); assertFalse( ps.contains( "/" + StringUtils.replace( pathstr, '/', '\\' ) + "/a" ) ); assertFalse( ps.contains( "/a/" + StringUtils.replace( pathstr, '/', '\\' ) ) ); } assertEquals( "Wrong count of iterations", 2, i ); ps.addPrefix( "/ab/c/" ); i = 0; for ( Iterator iter2 = ps.iterator(); iter2.hasNext(); ) { i++; String pathstr = (String) iter2.next(); assertTrue( pathstr.startsWith( "ab/c/" ) ); assertFalse( pathstr.startsWith( "ab/c//" ) ); assertTrue( ps.contains( pathstr ) ); assertTrue( ps.contains( "/" + pathstr ) ); assertTrue( ps.contains( "/" + StringUtils.replace( pathstr, '/', '\\' ) ) ); assertFalse( ps.contains( "/" + StringUtils.replace( pathstr, '/', '\\' ) + "/a" ) ); assertFalse( ps.contains( "/ab/" + StringUtils.replace( pathstr, '/', '\\' ) ) ); } assertEquals( "Wrong count of iterations", 2, i ); } /** * Test method for: * */ public void testPathsSetAddAlls() { Set s1set = new HashSet(); s1set.add( "/a/b" ); s1set.add( "a/b/c" ); s1set.add( "a\\b/c" ); s1set.add( "//1//2\3a" ); String[] s2ar = new String[]{"/a/b", "a2/b2/c2", "a2\\b2/c2", "//21//22\23a"}; PathSet ps1 = new PathSet( s1set ); assertEquals( "Unexpected PathSet size", 3, ps1.size() ); PathSet ps2 = new PathSet( s2ar ); assertEquals( "Unexpected PathSet size", 3, ps2.size() ); ps1.addAll( s2ar ); assertEquals( "Unexpected PathSet size", 5, ps1.size() ); ps2.addAll( s1set ); assertEquals( "Unexpected PathSet size", 5, ps2.size() ); for ( Iterator iter = ps1.iterator(); iter.hasNext(); ) { String str = (String) iter.next(); assertTrue( str, ps2.contains( str ) ); assertTrue( ps2.contains( "/" + str ) ); assertTrue( ps1.contains( str ) ); assertTrue( ps1.contains( "/" + str ) ); } for ( Iterator iter = ps2.iterator(); iter.hasNext(); ) { String str = (String) iter.next(); assertTrue( ps1.contains( str ) ); assertTrue( ps1.contains( "/" + str ) ); assertTrue( ps2.contains( str ) ); assertTrue( ps2.contains( "/" + str ) ); } ps1.addAll( s2ar, "/pref/" ); assertEquals( "Unexpected PathSet size", 8, ps1.size() ); ps2.addAll( s2ar, "/pref/" ); assertEquals( "Unexpected PathSet size", 8, ps2.size() ); for ( Iterator iter = ps1.iterator(); iter.hasNext(); ) { String str = (String) iter.next(); assertTrue( str, ps2.contains( str ) ); assertTrue( ps2.contains( "/" + str ) ); assertTrue( ps1.contains( str ) ); assertTrue( ps1.contains( "/" + str ) ); } for ( Iterator iter = ps2.iterator(); iter.hasNext(); ) { String str = (String) iter.next(); assertTrue( ps1.contains( str ) ); assertTrue( ps1.contains( "/" + str ) ); assertTrue( ps2.contains( str ) ); assertTrue( ps2.contains( "/" + str ) ); } } /** * Test method for 'org.apache.maven.plugin.war.PathSet.addAllFilesInDirectory(File, String)' * * @throws IOException if an io error occurred */ public void testAddAllFilesInDirectory() throws IOException { PathSet ps = new PathSet(); /* Preparing directory structure*/ File testDir = new File( "target/testAddAllFilesInDirectory" ); testDir.mkdirs(); File f1 = new File( testDir, "f1" ); f1.createNewFile(); File f2 = new File( testDir, "f2" ); f2.createNewFile(); File d1 = new File( testDir, "d1" ); File d1d2 = new File( testDir, "d1/d2" ); d1d2.mkdirs(); File d1d2f1 = new File( d1d2, "f1" ); d1d2f1.createNewFile(); File d1d2f2 = new File( d1d2, "f2" ); d1d2f2.createNewFile(); ps.addAllFilesInDirectory( new File( "target/testAddAllFilesInDirectory" ), "123/" ); assertEquals( "Unexpected PathSet size", 4, ps.size() ); /*No changes after adding duplicates*/ ps.addAllFilesInDirectory( new File( "target/testAddAllFilesInDirectory" ), "123/" ); assertEquals( "Unexpected PathSet size", 4, ps.size() ); /*Cleanup*/ f1.delete(); f2.delete(); /*No changes after adding a subset of files*/ ps.addAllFilesInDirectory( new File( "target/testAddAllFilesInDirectory" ), "123/" ); assertEquals( "Unexpected PathSet size", 4, ps.size() ); d1d2f1.delete(); d1d2f2.delete(); d1d2.delete(); d1.delete(); testDir.delete(); assertTrue( ps.contains( "123/f1" ) ); assertTrue( ps.contains( "/123/f1" ) ); assertTrue( ps.contains( "123\\f1" ) ); assertTrue( ps.contains( "123\\f2" ) ); assertTrue( ps.contains( "\\123/d1\\d2/f1" ) ); assertTrue( ps.contains( "123\\d1/d2\\f2" ) ); assertFalse( ps.contains( "123\\f3" ) ); } } maven-war-plugin-2.1.1/src/test/java/org/apache/maven/plugin/war/util/WarUtilsTest.java0000644000175000017500000000614411144561523030777 0ustar twernertwernerpackage org.apache.maven.plugin.war.util; /* * 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 junit.framework.TestCase; import org.apache.maven.model.Dependency; /** * Test the WarUtils. * * @author Dennis Lundberg * @version $Id: WarUtilsTest.java 743348 2009-02-11 14:40:19Z dennisl $ */ public class WarUtilsTest extends TestCase { /** * Test for MWAR-160. */ public void testDependencyEquals() { Dependency firstDependency = new Dependency(); firstDependency.setGroupId( "1" ); firstDependency.setArtifactId( "a" ); Dependency secondDependency = new Dependency(); secondDependency.setGroupId( "2" ); secondDependency.setArtifactId( "b" ); Dependency thirdDependency = new Dependency(); thirdDependency.setGroupId( "1" ); thirdDependency.setArtifactId( "c" ); Dependency fourthDependency = new Dependency(); fourthDependency.setGroupId( "4" ); fourthDependency.setArtifactId( "a" ); assertFalse( "dependencies 1:a and 2:b should not be equal", WarUtils.dependencyEquals( firstDependency, secondDependency ) ); assertFalse( "dependencies 1:a and 1:c should not be equal", WarUtils.dependencyEquals( firstDependency, thirdDependency ) ); assertFalse( "dependencies 1:a and 4:a should not be equal", WarUtils.dependencyEquals( firstDependency, fourthDependency ) ); assertFalse( "dependencies 2:b and 1:c should not be equal", WarUtils.dependencyEquals( secondDependency, thirdDependency ) ); assertFalse( "dependencies 2:b and 4:a should not be equal", WarUtils.dependencyEquals( secondDependency, fourthDependency ) ); assertFalse( "dependencies 1:c and 4:a should not be equal", WarUtils.dependencyEquals( thirdDependency, fourthDependency ) ); } }maven-war-plugin-2.1.1/src/test/java/org/apache/maven/plugin/war/WarOverlaysTest.java0000644000175000017500000006275011377555455030552 0ustar twernertwernerpackage org.apache.maven.plugin.war; /* * 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.maven.plugin.testing.stubs.ArtifactStub; import org.apache.maven.plugin.war.overlay.DefaultOverlay; import org.codehaus.plexus.util.FileUtils; import java.io.File; import java.io.FileFilter; import java.io.IOException; import java.util.ArrayList; import java.util.LinkedList; import java.util.List; /** * @author Stephane Nicoll */ public class WarOverlaysTest extends AbstractWarExplodedMojoTest { private static File pomFile = new File( getBasedir(), "target/test-classes/unit/waroverlays/default.xml" ); public void setUp() throws Exception { super.setUp(); generateFullOverlayWar( "overlay-full-1" ); generateFullOverlayWar( "overlay-full-2" ); generateFullOverlayWar( "overlay-full-3" ); } protected File getPomFile() { return pomFile; } protected File getTestDirectory() { return new File( getBasedir(), "target/test-classes/unit/waroverlays" ); } public void testEnvironment() throws Exception { // see setup } public void testNoOverlay() throws Exception { // setup test data final String testId = "no-overlay"; final File xmlSource = createXMLConfigDir( testId, new String[]{"web.xml"} ); final File webAppDirectory = setUpMojo( testId, null ); try { mojo.setWebXml( new File( xmlSource, "web.xml" ) ); mojo.execute(); // Validate content of the webapp assertDefaultContent( webAppDirectory ); assertWebXml( webAppDirectory ); } finally { cleanDirectory( webAppDirectory ); } } public void testDefaultOverlay() throws Exception { // setup test data final String testId = "default-overlay"; // Add an overlay final ArtifactStub overlay = buildWarOverlayStub( "overlay-one" ); final File webAppDirectory = setUpMojo( testId, new ArtifactStub[]{overlay} ); final List assertedFiles = new ArrayList(); try { mojo.execute(); assertedFiles.addAll( assertDefaultContent( webAppDirectory ) ); assertedFiles.addAll( assertWebXml( webAppDirectory ) ); assertedFiles.addAll( assertCustomContent( webAppDirectory, new String[]{"index.jsp", "login.jsp"}, "overlay file not found" ) ); // index and login come from overlay1 assertOverlayedFile( webAppDirectory, "overlay-one", "index.jsp" ); assertOverlayedFile( webAppDirectory, "overlay-one", "login.jsp" ); // Ok now check that there is no more files/directories final FileFilter filter = new FileFilterImpl( webAppDirectory, new String[]{MANIFEST_PATH} ); assertWebAppContent( webAppDirectory, assertedFiles, filter ); } finally { cleanDirectory( webAppDirectory ); } } public void testDefaultOverlays() throws Exception { // setup test data final String testId = "default-overlays"; // Add an overlay final ArtifactStub overlay = buildWarOverlayStub( "overlay-one" ); final ArtifactStub overlay2 = buildWarOverlayStub( "overlay-two" ); final File webAppDirectory = setUpMojo( testId, new ArtifactStub[]{overlay, overlay2} ); final List assertedFiles = new ArrayList(); try { mojo.execute(); assertedFiles.addAll( assertDefaultContent( webAppDirectory ) ); assertedFiles.addAll( assertWebXml( webAppDirectory ) ); assertedFiles.addAll( assertCustomContent( webAppDirectory, new String[]{"index.jsp", "login.jsp", "admin.jsp"}, "overlay file not found" ) ); // index and login come from overlay1 assertOverlayedFile( webAppDirectory, "overlay-one", "index.jsp" ); assertOverlayedFile( webAppDirectory, "overlay-one", "login.jsp" ); //admin comes from overlay2 // index and login comes from overlay1 assertOverlayedFile( webAppDirectory, "overlay-two", "admin.jsp" ); // Ok now check that there is no more files/directories final FileFilter filter = new FileFilterImpl( webAppDirectory, new String[]{MANIFEST_PATH} ); assertWebAppContent( webAppDirectory, assertedFiles, filter ); } finally { cleanDirectory( webAppDirectory ); } } /** * Merge a dependent WAR when a file in the war source directory * overrides one found in the WAR. *

* It also tests completeness of the resulting war as well as the proper * order of dependencies. * * @throws Exception if any error occurs */ public void testScenarioOneWithDefaulSettings() throws Exception { // setup test data final String testId = "scenario-one-default-settings"; // Add an overlay final ArtifactStub overlay1 = buildWarOverlayStub( "overlay-full-1" ); final ArtifactStub overlay2 = buildWarOverlayStub( "overlay-full-2" ); final ArtifactStub overlay3 = buildWarOverlayStub( "overlay-full-3" ); final File webAppDirectory = setUpMojo( testId, new ArtifactStub[]{overlay1, overlay2, overlay3}, new String[]{"org/sample/company/test.jsp", "jsp/b.jsp"} ); assertScenariOne( testId, webAppDirectory ); } /** * Tests that specifying the overlay explicitely has the same behavior as * the default (i.e. order, etc). *

* The default project is not specified in this case so it is processed * first by default * * @throws Exception if an error occurs */ public void testScenarioOneWithOverlaySettings() throws Exception { // setup test data final String testId = "scenario-one-overlay-settings"; // Add an overlay final ArtifactStub overlay1 = buildWarOverlayStub( "overlay-full-1" ); final ArtifactStub overlay2 = buildWarOverlayStub( "overlay-full-2" ); final ArtifactStub overlay3 = buildWarOverlayStub( "overlay-full-3" ); final File webAppDirectory = setUpMojo( testId, new ArtifactStub[]{overlay1, overlay2, overlay3}, new String[]{"org/sample/company/test.jsp", "jsp/b.jsp"} ); // Add the tags final List overlays = new ArrayList(); overlays.add( new DefaultOverlay( overlay1 ) ); overlays.add( new DefaultOverlay( overlay2 ) ); overlays.add( new DefaultOverlay( overlay3 ) ); mojo.setOverlays( overlays ); // current project ignored. Should be on top of the list assertScenariOne( testId, webAppDirectory ); } /** * Tests that specifying the overlay explicitely has the same behavior as * the default (i.e. order, etc). *

* The default project is explicitely specified so this should match the * default. * * @throws Exception if an error occurs */ public void testScenarioOneWithFullSettings() throws Exception { // setup test data final String testId = "scenario-one-full-settings"; // Add an overlay final ArtifactStub overlay1 = buildWarOverlayStub( "overlay-full-1" ); final ArtifactStub overlay2 = buildWarOverlayStub( "overlay-full-2" ); final ArtifactStub overlay3 = buildWarOverlayStub( "overlay-full-3" ); final File webAppDirectory = setUpMojo( testId, new ArtifactStub[]{overlay1, overlay2, overlay3}, new String[]{"org/sample/company/test.jsp", "jsp/b.jsp"} ); // Add the tags final List overlays = new ArrayList(); // Add the default project explicitely overlays.add( mojo.getCurrentProjectOverlay() ); // Other overlays overlays.add( new DefaultOverlay( overlay1 ) ); overlays.add( new DefaultOverlay( overlay2 ) ); overlays.add( new DefaultOverlay( overlay3 ) ); mojo.setOverlays( overlays ); // current project ignored. Should be on top of the list assertScenariOne( testId, webAppDirectory ); } /** * Runs the mojo and asserts a scenerio with 3 overlays and no * includes/excludes settings. * * @param testId thie id of the test * @param webAppDirectory the webapp directory * @throws Exception if an exception occurs */ private void assertScenariOne( String testId, File webAppDirectory ) throws Exception { final List assertedFiles = new ArrayList(); try { mojo.execute(); assertedFiles.addAll( assertWebXml( webAppDirectory ) ); assertedFiles.addAll( assertCustomContent( webAppDirectory, new String[]{"jsp/a.jsp", "jsp/b.jsp", "jsp/c.jsp", "jsp/d/a.jsp", "jsp/d/b.jsp", "jsp/d/c.jsp", "org/sample/company/test.jsp", "WEB-INF/classes/a.class", "WEB-INF/classes/b.class", "WEB-INF/classes/c.class", "WEB-INF/lib/a.jar", "WEB-INF/lib/b.jar", "WEB-INF/lib/c.jar"}, "overlay file not found" ) ); // Those files should come from the source webapp without any config assertDefaultFileContent( testId, webAppDirectory, "jsp/b.jsp" ); assertDefaultFileContent( testId, webAppDirectory, "org/sample/company/test.jsp" ); // Everything else comes from overlay1 (order of addition in the dependencies) assertOverlayedFile( webAppDirectory, "overlay-full-1", "jsp/a.jsp" ); assertOverlayedFile( webAppDirectory, "overlay-full-1", "jsp/c.jsp" ); assertOverlayedFile( webAppDirectory, "overlay-full-1", "jsp/d/a.jsp" ); assertOverlayedFile( webAppDirectory, "overlay-full-1", "jsp/d/b.jsp" ); assertOverlayedFile( webAppDirectory, "overlay-full-1", "jsp/d/c.jsp" ); assertOverlayedFile( webAppDirectory, "overlay-full-1", "WEB-INF/web.xml" ); assertOverlayedFile( webAppDirectory, "overlay-full-1", "WEB-INF/classes/a.class" ); assertOverlayedFile( webAppDirectory, "overlay-full-1", "WEB-INF/classes/b.class" ); assertOverlayedFile( webAppDirectory, "overlay-full-1", "WEB-INF/classes/c.class" ); assertOverlayedFile( webAppDirectory, "overlay-full-1", "WEB-INF/lib/a.jar" ); assertOverlayedFile( webAppDirectory, "overlay-full-1", "WEB-INF/lib/b.jar" ); assertOverlayedFile( webAppDirectory, "overlay-full-1", "WEB-INF/lib/c.jar" ); // Ok now check that there is no more files/directories final FileFilter filter = new FileFilterImpl( webAppDirectory, new String[]{MANIFEST_PATH} ); assertWebAppContent( webAppDirectory, assertedFiles, filter ); } finally { cleanDirectory( webAppDirectory ); } } public void testOverlaysIncludesExcludesWithMultipleDefinitions() throws Exception { // setup test data final String testId = "overlays-includes-excludes-multiple-defs"; // Add an overlay final ArtifactStub overlay1 = buildWarOverlayStub( "overlay-full-1" ); final ArtifactStub overlay2 = buildWarOverlayStub( "overlay-full-2" ); final ArtifactStub overlay3 = buildWarOverlayStub( "overlay-full-3" ); final File webAppDirectory = setUpMojo( testId, new ArtifactStub[]{overlay1, overlay2, overlay3}, new String[]{"org/sample/company/test.jsp", "jsp/b.jsp"} ); Overlay over1 = new DefaultOverlay( overlay3 ); over1.setExcludes( "**/a.*,**/c.*,**/*.xml" ); Overlay over2 = new DefaultOverlay( overlay1 ); over2.setIncludes( "jsp/d/*" ); over2.setExcludes( "jsp/d/a.jsp" ); Overlay over3 = new DefaultOverlay( overlay3 ); over3.setIncludes( "**/*.jsp" ); Overlay over4 = new DefaultOverlay( overlay2 ); mojo.setOverlays( new LinkedList() ); mojo.addOverlay( over1 ); mojo.addOverlay( over2 ); mojo.addOverlay( over3 ); mojo.addOverlay( mojo.getCurrentProjectOverlay()); mojo.addOverlay( over4 ); final List assertedFiles = new ArrayList(); try { mojo.execute(); assertedFiles.addAll( assertWebXml( webAppDirectory ) ); assertedFiles.addAll( assertCustomContent( webAppDirectory, new String[]{"jsp/a.jsp", "jsp/b.jsp", "jsp/c.jsp", "jsp/d/a.jsp", "jsp/d/b.jsp", "jsp/d/c.jsp", "org/sample/company/test.jsp", "WEB-INF/classes/a.class", "WEB-INF/classes/b.class", "WEB-INF/classes/c.class", "WEB-INF/lib/a.jar", "WEB-INF/lib/b.jar", "WEB-INF/lib/c.jar"}, "overlay file not found" ) ); assertOverlayedFile( webAppDirectory, "overlay-full-3", "jsp/a.jsp" ); assertOverlayedFile( webAppDirectory, "overlay-full-3", "jsp/b.jsp" ); assertOverlayedFile( webAppDirectory, "overlay-full-3", "jsp/c.jsp" ); assertOverlayedFile( webAppDirectory, "overlay-full-3", "jsp/d/a.jsp" ); assertOverlayedFile( webAppDirectory, "overlay-full-3", "jsp/d/b.jsp" ); assertOverlayedFile( webAppDirectory, "overlay-full-1", "jsp/d/c.jsp" ); assertDefaultFileContent( testId, webAppDirectory, "org/sample/company/test.jsp" ); assertOverlayedFile( webAppDirectory, "overlay-full-2", "WEB-INF/web.xml" ); assertOverlayedFile( webAppDirectory, "overlay-full-2", "WEB-INF/classes/a.class" ); assertOverlayedFile( webAppDirectory, "overlay-full-3", "WEB-INF/classes/b.class" ); assertOverlayedFile( webAppDirectory, "overlay-full-2", "WEB-INF/classes/c.class" ); assertOverlayedFile( webAppDirectory, "overlay-full-2", "WEB-INF/lib/a.jar" ); assertOverlayedFile( webAppDirectory, "overlay-full-3", "WEB-INF/lib/b.jar" ); assertOverlayedFile( webAppDirectory, "overlay-full-2", "WEB-INF/lib/c.jar" ); // Ok now check that there is no more files/directories final FileFilter filter = new FileFilterImpl( webAppDirectory, new String[]{MANIFEST_PATH} ); assertWebAppContent( webAppDirectory, assertedFiles, filter ); } finally { cleanDirectory( webAppDirectory ); } } public void testOverlaysIncludesExcludesWithMultipleDefinitions2() throws Exception { // setup test data final String testId = "overlays-includes-excludes-multiple-defs2"; // Add an overlay final ArtifactStub overlay1 = buildWarOverlayStub( "overlay-full-1" ); final ArtifactStub overlay2 = buildWarOverlayStub( "overlay-full-2" ); final ArtifactStub overlay3 = buildWarOverlayStub( "overlay-full-3" ); final File webAppDirectory = setUpMojo( testId, new ArtifactStub[]{overlay1, overlay2, overlay3}, new String[]{"org/sample/company/test.jsp", "jsp/b.jsp"} ); Overlay over1 = new DefaultOverlay( overlay3 ); over1.setExcludes( "**/a.*,**/c.*,**/*.xml,jsp/b.jsp" ); Overlay over2 = new DefaultOverlay( overlay1 ); over2.setIncludes( "jsp/d/*" ); over2.setExcludes( "jsp/d/a.jsp" ); Overlay over3 = new DefaultOverlay( overlay3 ); over3.setIncludes( "**/*.jsp" ); over3.setExcludes( "jsp/b.jsp" ); Overlay over4 = new DefaultOverlay( overlay2 ); mojo.setOverlays( new LinkedList() ); mojo.addOverlay( over1 ); mojo.addOverlay( over2 ); mojo.addOverlay( over3 ); mojo.addOverlay( mojo.getCurrentProjectOverlay() ); mojo.addOverlay( over4 ); final List assertedFiles = new ArrayList(); try { mojo.execute(); assertedFiles.addAll( assertWebXml( webAppDirectory ) ); assertedFiles.addAll( assertCustomContent( webAppDirectory, new String[]{"jsp/a.jsp", "jsp/b.jsp", "jsp/c.jsp", "jsp/d/a.jsp", "jsp/d/b.jsp", "jsp/d/c.jsp", "org/sample/company/test.jsp", "WEB-INF/classes/a.class", "WEB-INF/classes/b.class", "WEB-INF/classes/c.class", "WEB-INF/lib/a.jar", "WEB-INF/lib/b.jar", "WEB-INF/lib/c.jar"}, "overlay file not found" ) ); assertOverlayedFile( webAppDirectory, "overlay-full-3", "jsp/a.jsp" ); assertDefaultFileContent( testId, webAppDirectory, "jsp/b.jsp" ); assertOverlayedFile( webAppDirectory, "overlay-full-3", "jsp/c.jsp" ); assertOverlayedFile( webAppDirectory, "overlay-full-3", "jsp/d/a.jsp" ); assertOverlayedFile( webAppDirectory, "overlay-full-3", "jsp/d/b.jsp" ); assertOverlayedFile( webAppDirectory, "overlay-full-1", "jsp/d/c.jsp" ); assertDefaultFileContent( testId, webAppDirectory, "org/sample/company/test.jsp" ); assertOverlayedFile( webAppDirectory, "overlay-full-2", "WEB-INF/web.xml" ); assertOverlayedFile( webAppDirectory, "overlay-full-2", "WEB-INF/classes/a.class" ); assertOverlayedFile( webAppDirectory, "overlay-full-3", "WEB-INF/classes/b.class" ); assertOverlayedFile( webAppDirectory, "overlay-full-2", "WEB-INF/classes/c.class" ); assertOverlayedFile( webAppDirectory, "overlay-full-2", "WEB-INF/lib/a.jar" ); assertOverlayedFile( webAppDirectory, "overlay-full-3", "WEB-INF/lib/b.jar" ); assertOverlayedFile( webAppDirectory, "overlay-full-2", "WEB-INF/lib/c.jar" ); // Ok now check that there is no more files/directories final FileFilter filter = new FileFilterImpl( webAppDirectory, new String[]{MANIFEST_PATH} ); assertWebAppContent( webAppDirectory, assertedFiles, filter ); } finally { cleanDirectory( webAppDirectory ); } } public void testCacheWithUpdatedOverlay() throws Exception { // setup test data final String testId = "cache-updated-overlay"; // Add an overlay final ArtifactStub overlay = buildWarOverlayStub( "overlay-one" ); final ArtifactStub overlay2 = buildWarOverlayStub( "overlay-two" ); final File webAppDirectory = setUpMojo( testId, new ArtifactStub[]{overlay, overlay2} ); final List assertedFiles = new ArrayList(); try { // Use the cache setVariableValueToObject( mojo, "useCache", Boolean.TRUE ); setVariableValueToObject( mojo, "cacheFile", new File( mojo.getWorkDirectory(), "cache.xml" ) ); final LinkedList overlays = new LinkedList(); overlays.add( new DefaultOverlay( overlay ) ); overlays.add( new DefaultOverlay( overlay2 ) ); mojo.setOverlays( overlays ); mojo.execute(); // Now change the overlay order and make sure the right file is overwritten final LinkedList updatedOverlays = new LinkedList(); updatedOverlays.add( new DefaultOverlay( overlay2 ) ); updatedOverlays.add( new DefaultOverlay( overlay ) ); mojo.setOverlays( updatedOverlays ); mojo.execute(); assertedFiles.addAll( assertDefaultContent( webAppDirectory ) ); assertedFiles.addAll( assertWebXml( webAppDirectory ) ); assertedFiles.addAll( assertCustomContent( webAppDirectory, new String[]{"index.jsp", "login.jsp", "admin.jsp"}, "overlay file not found" ) ); // index and login come from overlay2 now assertOverlayedFile( webAppDirectory, "overlay-two", "index.jsp" ); assertOverlayedFile( webAppDirectory, "overlay-one", "login.jsp" ); assertOverlayedFile( webAppDirectory, "overlay-two", "admin.jsp" ); // Ok now check that there is no more files/directories final FileFilter filter = new FileFilterImpl( webAppDirectory, new String[]{MANIFEST_PATH} ); assertWebAppContent( webAppDirectory, assertedFiles, filter ); } finally { cleanDirectory( webAppDirectory ); } } public void testCacheWithRemovedOverlay() throws Exception { // setup test data final String testId = "cache-removed-overlay"; // Add an overlay final ArtifactStub overlay = buildWarOverlayStub( "overlay-one" ); final ArtifactStub overlay2 = buildWarOverlayStub( "overlay-two" ); final File webAppDirectory = setUpMojo( testId, new ArtifactStub[]{overlay, overlay2} ); final List assertedFiles = new ArrayList(); try { // Use the cache setVariableValueToObject( mojo, "useCache", Boolean.TRUE ); setVariableValueToObject( mojo, "cacheFile", new File( mojo.getWorkDirectory(), "cache.xml" ) ); final LinkedList overlays = new LinkedList(); overlays.add( new DefaultOverlay( overlay ) ); overlays.add( new DefaultOverlay( overlay2 ) ); mojo.setOverlays( overlays ); mojo.execute(); // Now remove overlay one the right file is overwritten final LinkedList updatedOverlays = new LinkedList(); updatedOverlays.add( new DefaultOverlay( overlay2 ) ); mojo.setOverlays( updatedOverlays ); // Remove overlay one as a dep mojo.getProject().getArtifacts().remove( overlay ); mojo.execute(); assertedFiles.addAll( assertDefaultContent( webAppDirectory ) ); assertedFiles.addAll( assertWebXml( webAppDirectory ) ); assertedFiles.addAll( assertCustomContent( webAppDirectory, new String[]{"index.jsp", "login.jsp", "admin.jsp"}, "overlay file not found" ) ); // index and login come from overlay2 now assertOverlayedFile( webAppDirectory, "overlay-two", "index.jsp" ); assertOverlayedFile( webAppDirectory, "overlay-one", "login.jsp" ); assertOverlayedFile( webAppDirectory, "overlay-two", "admin.jsp" ); // Ok now check that there is no more files/directories final FileFilter filter = new FileFilterImpl( webAppDirectory, new String[]{MANIFEST_PATH} ); assertWebAppContent( webAppDirectory, assertedFiles, filter ); } finally { cleanDirectory( webAppDirectory ); } } // Helpers /** * Asserts that the content of an overlayed file is correct. *

* Note that the filePath is relative to both the webapp * directory and the overlayed directory, defined by the overlayId. * * @param webAppDirectory the webapp directory * @param overlayId the id of the overlay * @param filePath the relative path * @throws IOException if an error occurred while reading the files */ protected void assertOverlayedFile( File webAppDirectory, String overlayId, String filePath ) throws IOException { final File webAppFile = new File( webAppDirectory, filePath ); final File overlayFile = getOverlayFile( overlayId, filePath ); assertEquals( "Wrong content for overlayed file " + filePath, FileUtils.fileRead( overlayFile ), FileUtils.fileRead( webAppFile ) ); } /** * Asserts that the content of an overlayed file is correct. *

* Note that the filePath is relative to both the webapp * directory and the overlayed directory, defined by the overlayId. * * @param testId te id of the test * @param webAppDirectory the webapp directory * @param filePath the relative path * @throws IOException if an error occurred while reading the files */ protected void assertDefaultFileContent( String testId, File webAppDirectory, String filePath ) throws Exception { final File webAppFile = new File( webAppDirectory, filePath ); final File sourceFile = new File( getWebAppSource( testId ), filePath ); final String expectedContent = sourceFile.toString(); assertEquals( "Wrong content for file " + filePath, expectedContent, FileUtils.fileRead( webAppFile ) ); } protected ArtifactStub generateSimpleWarArtifactStub( String id ) throws Exception { return buildWarOverlayStub( id ); } }maven-war-plugin-2.1.1/src/test/java/org/apache/maven/plugin/war/WarZipTest.java0000644000175000017500000001542011015344504027454 0ustar twernertwernerpackage org.apache.maven.plugin.war; /* * 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.maven.artifact.Artifact; import org.apache.maven.artifact.handler.ArtifactHandler; import org.apache.maven.plugin.war.overlay.DefaultOverlay; import org.apache.maven.plugin.war.stub.MavenZipProject; import org.apache.maven.plugin.war.stub.WarArtifactStub; import org.apache.maven.plugin.war.stub.ZipArtifactStub; import org.codehaus.plexus.util.FileUtils; import java.io.File; import java.util.LinkedList; /** * @author olamy * @version $Id: WarZipTest.java 659218 2008-05-22 19:28:04Z olamy $ * @since 7 Oct 07 */ public class WarZipTest extends AbstractWarMojoTest { WarMojo mojo; private static File pomFile = new File( getBasedir(), "src/test/resources/unit/warziptest/war-with-zip.xml" ); protected File getTestDirectory() { return new File( getBasedir(), "target/test-classes/unit/warziptest" ); } public void setUp() throws Exception { super.setUp(); mojo = (WarMojo) lookupMojo( "war", pomFile ); } private Artifact buildZipArtifact() throws Exception { ArtifactHandler artifactHandler = (ArtifactHandler) lookup( ArtifactHandler.ROLE, "jar" ); File zipFile = new File( getTestDirectory(), "foobar.zip" ); return new ZipArtifactStub( "src/test/resources/unit/warziptest", artifactHandler, zipFile ); } private File configureMojo( String testId ) throws Exception { MavenZipProject project = new MavenZipProject(); String outputDir = getTestDirectory().getAbsolutePath() + File.separatorChar + testId + "-output"; // clean up File outputDirFile = new File( outputDir ); if ( outputDirFile.exists() ) { FileUtils.deleteDirectory( outputDirFile ); } File webAppDirectory = new File( getTestDirectory(), testId ); WarArtifactStub warArtifact = new WarArtifactStub( getBasedir() ); String warName = "simple"; File webAppSource = createWebAppSource( testId ); File classesDir = createClassesDir( testId, true ); File xmlSource = createXMLConfigDir( testId, new String[]{"web.xml"} ); project.setArtifact( warArtifact ); this.configureMojo( mojo, new LinkedList(), classesDir, webAppSource, webAppDirectory, project ); setVariableValueToObject( mojo, "outputDirectory", outputDir ); setVariableValueToObject( mojo, "warName", warName ); setVariableValueToObject( mojo, "workDirectory", new File( getTestDirectory(), "work" ) ); mojo.setWebXml( new File( xmlSource, "web.xml" ) ); project.getArtifacts().add( buildZipArtifact() ); return webAppDirectory; } public void testOneZipWithNoSkip() throws Exception { File webAppDirectory = configureMojo( "one-zip" ); Overlay overlay = new DefaultOverlay( buildZipArtifact() ); //overlay.setSkip( false ); overlay.setType( "zip" ); mojo.addOverlay( overlay ); mojo.execute(); File foo = new File( webAppDirectory, "foo.txt" ); assertTrue( "foo.txt not exists", foo.exists() ); assertTrue( "foo.txt not a file", foo.isFile() ); File barDirectory = new File( webAppDirectory, "bar" ); assertTrue( "bar directory not exists", barDirectory.exists() ); assertTrue( "bar not a directory", barDirectory.isDirectory() ); File bar = new File( barDirectory, "bar.txt" ); assertTrue( "bar/bar.txt not exists", bar.exists() ); assertTrue( "bar/bar.txt not a file", bar.isFile() ); } public void testOneZipWithTargetPathOverlay() throws Exception { File webAppDirectory = configureMojo( "one-zip-overlay-targetPath" ); Overlay overlay = new DefaultOverlay( buildZipArtifact() ); overlay.setSkip( false ); overlay.setType( "zip" ); overlay.setTargetPath( "overridePath" ); mojo.addOverlay( overlay ); mojo.execute(); File foo = new File( webAppDirectory.getPath() + File.separatorChar + "overridePath", "foo.txt" ); assertTrue( "foo.txt not exists", foo.exists() ); assertTrue( "foo.txt not a file", foo.isFile() ); File barDirectory = new File( webAppDirectory.getPath() + File.separatorChar + "overridePath", "bar" ); assertTrue( "bar directory not exists", barDirectory.exists() ); assertTrue( "bar not a directory", barDirectory.isDirectory() ); File bar = new File( barDirectory, "bar.txt" ); assertTrue( "bar/bar.txt not exists", bar.exists() ); assertTrue( "bar/bar.txt not a file", bar.isFile() ); } public void testOneZipDefaultSkip() throws Exception { File webAppDirectory = configureMojo( "one-zip-overlay-skip" ); mojo.execute(); assertZipContentNotHere( webAppDirectory ); } public void testOneZipWithForceSkip() throws Exception { File webAppDirectory = configureMojo( "one-zip-overlay-skip" ); Overlay overlay = new DefaultOverlay( buildZipArtifact() ); overlay.setSkip( true ); overlay.setType( "zip" ); mojo.addOverlay( overlay ); mojo.execute(); assertZipContentNotHere( webAppDirectory ); } protected void assertZipContentNotHere( File webAppDirectory ) { File foo = new File( webAppDirectory.getPath() + File.separatorChar + "overridePath", "foo.txt" ); assertFalse( "foo.txt exists", foo.exists() ); assertFalse( "foo.txt a file", foo.isFile() ); File barDirectory = new File( webAppDirectory.getPath() + File.separatorChar + "overridePath", "bar" ); assertFalse( "bar directory exists", barDirectory.exists() ); assertFalse( "bar is a directory", barDirectory.isDirectory() ); File bar = new File( barDirectory, "bar.txt" ); assertFalse( "bar/bar.txt exists", bar.exists() ); assertFalse( "bar/bar.txt is a file", bar.isFile() ); } } maven-war-plugin-2.1.1/src/test/java/org/apache/maven/plugin/war/WarExplodedMojoTest.java0000644000175000017500000013565511453733464031335 0ustar twernertwernerpackage org.apache.maven.plugin.war; /* * 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.maven.artifact.handler.ArtifactHandler; import org.apache.maven.plugin.testing.stubs.ArtifactStub; import org.apache.maven.plugin.war.stub.AarArtifactStub; import org.apache.maven.plugin.war.stub.EJBArtifactStub; import org.apache.maven.plugin.war.stub.EJBArtifactStubWithClassifier; import org.apache.maven.plugin.war.stub.EJBClientArtifactStub; import org.apache.maven.plugin.war.stub.IncludeExcludeWarArtifactStub; import org.apache.maven.plugin.war.stub.JarArtifactStub; import org.apache.maven.plugin.war.stub.MarArtifactStub; import org.apache.maven.plugin.war.stub.MavenProjectArtifactsStub; import org.apache.maven.plugin.war.stub.MavenProjectBasicStub; import org.apache.maven.plugin.war.stub.PARArtifactStub; import org.apache.maven.plugin.war.stub.ResourceStub; import org.apache.maven.plugin.war.stub.TLDArtifactStub; import org.apache.maven.plugin.war.stub.WarArtifactStub; import org.codehaus.plexus.util.FileUtils; import java.io.BufferedReader; import java.io.File; import java.io.StringReader; import java.text.SimpleDateFormat; import java.util.LinkedList; import java.util.List; import java.util.Locale; public class WarExplodedMojoTest extends AbstractWarExplodedMojoTest { protected File getPomFile() { return new File( getBasedir(), "/target/test-classes/unit/warexplodedmojo/plugin-config.xml" ); } protected File getTestDirectory() { return new File( getBasedir(), "target/test-classes/unit/warexplodedmojo/test-dir" ); } /** * @throws Exception */ public void testSimpleExplodedWar() throws Exception { // setup test data String testId = "SimpleExplodedWar"; MavenProjectBasicStub project = new MavenProjectBasicStub(); File webAppSource = createWebAppSource( testId ); File classesDir = createClassesDir( testId, false ); File webAppResource = new File( getTestDirectory(), testId + "-resources" ); File webAppDirectory = new File( getTestDirectory(), testId ); File sampleResource = new File( webAppResource, "pix/panis_na.jpg" ); ResourceStub[] resources = new ResourceStub[]{new ResourceStub()}; createFile( sampleResource ); assertTrue( "sampeResource not found", sampleResource.exists() ); // configure mojo resources[0].setDirectory( webAppResource.getAbsolutePath() ); this.configureMojo( mojo, new LinkedList(), classesDir, webAppSource, webAppDirectory, project ); setVariableValueToObject( mojo, "webResources", resources ); mojo.execute(); // validate operation File expectedWebSourceFile = new File( webAppDirectory, "pansit.jsp" ); File expectedWebSource2File = new File( webAppDirectory, "org/web/app/last-exile.jsp" ); File expectedWebResourceFile = new File( webAppDirectory, "pix/panis_na.jpg" ); File expectedWEBINFDir = new File( webAppDirectory, "WEB-INF" ); File expectedMETAINFDir = new File( webAppDirectory, "META-INF" ); assertTrue( "source files not found: " + expectedWebSourceFile.toString(), expectedWebSourceFile.exists() ); assertTrue( "source files not found: " + expectedWebSource2File.toString(), expectedWebSource2File.exists() ); assertTrue( "resources doesn't exist: " + expectedWebResourceFile, expectedWebResourceFile.exists() ); assertTrue( "WEB-INF not found", expectedWEBINFDir.exists() ); assertTrue( "META-INF not found", expectedMETAINFDir.exists() ); // house keeping expectedWebSourceFile.delete(); expectedWebSource2File.delete(); expectedWebResourceFile.delete(); } /** * @throws Exception */ public void testSimpleExplodedWarWTargetPath() throws Exception { // setup test data String testId = "SimpleExplodedWar"; MavenProjectBasicStub project = new MavenProjectBasicStub(); File webAppSource = createWebAppSource( testId ); File classesDir = createClassesDir( testId, false ); File webAppResource = new File( getTestDirectory(), "resources" ); File webAppDirectory = new File( getTestDirectory(), testId ); File sampleResource = new File( webAppResource, "pix/panis_na.jpg" ); ResourceStub[] resources = new ResourceStub[]{new ResourceStub()}; createFile( sampleResource ); // configure mojo resources[0].setDirectory( webAppResource.getAbsolutePath() ); resources[0].setTargetPath( "targetPath" ); this.configureMojo( mojo, new LinkedList(), classesDir, webAppSource, webAppDirectory, project ); setVariableValueToObject( mojo, "webResources", resources ); mojo.execute(); // validate operation File expectedWebSourceFile = new File( webAppDirectory, "pansit.jsp" ); File expectedWebSource2File = new File( webAppDirectory, "org/web/app/last-exile.jsp" ); File expectedWebResourceFile = new File( webAppDirectory, "targetPath/pix/panis_na.jpg" ); File expectedWEBINFDir = new File( webAppDirectory, "WEB-INF" ); File expectedMETAINFDir = new File( webAppDirectory, "META-INF" ); assertTrue( "source files not found: " + expectedWebSourceFile.toString(), expectedWebSourceFile.exists() ); assertTrue( "source files not found: " + expectedWebSource2File.toString(), expectedWebSource2File.exists() ); assertTrue( "resources doesn't exist: " + expectedWebResourceFile, expectedWebResourceFile.exists() ); assertTrue( "WEB-INF not found", expectedWEBINFDir.exists() ); assertTrue( "META-INF not found", expectedMETAINFDir.exists() ); // house keeping expectedWebSourceFile.delete(); expectedWebSource2File.delete(); expectedWebResourceFile.delete(); } /** * @throws Exception */ public void testExplodedWar_WithCustomWebXML() throws Exception { // setup test data String testId = "ExplodedWar_WithCustomWebXML"; MavenProjectBasicStub project = new MavenProjectBasicStub(); File webAppSource = createWebAppSource( testId ); File classesDir = createClassesDir( testId, true ); File xmlSource = createXMLConfigDir( testId, new String[]{"web.xml"} ); File webAppDirectory = new File( getTestDirectory(), testId ); // configure mojo this.configureMojo( mojo, new LinkedList(), classesDir, webAppSource, webAppDirectory, project ); mojo.setWebXml( new File( xmlSource, "web.xml" ) ); mojo.execute(); // validate operation File expectedWebSourceFile = new File( webAppDirectory, "pansit.jsp" ); File expectedWebSource2File = new File( webAppDirectory, "org/web/app/last-exile.jsp" ); File expectedWEBXMLFile = new File( webAppDirectory, "WEB-INF/web.xml" ); File expectedMETAINFDir = new File( webAppDirectory, "META-INF" ); assertTrue( "source files not found: " + expectedWebSourceFile.toString(), expectedWebSourceFile.exists() ); assertTrue( "source files not found: " + expectedWebSource2File.toString(), expectedWebSource2File.exists() ); assertTrue( "WEB XML not found: " + expectedWEBXMLFile.toString(), expectedWEBXMLFile.exists() ); assertTrue( "META-INF not found", expectedMETAINFDir.exists() ); assertEquals( "WEB XML not correct", mojo.getWebXml().toString(), FileUtils.fileRead( expectedWEBXMLFile ) ); // house keeping expectedWebSourceFile.delete(); expectedWebSource2File.delete(); expectedWEBXMLFile.delete(); expectedMETAINFDir.delete(); } /** * @throws Exception */ public void testExplodedWar_WithContainerConfigXML() throws Exception { // setup test data String testId = "ExplodedWar_WithContainerConfigXML"; MavenProjectBasicStub project = new MavenProjectBasicStub(); File classesDir = createClassesDir( testId, true ); File webAppSource = createWebAppSource( testId ); File xmlSource = createXMLConfigDir( testId, new String[]{"config.xml"} ); File webAppDirectory = new File( getTestDirectory(), testId ); // configure mojo this.configureMojo( mojo, new LinkedList(), classesDir, webAppSource, webAppDirectory, project ); mojo.setContainerConfigXML( new File( xmlSource, "config.xml" ) ); mojo.execute(); // validate operation File expectedWebSourceFile = new File( webAppDirectory, "pansit.jsp" ); File expectedWebSource2File = new File( webAppDirectory, "org/web/app/last-exile.jsp" ); File expectedContainerConfigXMLFile = new File( webAppDirectory, "META-INF/config.xml" ); File expectedWEBINFDir = new File( webAppDirectory, "WEB-INF" ); assertTrue( "source files not found: " + expectedWebSourceFile.toString(), expectedWebSourceFile.exists() ); assertTrue( "source files not found: " + expectedWebSource2File.toString(), expectedWebSource2File.exists() ); assertTrue( "WEB-INF not found", expectedWEBINFDir.exists() ); assertTrue( "Container Config XML not found:" + expectedContainerConfigXMLFile.toString(), expectedContainerConfigXMLFile.exists() ); // house keeping expectedWebSourceFile.delete(); expectedWebSource2File.delete(); expectedContainerConfigXMLFile.delete(); expectedWEBINFDir.delete(); } /** * @throws Exception */ public void testExplodedWar_WithSimpleExternalWARFile() throws Exception { // setup test data MavenProjectArtifactsStub project = new MavenProjectArtifactsStub(); WarArtifactStub warArtifact = new WarArtifactStub( getBasedir() ); String testId = "ExplodedWar_WithSimpleExternalWARFile"; File webAppDirectory = new File( getTestDirectory(), testId ); File webAppSource = createWebAppSource( testId ); File classesDir = createClassesDir( testId, true ); File workDirectory = new File( getTestDirectory(), "/war/work-" + testId ); File simpleWarFile = warArtifact.getFile(); assertTrue( "simple war not found: " + simpleWarFile.toString(), simpleWarFile.exists() ); createDir( workDirectory ); // configure mojo project.addArtifact( warArtifact ); this.configureMojo( mojo, new LinkedList(), classesDir, webAppSource, webAppDirectory, project ); setVariableValueToObject( mojo, "workDirectory", workDirectory ); mojo.execute(); // validate operation - META-INF is automatically excluded so remove the file from the list File expectedWebSourceFile = new File( webAppDirectory, "pansit.jsp" ); File expectedWebSource2File = new File( webAppDirectory, "org/web/app/last-exile.jsp" ); File expectedWEBXMLFile = new File( webAppDirectory, "WEB-INF/web.xml" ); File expectedWARFile = new File( webAppDirectory, "/org/sample/company/test.jsp" ); assertTrue( "source files not found: " + expectedWebSourceFile.toString(), expectedWebSourceFile.exists() ); assertTrue( "source files not found: " + expectedWebSource2File.toString(), expectedWebSource2File.exists() ); // check simple.war in the unit test dir under resources to verify the list of files assertTrue( "web xml not found: " + expectedWEBXMLFile.toString(), expectedWEBXMLFile.exists() ); assertTrue( "war file not found: " + expectedWARFile.toString(), expectedWARFile.exists() ); // house keeping expectedWebSourceFile.delete(); expectedWebSource2File.delete(); expectedWEBXMLFile.delete(); expectedWARFile.delete(); } /** * Merge a dependent WAR when a file in the war source directory overrides one found in the WAR. */ public void testExplodedWarMergeWarLocalFileOverride() throws Exception { // setup test data MavenProjectArtifactsStub project = new MavenProjectArtifactsStub(); WarArtifactStub warArtifact = new WarArtifactStub( getBasedir() ); String testId = "testExplodedWarMergeWarLocalFileOverride"; File webAppDirectory = new File( getTestDirectory(), testId ); File webAppSource = getWebAppSource( testId ); File simpleJSP = new File( webAppSource, "org/sample/company/test.jsp" ); createFile( simpleJSP ); File workDirectory = new File( getTestDirectory(), "/war/work-" + testId ); createDir( workDirectory ); File classesDir = createClassesDir( testId, true ); // configure mojo project.addArtifact( warArtifact ); this.configureMojo( mojo, new LinkedList(), classesDir, webAppSource, webAppDirectory, project ); setVariableValueToObject( mojo, "workDirectory", workDirectory ); mojo.execute(); // validate operation File expectedFile = new File( webAppDirectory, "/org/sample/company/test.jsp" ); assertTrue( "file not found: " + expectedFile.toString(), expectedFile.exists() ); assertEquals( "file incorrect", simpleJSP.toString(), FileUtils.fileRead( expectedFile ) ); // check when the merged war file is newer - so set an old time on the local file long time = new SimpleDateFormat( "yyyy-MM-dd", Locale.US ).parse( "2005-1-1" ).getTime(); simpleJSP.setLastModified( time ); expectedFile.setLastModified( time ); project.addArtifact( warArtifact ); this.configureMojo( mojo, new LinkedList(), classesDir, webAppSource, webAppDirectory, project ); setVariableValueToObject( mojo, "workDirectory", workDirectory ); mojo.execute(); assertTrue( "file not found: " + expectedFile.toString(), expectedFile.exists() ); assertEquals( "file incorrect", simpleJSP.toString(), FileUtils.fileRead( expectedFile ) ); // house keeping expectedFile.delete(); } // The last modified thingy behavior is not applicable anymore. This is the only test that // has been removed. // /** // * Merge a dependent WAR that gets updated since the last run. // */ // public void testExplodedWarMergeWarUpdated() // throws Exception // { // // setup test data // MavenProjectArtifactsStub project = new MavenProjectArtifactsStub(); // WarArtifactStub warArtifact = new WarArtifactStub( getBasedir() ); // // String testId = "testExplodedWarMergeWarUpdated"; // File webAppDirectory = new File( getTestDirectory(), testId ); // FileUtils.deleteDirectory( webAppDirectory ); // // File webAppSource = getWebAppSource( testId ); // // File workDirectory = new File( getTestDirectory(), "/war/work-" + testId ); // createDir( workDirectory ); // // File classesDir = createClassesDir( testId, true ); // // // configure mojo // project.addArtifact( warArtifact ); // this.configureMojo( mojo, new LinkedList(), classesDir, webAppSource, webAppDirectory, project ); // setVariableValueToObject( mojo, "workDirectory", workDirectory ); // mojo.execute(); // // // validate operation // File expectedFile = new File( webAppDirectory, "/org/sample/company/test.jsp" ); // // assertTrue( "file not found: " + expectedFile.toString(), expectedFile.exists() ); // assertEquals( "file incorrect", "", FileUtils.fileRead( expectedFile ) ); // // // update file, so the local one is older // warArtifact.setFile( new File( warArtifact.getFile().getParentFile(), "simple-updated.war" ) ); // // mojo.execute(); // // assertTrue( "file not found: " + expectedFile.toString(), expectedFile.exists() ); // assertEquals( "file incorrect", "updated\n", FileUtils.fileRead( expectedFile ) ); // // // update file, so the local one is newer // warArtifact.setFile( new File( warArtifact.getFile().getParentFile(), "simple.war" ) ); // // mojo.execute(); // // assertTrue( "file not found: " + expectedFile.toString(), expectedFile.exists() ); // assertEquals( "file incorrect", "updated\n", FileUtils.fileRead( expectedFile ) ); // // // house keeping // expectedFile.delete(); // } /** * @throws Exception */ public void testExplodedWar_WithEJB() throws Exception { // setup test data String testId = "ExplodedWar_WithEJB"; MavenProjectArtifactsStub project = new MavenProjectArtifactsStub(); File webAppDirectory = new File( getTestDirectory(), testId ); File webAppSource = createWebAppSource( testId ); File classesDir = createClassesDir( testId, true ); EJBArtifactStub ejbArtifact = new EJBArtifactStub( getBasedir() ); File ejbFile = ejbArtifact.getFile(); assertTrue( "ejb jar not found: " + ejbFile.toString(), ejbFile.exists() ); // configure mojo project.addArtifact( ejbArtifact ); this.configureMojo( mojo, new LinkedList(), classesDir, webAppSource, webAppDirectory, project ); mojo.execute(); // validate operation File expectedWebSourceFile = new File( webAppDirectory, "pansit.jsp" ); File expectedWebSource2File = new File( webAppDirectory, "org/web/app/last-exile.jsp" ); // final name form is -. File expectedEJBArtifact = new File( webAppDirectory, "WEB-INF/lib/ejbartifact-0.0-Test.jar" ); // File expectedEJBArtifact = new File( webAppDirectory, "WEB-INF/lib/ejbartifact-0.0-Test.jar" ); assertTrue( "source files not found: " + expectedWebSourceFile.toString(), expectedWebSourceFile.exists() ); assertTrue( "source files not found: " + expectedWebSource2File.toString(), expectedWebSource2File.exists() ); assertTrue( "ejb artifact not found: " + expectedEJBArtifact.toString(), expectedEJBArtifact.exists() ); // house keeping expectedWebSourceFile.delete(); expectedWebSource2File.delete(); expectedEJBArtifact.delete(); } public void testExplodedWarWithJar() throws Exception { // setup test data String testId = "ExplodedWarWithJar"; MavenProjectArtifactsStub project = new MavenProjectArtifactsStub(); File webAppDirectory = new File( getTestDirectory(), testId ); File webAppSource = createWebAppSource( testId ); File classesDir = createClassesDir( testId, true ); ArtifactHandler artifactHandler = (ArtifactHandler) lookup( ArtifactHandler.ROLE, "jar" ); ArtifactStub jarArtifact = new JarArtifactStub( getBasedir(), artifactHandler ); File jarFile = jarArtifact.getFile(); assertTrue( "jar not found: " + jarFile.toString(), jarFile.exists() ); // configure mojo project.addArtifact( jarArtifact ); this.configureMojo( mojo, new LinkedList(), classesDir, webAppSource, webAppDirectory, project ); mojo.execute(); // validate operation File expectedWebSourceFile = new File( webAppDirectory, "pansit.jsp" ); File expectedWebSource2File = new File( webAppDirectory, "org/web/app/last-exile.jsp" ); // final name form is -. File expectedJarArtifact = new File( webAppDirectory, "WEB-INF/lib/jarartifact-0.0-Test.jar" ); assertTrue( "source files not found: " + expectedWebSourceFile.toString(), expectedWebSourceFile.exists() ); assertTrue( "source files not found: " + expectedWebSource2File.toString(), expectedWebSource2File.exists() ); assertTrue( "jar artifact not found: " + expectedJarArtifact.toString(), expectedJarArtifact.exists() ); // house keeping expectedWebSourceFile.delete(); expectedWebSource2File.delete(); expectedJarArtifact.delete(); } /** * @throws Exception */ public void testExplodedWar_WithEJBClient() throws Exception { // setup test data String testId = "ExplodedWar_WithEJB"; MavenProjectArtifactsStub project = new MavenProjectArtifactsStub(); File webAppDirectory = new File( getTestDirectory(), testId ); File webAppSource = createWebAppSource( testId ); File classesDir = createClassesDir( testId, true ); EJBClientArtifactStub ejbArtifact = new EJBClientArtifactStub( getBasedir() ); File ejbFile = ejbArtifact.getFile(); assertTrue( "ejb jar not found: " + ejbFile.toString(), ejbFile.exists() ); // configure mojo project.addArtifact( ejbArtifact ); this.configureMojo( mojo, new LinkedList(), classesDir, webAppSource, webAppDirectory, project ); mojo.execute(); // validate operation File expectedWebSourceFile = new File( webAppDirectory, "pansit.jsp" ); File expectedWebSource2File = new File( webAppDirectory, "org/web/app/last-exile.jsp" ); // final name form is -. File expectedEJBArtifact = new File( webAppDirectory, "WEB-INF/lib/ejbclientartifact-0.0-Test-client.jar" ); assertTrue( "source files not found: " + expectedWebSourceFile.toString(), expectedWebSourceFile.exists() ); assertTrue( "source files not found: " + expectedWebSource2File.toString(), expectedWebSource2File.exists() ); assertTrue( "ejb artifact not found: " + expectedEJBArtifact.toString(), expectedEJBArtifact.exists() ); // house keeping expectedWebSourceFile.delete(); expectedWebSource2File.delete(); expectedEJBArtifact.delete(); } /** * @throws Exception */ public void testExplodedWar_WithTLD() throws Exception { // setup test data String testId = "ExplodedWar_WithTLD"; MavenProjectArtifactsStub project = new MavenProjectArtifactsStub(); File webAppDirectory = new File( getTestDirectory(), testId ); File webAppSource = createWebAppSource( testId ); File classesDir = createClassesDir( testId, true ); TLDArtifactStub tldArtifact = new TLDArtifactStub( getBasedir() ); File tldFile = tldArtifact.getFile(); assertTrue( "tld jar not found: " + tldFile.getAbsolutePath(), tldFile.exists() ); // configure mojo project.addArtifact( tldArtifact ); this.configureMojo( mojo, new LinkedList(), classesDir, webAppSource, webAppDirectory, project ); mojo.execute(); // validate operation File expectedWebSourceFile = new File( webAppDirectory, "pansit.jsp" ); File expectedWebSource2File = new File( webAppDirectory, "org/web/app/last-exile.jsp" ); // final name form is -. File expectedTLDArtifact = new File( webAppDirectory, "WEB-INF/tld/tldartifact-0.0-Test.tld" ); assertTrue( "source files not found: " + expectedWebSourceFile.toString(), expectedWebSourceFile.exists() ); assertTrue( "source files not found: " + expectedWebSource2File.toString(), expectedWebSource2File.exists() ); assertTrue( "tld artifact not found: " + expectedTLDArtifact.toString(), expectedTLDArtifact.exists() ); // house keeping expectedWebSourceFile.delete(); expectedWebSource2File.delete(); expectedTLDArtifact.delete(); } /** * @throws Exception */ public void testExplodedWar_WithPAR() throws Exception { // setup test data String testId = "ExplodedWar_WithPAR"; MavenProjectArtifactsStub project = new MavenProjectArtifactsStub(); File webAppDirectory = new File( getTestDirectory(), testId ); File webAppSource = createWebAppSource( testId ); File classesDir = createClassesDir( testId, true ); PARArtifactStub parartifact = new PARArtifactStub( getBasedir() ); File parFile = parartifact.getFile(); assertTrue( "par not found: " + parFile.getAbsolutePath(), parFile.exists() ); // configure mojo project.addArtifact( parartifact ); this.configureMojo( mojo, new LinkedList(), classesDir, webAppSource, webAppDirectory, project ); mojo.execute(); // validate operation File expectedWebSourceFile = new File( webAppDirectory, "pansit.jsp" ); File expectedWebSource2File = new File( webAppDirectory, "org/web/app/last-exile.jsp" ); // final name form is -. File expectedPARArtifact = new File( webAppDirectory, "WEB-INF/lib/parartifact-0.0-Test.jar" ); assertTrue( "source files not found: " + expectedWebSourceFile.toString(), expectedWebSourceFile.exists() ); assertTrue( "source files not found: " + expectedWebSource2File.toString(), expectedWebSource2File.exists() ); assertTrue( "par artifact not found: " + expectedPARArtifact.toString(), expectedPARArtifact.exists() ); // house keeping expectedWebSourceFile.delete(); expectedWebSource2File.delete(); expectedPARArtifact.delete(); } public void testExplodedWarWithAar() throws Exception { // setup test data String testId = "ExplodedWarWithAar"; MavenProjectArtifactsStub project = new MavenProjectArtifactsStub(); File webAppDirectory = new File( getTestDirectory(), testId ); File webAppSource = createWebAppSource( testId ); File classesDir = createClassesDir( testId, true ); // Fake here since the aar artifact handler does not exist: no biggie ArtifactHandler artifactHandler = (ArtifactHandler) lookup( ArtifactHandler.ROLE, "jar" ); ArtifactStub aarArtifact = new AarArtifactStub( getBasedir(), artifactHandler ); File aarFile = aarArtifact.getFile(); assertTrue( "jar not found: " + aarFile.toString(), aarFile.exists() ); // configure mojo project.addArtifact( aarArtifact ); this.configureMojo( mojo, new LinkedList(), classesDir, webAppSource, webAppDirectory, project ); mojo.execute(); // validate operation File expectedWebSourceFile = new File( webAppDirectory, "pansit.jsp" ); File expectedWebSource2File = new File( webAppDirectory, "org/web/app/last-exile.jsp" ); // final name form is -. File expectedJarArtifact = new File( webAppDirectory, "WEB-INF/services/aarartifact-0.0-Test.jar" ); assertTrue( "source files not found: " + expectedWebSourceFile.toString(), expectedWebSourceFile.exists() ); assertTrue( "source files not found: " + expectedWebSource2File.toString(), expectedWebSource2File.exists() ); assertTrue( "jar artifact not found: " + expectedJarArtifact.toString(), expectedJarArtifact.exists() ); // house keeping expectedWebSourceFile.delete(); expectedWebSource2File.delete(); expectedJarArtifact.delete(); } public void testExplodedWarWithMar() throws Exception { // setup test data String testId = "ExplodedWarWithMar"; MavenProjectArtifactsStub project = new MavenProjectArtifactsStub(); File webAppDirectory = new File( getTestDirectory(), testId ); File webAppSource = createWebAppSource( testId ); File classesDir = createClassesDir( testId, true ); // Fake here since the mar artifact handler does not exist: no biggie ArtifactHandler artifactHandler = (ArtifactHandler) lookup( ArtifactHandler.ROLE, "jar" ); ArtifactStub marArtifact = new MarArtifactStub( getBasedir(), artifactHandler ); File marFile = marArtifact.getFile(); assertTrue( "jar not found: " + marFile.toString(), marFile.exists() ); // configure mojo project.addArtifact( marArtifact ); this.configureMojo( mojo, new LinkedList(), classesDir, webAppSource, webAppDirectory, project ); mojo.execute(); // validate operation File expectedWebSourceFile = new File( webAppDirectory, "pansit.jsp" ); File expectedWebSource2File = new File( webAppDirectory, "org/web/app/last-exile.jsp" ); // final name form is -. File expectedJarArtifact = new File( webAppDirectory, "WEB-INF/modules/marartifact-0.0-Test.jar" ); assertTrue( "source files not found: " + expectedWebSourceFile.toString(), expectedWebSourceFile.exists() ); assertTrue( "source files not found: " + expectedWebSource2File.toString(), expectedWebSource2File.exists() ); assertTrue( "jar artifact not found: " + expectedJarArtifact.toString(), expectedJarArtifact.exists() ); // house keeping expectedWebSourceFile.delete(); expectedWebSource2File.delete(); expectedJarArtifact.delete(); } /** * @throws Exception */ public void testExplodedWar_WithDuplicateDependencies() throws Exception { // setup test data String testId = "ExplodedWar_WithDuplicateDependencies"; MavenProjectArtifactsStub project = new MavenProjectArtifactsStub(); File webAppDirectory = new File( getTestDirectory(), testId ); File webAppSource = createWebAppSource( testId ); File classesDir = createClassesDir( testId, true ); EJBArtifactStub ejbArtifact = new EJBArtifactStub( getBasedir() ); EJBArtifactStub ejbArtifactDup = new EJBArtifactStub( getBasedir() ); File ejbFile = ejbArtifact.getFile(); // ejbArtifact has a hard coded file, only one assert is needed assertTrue( "ejb not found: " + ejbFile.getAbsolutePath(), ejbFile.exists() ); // configure mojo ejbArtifact.setGroupId( "org.sample.ejb" ); ejbArtifactDup.setGroupId( "org.dup.ejb" ); project.addArtifact( ejbArtifact ); project.addArtifact( ejbArtifactDup ); this.configureMojo( mojo, new LinkedList(), classesDir, webAppSource, webAppDirectory, project ); mojo.execute(); // validate operation File expectedWebSourceFile = new File( webAppDirectory, "pansit.jsp" ); File expectedWebSource2File = new File( webAppDirectory, "org/web/app/last-exile.jsp" ); // final name form is -. File expectedEJBArtifact = new File( webAppDirectory, "WEB-INF/lib/org.sample.ejb-ejbartifact-0.0-Test.jar" ); File expectedEJBDupArtifact = new File( webAppDirectory, "WEB-INF/lib/org.dup.ejb-ejbartifact-0.0-Test.jar" ); assertTrue( "source files not found: " + expectedWebSourceFile.toString(), expectedWebSourceFile.exists() ); assertTrue( "source files not found: " + expectedWebSource2File.toString(), expectedWebSource2File.exists() ); assertTrue( "ejb artifact not found: " + expectedEJBArtifact.toString(), expectedEJBArtifact.exists() ); assertTrue( "ejb dup artifact not found: " + expectedEJBDupArtifact.toString(), expectedEJBDupArtifact.exists() ); // house keeping expectedWebSourceFile.delete(); expectedWebSource2File.delete(); expectedEJBArtifact.delete(); expectedEJBDupArtifact.delete(); } /** * @throws Exception */ public void testExplodedWar_DuplicateWithClassifier() throws Exception { // setup test data String testId = "ExplodedWar_DuplicateWithClassifier"; MavenProjectArtifactsStub project = new MavenProjectArtifactsStub(); File webAppDirectory = new File( getTestDirectory(), testId ); File webAppSource = createWebAppSource( testId ); File classesDir = createClassesDir( testId, true ); EJBArtifactStub ejbArtifact = new EJBArtifactStub( getBasedir() ); EJBArtifactStubWithClassifier ejbArtifactDup = new EJBArtifactStubWithClassifier( getBasedir() ); File ejbFile = ejbArtifact.getFile(); // ejbArtifact has a hard coded file, only one assert is needed assertTrue( "ejb not found: " + ejbFile.getAbsolutePath(), ejbFile.exists() ); // configure mojo ejbArtifact.setGroupId( "org.sample.ejb" ); ejbArtifactDup.setGroupId( "org.sample.ejb" ); ejbArtifactDup.setClassifier( "classifier" ); project.addArtifact( ejbArtifact ); project.addArtifact( ejbArtifactDup ); this.configureMojo( mojo, new LinkedList(), classesDir, webAppSource, webAppDirectory, project ); mojo.execute(); // validate operation File expectedWebSourceFile = new File( webAppDirectory, "pansit.jsp" ); File expectedWebSource2File = new File( webAppDirectory, "org/web/app/last-exile.jsp" ); // final name form is -. File expectedEJBArtifact = new File( webAppDirectory, "WEB-INF/lib/ejbartifact-0.0-Test.jar" ); File expectedEJBDupArtifact = new File( webAppDirectory, "WEB-INF/lib/ejbartifact-0.0-Test-classifier.jar" ); assertTrue( "source files not found: " + expectedWebSourceFile.toString(), expectedWebSourceFile.exists() ); assertTrue( "source files not found: " + expectedWebSource2File.toString(), expectedWebSource2File.exists() ); assertTrue( "ejb artifact not found: " + expectedEJBArtifact.toString(), expectedEJBArtifact.exists() ); assertTrue( "ejb dup artifact not found: " + expectedEJBDupArtifact.toString(), expectedEJBDupArtifact.exists() ); // house keeping expectedWebSourceFile.delete(); expectedWebSource2File.delete(); expectedEJBArtifact.delete(); expectedEJBDupArtifact.delete(); } /** * @throws Exception */ public void testExplodedWar_WithClasses() throws Exception { // setup test data String testId = "ExplodedWar_WithClasses"; MavenProjectBasicStub project = new MavenProjectBasicStub(); File webAppDirectory = new File( getTestDirectory(), testId ); File webAppSource = createWebAppSource( testId ); File classesDir = createClassesDir( testId, false ); // configure mojo this.configureMojo( mojo, new LinkedList(), classesDir, webAppSource, webAppDirectory, project ); mojo.execute(); // validate operation File expectedWebSourceFile = new File( webAppDirectory, "pansit.jsp" ); File expectedWebSource2File = new File( webAppDirectory, "org/web/app/last-exile.jsp" ); // final name form is -. File expectedClass = new File( webAppDirectory, "WEB-INF/classes/sample-servlet.class" ); assertTrue( "source files not found: " + expectedWebSourceFile.toString(), expectedWebSourceFile.exists() ); assertTrue( "source files not found: " + expectedWebSource2File.toString(), expectedWebSource2File.exists() ); assertTrue( "classes not found: " + expectedClass.toString(), expectedClass.exists() ); // house keeping expectedWebSourceFile.delete(); expectedWebSource2File.delete(); expectedClass.delete(); } public void testExplodedWar_WithSourceIncludeExclude() throws Exception { // setup test data String testId = "ExplodedWar_WithSourceIncludeExclude"; MavenProjectBasicStub project = new MavenProjectBasicStub(); File webAppSource = createWebAppSource( testId ); File classesDir = createClassesDir( testId, true ); File webAppDirectory = new File( getTestDirectory(), testId ); // configure mojo this.configureMojo( mojo, new LinkedList(), classesDir, webAppSource, webAppDirectory, project ); setVariableValueToObject( mojo, "warSourceIncludes", "**/*sit.jsp" ); setVariableValueToObject( mojo, "warSourceExcludes", "**/last*.*" ); mojo.execute(); // validate operation File expectedWebSourceFile = new File( webAppDirectory, "pansit.jsp" ); File expectedWebSource2File = new File( webAppDirectory, "org/web/app/last-exile.jsp" ); File expectedWEBXMLDir = new File( webAppDirectory, "WEB-INF" ); File expectedMETAINFDir = new File( webAppDirectory, "META-INF" ); assertTrue( "source files not found: " + expectedWebSourceFile.toString(), expectedWebSourceFile.exists() ); assertFalse( "source files found: " + expectedWebSource2File.toString(), expectedWebSource2File.exists() ); assertTrue( "WEB XML not found: " + expectedWEBXMLDir.toString(), expectedWEBXMLDir.exists() ); assertTrue( "META-INF not found", expectedMETAINFDir.exists() ); // house keeping expectedWebSourceFile.delete(); expectedWebSource2File.delete(); expectedWEBXMLDir.delete(); expectedMETAINFDir.delete(); } public void testExplodedWar_WithWarDependencyIncludeExclude() throws Exception { // setup test data String testId = "ExplodedWar_WithWarDependencyIncludeExclude"; MavenProjectArtifactsStub project = new MavenProjectArtifactsStub(); IncludeExcludeWarArtifactStub includeexcludeWarArtifact = new IncludeExcludeWarArtifactStub( getBasedir() ); File webAppDirectory = new File( getTestDirectory(), testId ); File webAppSource = createWebAppSource( testId ); File classesDir = createClassesDir( testId, true ); File workDirectory = new File( getTestDirectory(), "/war/work-" + testId ); File includeExcludeWarFile = includeexcludeWarArtifact.getFile(); assertTrue( "war not found: " + includeExcludeWarFile.toString(), includeExcludeWarFile.exists() ); createDir( workDirectory ); // configure mojo project.addArtifact( includeexcludeWarArtifact ); this.configureMojo( mojo, new LinkedList(), classesDir, webAppSource, webAppDirectory, project ); setVariableValueToObject( mojo, "dependentWarIncludes", "**/*Include.jsp,**/*.xml" ); setVariableValueToObject( mojo, "dependentWarExcludes", "**/*Exclude*,**/MANIFEST.MF" ); setVariableValueToObject( mojo, "workDirectory", workDirectory ); mojo.execute(); // validate operation File expectedWebSourceFile = new File( webAppDirectory, "pansit.jsp" ); File expectedWebSource2File = new File( webAppDirectory, "org/web/app/last-exile.jsp" ); File expectedManifestFile = new File( webAppDirectory, "META-INF/MANIFEST.MF" ); File expectedWEBXMLFile = new File( webAppDirectory, "WEB-INF/web.xml" ); File expectedIncludedWARFile = new File( webAppDirectory, "/org/sample/company/testInclude.jsp" ); File expectedExcludedWarfile = new File( webAppDirectory, "/org/sample/companyExclude/test.jsp" ); assertTrue( "source files not found: " + expectedWebSourceFile.toString(), expectedWebSourceFile.exists() ); assertTrue( "source files not found: " + expectedWebSource2File.toString(), expectedWebSource2File.exists() ); // check include-exclude.war in the unit test dir under resources to verify the list of files assertTrue( "web xml not found: " + expectedWEBXMLFile.toString(), expectedWEBXMLFile.exists() ); assertFalse( "manifest file found: " + expectedManifestFile.toString(), expectedManifestFile.exists() ); assertTrue( "war file not found: " + expectedIncludedWARFile.toString(), expectedIncludedWARFile.exists() ); assertFalse( "war file not found: " + expectedExcludedWarfile.toString(), expectedExcludedWarfile.exists() ); // house keeping expectedWebSourceFile.delete(); expectedWebSource2File.delete(); expectedManifestFile.delete(); expectedWEBXMLFile.delete(); expectedIncludedWARFile.delete(); expectedExcludedWarfile.delete(); } public void testExplodedWarWithSourceModificationCheck() throws Exception { // setup test data String testId = "ExplodedWarWithSourceModificationCheck"; MavenProjectBasicStub project = new MavenProjectBasicStub(); File webAppSource = createWebAppSource( testId ); File classesDir = createClassesDir( testId, false ); File webAppDirectory = new File( getTestDirectory(), testId ); // configure mojo this.configureMojo( mojo, new LinkedList(), classesDir, webAppSource, webAppDirectory, project ); // destination file is already created manually containing an "error" string // source is newer than the destination file mojo.execute(); // validate operation File expectedWEBINFDir = new File( webAppDirectory, "WEB-INF" ); File expectedMETAINFDir = new File( webAppDirectory, "META-INF" ); File expectedWebSourceFile = new File( webAppDirectory, "pansit.jsp" ); File expectedWebSource2File = new File( webAppDirectory, "org/web/app/last-exile.jsp" ); assertTrue( "source files not found: " + expectedWebSourceFile.toString(), expectedWebSourceFile.exists() ); assertTrue( "source files not found: " + expectedWebSource2File.toString(), expectedWebSource2File.exists() ); assertTrue( "WEB-INF not found", expectedWEBINFDir.exists() ); assertTrue( "META-INF not found", expectedMETAINFDir.exists() ); // 1st phase destination is older than source // destination starts with a value of error replaced with a blank source assertFalse( "source files not updated with new copy: " + expectedWebSourceFile.toString(), "error".equals( FileUtils.fileRead( expectedWebSourceFile ) ) ); // TODO: uncomment when lastModified problem is resolved // FileWriter writer = new FileWriter(expectedWebSourceFile); // // // 2nd phase destination is newer than source // // destination should not be replaced with an blank source // writer.write("newdata"); // mojo.execute(); // reader = new FileReader(expectedWebSourceFile); // reader.read(data); // assertTrue("source file updated with old copy: " // +expectedWebSourceFile.toString(),String.valueOf(data).equals("newdata") ); } // house keeping expectedWEBINFDir.delete(); expectedMETAINFDir.delete(); expectedWebSourceFile.delete(); expectedWebSource2File.delete(); } public void testExplodedWarWithOutputFileNameMapping() throws Exception { // setup test data String testId = "ExplodedWarWithFileNameMapping"; MavenProjectArtifactsStub project = new MavenProjectArtifactsStub(); File webAppDirectory = new File( getTestDirectory(), testId ); File webAppSource = createWebAppSource( testId ); File classesDir = createClassesDir( testId, true ); ArtifactHandler artifactHandler = (ArtifactHandler) lookup( ArtifactHandler.ROLE, "jar" ); ArtifactStub jarArtifact = new JarArtifactStub( getBasedir(), artifactHandler ); File jarFile = jarArtifact.getFile(); assertTrue( "jar not found: " + jarFile.toString(), jarFile.exists() ); // configure mojo project.addArtifact( jarArtifact ); mojo.setOutputFileNameMapping( "@{artifactId}@.@{extension}@" ); this.configureMojo( mojo, new LinkedList(), classesDir, webAppSource, webAppDirectory, project ); mojo.execute(); // validate operation File expectedWebSourceFile = new File( webAppDirectory, "pansit.jsp" ); File expectedWebSource2File = new File( webAppDirectory, "org/web/app/last-exile.jsp" ); // final name form is -. File expectedJarArtifact = new File( webAppDirectory, "WEB-INF/lib/jarartifact.jar" ); assertTrue( "source files not found: " + expectedWebSourceFile.toString(), expectedWebSourceFile.exists() ); assertTrue( "source files not found: " + expectedWebSource2File.toString(), expectedWebSource2File.exists() ); assertTrue( "jar artifact not found: " + expectedJarArtifact.toString(), expectedJarArtifact.exists() ); // house keeping expectedWebSourceFile.delete(); expectedWebSource2File.delete(); expectedJarArtifact.delete(); } /** * @throws Exception */ public void testExplodedWarWithOutputFileNameMappingAndDuplicateDependencies() throws Exception { // setup test data String testId = "ExplodedWarWithFileNameMappingAndDuplicateDependencies"; MavenProjectArtifactsStub project = new MavenProjectArtifactsStub(); File webAppDirectory = new File( getTestDirectory(), testId ); File webAppSource = createWebAppSource( testId ); File classesDir = createClassesDir( testId, true ); EJBArtifactStub ejbArtifact = new EJBArtifactStub( getBasedir() ); EJBArtifactStub ejbArtifactDup = new EJBArtifactStub( getBasedir() ); File ejbFile = ejbArtifact.getFile(); // ejbArtifact has a hard coded file, only one assert is needed assertTrue( "ejb not found: " + ejbFile.getAbsolutePath(), ejbFile.exists() ); // configure mojo ejbArtifact.setGroupId( "org.sample.ejb" ); ejbArtifactDup.setGroupId( "org.dup.ejb" ); project.addArtifact( ejbArtifact ); project.addArtifact( ejbArtifactDup ); mojo.setOutputFileNameMapping( "@{artifactId}@.@{extension}@" ); this.configureMojo( mojo, new LinkedList(), classesDir, webAppSource, webAppDirectory, project ); mojo.execute(); // validate operation File expectedWebSourceFile = new File( webAppDirectory, "pansit.jsp" ); File expectedWebSource2File = new File( webAppDirectory, "org/web/app/last-exile.jsp" ); // final name form is -. File expectedEJBArtifact = new File( webAppDirectory, "WEB-INF/lib/org.sample.ejb-ejbartifact.jar" ); File expectedEJBDupArtifact = new File( webAppDirectory, "WEB-INF/lib/org.dup.ejb-ejbartifact.jar" ); assertTrue( "source files not found: " + expectedWebSourceFile.toString(), expectedWebSourceFile.exists() ); assertTrue( "source files not found: " + expectedWebSource2File.toString(), expectedWebSource2File.exists() ); assertTrue( "ejb artifact not found: " + expectedEJBArtifact.toString(), expectedEJBArtifact.exists() ); assertTrue( "ejb dup artifact not found: " + expectedEJBDupArtifact.toString(), expectedEJBDupArtifact.exists() ); // house keeping expectedWebSourceFile.delete(); expectedWebSource2File.delete(); expectedEJBArtifact.delete(); expectedEJBDupArtifact.delete(); } /* --------------------- 2.1 Overlay tests ----------------------------------- */ /*---------------------------*/ } maven-war-plugin-2.1.1/src/test/java/org/apache/maven/plugin/war/AbstractWarExplodedMojoTest.java0000644000175000017500000002424011046132465032774 0ustar twernertwernerpackage org.apache.maven.plugin.war; /* * 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.maven.plugin.testing.stubs.ArtifactStub; import org.apache.maven.plugin.war.stub.MavenProjectArtifactsStub; import org.codehaus.plexus.util.FileUtils; import java.io.File; import java.io.FileFilter; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.LinkedList; import java.util.List; /** * @author Stephane Nicoll */ public abstract class AbstractWarExplodedMojoTest extends AbstractWarMojoTest { protected WarExplodedMojo mojo; public void setUp() throws Exception { super.setUp(); mojo = (WarExplodedMojo) lookupMojo( "exploded", getPomFile() ); } /** * Returns the pom configuration to use. * * @return the pom configuration */ protected abstract File getPomFile(); /** * Returns the test directory to use. * * @return the test directory */ protected abstract File getTestDirectory(); /** * Configures the exploded mojo for the specified test. *

* If the sourceFiles parameter is null, sample * JSPs are created by default. * * @param testId the id of the test * @param artifactStubs the dependencies (may be null) * @param sourceFiles the source files to create (may be null) * @return the webapp directory * @throws Exception if an error occurs while configuring the mojo */ protected File setUpMojo( final String testId, ArtifactStub[] artifactStubs, String[] sourceFiles ) throws Exception { final MavenProjectArtifactsStub project = new MavenProjectArtifactsStub(); final File webAppDirectory = new File( getTestDirectory(), testId ); // Create the webapp sources File webAppSource; if ( sourceFiles == null ) { webAppSource = createWebAppSource( testId ); } else { webAppSource = createWebAppSource( testId, false ); for ( int i = 0; i < sourceFiles.length; i++ ) { String sourceFile = sourceFiles[i]; File sample = new File( webAppSource, sourceFile ); createFile( sample ); } } final File classesDir = createClassesDir( testId, true ); final File workDirectory = new File( getTestDirectory(), "/war/work-" + testId ); createDir( workDirectory ); if ( artifactStubs != null ) { for ( int i = 0; i < artifactStubs.length; i++ ) { ArtifactStub artifactStub = artifactStubs[i]; project.addArtifact( artifactStub ); } } configureMojo( mojo, new LinkedList(), classesDir, webAppSource, webAppDirectory, project ); setVariableValueToObject( mojo, "workDirectory", workDirectory ); return webAppDirectory; } /** * Configures the exploded mojo for the specified test. * * @param testId the id of the test * @param artifactStubs the dependencies (may be null) * @return the webapp directory * @throws Exception if an error occurs while configuring the mojo */ protected File setUpMojo( final String testId, ArtifactStub[] artifactStubs ) throws Exception { return setUpMojo( testId, artifactStubs, null ); } /** * Cleans up a directory. * * @param directory the directory to remove * @throws IOException if an error occurred while removing the directory */ protected void cleanDirectory( File directory ) throws IOException { if ( directory != null && directory.isDirectory() && directory.exists() ) { FileUtils.deleteDirectory( directory ); } } /** * Asserts the default content of the war based on the specified * webapp directory. * * @param webAppDirectory the webapp directory * @return a list of File objects that have been asserted */ protected List assertDefaultContent( File webAppDirectory ) { // Validate content of the webapp File expectedWebSourceFile = new File( webAppDirectory, "pansit.jsp" ); File expectedWebSource2File = new File( webAppDirectory, "org/web/app/last-exile.jsp" ); assertTrue( "source file not found: " + expectedWebSourceFile.toString(), expectedWebSourceFile.exists() ); assertTrue( "source file not found: " + expectedWebSource2File.toString(), expectedWebSource2File.exists() ); final List content = new ArrayList(); content.add( expectedWebSourceFile ); content.add( expectedWebSource2File ); return content; } /** * Asserts the web.xml file of the war based on the specified * webapp directory. * * @param webAppDirectory the webapp directory * @return a list with the web.xml File object */ protected List assertWebXml( File webAppDirectory ) { File expectedWEBXMLFile = new File( webAppDirectory, "WEB-INF/web.xml" ); assertTrue( "web xml not found: " + expectedWEBXMLFile.toString(), expectedWEBXMLFile.exists() ); final List content = new ArrayList(); content.add( expectedWEBXMLFile ); return content; } /** * Asserts custom content of the war based on the specified webapp * directory. * * @param webAppDirectory the webapp directory * @param filePaths an array of file paths relative to the webapp directory * @param customMessage a custom message if an assertion fails * @return a list of File objects that have been inspected */ protected List assertCustomContent( File webAppDirectory, String[] filePaths, String customMessage ) { final List content = new ArrayList(); for ( int i = 0; i < filePaths.length; i++ ) { String filePath = filePaths[i]; final File expectedFile = new File( webAppDirectory, filePath ); if ( customMessage != null ) { assertTrue( customMessage + " - " + expectedFile.toString(), expectedFile.exists() ); } else { assertTrue( "source file not found: " + expectedFile.toString(), expectedFile.exists() ); } content.add( expectedFile ); } return content; } /** * Asserts that the webapp contains only the specified files. * * @param webAppDirectory the webapp directory * @param expectedFiles the expected files * @param filter an optional filter to ignore some resources */ protected void assertWebAppContent( File webAppDirectory, List expectedFiles, FileFilter filter ) { final List webAppContent = new ArrayList(); if ( filter != null ) { buildFilesList( webAppDirectory, filter, webAppContent ); } else { buildFilesList( webAppDirectory, new FileFilterImpl( webAppDirectory, null ), webAppContent ); } // Now we have the files, sort them. Collections.sort( expectedFiles ); Collections.sort( webAppContent ); assertEquals( "Invalid webapp content, expected " + expectedFiles.size() + "file(s) " + expectedFiles + " but got " + webAppContent.size() + " file(s) " + webAppContent, expectedFiles, webAppContent ); } /** * Builds the list of files and directories from the specified dir. *

* Note that the filter is not used the usual way. If the filter does * not accept the current file, it's not added but yet the subdirectories * are added if any. * * @param dir the base directory * @param filter the filter * @param content the current content, updated recursivly */ private void buildFilesList( final File dir, FileFilter filter, final List content ) { final File[] files = dir.listFiles(); for ( int i = 0; i < files.length; i++ ) { File file = files[i]; // Add the file if the filter is ok with it if ( filter.accept( file ) ) { content.add( file ); } // Even if the file is not accepted and is a directory, add it if ( file.isDirectory() ) { buildFilesList( file, filter, content ); } } } class FileFilterImpl implements FileFilter { private final List rejectedFilePaths; private final int webAppDirIndex; public FileFilterImpl( File webAppDirectory, String[] rejectedFilePaths ) { if ( rejectedFilePaths != null ) { this.rejectedFilePaths = Arrays.asList( rejectedFilePaths ); } else { this.rejectedFilePaths = new ArrayList(); } this.webAppDirIndex = webAppDirectory.getAbsolutePath().length() + 1; } public boolean accept( File file ) { String effectiveRelativePath = buildRelativePath( file ); return !( rejectedFilePaths.contains( effectiveRelativePath ) || file.isDirectory() ); } private String buildRelativePath( File f ) { return f.getAbsolutePath().substring( webAppDirIndex ); } } } maven-war-plugin-2.1.1/src/test/java/org/apache/maven/plugin/war/WarMojoTest.java0000644000175000017500000004643611454302534027635 0ustar twernertwernerpackage org.apache.maven.plugin.war; /* * 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.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.war.stub.MavenProject4CopyConstructor; import org.apache.maven.plugin.war.stub.ProjectHelperStub; import org.apache.maven.plugin.war.stub.WarArtifact4CCStub; import org.codehaus.plexus.util.IOUtil; import java.io.File; import java.io.IOException; import java.util.Enumeration; import java.util.HashMap; import java.util.LinkedList; import java.util.Map; import java.util.jar.JarEntry; import java.util.jar.JarFile; import java.util.zip.ZipEntry; /** * comprehensive test on buildExplodedWebApp is done on WarExplodedMojoTest */ public class WarMojoTest extends AbstractWarMojoTest { WarMojo mojo; private static File pomFile = new File( getBasedir(), "target/test-classes/unit/warmojotest/plugin-config-primary-artifact.xml" ); protected File getTestDirectory() { return new File( getBasedir(), "target/test-classes/unit/warmojotest" ); } public void setUp() throws Exception { super.setUp(); mojo = (WarMojo) lookupMojo( "war", pomFile ); } public void testEnvironment() throws Exception { // see setup } public void testSimpleWar() throws Exception { String testId = "SimpleWar"; MavenProject4CopyConstructor project = new MavenProject4CopyConstructor(); String outputDir = getTestDirectory().getAbsolutePath() + "/" + testId + "-output"; File webAppDirectory = new File( getTestDirectory(), testId ); WarArtifact4CCStub warArtifact = new WarArtifact4CCStub( getBasedir() ); String warName = "simple"; File webAppSource = createWebAppSource( testId ); File classesDir = createClassesDir( testId, true ); File xmlSource = createXMLConfigDir( testId, new String[]{"web.xml"} ); project.setArtifact( warArtifact ); this.configureMojo( mojo, new LinkedList(), classesDir, webAppSource, webAppDirectory, project ); setVariableValueToObject( mojo, "outputDirectory", outputDir ); setVariableValueToObject( mojo, "warName", warName ); mojo.setWebXml( new File( xmlSource, "web.xml" ) ); mojo.execute(); //validate jar file File expectedJarFile = new File( outputDir, "simple.war" ); assertJarContent( expectedJarFile, new String[]{"META-INF/MANIFEST.MF", "WEB-INF/web.xml", "pansit.jsp", "org/web/app/last-exile.jsp", "META-INF/maven/org.apache.maven.test/maven-test-plugin/pom.xml", "META-INF/maven/org.apache.maven.test/maven-test-plugin/pom.properties"}, new String[]{null, mojo.getWebXml().toString(), null, null, null, null} ); } public void testClassifier() throws Exception { String testId = "Classifier"; MavenProject4CopyConstructor project = new MavenProject4CopyConstructor(); String outputDir = getTestDirectory().getAbsolutePath() + "/" + testId + "-output"; File webAppDirectory = new File( getTestDirectory(), testId ); WarArtifact4CCStub warArtifact = new WarArtifact4CCStub( getBasedir() ); ProjectHelperStub projectHelper = new ProjectHelperStub(); String warName = "simple"; File webAppSource = createWebAppSource( testId ); File classesDir = createClassesDir( testId, true ); File xmlSource = createXMLConfigDir( testId, new String[]{"web.xml"} ); project.setArtifact( warArtifact ); this.configureMojo( mojo, new LinkedList(), classesDir, webAppSource, webAppDirectory, project ); setVariableValueToObject( mojo, "projectHelper", projectHelper ); setVariableValueToObject( mojo, "classifier", "test-classifier" ); setVariableValueToObject( mojo, "outputDirectory", outputDir ); setVariableValueToObject( mojo, "warName", warName ); mojo.setWebXml( new File( xmlSource, "web.xml" ) ); mojo.execute(); //validate jar file File expectedJarFile = new File( outputDir, "simple-test-classifier.war" ); assertJarContent( expectedJarFile, new String[]{"META-INF/MANIFEST.MF", "WEB-INF/web.xml", "pansit.jsp", "org/web/app/last-exile.jsp", "META-INF/maven/org.apache.maven.test/maven-test-plugin/pom.xml", "META-INF/maven/org.apache.maven.test/maven-test-plugin/pom.properties"}, new String[]{null, mojo.getWebXml().toString(), null, null, null, null} ); } public void testPrimaryArtifact() throws Exception { String testId = "PrimaryArtifact"; MavenProject4CopyConstructor project = new MavenProject4CopyConstructor(); String outputDir = getTestDirectory().getAbsolutePath() + "/" + testId + "-output"; File webAppDirectory = new File( getTestDirectory(), testId ); WarArtifact4CCStub warArtifact = new WarArtifact4CCStub( getBasedir() ); ProjectHelperStub projectHelper = new ProjectHelperStub(); String warName = "simple"; File webAppSource = createWebAppSource( testId ); File classesDir = createClassesDir( testId, true ); File xmlSource = createXMLConfigDir( testId, new String[]{"web.xml"} ); warArtifact.setFile( new File( "error.war" ) ); project.setArtifact( warArtifact ); this.configureMojo( mojo, new LinkedList(), classesDir, webAppSource, webAppDirectory, project ); setVariableValueToObject( mojo, "projectHelper", projectHelper ); setVariableValueToObject( mojo, "outputDirectory", outputDir ); setVariableValueToObject( mojo, "warName", warName ); mojo.setWebXml( new File( xmlSource, "web.xml" ) ); mojo.execute(); //validate jar file File expectedJarFile = new File( outputDir, "simple.war" ); assertJarContent( expectedJarFile, new String[]{"META-INF/MANIFEST.MF", "WEB-INF/web.xml", "pansit.jsp", "org/web/app/last-exile.jsp", "META-INF/maven/org.apache.maven.test/maven-test-plugin/pom.xml", "META-INF/maven/org.apache.maven.test/maven-test-plugin/pom.properties"}, new String[]{null, mojo.getWebXml().toString(), null, null, null, null} ); } public void testNotPrimaryArtifact() throws Exception { // use a different pom File pom = new File( getBasedir(), "target/test-classes/unit/warmojotest/not-primary-artifact.xml" ); mojo = (WarMojo) lookupMojo( "war", pom ); String testId = "NotPrimaryArtifact"; MavenProject4CopyConstructor project = new MavenProject4CopyConstructor(); String outputDir = getTestDirectory().getAbsolutePath() + "/" + testId + "-output"; File webAppDirectory = new File( getTestDirectory(), testId ); WarArtifact4CCStub warArtifact = new WarArtifact4CCStub( getBasedir() ); ProjectHelperStub projectHelper = new ProjectHelperStub(); String warName = "simple"; File webAppSource = createWebAppSource( testId ); File classesDir = createClassesDir( testId, true ); File xmlSource = createXMLConfigDir( testId, new String[]{"web.xml"} ); warArtifact.setFile( new File( "error.war" ) ); project.setArtifact( warArtifact ); this.configureMojo( mojo, new LinkedList(), classesDir, webAppSource, webAppDirectory, project ); setVariableValueToObject( mojo, "projectHelper", projectHelper ); setVariableValueToObject( mojo, "outputDirectory", outputDir ); setVariableValueToObject( mojo, "warName", warName ); mojo.setWebXml( new File( xmlSource, "web.xml" ) ); mojo.execute(); //validate jar file File expectedJarFile = new File( outputDir, "simple.war" ); assertJarContent( expectedJarFile, new String[]{"META-INF/MANIFEST.MF", "WEB-INF/web.xml", "pansit.jsp", "org/web/app/last-exile.jsp", "META-INF/maven/org.apache.maven.test/maven-test-plugin/pom.xml", "META-INF/maven/org.apache.maven.test/maven-test-plugin/pom.properties"}, new String[]{null, mojo.getWebXml().toString(), null, null, null, null} ); } public void testMetaInfContent() throws Exception { String testId = "SimpleWarWithMetaInfContent"; MavenProject4CopyConstructor project = new MavenProject4CopyConstructor(); String outputDir = getTestDirectory().getAbsolutePath() + "/" + testId + "-output"; File webAppDirectory = new File( getTestDirectory(), testId ); WarArtifact4CCStub warArtifact = new WarArtifact4CCStub( getBasedir() ); String warName = "simple"; File webAppSource = createWebAppSource( testId ); File classesDir = createClassesDir( testId, true ); File xmlSource = createXMLConfigDir( testId, new String[]{"web.xml"} ); // Create the sample config.xml final File configFile = new File( webAppSource, "META-INF/config.xml" ); createFile( configFile, "" ); project.setArtifact( warArtifact ); this.configureMojo( mojo, new LinkedList(), classesDir, webAppSource, webAppDirectory, project ); setVariableValueToObject( mojo, "outputDirectory", outputDir ); setVariableValueToObject( mojo, "warName", warName ); mojo.setWebXml( new File( xmlSource, "web.xml" ) ); mojo.execute(); //validate jar file File expectedJarFile = new File( outputDir, "simple.war" ); assertJarContent( expectedJarFile, new String[]{"META-INF/MANIFEST.MF", "META-INF/config.xml", "WEB-INF/web.xml", "pansit.jsp", "org/web/app/last-exile.jsp", "META-INF/maven/org.apache.maven.test/maven-test-plugin/pom.xml", "META-INF/maven/org.apache.maven.test/maven-test-plugin/pom.properties"}, new String[]{null, null, mojo.getWebXml().toString(), null, null, null, null} ); } public void testMetaInfContentWithContainerConfig() throws Exception { String testId = "SimpleWarWithContainerConfig"; MavenProject4CopyConstructor project = new MavenProject4CopyConstructor(); String outputDir = getTestDirectory().getAbsolutePath() + "/" + testId + "-output"; File webAppDirectory = new File( getTestDirectory(), testId ); WarArtifact4CCStub warArtifact = new WarArtifact4CCStub( getBasedir() ); String warName = "simple"; File webAppSource = createWebAppSource( testId ); File classesDir = createClassesDir( testId, true ); File xmlSource = createXMLConfigDir( testId, new String[]{"web.xml"} ); // Create the sample config.xml final File configFile = new File( webAppSource, "META-INF/config.xml" ); createFile( configFile, "" ); project.setArtifact( warArtifact ); this.configureMojo( mojo, new LinkedList(), classesDir, webAppSource, webAppDirectory, project ); setVariableValueToObject( mojo, "outputDirectory", outputDir ); setVariableValueToObject( mojo, "warName", warName ); mojo.setWebXml( new File( xmlSource, "web.xml" ) ); mojo.setContainerConfigXML( configFile ); mojo.execute(); //validate jar file File expectedJarFile = new File( outputDir, "simple.war" ); assertJarContent( expectedJarFile, new String[]{"META-INF/MANIFEST.MF", "META-INF/config.xml", "WEB-INF/web.xml", "pansit.jsp", "org/web/app/last-exile.jsp", "META-INF/maven/org.apache.maven.test/maven-test-plugin/pom.xml", "META-INF/maven/org.apache.maven.test/maven-test-plugin/pom.properties"}, new String[]{null, null, mojo.getWebXml().toString(), null, null, null, null} ); } public void testFailOnMissingWebXmlFalse() throws Exception { String testId = "SimpleWarMissingWebXmlFalse"; MavenProject4CopyConstructor project = new MavenProject4CopyConstructor(); String outputDir = getTestDirectory().getAbsolutePath() + "/" + testId + "-output"; File webAppDirectory = new File( getTestDirectory(), testId ); WarArtifact4CCStub warArtifact = new WarArtifact4CCStub( getBasedir() ); String warName = "simple"; File webAppSource = createWebAppSource( testId ); File classesDir = createClassesDir( testId, true ); project.setArtifact( warArtifact ); this.configureMojo( mojo, new LinkedList(), classesDir, webAppSource, webAppDirectory, project ); setVariableValueToObject( mojo, "outputDirectory", outputDir ); setVariableValueToObject( mojo, "warName", warName ); mojo.setFailOnMissingWebXml( false ); mojo.execute(); //validate jar file File expectedJarFile = new File( outputDir, "simple.war" ); final Map jarContent = assertJarContent( expectedJarFile, new String[]{"META-INF/MANIFEST.MF", "pansit.jsp", "org/web/app/last-exile.jsp", "META-INF/maven/org.apache.maven.test/maven-test-plugin/pom.xml", "META-INF/maven/org.apache.maven.test/maven-test-plugin/pom.properties"}, new String[]{null, null, null, null, null} ); assertFalse( "web.xml should be missing", jarContent.containsKey( "WEB-INF/web.xml" ) ); } public void testFailOnMissingWebXmlTrue() throws Exception { String testId = "SimpleWarMissingWebXmlTrue"; MavenProject4CopyConstructor project = new MavenProject4CopyConstructor(); String outputDir = getTestDirectory().getAbsolutePath() + "/" + testId + "-output"; File webAppDirectory = new File( getTestDirectory(), testId ); WarArtifact4CCStub warArtifact = new WarArtifact4CCStub( getBasedir() ); String warName = "simple"; File webAppSource = createWebAppSource( testId ); File classesDir = createClassesDir( testId, true ); project.setArtifact( warArtifact ); this.configureMojo( mojo, new LinkedList(), classesDir, webAppSource, webAppDirectory, project ); setVariableValueToObject( mojo, "outputDirectory", outputDir ); setVariableValueToObject( mojo, "warName", warName ); mojo.setFailOnMissingWebXml( true ); try { mojo.execute(); fail( "Building of the war isn't possible because web.xml is missing" ); } catch ( MojoExecutionException e ) { //expected behaviour } } public void testAttachClasses() throws Exception { String testId = "AttachClasses"; MavenProject4CopyConstructor project = new MavenProject4CopyConstructor(); String outputDir = getTestDirectory().getAbsolutePath() + "/" + testId + "-output"; File webAppDirectory = new File( getTestDirectory(), testId ); WarArtifact4CCStub warArtifact = new WarArtifact4CCStub( getBasedir() ); String warName = "simple"; File webAppSource = createWebAppSource( testId ); File classesDir = createClassesDir( testId, false ); File xmlSource = createXMLConfigDir( testId, new String[]{"web.xml"} ); project.setArtifact( warArtifact ); this.configureMojo( mojo, new LinkedList(), classesDir, webAppSource, webAppDirectory, project ); setVariableValueToObject( mojo, "outputDirectory", outputDir ); setVariableValueToObject( mojo, "warName", warName ); mojo.setWebXml( new File( xmlSource, "web.xml" ) ); mojo.setAttachClasses( true ); mojo.execute(); //validate jar file File expectedJarFile = new File( outputDir, "simple-classes.jar" ); assertJarContent( expectedJarFile, new String[]{"META-INF/MANIFEST.MF", "sample-servlet.class"}, new String[]{null, null} ); } public void testAttachClassesWithCustomClassifier() throws Exception { String testId = "AttachClassesCustomClassifier"; MavenProject4CopyConstructor project = new MavenProject4CopyConstructor(); String outputDir = getTestDirectory().getAbsolutePath() + "/" + testId + "-output"; File webAppDirectory = new File( getTestDirectory(), testId ); WarArtifact4CCStub warArtifact = new WarArtifact4CCStub( getBasedir() ); String warName = "simple"; File webAppSource = createWebAppSource( testId ); File classesDir = createClassesDir( testId, false ); File xmlSource = createXMLConfigDir( testId, new String[]{"web.xml"} ); project.setArtifact( warArtifact ); this.configureMojo( mojo, new LinkedList(), classesDir, webAppSource, webAppDirectory, project ); setVariableValueToObject( mojo, "outputDirectory", outputDir ); setVariableValueToObject( mojo, "warName", warName ); mojo.setWebXml( new File( xmlSource, "web.xml" ) ); mojo.setAttachClasses( true ); mojo.setClassesClassifier( "mystuff" ); mojo.execute(); //validate jar file File expectedJarFile = new File( outputDir, "simple-mystuff.jar" ); assertJarContent( expectedJarFile, new String[]{"META-INF/MANIFEST.MF", "sample-servlet.class"}, new String[]{null, null} ); } protected Map assertJarContent( final File expectedJarFile, final String[] files, final String[] filesContent ) throws IOException { // Sanity check assertEquals( "Could not test, files and filesContent lenght does not match", files.length, filesContent.length ); assertTrue( "war file not created: " + expectedJarFile.toString(), expectedJarFile.exists() ); final Map jarContent = new HashMap(); final JarFile jarFile = new JarFile( expectedJarFile ); JarEntry entry; Enumeration enumeration = jarFile.entries(); while ( enumeration.hasMoreElements() ) { entry = (JarEntry) enumeration.nextElement(); Object previousValue = jarContent.put( entry.getName(), entry ); assertNull( "Duplicate Entry in Jar File: " + entry.getName(), previousValue ); } for ( int i = 0; i < files.length; i++ ) { String file = files[i]; assertTrue( "File[" + file + "] not found in archive", jarContent.containsKey( file ) ); if ( filesContent[i] != null ) { assertEquals( "Content of file[" + file + "] does not match", filesContent[i], IOUtil.toString( jarFile.getInputStream( (ZipEntry) jarContent.get( file ) ) ) ); } } return jarContent; } } maven-war-plugin-2.1.1/src/test/java/org/apache/maven/plugin/war/AbstractWarMojoTest.java0000644000175000017500000002277711015344504031317 0ustar twernertwernerpackage org.apache.maven.plugin.war; /* * 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.maven.execution.MavenSession; import org.apache.maven.plugin.testing.AbstractMojoTestCase; import org.apache.maven.plugin.testing.stubs.ArtifactStub; import org.apache.maven.plugin.war.stub.MavenProjectBasicStub; import org.apache.maven.plugin.war.stub.WarOverlayStub; import org.apache.maven.shared.filtering.MavenFileFilter; import org.codehaus.plexus.archiver.Archiver; import org.codehaus.plexus.archiver.ArchiverException; import org.codehaus.plexus.archiver.jar.JarArchiver; import org.codehaus.plexus.util.FileUtils; import java.io.File; import java.io.IOException; import java.util.Arrays; import java.util.Iterator; import java.util.List; public abstract class AbstractWarMojoTest extends AbstractMojoTestCase { protected static final File OVERLAYS_TEMP_DIR = new File( getBasedir(), "target/test-overlays/" ); protected static final File OVERLAYS_ROOT_DIR = new File( getBasedir(), "target/test-classes/overlays/" ); protected static final String MANIFEST_PATH = "META-INF" + File.separator + "MANIFEST.MF"; protected abstract File getTestDirectory() throws Exception; /** * initialize required parameters * * @param mojo * @param filters * @param classesDir * @param webAppSource * @param webAppDir * @param project * @throws Exception */ protected void configureMojo( AbstractWarMojo mojo, List filters, File classesDir, File webAppSource, File webAppDir, MavenProjectBasicStub project ) throws Exception { setVariableValueToObject( mojo, "filters", filters ); setVariableValueToObject( mojo, "useCache", Boolean.FALSE ); setVariableValueToObject( mojo, "mavenFileFilter", lookup( MavenFileFilter.class.getName() ) ); MavenSession mavenSession = new MavenSession( null, null, null, null, null, null, null, System.getProperties(), null ); setVariableValueToObject( mojo, "session", mavenSession ); mojo.setClassesDirectory( classesDir ); mojo.setWarSourceDirectory( webAppSource ); mojo.setWebappDirectory( webAppDir ); mojo.setProject( project ); } /** * create an isolated xml dir * * @param id * @param xmlFiles * @return * @throws Exception */ protected File createXMLConfigDir( String id, String[] xmlFiles ) throws Exception { File xmlConfigDir = new File( getTestDirectory(), "/" + id + "-test-data/xml-config" ); File XMLFile; createDir( xmlConfigDir ); if ( xmlFiles != null ) { Iterator iterator = Arrays.asList( xmlFiles ).iterator(); while ( iterator.hasNext() ) { XMLFile = new File( xmlConfigDir, (String) iterator.next() ); createFile( XMLFile ); } } return xmlConfigDir; } /** * Returns the webapp source directory for the specified id. * * @param id the id of the test * @return the source directory for that test * @throws Exception if an exception occurs */ protected File getWebAppSource( String id ) throws Exception { return new File( getTestDirectory(), "/" + id + "-test-data/source" ); } /** * create an isolated web source with a sample jsp file * * @param id * @return * @throws Exception */ protected File createWebAppSource( String id, boolean createSamples ) throws Exception { File webAppSource = getWebAppSource( id ); if ( createSamples ) { File simpleJSP = new File( webAppSource, "pansit.jsp" ); File jspFile = new File( webAppSource, "org/web/app/last-exile.jsp" ); createFile( simpleJSP ); createFile( jspFile ); } return webAppSource; } protected File createWebAppSource( String id ) throws Exception { return createWebAppSource( id, true ); } /** * create a class directory with or without a sample class * * @param id * @param empty * @return * @throws Exception */ protected File createClassesDir( String id, boolean empty ) throws Exception { File classesDir = new File( getTestDirectory() + "/" + id + "-test-data/classes/" ); createDir( classesDir ); if ( !empty ) { createFile( new File( classesDir + "/sample-servlet.class" ) ); } return classesDir; } protected void createDir( File dir ) { if ( !dir.exists() ) { assertTrue( "can not create test dir: " + dir.toString(), dir.mkdirs() ); } } protected void createFile( File testFile, String body ) throws Exception { createDir( testFile.getParentFile() ); FileUtils.fileWrite( testFile.toString(), body ); assertTrue( "could not create file: " + testFile, testFile.exists() ); } protected void createFile( File testFile ) throws Exception { createFile( testFile, testFile.toString() ); } /** * Generates test war *

* Generates war with such a structure: *

*

* Each of the files will contain: id+'-'+path * * @param id the id of the overlay containing the full structure * @return the war file * @throws Exception if an error occurs */ protected File generateFullOverlayWar( String id ) throws Exception { final File destFile = new File( OVERLAYS_TEMP_DIR, id + ".war" ); if ( destFile.exists() ) { return destFile; } // Archive was not yet created for that id so let's create it final File rootDir = new File( OVERLAYS_ROOT_DIR, id ); rootDir.mkdirs(); String[] filePaths = new String[]{"jsp/d/a.jsp", "jsp/d/b.jsp", "jsp/d/c.jsp", "jsp/a.jsp", "jsp/b.jsp", "jsp/c.jsp", "WEB-INF/classes/a.class", "WEB-INF/classes/b.class", "WEB-INF/classes/c.class", "WEB-INF/lib/a.jar", "WEB-INF/lib/b.jar", "WEB-INF/lib/c.jar", "WEB-INF/web.xml"}; for ( int i = 0; i < filePaths.length; i++ ) { createFile( new File( rootDir, filePaths[i] ), id + "-" + filePaths[i] ); } createArchive( rootDir, destFile ); return destFile; } // Overlay utilities /** * Builds a test overlay. * * @param id the id of the overlay (see test/resources/overlays) * @return a test war artifact with the content of the given test overlay */ protected ArtifactStub buildWarOverlayStub( String id ) { // Create war file final File destFile = new File( OVERLAYS_TEMP_DIR, id + ".war" ); if ( !destFile.exists() ) { createArchive( new File( OVERLAYS_ROOT_DIR, id ), destFile ); } return new WarOverlayStub( getBasedir(), id, destFile ); } protected File getOverlayFile( String id, String filePath ) { final File overlayDir = new File( OVERLAYS_ROOT_DIR, id ); final File file = new File( overlayDir, filePath ); // Make sure the file exists assertTrue( "Overlay file " + filePath + " does not exist for overlay " + id + " at " + file.getAbsolutePath(), file.exists() ); return file; } protected void createArchive( final File directory, final File destinationFile ) { try { //WarArchiver archiver = new WarArchiver(); Archiver archiver = new JarArchiver(); archiver.setDestFile( destinationFile ); archiver.addDirectory( directory ); //archiver.setWebxml( new File(directory, "WEB-INF/web.xml")); // create archive archiver.createArchive(); } catch ( ArchiverException e ) { e.printStackTrace(); fail( "Failed to create overlay archive " + e.getMessage() ); } catch ( IOException e ) { e.printStackTrace(); fail( "Unexpected exception " + e.getMessage() ); } } }maven-war-plugin-2.1.1/src/test/java/org/apache/maven/plugin/war/WarInPlaceMojoTest.java0000644000175000017500000000677511015344504031067 0ustar twernertwernerpackage org.apache.maven.plugin.war; /* * 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.maven.plugin.war.stub.MavenProjectBasicStub; import org.apache.maven.plugin.war.stub.ResourceStub; import java.io.File; import java.util.LinkedList; public class WarInPlaceMojoTest extends AbstractWarMojoTest { protected static final String pomFilePath = getBasedir() + "/target/test-classes/unit/warexplodedinplacemojo/plugin-config.xml"; protected File getTestDirectory() throws Exception { return new File( getBasedir(), "target/test-classes/unit/warexplodedinplacemojo/test-dir" ); } private WarInPlaceMojo mojo; public void setUp() throws Exception { super.setUp(); mojo = (WarInPlaceMojo) lookupMojo( "inplace", pomFilePath ); assertNotNull( mojo ); } public void testEnvironment() throws Exception { // see setUp } /** * @throws Exception */ public void testSimpleExplodedInplaceWar() throws Exception { // setup test data String testId = "SimpleExplodedInplaceWar"; MavenProjectBasicStub project = new MavenProjectBasicStub(); File webAppSource = createWebAppSource( testId ); File classesDir = createClassesDir( testId, true ); File webAppResource = new File( getTestDirectory(), "resources" ); File sampleResource = new File( webAppResource, "pix/panis_na.jpg" ); ResourceStub[] resources = new ResourceStub[]{new ResourceStub()}; createFile( sampleResource ); // configure mojo resources[0].setDirectory( webAppResource.getAbsolutePath() ); this.configureMojo( mojo, new LinkedList(), classesDir, webAppSource, null, project ); setVariableValueToObject( mojo, "webResources", resources ); mojo.execute(); // validate operation File expectedWebSourceFile = new File( webAppSource, "pansit.jsp" ); File expectedWebSource2File = new File( webAppSource, "org/web/app/last-exile.jsp" ); File expectedWebResourceFile = new File( webAppSource, "pix/panis_na.jpg" ); File expectedWEBINFDir = new File( webAppSource, "WEB-INF" ); File expectedMETAINFDir = new File( webAppSource, "META-INF" ); assertTrue( "source files not found: " + expectedWebSourceFile.toString(), expectedWebSourceFile.exists() ); assertTrue( "source files not found: " + expectedWebSource2File.toString(), expectedWebSource2File.exists() ); assertTrue( "resources doesn't exist: " + expectedWebResourceFile, expectedWebResourceFile.exists() ); assertTrue( "WEB-INF not found", expectedWEBINFDir.exists() ); assertTrue( "META-INF not found", expectedMETAINFDir.exists() ); } } maven-war-plugin-2.1.1/src/test/java/org/apache/maven/plugin/war/WarManifestMojoTest.java0000644000175000017500000001271411430617163031315 0ustar twernertwernerpackage org.apache.maven.plugin.war; /* * 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.maven.archiver.MavenArchiveConfiguration; import org.apache.maven.plugin.testing.AbstractMojoTestCase; import org.codehaus.plexus.util.FileUtils; import java.io.File; /** * @author Allan Ramirez */ public class WarManifestMojoTest extends AbstractMojoTestCase { File testPom; WarManifestMojo mojo; public void testEnvironment() throws Exception { loadMojo( "target/test-classes/unit/manifest/basic-manifest-test/plugin-config.xml" ); } public void testBasicManifest() throws Exception { loadMojo( "target/test-classes/unit/manifest/basic-manifest-test/plugin-config.xml" ); mojo.execute(); File warSourceDir = (File) getVariableValueFromObject( mojo, "warSourceDirectory" ); File manifestDir = new File( warSourceDir, "META-INF" ); File manifest = new File( manifestDir, "MANIFEST.MF" ); assertTrue( manifest.exists() ); } public void testManifestWithClasspath() throws Exception { loadMojo( "target/test-classes/unit/manifest/manifest-with-classpath/plugin-config.xml" ); MavenArchiveConfiguration config = (MavenArchiveConfiguration) getVariableValueFromObject( mojo, "archive" ); mojo.execute(); assertTrue( config.getManifest().isAddClasspath() ); File warSourceDir = (File) getVariableValueFromObject( mojo, "warSourceDirectory" ); File manifestDir = new File( warSourceDir, "META-INF" ); File manifest = new File( manifestDir, "MANIFEST.MF" ); assertTrue( manifest.exists() ); String content = FileUtils.fileRead( manifest ); int idx = content.indexOf( "Class-Path" ); assertTrue( idx >= 0 ); } public void testManifestWithMainClass() throws Exception { loadMojo( "target/test-classes/unit/manifest/manifest-with-main-class/plugin-config.xml" ); MavenArchiveConfiguration config = (MavenArchiveConfiguration) getVariableValueFromObject( mojo, "archive" ); mojo.execute(); assertEquals( "org.dummy.test.SomeClass", config.getManifest().getMainClass() ); File warSourceDir = (File) getVariableValueFromObject( mojo, "warSourceDirectory" ); File manifestDir = new File( warSourceDir, "META-INF" ); File manifest = new File( manifestDir, "MANIFEST.MF" ); assertTrue( manifest.exists() ); String content = FileUtils.fileRead( manifest ); int idx = content.indexOf( "Main-Class" ); assertTrue( idx >= 0 ); } public void testManifestWithOtherAttributes() throws Exception { loadMojo( "target/test-classes/unit/manifest/manifest-with-other-attrs/plugin-config.xml" ); MavenArchiveConfiguration config = (MavenArchiveConfiguration) getVariableValueFromObject( mojo, "archive" ); mojo.execute(); assertTrue( config.getManifest().isAddExtensions() ); File warSourceDir = (File) getVariableValueFromObject( mojo, "warSourceDirectory" ); File manifestDir = new File( warSourceDir, "META-INF" ); File manifest = new File( manifestDir, "MANIFEST.MF" ); assertTrue( manifest.exists() ); String content = FileUtils.fileRead( manifest ); int idx = content.indexOf( "Specification-Title" ); assertTrue( idx >= 0 ); idx = content.indexOf( "Specification-Vendor" ); assertTrue( idx >= 0 ); idx = content.indexOf( "Implementation-Vendor" ); assertTrue( idx >= 0 ); } public void testManifestWithCustomAttributes() throws Exception { loadMojo( "target/test-classes/unit/manifest/manifest-with-custom-attrs/plugin-config.xml" ); MavenArchiveConfiguration config = (MavenArchiveConfiguration) getVariableValueFromObject( mojo, "archive" ); mojo.execute(); assertTrue( config.getManifest().isAddExtensions() ); File warSourceDir = (File) getVariableValueFromObject( mojo, "warSourceDirectory" ); File manifestDir = new File( warSourceDir, "META-INF" ); File manifest = new File( manifestDir, "MANIFEST.MF" ); assertTrue( manifest.exists() ); String content = FileUtils.fileRead( manifest ); int idx = content.indexOf( "Specification-Title" ); assertTrue( idx >= 0 ); idx = content.indexOf( "Custom-Version" ); assertTrue( idx >= 0); } public void loadMojo( String pluginXml ) throws Exception { testPom = new File( getBasedir(), pluginXml ); mojo = (WarManifestMojo) lookupMojo( "manifest", testPom ); assertNotNull( mojo ); } } maven-war-plugin-2.1.1/src/test/java/org/apache/maven/plugin/war/overlay/0000755000175000017500000000000011641142606026220 5ustar twernertwernermaven-war-plugin-2.1.1/src/test/java/org/apache/maven/plugin/war/overlay/OverlayManagerTest.java0000644000175000017500000002121411377555455032657 0ustar twernertwernerpackage org.apache.maven.plugin.war.overlay; /* * 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.maven.plugin.testing.stubs.ArtifactStub; import org.apache.maven.plugin.war.Overlay; import org.apache.maven.plugin.war.stub.MavenProjectArtifactsStub; import org.apache.maven.plugin.war.stub.WarArtifactStub; import org.codehaus.plexus.PlexusTestCase; import java.util.ArrayList; import java.util.List; /** * @author Stephane Nicoll * @version $Id: OverlayManagerTest.java 948982 2010-05-27 20:50:53Z krosenvold $ */ public class OverlayManagerTest extends PlexusTestCase { public static final String DEFAULT_INCLUDES = "**/**"; public static final String DEFAULT_EXCLUDES = "META-INF/MANIFEST.MF"; public void testEmptyProject() throws Exception { final MavenProjectArtifactsStub project = new MavenProjectArtifactsStub(); final List overlays = new ArrayList(); try { final Overlay currentProjectOVerlay = Overlay.createInstance(); OverlayManager manager = new OverlayManager( overlays, project, DEFAULT_INCLUDES, DEFAULT_EXCLUDES, currentProjectOVerlay ); assertNotNull( manager.getOverlays() ); assertEquals( 1, manager.getOverlays().size() ); assertEquals( currentProjectOVerlay, manager.getOverlays().get( 0 ) ); } catch ( InvalidOverlayConfigurationException e ) { e.printStackTrace(); fail( "Should not have failed to validate a valid overly config " + e.getMessage() ); } } public void testAutodetectSimpleOverlay( Overlay currentProjectOverlay ) throws Exception { final MavenProjectArtifactsStub project = new MavenProjectArtifactsStub(); final ArtifactStub first = newWarArtifact( "test", "test-webapp" ); project.addArtifact( first ); final List overlays = new ArrayList(); try { final Overlay overlay = currentProjectOverlay; OverlayManager manager = new OverlayManager( overlays, project, DEFAULT_INCLUDES, DEFAULT_EXCLUDES, overlay ); assertNotNull( manager.getOverlays() ); assertEquals( 2, manager.getOverlays().size() ); assertEquals( overlay, manager.getOverlays().get( 0 ) ); assertEquals( new DefaultOverlay( first ), manager.getOverlays().get( 1 ) ); } catch ( InvalidOverlayConfigurationException e ) { e.printStackTrace(); fail( "Should not have failed to validate a valid overlay config " + e.getMessage() ); } } public void testSimpleOverlay() throws Exception { final MavenProjectArtifactsStub project = new MavenProjectArtifactsStub(); final ArtifactStub first = newWarArtifact( "test", "test-webapp" ); project.addArtifact( first ); final List overlays = new ArrayList(); overlays.add( new DefaultOverlay( first ) ); try { final Overlay currentProjectOverlay = Overlay.createInstance(); OverlayManager manager = new OverlayManager( overlays, project, DEFAULT_INCLUDES, DEFAULT_EXCLUDES, currentProjectOverlay ); assertNotNull( manager.getOverlays() ); assertEquals( 2, manager.getOverlays().size() ); assertEquals( Overlay.createInstance(), manager.getOverlays().get( 0 ) ); assertEquals( overlays.get( 0 ), manager.getOverlays().get( 1 ) ); } catch ( InvalidOverlayConfigurationException e ) { e.printStackTrace(); fail( "Should not have failed to validate a valid overlay config " + e.getMessage() ); } } public void testUnknonwnOverlay() throws Exception { final MavenProjectArtifactsStub project = new MavenProjectArtifactsStub(); final ArtifactStub first = newWarArtifact( "test", "test-webapp" ); project.addArtifact( first ); final List overlays = new ArrayList(); overlays.add( new Overlay( "test", "test-webapp-2" ) ); try { final Overlay currentProjectOVerlay = Overlay.createInstance(); new OverlayManager( overlays, project, DEFAULT_INCLUDES, DEFAULT_EXCLUDES, currentProjectOVerlay ); fail( "Should have failed to validate an unknown overlay" ); } catch ( InvalidOverlayConfigurationException e ) { // OK } } public void testCustomCurrentProject() throws Exception { final MavenProjectArtifactsStub project = new MavenProjectArtifactsStub(); final ArtifactStub first = newWarArtifact( "test", "test-webapp" ); final ArtifactStub second = newWarArtifact( "test", "test-webapp-2" ); project.addArtifact( first ); project.addArtifact( second ); final List overlays = new ArrayList(); overlays.add( new DefaultOverlay( first ) ); final Overlay currentProjectOverlay = Overlay.createInstance(); overlays.add( currentProjectOverlay ); try { OverlayManager manager = new OverlayManager( overlays, project, DEFAULT_INCLUDES, DEFAULT_EXCLUDES, currentProjectOverlay ); assertNotNull( manager.getOverlays() ); assertEquals( 3, manager.getOverlays().size() ); assertEquals( overlays.get( 0 ), manager.getOverlays().get( 0 ) ); assertEquals( currentProjectOverlay, manager.getOverlays().get( 1 ) ); assertEquals( new DefaultOverlay( second ), manager.getOverlays().get( 2 ) ); } catch ( InvalidOverlayConfigurationException e ) { e.printStackTrace(); fail( "Should not have failed to validate a valid overlay config " + e.getMessage() ); } } public void testOverlaysWithSameArtifactAndGroupId() throws Exception { final MavenProjectArtifactsStub project = new MavenProjectArtifactsStub(); final ArtifactStub first = newWarArtifact( "test", "test-webapp" ); final ArtifactStub second = newWarArtifact( "test", "test-webapp", "my-classifier" ); project.addArtifact( first ); project.addArtifact( second ); final List overlays = new ArrayList(); overlays.add( new DefaultOverlay( first ) ); overlays.add( new DefaultOverlay( second ) ); try { final Overlay currentProjectOverlay = Overlay.createInstance(); OverlayManager manager = new OverlayManager( overlays, project, DEFAULT_INCLUDES, DEFAULT_EXCLUDES, currentProjectOverlay ); assertNotNull( manager.getOverlays() ); assertEquals( 3, manager.getOverlays().size() ); assertEquals( currentProjectOverlay, manager.getOverlays().get( 0 ) ); assertEquals( overlays.get( 0 ), manager.getOverlays().get( 1 ) ); assertEquals( overlays.get( 1 ), manager.getOverlays().get( 2 ) ); } catch ( InvalidOverlayConfigurationException e ) { e.printStackTrace(); fail( "Should not have failed to validate a valid overlay config " + e.getMessage() ); } } protected ArtifactStub newWarArtifact( String groupId, String artifactId, String classifier ) { final WarArtifactStub a = new WarArtifactStub( getBasedir() ); a.setGroupId( groupId ); a.setArtifactId( artifactId ); if ( classifier != null ) { a.setClassifier( classifier ); } return a; } protected ArtifactStub newWarArtifact( String groupId, String artifactId ) { return newWarArtifact( groupId, artifactId, null ); } } maven-war-plugin-2.1.1/src/site/0000755000175000017500000000000011641142610016371 5ustar twernertwernermaven-war-plugin-2.1.1/src/site/apt/0000755000175000017500000000000011641142607017163 5ustar twernertwernermaven-war-plugin-2.1.1/src/site/apt/examples/0000755000175000017500000000000011641142610020773 5ustar twernertwernermaven-war-plugin-2.1.1/src/site/apt/examples/war-manifest-guide.apt.vm0000644000175000017500000000665011431730532025624 0ustar twernertwerner ------ WAR Manifest Customization ------ Pete Marvin King ------ 2008-08-03 ------ ~~ 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. ~~ NOTE: For help with the syntax of this file, see: ~~ http://maven.apache.org/doxia/references/apt-format.html WAR Manifest Customization The manifest can be customized by configuring the WAR Plugin's archiver. For full information on the different configuration options available check the documentation for {{{http://maven.apache.org/shared/maven-archiver/index.html}Maven Archiver}}. This version of Maven WAR Plugin uses Maven Archiver ${mavenArchiverVersion}. *Generating a manifest classpath Generating a manifest classpath for a WAR is similar to for a JAR, but there are a couple of slight differences since you normally don't want a JAR in both the manifest classpath and the <<>> directory. Customize the WAR Plugin's archiver: +--------------------+ ... org.apache.maven.plugins maven-war-plugin ${project.version} true ... ... +--------------------+ Now, you can control which dependencies are included in <<>> and in the manifest classpath by following these examples. Maven will follow the transitive dependency tree until it gets to artifacts scoped as "provided". <> No way is shown how to include a dependency in <<>> but not in the manifest classpath. +--------------------+ ... org.foo bar-jar1 ${pom.version} true org.foo bar-jar2 ${pom.version} org.foo bar-jar3 ${pom.version} provided ... ... +--------------------+ Check the {{{http://maven.apache.org/guides/mini/guide-manifest.html}Guide to Working with Manifests}} for more examples. maven-war-plugin-2.1.1/src/site/apt/examples/skinny-wars.apt.vm0000644000175000017500000001244611431730651024423 0ustar twernertwerner ------ Creating Skinny WARs ------ Mike Perham ------ 2008-08-03 ------ ~~ 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. ~~ NOTE: For help with the syntax of this file, see: ~~ http://maven.apache.org/doxia/references/apt-format.html Creating Skinny WARs In a typical J2EE environment, a WAR is packaged within an EAR for deployment. The WAR can contain all its dependent JARs in <<>> but then the EAR can quickly grow very large if there are multiple WARs, due to the presence of duplicate JARs. Instead the J2EE specification allows WARs to reference external JARs packaged within the EAR via the <<>> setting in their <<>>. The Maven WAR and EAR Plugins do not directly support this mode of operation but we can fake it through some POM and configuration magic. First you need to tell Maven to exclude the dependent JARs and add references to them in the <<>> instead. This goes into your WAR project's <<>>: +-----------------+ ... maven-war-plugin ${project.version} WEB-INF/lib/*.jar true lib/ ... +-----------------+ Here's another variant of the above example, but this time we use <<<\>>> to select a few JARs to be included in the WAR. This is useful when there is a need to package a small, but non-empty, subset of JARs into the WAR. When making an EAR of skinny WARs, one wants to package all of the JARs into the EAR. Sometimes a list of JARs must be packaged into the WAR though in order for it to work properly, like with tag libraries. +-----------------+ ... maven-war-plugin ${project.version} WEB-INF/lib/my-tag-library.jar,**/*.xml,**/*.properties,**/*.class,**/*.png,**/*.css,**/*.js,**/*.jsp true lib/ ... +-----------------+ Next we need to change the EAR project's <<>> to package those dependent JARs in the EAR. Notice that we package everything into a <<>> directory within the EAR. This is just my own personal preference to distinguish between J2EE modules (which will be packaged in the root of the EAR) and Java libraries (which are packaged in <<>>). +-----------------+ ... maven-ear-plugin 2.3.2 lib/ ... +-----------------+ Now the painful part. Your EAR project's <<>> needs to list every dependency that the WAR has. This is because Maven assumes fat WARs and does not include transitive dependencies of WARs within the EAR. +-----------------+ .... com.acme shared-jar 1.0.0 com.acme war1 1.0.0 war com.acme war2 1.0.0 war ... +-----------------+ Your EAR will contain something like this: +-----------------+ . |-- META-INF | `-- application.xml |-- lib | `-- shared-jar-1.0.0.jar |-- war1-1.0.0.war `-- war2-1.0.0.war +-----------------+ * Alternatives Our users have submitted alternatives to the above recipe on {{{http://docs.codehaus.org/display/MAVENUSER/Solving+the+Skinny+Wars+problem}the Wiki}}.maven-war-plugin-2.1.1/src/site/apt/examples/rapid-testing-jetty6-plugin.apt0000644000175000017500000000466611431730651027013 0ustar twernertwerner ------ Rapid Testing Using the Jetty Plugin ------ Pete Marvin King ------ 2008-08-03 ------ ~~ 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. ~~ NOTE: For help with the syntax of this file, see: ~~ http://maven.apache.org/doxia/references/apt-format.html Rapid Testing Using the Jetty Plugin Normally, testing a web application involves compiling Java sources, creating a WAR and deploying it to a web container. Using the Jetty Plugin enables you to quickly test your web application by skipping the last two steps. By default the Jetty Plugin scans <<>> for any changes in your Java sources and <<>> for changes to your web sources. The Jetty Plugin will automatically reload the modified classes and web sources. To use the Jetty Plugin just add the following in your <<>>: +-----------------+ ... org.mortbay.jetty maven-jetty-plugin 6.1.10 10 8080 60000 ... ... +-----------------+ Then start Jetty: +-----------------+ mvn jetty:run +-----------------+ The command will block with Jetty listening on port 8080. Check the {{{http://docs.codehaus.org/display/JETTY/Maven+Jetty+Plugin}Jetty Plugin documentation}} for more details. maven-war-plugin-2.1.1/src/site/apt/examples/file-name-mapping.apt0000644000175000017500000000413311431730651024775 0ustar twernertwerner ------ Using File Name Mapping ------ Stephane Nicoll Dennis Lundberg ------ 2010-05-24 ~~ 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. ~~ NOTE: For help with the syntax of this file, see: ~~ http://maven.apache.org/doxia/references/apt-format.html Using File Name Mapping It might be necessary to customize the file name of libraries and TLDs. By default, those resources are stored using the following pattern: +----- @{artifactId}@-@{version}@.@{extension}@ +----- If the artifact has a classifier the default pattern is of course: +----- @{artifactId}@-@{version}@-@{classifier}@.@{extension}@ +----- The <<>> parameter allows you to give a custom pattern. Each token defined in the pattern will be replaced with a value from the current artifact. You can use any property of Artifact and ArtifactHandler as a token. There is also a special token named <<>> that can be used, since 2.1. It will add the string "-yourclassifier" if and only if the artifact has a classifier. For instance, to store the libraries and TLDs without version numbers or classifiers, use the following pattern: +----- @{artifactId}@.@{extension}@ +----- To store the libraries and TLDs without version numbers but with classifiers (if they exist), use the following pattern: +----- @{artifactId}@@{dashClassifier?}@.@{extension}@ +----- maven-war-plugin-2.1.1/src/site/apt/examples/adding-filtering-webresources.apt.vm0000644000175000017500000002514311456572207030061 0ustar twernertwerner ------ Adding and Filtering External Web Resources ------ Pete Marvin King ------ 2008-08-03 ------ ~~ 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. ~~ NOTE: For help with the syntax of this file, see: ~~ http://maven.apache.org/doxia/references/apt-format.html Adding and Filtering External Web Resources The default resource directory for all Maven projects is <<>> which will end up in <<>> and in <<>> in the WAR. The directory structure will be preserved in the process. The WAR Plugin is also capable of including resources not found in the default resource directory through the <<>> parameter. *Adding web resources +-------+ ... org.apache.maven.plugins maven-war-plugin ${project.version} resource2 ... +-------+ Using our sample project in the {{{../usage.html}usage section}} with an added external resource, like this: +----------+ . |-- pom.xml |-- resource2 | |-- external-resource.jpg | `-- image2 | `-- external-resource2.jpg `-- src `-- main |-- java | `-- com | `-- example | `-- projects | `-- SampleAction.java |-- resources | `-- images | `-- sampleimage.jpg `-- webapp |-- WEB-INF | `-- web.xml |-- index.jsp `-- jsp `-- websource.jsp +----------+ would end up in the WAR as: +----------+ documentedproject-1.0-SNAPSHOT.war |-- META-INF | |-- MANIFEST.MF | `-- maven | `-- com.example.projects | `-- documentedproject | |-- pom.properties | `-- pom.xml |-- WEB-INF | |-- classes | | |-- com | | | `-- example | | | `-- projects | | | `-- SampleAction.class | | `-- images | | `-- sampleimage.jpg | `-- web.xml |-- external-resource.jpg |-- image2 | `-- external-resource2.jpg |-- index.jsp `-- jsp `-- websource.jsp +----------+ <<>> and <<>> are copied to the root of the WAR, preserving the directory structure. *Configuring web Resources <<>> is a list of resources. All options of resource are supported. A web resource * can have includes/excludes * can be filtered * is not limited to the default destination - the root of the WAR **Includes/Excludes To include all jpgs in the WAR we can add the following to our POM configuration from above: +----------+ ... resource2 **/*.jpg ... +----------+ To exclude the <<>> directory from the WAR add this: +----------+ ... resource2 **/image2 ... +----------+ Be careful when mixing includes and excludes, excludes will have a higher priority. Includes can not override excludes if a resource matches both. Having this configuration will exclude all jpgs from the WAR: +----------+ ... resource2/ image2/*.jpg **/*.jpg ... +----------+ Here's another example of how to specify include and exclude patterns: +----------+ ... **/pattern1 *pattern2 *pattern3/pattern3 pattern4/pattern4 ... +----------+ **Filtering Using our example above, we can also configure filters for our resources. We will add a hypothetical <<>> directory to our project: +----------+ . |-- configurations | |-- config.cfg | `-- properties | `-- config.prop |-- pom.xml |-- resource2 | |-- external-resource.jpg | `-- image2 | `-- external-resource2.jpg `-- src `-- main |-- java | `-- com | `-- example | `-- projects | `-- SampleAction.java |-- resources | `-- images | `-- sampleimage.jpg `-- webapp |-- WEB-INF | `-- web.xml |-- index.jsp `-- jsp `-- websource.jsp +----------+ To prevent corrupting your binary files when filtering is enabled, you can configure a list of file extensions that will not be filtered. +----------+ ... properties/config.prop pdf resource2 false configurations true **/properties ... +----------+ *** <<>> +----------+ interpolated_property=some_config_value +----------+ *** <<>> +----------+ ${interpolated_property} +----------+ The resulting WAR would be: +----------+ documentedproject-1.0-SNAPSHOT.war |-- META-INF | |-- MANIFEST.MF | `-- maven | `-- com.example.projects | `-- documentedproject | |-- pom.properties | `-- pom.xml |-- WEB-INF | |-- classes | | |-- com | | | `-- example | | | `-- projects | | | `-- SampleAction.class | | `-- images | | `-- sampleimage.jpg | `-- web.xml |-- config.cfg |-- external-resource.jpg |-- image2 | `-- external-resource2.jpg |-- index.jsp `-- jsp `-- websource.jsp +----------+ and the content of <<>> would be: +----------+ some_config_value +----------+ **Overriding the default destination directory By default web resources are copied to the root of the WAR, as shown in the previous example. To override the default destination directory, specify the target path. +----------+ ... ... configurations WEB-INF true **/properties ... +----------+ Using the sample project the resulting WAR would look like this: +----------+ documentedproject-1.0-SNAPSHOT.war |-- META-INF | |-- MANIFEST.MF | `-- maven | `-- com.example.projects | `-- documentedproject | |-- pom.properties | `-- pom.xml |-- WEB-INF | |-- classes | | |-- com | | | `-- example | | | `-- projects | | | `-- SampleAction.class | | `-- images | | `-- sampleimage.jpg | |-- config.cfg | `-- web.xml |-- external-resource.jpg |-- image2 | `-- external-resource2.jpg |-- index.jsp `-- jsp `-- websource.jsp +----------+ maven-war-plugin-2.1.1/src/site/apt/usage.apt.vm0000644000175000017500000001336211431730651021422 0ustar twernertwerner ------ Usage ------ Pete Marvin King ------ 2010-08-15 ------ ~~ 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. ~~ NOTE: For help with the syntax of this file, see: ~~ http://maven.apache.org/doxia/references/apt-format.html Usage There are 4 ways to use the WAR Plugin: * using the <<>> phase with the project package type as <<>> * invocation of the <<>> goal * invocation of the <<>> goal * invocation of the <<>> goal [] <> When using the <<>> goals it is assumed that the <<>> phase is already done. The WAR Plugin is not responsible for compiling the java sources or copying the resources. *Using the <<>> phase with the project package type as war / invocation of the <<>> goal This is the normal way of using the WAR Plugin. To illustrate, here's the <<>> for our project: +----------+ ... com.example.projects documentedproject war 1.0-SNAPSHOT Documented Project http://example.com ... +----------+ The project's structure looks like this: +----------+ |-- pom.xml `-- src `-- main |-- java | `-- com | `-- example | `-- projects | `-- SampleAction.java |-- resources | `-- images | `-- sampleimage.jpg `-- webapp |-- WEB-INF | `-- web.xml |-- index.jsp `-- jsp `-- websource.jsp +----------+ Invoking +----------+ mvn package +----------+ or +----------+ mvn compile war:war +----------+ will generate the WAR file <<>>. Here are the contents of that WAR file: +----------+ documentedproject-1.0-SNAPSHOT.war |-- META-INF | |-- MANIFEST.MF | `-- maven | `-- com.example.projects | `-- documentedproject | |-- pom.properties | `-- pom.xml |-- WEB-INF | |-- classes | | |-- com | | | `-- example | | | `-- projects | | | `-- SampleAction.class | | `-- images | | `-- sampleimage.jpg | `-- web.xml |-- index.jsp `-- jsp `-- websource.jsp +----------+ *Invocation of <<>> goal To speed up testing during the developement phase, <<>> can be used to generate the WAR in exploded form. Use the same project as above and invoke: +----------+ mvn compile war:exploded +----------+ This will generate an exploded version of the WAR in <<>>. The contents of that directory looks like this: +----------+ documentedproject-1.0-SNAPSHOT |-- META-INF |-- WEB-INF | |-- classes | | |-- com | | | `-- example | | | `-- projects | | | `-- SampleAction.class | | `-- images | | `-- sampleimage.jpg | `-- web.xml |-- index.jsp `-- jsp `-- websource.jsp +----------+ The default directory for the exploded WAR is <<>>>. The <<>> is usually in the form of <<<\-\>>>. This default directory can be overridden by specifying the <<>> parameter. +-------+ ... org.apache.maven.plugins maven-war-plugin ${project.version} /sample/servlet/container/deploy/directory ... +-------+ *Invocation of <<>> goal Another variation of <<>> is <<>>. With <<>> the exploded WAR is created in the webapp source, which defaults to <<>>. Use our sample project above, and invoke: +----------+ mvn compile war:inplace +----------+ This will result in: +----------+ |-- pom.xml |-- src | `-- main | |-- java | | `-- com | | `-- example | | `-- projects | | `-- SampleAction.java | |-- resources | | `-- images | | `-- sampleimage.jpg | `-- webapp | |-- META-INF | |-- WEB-INF | | |-- classes | | | |-- com | | | | `-- example | | | | `-- projects | | | | `-- SampleAction.class | | | `-- images | | | `-- sampleimage.jpg | | `-- web.xml | |-- index.jsp | `-- jsp | `-- websource.jsp `-- target `-- classes |-- com | `-- example | `-- projects | `-- SampleAction.class `-- images `-- sampleimage.jpg +----------+ maven-war-plugin-2.1.1/src/site/apt/overlays.apt.vm0000644000175000017500000003015511431606203022154 0ustar twernertwerner ------ Overlays ------ Pete Marvin King Stephane Nicoll Dennis Lundberg ------ 2010-08-14 ~~ 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. ~~ NOTE: For help with the syntax of this file, see: ~~ http://maven.apache.org/doxia/references/apt-format.html Overlays Overlays are used to share common resources across multiple web applications. The dependencies of a WAR project are collected in <<>>, except for WAR artifacts which are overlayed on the WAR project itself. * Overlays at a glance To demonstrate, given this structure for the project <<>>: +-----------------+ |-- pom.xml `-- src `-- main |-- java | `-- com | `-- example | `-- projects | `-- SampleAction.java |-- resources | |-- images | | `-- sampleimage.jpg | `-- sampleresource `-- webapp |-- WEB-INF | `-- web.xml |-- index.jsp `-- jsp `-- websource.jsp +-----------------+ The project depends on another WAR artifact, <<>>, which is declared as a dependency in the project's <<>>: +-----------------+ ... com.example.projects documentedprojectdependency 1.0-SNAPSHOT war runtime ... ... +-----------------+ The structure for the <<>> WAR file looks like this: +-----------------+ documentedprojectdependency-1.0-SNAPSHOT.war |-- META-INF | |-- MANIFEST.MF | `-- maven | `-- com.example.projects | `-- documentedprojectdependency | |-- pom.properties | `-- pom.xml |-- WEB-INF | |-- classes | | |-- com | | | `-- example | | | `-- projects | | | `-- SampleActionDependency.class | | `-- images | | `-- sampleimage-dependency.jpg | `-- web.xml `-- index-dependency.jsp +-----------------+ The resulting WAR would end up like this: +-----------------+ |-- META-INF | |-- MANIFEST.MF | `-- maven | `-- com.example.projects | `-- documentedproject | |-- pom.properties | `-- pom.xml |-- WEB-INF | |-- classes | | |-- com | | | `-- example | | | `-- projects | | | |-- SampleAction.class | | | `-- SampleActionDependency.class | | `-- images | | |-- sampleimage-dependency.jpg | | `-- sampleimage.jpg | `-- web.xml |-- index-dependency.jsp |-- index.jsp `-- jsp `-- websource.jsp +-----------------+ The <<>> file above comes from <<>>. * Overlay types The WAR Plugin handles both <> and <> artifacts as overlays. However, for backward compatibility reasons, zip overlays are handled only if they are defined explicitly in the plugin's configuration. * Configuring Overlays In previous versions of the WAR Plugin, no configuration was necessary. This is still the case if you are happy with the default settings. However, if you need more control, read on! The <<<\<{overlay}\>>>> element can have the following child elements: * <> - the id of the overlay. If none is provided, the WAR Plugin will generate one. * <> - the groupId of the overlay artifact you want to configure. * <> - the artifactId of the overlay artifact you want to configure. * <> - the type of the overlay artifact you want to configure. Default value is: <<>>. * <> - the classifier of the overlay artifact you want to configure if multiple artifacts matches the groupId/artifactId. * <> - the files to include. By default, all files are included. * <> - the files to exclude. By default, the <<>> directory is excluded. * <> - the target relative path in the webapp structure, which is only available for overlays of type <<>>. By default, the content of the overlay is added in the root structure of the webapp. * <> - set to <<>> to skip this overlay. Default value is: <<>>. [] For instance, to exclude the <<>> of our <<>> <<>> overlay above: +-----------------+ ... org.apache.maven.plugins maven-war-plugin ${project.version} com.example.projects documentedprojectdependency WEB-INF/classes/images/sampleimage-dependency.jpg ... +-----------------+ * Overlays packaging Overlays are applied with a first-win strategy (hence if a file has been copied by one overlay, it won't be copied by another). Overlays are applied in the order in which they are defined in the <<<\>>> configuration. If no configuration is provided, the order in which the dependencies are defined in the POM is used (warning: this is not deterministic, especially if you have overlays as transitive dependencies). In case of a mixed situation (e.g. configured overlays and non-configured overlays), non-configured overlays are applied after configured overlays. By default, the source of the project (a.k.a the current build) is added first (e.g. before any overlay is applied). The current build is defined as a special overlay with no <<>>, <<>>. If overlays need to be applied first, simply configure the current build after those overlays. For instance, if <<>> from the <<>> group is a dependency of the project and needs to be applied before the project's own source, do as follows: +-----------------+ ... org.apache.maven.plugins maven-war-plugin ${project.version} com.example.projects my-webapp ... +-----------------+ <> In the scenario above, any other WAR dependency will be applied after the current build since they have not been configured in the <<<\>>> element. To perform an even more fine grained overwriting policy, overlays can be packaged multiple times with different includes/excludes. For instance if the <<>> file of the overlay <<>> <> be set in the webapp but other files can be controlled the regular way, define two overlay configurations for <<>>: +-----------------+ ... org.apache.maven.plugins maven-war-plugin ${project.version} my-webapp-index.jsp com.example.projects my-webapp index.jsp my-webapp com.example.projects my-webapp ... +-----------------+ * Overlay global settings The following settings can be specified globally and modify the way all overlays are applied. * <> - sets the default includes to apply to all overlays. Any overlay that has no specific <<>> element will inherit this setting by default. +-----------------+ ... org.apache.maven.plugins maven-war-plugin ${project.version} **/IncludeME,**/images ... +-----------------+ * <> - sets the default excludes to apply to all overlays. Any overlay that has no specific <<>> element will inherit this setting by default. +-----------------+ ... org.apache.maven.plugins maven-war-plugin ${project.version} WEB-INF/web.xml,index.* ... +-----------------+ * <> - sets the directory where overlays will be temporarily extracted. +-----------------+ ... org.apache.maven.plugins maven-war-plugin ${project.version} /tmp/extract_here ... +-----------------+ * <> - set to <<>> to enable the webapp structure cache. Default value is: <<>>. +-----------------+ ... org.apache.maven.plugins maven-war-plugin ${project.version} true ... +-----------------+ * Zip dependencies with overlays To use a <> dependency as an overlay you have to configure it explicitly in the plugin's configuration. For instance to inject the content of a zip overlay in the <<>> directory of the webapp, do as follows: +-----------------+ ... org.apache.maven.plugins maven-war-plugin ${project.version} zipGroupId zipArtifactId zip scripts ... +-----------------+ maven-war-plugin-2.1.1/src/site/apt/tips/0000755000175000017500000000000011641142607020142 5ustar twernertwernermaven-war-plugin-2.1.1/src/site/apt/index.apt0000644000175000017500000001016011431730651020775 0ustar twernertwerner ------ Introduction ------ Pete Marvin King ------ 2010-08-15 ------ ~~ 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. ~~ NOTE: For help with the syntax of this file, see: ~~ http://maven.apache.org/doxia/references/apt-format.html Maven WAR Plugin The WAR Plugin is responsible for collecting all artifact dependencies, classes and resources of the web application and packaging them into a web application archive. * Goals Overview * {{{./war-mojo.html}war:war}} is the default goal invoked during the <<>> phase for projects with a packaging type of <<>>. It builds a WAR file. * {{{./exploded-mojo.html}war:exploded}} is generally used to speed up testing during the developement phase by creating an exploded webapp in a specified directory. * {{{./inplace-mojo.html}war:inplace}} another variation of <<>> where the webapp is instead generated in the web application source directory, which is <<>> by default. * {{{./manifest-mojo.html}war:manifest}} generates a manifest for this webapp. The manifest file is created in the web application source directory. [] * Usage General instructions on how to use the WAR Plugin can be found on the {{{./usage.html}usage page}}. Some more specific use cases are described in the examples given below. To share common resources across multiple web applications, see the documentation about using {{{./overlays.html}overlays}}. Last but not least, users occasionally contribute additional examples, tips or errata to the {{{http://docs.codehaus.org/display/MAVENUSER/WAR+Plugin}plugin's wiki page}}. In case you still have questions regarding the plugin's usage, please have a look at the {{{./faq.html}FAQ}} and feel free to contact the {{{./mail-lists.html}user mailing list}}. The posts to the mailing list are archived and could already contain the answer to your question as part of an older thread. Hence, it is also worth browsing/searching the {{{./mail-lists.html}mail archive}}. If you feel like the plugin is missing a feature or has a defect, you can fill a feature request or bug report in our {{{./issue-tracking.html}issue tracker}}. When creating a new issue, please provide a comprehensive description of your concern. Especially for fixing bugs it is crucial that the developers can reproduce your problem. For this reason, entire debug logs, POMs or most preferably little demo projects attached to the issue are very much appreciated. Of course, patches are welcome, too. Contributors can check out the project from our {{{./source-repository.html}source repository}} and will find supplementary information in the {{{http://maven.apache.org/guides/development/guide-helping.html}guide to helping with Maven}}. * Examples To provide you with better understanding on some usages of the Maven WAR Plugin, you can take a look into the following examples: * {{{./examples/adding-filtering-webresources.html}Adding and Filtering External Web Resources}} * {{{./examples/war-manifest-guide.html}WAR Manifest Customization}} * {{{./examples/rapid-testing-jetty6-plugin.html}Rapid Testing the Jetty Plugin}} * {{{./examples/skinny-wars.html}Creating Skinny WARs}} * {{{./examples/file-name-mapping.html}Using File Name Mapping}} [] * Related links * {{{./http://maven.apache.org/guides/mini/guide-archive-configuration.html}Exclusion of Maven Descriptors}} [] maven-war-plugin-2.1.1/src/site/site.xml0000644000175000017500000000360111237277115020071 0ustar twernertwerner

maven-war-plugin-2.1.1/src/site/fml/0000755000175000017500000000000011641142610017147 5ustar twernertwernermaven-war-plugin-2.1.1/src/site/fml/faq.fml.vm0000644000175000017500000001271611431731544021055 0ustar twernertwerner How is filtering done in the WAR plugin?

To enable filtering of web.xml you must configure the WAR Plugin like this: maven-war-plugin ${project.version} true ]]>

Examples can be found here.

How does the classifier of dependency artifacts affect my WAR project?

When used, the copy of the dependency artifact in your project will have the classifier appended to its filename. This can be used to differentiate duplicate artifacts.

How do I exclude transitive dependencies from my project?

Give it a "provided" scope.

What's the difference between using dependentWarExclude and provided scope?

dependentWarExclude is used in overlays for excluding dependent WAR files from the assembled webapp.

How do I exclude files in my web resources?

Use the <webResources> / <exclude> parameter to identify the tokens to exclude.

For more information refer to Adding and Filtering External Web Resources.

How do I exclude files when doing overlays?

Use the dependentWarExcludes parameter to identify the tokens to exclude.

Where can I find the documentation for the plugin's configuration?

For each goal, you can use the documentation from the plugin site.

If you need a specific version, generate it using mvn site:site or use: ]]>

How do I create a JAR containing the classes in my webapp?

If you would simply like to package the classes and resources as a JAR in WEB-INF/lib rather than as loose files under WEB-INF/classes, use the following configuration:

maven-war-plugin ${project.version} true ]]>

If you need to re-use this JAR in another project, the recommended approach is to move the classes to a separate module that builds a JAR, and then declare a dependency on that JAR from your webapp as well as from any other projects that need it.

If you can't move the classes to another project, you can deploy the classes and resources included in your webapp as an "attached" artifact, with a classifier, by using the following configuration:

... mywebapp 1.0-SNAPSHOT ... maven-war-plugin ${project.version} true ... ]]>

This will result in two artifacts being deployed: mywebapp-1.0-SNAPSHOT.war and mywebapp-1.0-SNAPSHOT-classes.jar.

maven-war-plugin-2.1.1/src/it/0000755000175000017500000000000011641142610016041 5ustar twernertwernermaven-war-plugin-2.1.1/src/it/MWAR-133/0000755000175000017500000000000011641142610017113 5ustar twernertwernermaven-war-plugin-2.1.1/src/it/MWAR-133/pom.xml0000644000175000017500000000375011060574022020436 0ustar twernertwerner 4.0.0 testwar MWAR-133 war 1.0-SNAPSHOT MWAR-133 Maven Webapp MWAR-133 it src/main/resources true maven-war-plugin @pom.version@ src/main/webresources true org.codehaus.plexus plexus-utils 1.4.6 maven-war-plugin-2.1.1/src/it/MWAR-133/src/0000755000175000017500000000000011641142610017702 5ustar twernertwernermaven-war-plugin-2.1.1/src/it/MWAR-133/src/main/0000755000175000017500000000000011641142610020626 5ustar twernertwernermaven-war-plugin-2.1.1/src/it/MWAR-133/src/main/webapp/0000755000175000017500000000000011641142610022104 5ustar twernertwernermaven-war-plugin-2.1.1/src/it/MWAR-133/src/main/webapp/WEB-INF/0000755000175000017500000000000011641142610023133 5ustar twernertwernermaven-war-plugin-2.1.1/src/it/MWAR-133/src/main/webapp/WEB-INF/web.xml0000644000175000017500000000172211045075710024440 0ustar twernertwerner Archetype Created Web Application maven-war-plugin-2.1.1/src/it/MWAR-133/src/main/webresources/0000755000175000017500000000000011641142610023336 5ustar twernertwernermaven-war-plugin-2.1.1/src/it/MWAR-133/src/main/webresources/filtered.properties0000644000175000017500000000010311060574022027245 0ustar twernertwerner# # Not Replaced with the pom version # app.version=${node.version}maven-war-plugin-2.1.1/src/it/MWAR-133/goals.txt0000644000175000017500000000002311045071614020757 0ustar twernertwernerclean war:exploded maven-war-plugin-2.1.1/src/it/MWAR-133/verify.bsh0000644000175000017500000000412011431607526021123 0ustar twernertwerner /* * 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 java.io.*; import org.codehaus.plexus.util.*; boolean result = true; try { File target = new File( basedir, "target" ); if ( !target.exists() || !target.isDirectory() ) { System.err.println( "target file is missing or not a directory." ); return false; } File webappDirectory = new File( target, "MWAR-133-1.0-SNAPSHOT" ); if ( !webappDirectory.exists() || !webappDirectory.isDirectory() ) { System.err.println( "webappDirectory is missing or not a directory." ); return false; } File filtered = new File ( webappDirectory, "filtered.properties" ); if ( !filtered.exists() || filtered.isDirectory() ) { System.err.println( "filtered.properties file is missing or a directory." ); return false; } System.out.println (" before reading param " ); FileInputStream fis = new FileInputStream ( filtered ); String paramContent = IOUtil.toString ( fis ); int indexOf = paramContent.indexOf( "app.version=${node.version}" ); if ( indexOf < 0) { System.err.println( "filtered.properties was not filtered with the value of ${node.version}" ); return false; } } catch( Throwable e ) { e.printStackTrace(); result = false; } return result; maven-war-plugin-2.1.1/src/it/MWAR-143/0000755000175000017500000000000011641142610017114 5ustar twernertwernermaven-war-plugin-2.1.1/src/it/MWAR-143/pom.xml0000644000175000017500000000401610771710445020444 0ustar twernertwerner 4.0.0 debug.war MWAR-143 pom 1.0-SNAPSHOT MWAR-143 Maven Webapp http://maven.apache.org maven-war-plugin @pom.version@ jpg war-common war-filter-overlay debug.war common-overlay 1.0-SNAPSHOT maven-war-plugin-2.1.1/src/it/MWAR-143/war-common/0000755000175000017500000000000011641142610021173 5ustar twernertwernermaven-war-plugin-2.1.1/src/it/MWAR-143/war-common/pom.xml0000644000175000017500000000351610772000266022521 0ustar twernertwerner 4.0.0 debug.war MWAR-143 1.0-SNAPSHOT common-overlay war org.apache.maven.plugins maven-war-plugin properties src/main/images true maven-war-plugin-2.1.1/src/it/MWAR-143/war-common/src/0000755000175000017500000000000011641142610021762 5ustar twernertwernermaven-war-plugin-2.1.1/src/it/MWAR-143/war-common/src/main/0000755000175000017500000000000011641142610022706 5ustar twernertwernermaven-war-plugin-2.1.1/src/it/MWAR-143/war-common/src/main/webapp/0000755000175000017500000000000011641142610024164 5ustar twernertwernermaven-war-plugin-2.1.1/src/it/MWAR-143/war-common/src/main/webapp/WEB-INF/0000755000175000017500000000000011641142610025213 5ustar twernertwernermaven-war-plugin-2.1.1/src/it/MWAR-143/war-common/src/main/webapp/WEB-INF/web.xml0000644000175000017500000000045611431607526026530 0ustar twernertwerner maven-war-plugin-2.1.1/src/it/MWAR-143/war-common/src/main/images/0000755000175000017500000000000011641142610024153 5ustar twernertwernermaven-war-plugin-2.1.1/src/it/MWAR-143/war-common/src/main/images/duke-beer.jpg0000755000175000017500000074071210755430122026541 0ustar twernertwernerJFIFHHExifII*122FiZAdobe Photoshop 7.02004:10:24 20:45:18F CC]~" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?((((((((((((((((((((((((~Ӛ Z&YVj ִ;U>)-n#q%0:bڙqگBG#wem;|q9PGFgN.0&a!?}[M,VuT/\~.س.%<;F_뺷<_}^^Fw%{J.OMCqR7##2[ _W~>/zM+ŸÏ/dJ5!O&ab}kK+-4QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEW}/7/K7f⩭^F_i˧EF1` v1^_Η9C e3V_?%1;ҷ> eQQ]͛,vb-?\a7/⏈*G(E\Vwj."P7U@yo-W, psgw Pt<(rڲnV'8Ig>yZ_/=n^n1]b-2"d/8hWEdbVE7]ګᮅn|6*ӬL⇂a4y<5w][}yj,o3^5O?h?oi[veh-5hҋ/E0Fw˳6YG'%Mn6Ba} u$wss=qݿZd'i}?a_|q9~XrO<MwKII\63 q^t${9q\Fd s0Oס<_|zkFךNwԬ_+Sd" ճY /M.? ?-wᕴA>M%ޥnAttMW7As&~a@m0Ky̓z:O ۨOٟ|y]mil >wxRX[g`5 ;h m%. D\sE|||>/2t?_Ey4񬖋5w24gg};QXbKdf/h((((((((((((((((((((((((((((((((((((((((((((((((((ߋ?7s៎*g-x[xc{$h($ DX|L 5hZ߁:9${Y!x8 (KʦX7>[*\oU؊ qi|AO~%g]xK}]ɐk?ukF-6%L KH7ke B {d=8><+ 8s{:ݐ'GO_|g[Ǿ8=@ʞzA{vz9$|ֺ8q=F?b\'G=@g+,oPyzڼgZWs⾋ԭ+d`ONyƱ`$VA 6@W7E٧mK¾"`%E$1*%xE.|m. RV.[Iet[q E|#mO>>k^1-ӤXw!+ xm4-$#-@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@O$ǁ?g̾|M r/,I R[(f!,Y8x_S?ek_{tAx+Y]^N/n50VSSb1[@_2$.1FG ( `~=#9:Vu=?O@+Izsߑ@ >c8u6Gfqzpq:~suϒ}={?2An8CX8pz܃9$99f̹G1~;su`Wn{\˃Аy@I$鎹#\N@*@9&<[[ӷeO QӞ1uK  AV`Nq׌G ^īvx$@]1य़W[֟a!"#_tIwڴgre</h/?'|v+?;:&jB\4ؓiZؚP%{wFo.ʒzs@bf{M[ĝB _Ÿ|6Cٳ۾˔=o|jw QxS-wzvXtq$Se `h((((((((((((((((((((((((((((((((((((((((((((((((Ϳ+>e?؋⧍tg?AoŞ;7V;2[/ZˬzC_ڴpHYsGo䜱bORܑki4+;&X"3secr<,*r@vj,~@O8Ͼ} xQ=yƯۧSߎjKꠌ猀zu{#8RQ>s]ϩGZTק|voʲ8ݏLxڀ1eP n0$Ӷ1Gsڵe9LzϽgK}z*ʔpÂps#H+*0oz8lA[R:N3NY0sq@e9xs=ʼUy#W^ÐNsS:vAPAR8\ Bsqߌ?\NAܭFzbլHf;9׏+8H?^W9>%/>9${σ&ԧղ#\i$!M_Ng H?>-Ϗ|-3\ERӵ _OtmCL-u :hm/l/`"V{imԕep((((((((((((((((((((((((((((((((((((((((((((((+>:|_>4xMk kŚ ݦg$i+lU’^O8Ÿ~ot{o X]GRbE%mR_|a {N񷉼uLHȚ5{bkKo9ao h@d ds@m#Mq$.G׎xxu8 rG8Ú>^y<N/As?Ƙ`=֤=>ϰn Ü}.sN{s}z֣ӜxF:$s("@~n1߯qϯYHF1Z.0׹T^zGPr=:cu98 c{?g̤nquG^y烞TeN\;ș)n1A?8?zDs=#k-#Ryk$s~ku S0*`qN0AGj|88>Ƹ]Nr3Br>tW'u9xSNYQe*A<wWv,s矼:灊nH6|c86w?5o ßlj֩-'⾹|°'m3o/&;>NE\nƏ4qZΟ0{9#4'IbH䍃$n#!ЩH q_3:Ȯt==OWOm?'.ojGfM3';r5$BOOumZB((((((((((((((((((((((((((((((((((((((((((((((nn hy`i%i\Kf$U$W~ߟߵOEǃ;.#yd;wO4n `fo+5ljq35{ăǿODuPxMZǖ+kk+MMFV\jv b  ^3`4 UPq1ֶcv8*W#9#לsZH Ќg8N`p'~ 郎G|1y##IێN}3^>NrpF8I#r;֜8rqЃYP\G<'<fI9x8LqW>֨ȸ8㞀}GR~OR 98Nj?=zvҩ9v9  tϧozϞ5`p:gzcjuo\U Мz`@8*rFu[CQ%X`6G^: 0W}ӒA=\+TO\`qȠ'mHv`?xgWrPpI:r9^[ 628=rO. ny rB8?*.Qs.2+I%ʹqku 0 & "+) )WAr;xddԟZz8@ l?h ~Ɵ⎽~|gtHwt;9CA:zH?Nm$cMJpHQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQE֊NnIxK _s[Ѵ{GR=SMeDi$H_cWDM|5P~|R7ᮩ>$>L]vo3LMe9'*\ٕyumEUԭ-[ "tAqms\@񲲺HUDQ@Q@Q@Q@Q@!Oo֖Gj <*wՌxcAd*k:dKLUe>lm*RJX _]|­PK~:}ρmRwOi(7pZl0} q**(RGN}x\Հ}kZg/xYEjwzږ^Nn羹݉gy '&X>'#Kc }ɫcn0J;Ajq@H9֕3s ܷ<' p:qO=(IU7BG>Lv׭)>Ӹ=1 :H?_ΩHy;ᚺ 9PSpIL.Nz*˜߮ KOĝjM/^uNIZ'Ux{UG/l$gʘ$D]];w#2koMyus%Z.//Zs#;1,ʼn'59|`M_ 4u_xþ N $}/ iK.HauI˖i=:&z9=|CQ?m ?✺u]Snu y4[0٤eޞuxR"R[?Wn~&?iO#57O6+/'kxOWv>MW!.{[fOh[v?t>>A?c٢[;o>%ӜCuiso ޟp]G!~ 6 GC|R?5+g #,FNB _/xALJV|jyiZ`rr[-s_n;-"ªH0n+%rz-?~mm#c4?4^"^(ӣYnbgP`~?OC3cߏ4X/iVS=6"Plo]yݲ6gQ;ÿ3ɿ<%W< 5[I?⺋p>gxQ5m47sq OoN2W2+=4_[ %s'clxwǿ5O6%G$_ /V_wSq-$s)wqҷ1((8o~F-!G[K6^B5l#Lʥ|LD(XW?g/ ͟&|q.zeٝVݗHX%0jik,Rk[i3ş>&od|c#׌Cy#olɆ% vCq Ze)\`>cJ!R9G z8\FA<~aPx:ߧNG@#>#u d?n5\r8'~Y*egӞs9=A'~}z{9vpR`g {g `3@`~U}:l}sqZRc@$ldv+6ot=zx(I@LUe=Oawu9ϠUF~y93zqQr;dzz~VLt?ҭ8:by9}P9$gw3=2?R@0T>#<Z 7\=U{s=: 9=(H9#?~uFUA<OҴd9`3@sۯ^q@G'<J`?tg=q}r?wHO>t5ŐF;>yO>7x>ˈW?bsC/'8ӿ.y\b3@$)y'=>}?_nx+Hy[zx4S򌑓r9>s<)F _Ki&|{qk>C];wWmuiow %yu͸!Qs9s7a wݨf?`۟{ǿ:Moma]&kxYwmc9K'r[[lfBɷ tߋ~"q7о4|,kM߃Vd턄e}*+mq:i_o|{?|=: 6*~1}#V7~d$2x(QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQYh:^ZZXino%XID);_~xſ>#~?4Kx\-Xi1%`kmYdHVfW_-=%?_e _xQS`5Ϡ꺌qX[Gg44#l|5)Gi3_i/ÿ\vEODcG* 4]>A5dF ?|;NgdVp Q,k,[ڣW'ovg] g+> k%Ⲃ&&8̩r;_^gu=io4n. A99A~|(DW6}gsu/AIUn%H<=D@3_^ICŸoK>`r[:ohnlע<:hѰ)yQEBݽ\қN|%-.'n_4="T-b PYFVͮ(Wq~4^*ê tgY:5ּ̘eL@ $.jV?kj?5HB@o|!l̇KYl:%$p 9|W,O~ v1[XQBFDh&R-oy[ԝb>/i~WF wC glI5wONKo5MZZә2x'z2xF7{R!3VI*G~Q|[grM{D3 L}kV1+{$\X^Kn yCE(eYH!#o >1~ٿL ju}K~ x?&Ƴ=޵ZK֡jY}S]ulnK$4?{D7Aygg#vF11gWa?MQ-e^rpi^7rj>"LF+]J6f՜31w7WH[]ZƳ[+,#)!UЀ~$Co2N=ޯjRJѬ彺dyvHEI"(vkU+VǷxiyg N Kio.ՀH!~-Dqi9zh^*h_I~i@O v96:^Fr랣jiƤs0sj)zqӰ :g2A@A>tg|=&8BO#'@~?AQ188q LF}Lu?U{(鎜s=ѐq98zϓ*q瞃JN㓎t'UJCVg錌uϦUqϡ(q[=۵V~A9:dU[>N? d3_˭U~8urr;շ]n1wPI''<'O}>\3H?O<$Θ g=1}>rz9POCԜOo^3X)NrOgr7GP=xU^$NO@HzgMHm23+WgV?ݵnbZ$Ŀoie9a?ҍgUmtrW?M?ef]&٣8 J0]N:(> G˦톁x<9c oHþђEoxUǕi,6F#?p~V^ 喔&JW\֯eO2 xapOm)K( ;Do3hOh>1|>ulx?Ky|1?id`su i%fG'5o=v|_>|e5k.j:uOȕ W?XfM%dqR߱ Z]ZZ+XݣUؑOZw𭍍hGKqDZB@@ ҿD> _X vUFH#'8GY˚Z]$F>wk+K,hQ x8_v]C$$C~`ݐA95Ϸq#$ xN:~u_h/p'2(fQgN1e%nӕ_,?g4eԫq;H?s7Heeny {\7ċU7WTxz0u'Vc &1THp<3mm/ѼB86BlPw'BhRkL1 F7bI'q;^W;$|Ē0sA_?ڤx`8xؐI钭sJgG VG˻?a{ķO>!k߁3\m=Ӗ>\4HHżvsFd6XYvvwm{aeYJ\_5t7'>[_hҮ/i97E./'Z1lj#}?N_ 5<) OQVǗ֞ ii=-u!՞[s xV?o ;ߍsF]h-So `WDYbVyD=P9,1Fq‚NA$+2q珦}}<XZWVuToc]*ف\3^(qqXe5j.wKGF#QCspɜq {Eu)EFq=#Zy}}~:z~0x][ $@uC#HN:~ωlak+a}]3m蘿$FH;R]r/\yn:{g}~۳.ti>02[j6%[̷ Fpw3;ΛGkkA9^m鄺E쀢M H꓿K~;} ׿Qu]< 8 ^B q;j2Xu>Wds:'#S~28psUwG9U#=229#~T~8$V'$U~<zr 韥\~@O^{ӵV~t8)u5Y߯׶i@$9RIG8cx scW\{s>Յ:sЁssC9>AV5>$dtF2p3߰=<G|3 sN@מqsv { 9\Fo0G<:.a';W#idg?Z gLYUf<G<Wh%?5M7NF>'kڂv࿈Q0@c1qq<ߌg\Mw}妯iZymzs5jsŝ峬\Ə:R?ڌtWc~ݿmfoݵuÐW[DKn5;|Z [7HGH!qo'PEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEP_ g*o% ++9Z^۝wDm%x0%%@O?#gF?]_Ŀ}q~_CX."~4M<|,Q|= .ǃb7Ŭ+pBT(+u[ZfqſZwu1|93[CEmG ^mNHmJI+EQCikkp 67086= H{r0@Ed@k=$5f`X6B1׃ #g=KN`ʈ;}w;E rf~sLnYw1EmvJHXT _qOJ/ @R@"@q`'Phzg_iVWnUecG?O~nxGڦ$H-!vz⮳a}$GNGPO'8a[WTWXrB2rٱOjN)dyEwF2+Pw?$|GO\^%h8,aqt4"ivF'mMۻxf[`FWhUscZBu71W~/PtGd}2gw|r5/7G5Mɧڧ a41- RƬҦVG#?#ßl:3> _PH>ТImy-羚F(Kfq"+~_w\_^,!kXxmn)@n_<Z~ioG']I4^81\RMP3]>=Բ;ss,3Ym<ֶ%#(rw?`h/+&/lڻO7coTaq= a4j$T0ڻġW\ד{s٣os=S@ѿE^_\7_3M nyKDm*ۖJ1bJKB>Aft[.~]wp֫?R~H:s@یW^:uqH#UYr0z:2g>׾qҲBA8=AMpr}'q5q d9߁u5:gy}C@\  9[r۷dq8;s]9 NI}:\#8$sh! ߌ zW_M?(7ğ&?[ᯏ^ [xr^'Q_in& :$Ey_h~8|#%~O k| ޛüp}S[[g֗vsN4NQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEWQ/'o)o?٧5 ?WZ &FwgKbQS(Y*~1 9x+_{ew] /i^}#.INKk#o,L~"\Xy+I?c?k'G D"2?EQ Q|DѺId4F}He{hBgYoUGyO39x!$bFp8œqLWEaRLfRTҶr#}xWcCWcS#r?2gO)csfYz<93I;}xR |=/$~Lc~ݳB2+[z׌h4&KWKkBbU-Fi%bFfCF쬈Wi? DPw07$ԟWG#/ -EK_dbrյwWT__^)Ӿ%~պ9[@&m @o`h(զ o I.~~wi'9u?k:Bm6&oWR@r )[?)h|%~վ4Ҿ#% GceY\|93[CR"ҭ:QFws%GM3+?"Ú&hǒ?|#I;.eդ ȬQ7(`Wï rXh5i XCq'!uĄ*ܳ2Xkoi'DA?^?j,ݝe@*xgA޵ilXPIvρ<]^2'8ހ)3oʾo(]ܘI?66y+_FIlr1NGs#!̯%ٶFoY2Sf|mfI; rqV@3|q}h1f8 `?T$ˏLcIӎ*x+JTmc%*ĀvJD0 |HPla ுs Q~"{u?5:&fKa'6=߱1z T'CA'=,^]p ߭Vs_c=n?Z zHg8=`tEYsz rpy~nGs { g<Vl`s85a!v#N ׎1q֫>N;:έ?9'yǏǭZn3pFq?߅UpF^΀+0g{{t;v;ߒ \syH5RLQvPI0zqCuQp1d?2;~瓞:T2sǨr:Ptdd898_α^m r;Mޝyqtǥs 9' ^ΰI' @Gp=";צ1ǯAӏְdLgӭs'\gퟭeL)p<7 ~2r8}rYsuc@3njr2H}OL1j%C铂IpEeLA=qf9cǽb\D19#Ȯ<~q' yz~T[ ԃ׮1~:zJAPzq^q w9s`mpA09<~ W9cǿHW~y!?kX+{q"/^1Y=OxkEWFWGPUPAKQ ̬ +GWioᅧI@iO>&֯]Kmm{ B Kq{cz+h((((((((((((((((((((((((((((((((Xj}Yfeuj6Q,ַImyiq %[ydGS+x5P_~ ~_+8:_i? ~-Fwu׀/ 5rVOZ!E(*?+_0|2Gm8dm1B;J7̺4230R7( wи^¾ďm4i|yuWx įq5v,@gz~pYv6^e>$:cީu -|ImS4v`(JYsF-sljj+B?h4~ 1ỻ>!jPG? ZK M~k| CG>2x0o4[sZ\öVjl&G6੿w3Ν#o?-xJ}sY/%nZKyKf`rkRNj/=hTk> g\K=I^X1keAp"5b#H/#K NJ_Ohm5y- e">F!A2Cx;֢Uk x.=Z3XpF[nUlR2|FKӣҴdM#`QR#ET@UU Yc&II% l=9Z-GDTVV`7ěPKk$ !rFs>1d(q^}2?*ψW€eu8-ç#gZ#;Ns^Ƽs^&!cۨ>p8׊j-Ke_UA ʹ+cbMΡ;33b]?7=z:WݱgRH' G$."Q2$F9= ~v[;Yc5Kk@W>l@7;rqWBRB2yW'/^W+fjvh՗;T,hGU ?x?zk`/|K 5{ɎB-, *WV? |3~ ic(wP YyA b?l4{_4U~0MwS=k=E1mݱ.r_4:upgiqsnIፄCi":k [?F9s}?֦zV9eM,/ugg )U$c^{-6: O[=3-ρCo _˧X@N|`g('pr3 UbI9鑓2OnnxY! HT1X4r#((d3T? {822N: 늮<1g9ǵO&=s לqY_l::Y=9zg?y AUXdr30=Vo ?qUFyz5i2y?@~]; Ny@3}s֪ːwq\~imOq%jOɧJx#L.`pT0jpu+TTɥvWf؈ar\~" P蝽]H <ө#<SNpI?jkLxoöw7р68,r ri|6W^6:( ڣZ4/&"c+TTlD)~G|L)~1=X|IZm@gpH㠪W?-(Av$my5,=?K#}kƚ1\_b# |'_113o1G5i5 &V`hx4g'WVӣ9zX0-0~k#6=%fQ ^9V\ɀF:䞹V^&Km]ƣϺ W\/ 1\ׇ#]Ӑ`"m`y2#W8(IM~\A_%S T+ӓ;gL^OzD2xO_\u[-{;?ԭ|~89#<>|_4|dyso_ |O*݌\i""m/ ,X_s[`r}N}k`dȠG5ooQ7CjIP9{t!*s%ژ\WZ}c?k_T G ^ZWӼGD72ܬ>cWU4{o@Pnۨ[Ii:znjFaiiZseiڅwvWKm,r#!@Ã@QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEE&?:QKkjt~ 5{~%XZ.I^'5 4a kMkSmt H̳4\"-#+;*S?~)~?࢟m&I> xkAm<b#ҦXoE|o bEʩj][iJRO ! O7k x--!]½P"ڈj+8[m HY?ਿ_k_Y~_$6"M}WL;}VQ#Zӽ#^X [/|fԵ_vil.?25-%[$<UqNyҸ={]6IqQ:AI8u*x' _ _ ᾡmfxs~־"\0-KTtHlRޤw,?~Q)mOu__Яψl|>S0[-^%$巷G  Rx_~x⧋7o4֝-P/>[}#NȈ%5fTq_x߶?uoWW &2iS2I7|W#4v1crT?FO +e7ExeCoOkkLj /-\ )'203A]N|Fj o=@: no[l) Joj;>7bR/FM"X Y0@ y||#|÷|!oyMt4K_.c^=i.ܰ^%xkeז4 aar$dy8S!WR@*9y~ϖ^ X^2N&="[ wSy{gso&V|JyGo?< e|xWӠ%͖FvGter*yuc | >߃gLQ&|C̳CoӉ_uͽsf{q g!dCOo||lծYO HeF!Ftmv*[ #l"x _Z^iNoh_Pjֶiis옛xbkkOZmnj+deI H՟iQ~J?C:N6gCTO#IAf=b ;}>֞ ï^4կv“\O$k'@yݹlN~?ki-Ŷ^#Ԯc^DkIR81E=2Ij͌wlw@Qهž _tkhqַo ˧o 9[/dROh:lz<? Zb28M#x HP18<#NRx {x}ϜgwP ^O@{w6;=|Ualt?R/;iV1EVvjwe4^ 0+ *؊(۱eYFgcFat'vDm@Xf+kxcigyVbyif* PNXw Mw&'}7|,Ax}@@mE 67TșVn/xsxHf퇛$.s*-7*)>k[$Œ.\; u|L`THߗegoB>"1^燡6j]vSϕ-|U&6R>2FbB H$澀gaf*X䌒O#?}߆)8UAAn~UjV8_fk%)֔?=>HP:07a(ӥQ ]F ͵mdoͶ|ɡ|Dj$@q^4.b@Aq?OcQ랜v58p$|\n.[|?ECE۫KG",708Cp0?i,cCrAC`y 6>m OHayEyu?[s; sNa ^@L#߯?BOr3Sn7_Wv(' ϔ^1~~_|>NCq`qڽmlgyyU@ǧ{~T{jUL+ħ85/%\XY 0?j-w*2my8sf >g!qұ4 )c׏j0.W>G7!̡7OIO?2|E'WeRpqr3=WϾ)'o2 m'V0I'+_:,7+B<сiƍT1rOL_YUjn^xU,*'OK3#U9 "NGs\>"0< 9N7(L~8:ҾngˆfHuN x}+ܗqX_ikf xM1|.^XZ%4|VZ>}7q`HYr8ʰgX7$ϯl QM{*IːJL"BGJso6( N"P\ny fOxF>.|mpj f8]F/+[۫܎G_D (8^0O_gh?+g |}C5?٧ĺܓK⟇z:KY][A4N3[oEo>{n6G4RH9uRH#8##k^7߈^_%<]_hy.݉V9Z~C(qtiOTkx+ m"Gl4_><m8w]:7b(5-1,^Y]綘U2B(((((((((((((((((((((((((((((5kI揪x_l}D5mcVԮ"3OvT)GrU $Zuux?xY~xmxP@ x2Esh焝jS_7Jwn3Gy.dEb mH<^f:ߏ%߅5[w:,#Zcl;2kMrN_%KNzwϨ5:nR5}b;.HE~>b lślrkҼ-HN0 p3=3޼x Hg`;*m[.n¿?idžYm[Oqj5ز& d|]!hSO Úķ:v%w:&`ct- O"$?6|E;|?|!? 6zvi6 d-ƧrSuKqs1ir5r:?O߳'o㧍iχ~zƱ -{_>{EȵbH`KY&|EWi.-l3]5CjP6RR7  3@xx2}#HCqSl(whnZFv1Yʶީ7w xSZM&aѼ;]4Vp")2K'8 #;3e'?~u\Dq,i>l9S%@kw:5凂47O u[)5{u2,+sԖRlIMܻSd1y#E)E~>Egy(Rn-^"6J!:uWa1s_? OxW aԵ7Ӡ[u7ElaRlyr8=w-hxsYOÞ#$ gN^,$s2u n|1,OocM O_Yb_2.a#IDQ#,f7K2HwS n`drL1VVʈ< R'>mI<[]vP\YGu: S)%` ~?s{k2[XIc ݋ۣ}^,FȂi0T!FOjҶiaimq=֟K14dQp܃seQڳevq&ϧ [+?f^IW:|pi|+kkuy[0tdXXtEZ/ ]fIMXU.-ǗnD0>:;h xexo4Fw?!$p_")G8cF+^{,Wflߛ}ׅ7ٵ<&SE˩F%;>X/6KwطB_ċ4yH95Zb'c˵`&v$r ~Al!v $+Y,0&IY1c$I{oہlɏ9ׇ%i 0'o9>Wq;48BOHǶz?E=1Q4}s{ЎHZOoPhmf{G1\u~]`{kL~R=O^z=3Y0յxװq֨C=3;z ّy hc OU8>{Vr-QJ_s=>/ycp9un:{,@9XV<mfMIC`V(tY^$az{VHcUb@ o^}k1O\}GWhg>:{ׯ 8?9r<>&j j]l|i⯇\9H'U>u`r2Pg9s鮩'JF>+I8.RRwq@;pk첼Z|wv_Ү˯cĞ ܱ-5)6ua r>ecW}۽Fgb^9闋y؀n'Е cLJR V_V*kirxzbquwxѓ(wGڟE)&7 [f8[|9&wo 7/V,6?^C'IfAo{^ѼU'iZNhzsci7vgqkI6RC,ƷgwI%4(:p|$w Qq7/%Ag}[VG8-n'mkY[ypm2fGMT5%/zId8ʘ,ƃR.G[EҊ<(((((((((((((((((((((((( +߲_bß?i^09⟋|ANF+PԺf$x#Wu¿[>|BŤVtK^U& zs_=Jf7Է&1ݰxgHPh3b`p [ ^дW>\`կx 0}w|c?B0[-:p$q//_i9eVh?lF\uv TH2+[m`ľ)~1|Sxg BYI h3v]R|/5EiyTy5Qk$潺r^kWwcFv$_ m}{~ip'4=YisQKf;`^;)%D_u}JWn ]l3PHx{Kxߕ[3I 1wf,ıf>xR%Z:Eo5ʲ_1 +fzt>ZF3vF(#EFeCzU5<Ą8OZ׉o|ey iY[͎$aCo K&5>D25h UvYdw`ɴ.XŗH۷a"#8`E Q0%4#`UPG }i]9tH/F3(KHJЉ w['G^~[P8%(I.@C=b9mZ?etr-uk$qTdrru}mp-|'+yi^ ٢}2 Ǹwvy"D( Vʵ}QMW#;%ĮO+Ec$Z?3~>|Ѽ;:AxsLQlmn)#LJ-s9\g;k{H4Ăho GRL][[kXP(ȕ&e8EE p4K1|lc%n%ia.G*t?,b*4Xj's}XA'-JeI]P5? ju\ı_j{ik,Y& s"7E I/A\v3ij^4 [C&h&0҅p54uߋ_u;km[Z}-Ok[mhMݛxL 9;|gi UYmIRC7vK*kq2ˑ#xrq'NhTV(=\iTHӓwvv^ſe}7}=*Ht KI,9O*!{򊇍$Y!w+y?ி ;/")IT;呯Ur2d 7Zm'SkUU[Jc0$ ߳m4Msx;A^js5iM*9x*<4ENx.ἷc._%7+J"nv{v]̱4`d4#?wXM*vmݿg"YOܭ},}h%\M+# Ix{?cx4ڭuڶc.AW>M#IQz߅gU.,Oyׯ$GoZ#XvT^ i OAGCʔl0ȭ|/ >(eجu\O U8nӌ\yvG\*'1tM7{^-/oF4 {;VZA#kxX$/ 1y+D1R xM0j}YYKKF^),53Y++_w״+2PQ6~-ojk,+2%P21/mzh5Mc]֎|=/H,E鍐LYB=i's#8z*WZ\WZiE<,+ueK +Rv=E?o%-&j֓uk=;No0p<"Hbv,#Eú?mSXbdT I9Q*X_2t84 趑iz؛kqh|oFWkX`\!ec׈(=?F,DuMIssv_3s>jޖyMࠓtU-mmzO q}a8w&+fY>|hR;*ɵm^2 *5& k:]]Am39 Hi l3|;a ;T&N#'N|' 7ZQݢY-"ҌۖfѴՒ_б$ɂY=3M4DTFм7XL6H5ۻZ/V?܏Wѷ?L–u֥E j+J>ﴛmE[m2 'E%U@^D?N0>ۯAVA2[{[v_ lۿ8G_J!^G=yqԡ@ ЊSmCg!y}E8'u?O?~T=>V23?xM רqz'}?%(Rx>>֘S*cG|>vh-N\sqxQuZFpFsHȎ;CѣSo;zdx\I/$+.b du=_A펙hԳIpxh<:3o\A= >j19sֽ۟F${q<W؎}>5KY?~a`Sm<_]W3G9믝|afjF^çGN}q[$d$}ku\Rݎd>~2T%-.cJ'J*moo?5' w%gv~ ?_ĶM_^|? |L`k-c&hb[9#AWX_C+>5 |KԵ;㖥|Ml>xپɥ|S,6TZl&Px?M'm$F_EWYQ@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@?}5*ui:n^jgPy].xLӯEb_i#[x u!ǎ~]|Hcۆ> |vqH/b]h,׋eć˖;xf'QR ;;F߷:(Ew7C|Dj*VotYL#̀p:c?xG !tdڶ,MݴLP<2*uf$nC~?_OU^]/>0ZGw)/Ѱsy-zE̠'YOomS⏁eՏ|*QqN6shMhjV E_:4CUj/7}S_u/.j^!6g Nh0_黾:`b[&5ϩ9xkC?o_~:~__xKĺ|>NPjRl1km\<b7W  *%վ#z[_5hL<wRΥ##Y%zf4(c6?6_#|} |?a P;o!tSdiGRП [O4k$"bz k^6 xRKdY!?;' @jk<7㿆Ty1 J @GL&I I4* 4Q1?o߈ F-tɟY hdY%mr^ 8f㗇3+[Loq[DZ4$nY$I'='k6y{uwxN/q%i)k?:RF;ejoPM}ffYlR3: fDQ"0O_j~$^Ց#ҵەPϨW1j2wCQaLog g=Ng tTF+ݒߗ帬ʷA7yJO1]ܞ˹พTЮ$Pd}FKxfohkIl.#V8㴉;I8؏!uهNorxv,Q'|iRFk'c nWO:LNxgKD!4 .8ګ*co5Nm; ԣ&j6t *%*7%cwK X?$g<c}F_м1o,޵j7^i:]q4~6BG_4qwе3ㇹ𧌼9uy/GTn_nV\uA{hq]\o dYT+ß12q&Ifp8?m$ێK/o`,-ohXEOM{ioqXm/G `][ l0ySu\|%Gq,E;=n|իZU1jV&͆ &xkifp[?R`~ _RMV)xLy=I_KYqpl^&\{.&?[D-oF-m.<6?u=,RE=+*O*F?c6Ayx:HM? ӵ-kL^k?-ܡKnex\ӞO]O~ZGH@$f&HУa4"PB2`Ec#'&uAoo5k A5 $ ȏs,mdpLp+<{V5ߏ_E/kEӤdH$|Rׯ$/.Kj#ybA@9> ?'~"_#< 5߂af;A\+n_?3%(3:QƭK\mt;jv?SWfKaH!6s{q%ͅ[o[Ao5HӂeY7^y ~/ =gu˛-#N2q:쑴a\\lM1SCثY/2=Υై|idž>MZV*Vmc]OF"knG&'4+BrlI5RI4{(k]qU9ES\ܾM}~f%?doN-ċ|@piEqH%E2E, _&^*@״h4KO,.T0V{[xX < cQgO9->`Iob21_;)K~x?xﯵ_ \2H8څ#q3W1Z|udTQEEY%e0FhP(⬢moVօ";NӵR{yNddl3sxvKD^;!pxϵ~axܹ ZIJF䵯t /R3.N0H|EEbrTc'9m*a(x+.jTI6epFVH~1CDlj!ܓk6a%:Gh%2r;.r+u͎m֟bҼ9p{I5!\_~@|Z4{4 [BB0F@\Lj5-{%9!mtc#3\}q^gR,;um5cڜo0.Catx5š5f7hWTtEY6T QY Wu-eo i G#2i-`H_wvn ߰do%ڼ:/koQe%[~ҽj5LڭfΒ;S:hЍ X|+Ig~6V_C\|2:lWAV?>׿~6x~//<#g\xMJ޾gsoі%aZO+(Si5DmnCLg׽Etc'OAc؞@pk q3UۢZy$_pQ>jEROO~GD_N2@<u}qma*v_13')'q'>8zq ~Q:?L?KxA8F?ʶVѲ8;Un:N{gQcXȧ/>a9OF`x ?ֺ`Gj6'8R^C\QǤJPx?xg$'1Zo+tSV)-VDX^1}]e*9 zg/=ךV$r+*I=>5 D.-k? ܦ:XNnI>ׅad=:v~_ZC nKOkź=v[ŗ_S7cӵ ~Z;gqcZǞY10뎜ҿUPt5^Nۯ{Xm8Qij?ۆxn.DtYa %eeee%X0 jj>_+$MY>4ڗM{]7?t/Mv 4BL>-Rv_!_SH#׏-J- (9(((+s1 :_5k=S[Q-FO!fmf V¬>ҖXI"$i$F q,H@D $J ]⏏׵h-K+xZ"͹H!+os/eÿ {onpjD-33b.UV9یqL'>WO Z? YZ@obkkr,u+; q$'gtψ[\^>8ҦNJm,Fw^ Ho18GUHݗk" h<׎Ҽ_\>4'\ռ% v熼QoBl%Y2K{PA`T@?:<X4ۓ|=U3AN)fZ-EK8%-PH-qh(((((((((((((((((((G~~վ>!O)nbӭ+gq麅ϣQK4V$eͱO:E G<0;~~_|b:/Wm6]0މmHlK]W[u[?d?Pr^Ӯc֣F W=iizPˮOc7߄rQ+ IsieB/ilXbs\ьo(ii$]=yu>YNתPvOϛ_$~ֿpǟ/M|3o w.c<ֻ*j'!q(Bsh$|Y&;3P:a~8>QQ %(Fv/}n_PBcjC&׌yG⾔lp"J8G?cb}ĊqUQHquW:G;@y5+ᶶ $$3rz5],7T_;6QRE:(pjv7_W x%C"FrH+kf[/Y+HRmF qa$SOߍkO O]W_S*6CN#GG¿>4coiR'Ӗܶ1}̳;UmhE6m|GROMN$9*-~?;hjJ-9u6%᳌d_>+]?g/.u:׈6TΨI-Jac|ge;7Opo7yGr|I◸]#8?\'/2L$nYAsx-;FϔPkȳNUINiӕi&}576ƫ*|vQZ';#dh_ُq,]~"xpc\>,1_G|W5$3FWǃnM74V~]0r5~0h?m5IIEsxuHIldW2As^wQtt'!vo_eʑҽj[KHUZQImغ VJQצɮh?ਞYᗆ9#MS_ysͳ<5Xd8Ŀ)[k>o{1>H5 a,g^ZŸ}Eei[q-(eYƫ݋Q'oGs4r)7n%LZ}:Ď'w=#eOrT匴0!I|梛v=Xe:15e?~Fx:Eψ_[ݐ$ Yx ]/{$tF|c5CXhWWʶ1}\>}k-Ao۠,Ti{#Py>a %SyyIus,98j+~H9Itn˻?5k1-a|lsvsXo:hѰ}Aod,ӂ@$_7dJCz2wq9Z[/!#P9u+kݫúE`D@$g稯mBօd$ $c6#;98_SX:15+;Ԕov|6®p8q8Q`pԥJɨ*.XUznNmur}i`IytպG 8 ggI58M9_/LL/j,5֩+ԕx*ھ4z#\w~s  dRIK4L$Q5W񻋌v?W"Nc5$4::4jq#SLE^m nnֹⱐ+Xʂɟo߹s`[SPN@=p3;Bi6=89OnigۄNc$kѣˉhaJvim!^Í1C8#oJx D::vW>uS:gߠ[I_)$u>H$>X} FdWzoHzW ]?=seQq*)UN_s˝8ad gr;b,㧧^^hE7 ׮A㟯J 4IQ=;c+ȭYnyNb? ^Az,|g:zc{hyg?=sLjB[&}g}]Gn?CT99DJәy9yYvRy8@۱y{8 <+&鰧x==k$҅.Cq:;uW zzNa`}70;s^6췺>#:p˻+԰Ks󁟼rqzWo͞x'J5y8Oҽ5{LW$jK~Ov=kϵXV$@mD}ぜuy#>;'U#'aI>G.{y6h"9?Lx)WO;z}xϯq}{b_.8$qP̺7ψ|}=\cOúƒ4Hچ$Nkol1Z_ l~ޟÏ/ldG|*o CZ 7<̳[ˀ67ַILl]*?WX]kMՕoe(e,m pU_>1x?g|lqC=^-5=3BAD6_V=Qݞ4MS#ӧ^ҿͻ UCs#HRl>xV9eK/..Fss&Vԃ)P`ԡT]_\a092HΜ.XG5"Y-SNݮ>˃jWxzP/?4={5?9LV&7 .𵔳N+Ool[8 Bm5x4;hC\C!a~`k9ahЈ4l# 27]d圖9]!Ff-_ҿ3\BQV3BB =n,A:N1~zj0-};I  4 u Ƙ^Bdi5L$s~bf Vvo/`c{X̕؀FݎH#E%=z6/E .Kd`%uQHlz6+W_QN܅y;Ex(ln6M=lȾ;+n6#N(/8p0{^7J_NCnqI#u9v$Cy둺RmN\5+|5PGڋP> N}H9p^2&FMZXJ9^sq8]vVKKmx.>%gUXկY9t;m**bJX.Âo99uZ[υa qgVJO(aN0G;GBxz*MF֌URyڤhڪr{ݻrO 21Gq8'U.{v.k״hW XpGkZmS.NZEG N*OK=ǒUkhxΫu棏+hut0\lgp:z {=g$lT)9 9?¸ Ipm?x^HUU$k1.Y.[upz&wrII#=94'kQ9$m<dc` [BJ7zt泂M_Go- ]㞸$+5[V؁P8<T =|Kfh=@קa\\ɺ:/v>|bKy90G^>&Yʁ: bҚƗ,b2X =kD W!p:c+\Ds7s>YE0Hс={W^3hnpwHr:Vmvlp2{z541%,2!9Z !Tb+pՌM>ݾw?؛|N~ x`~9 Q &Vk.2fXu\1_Fo|&y7^mi Q妕VB!^ey _q㌂A};řg4a Wj>xI/I?G2x)[-Bn?V嵥)srHN8ֵ;'3VX\~5X[o `F:{s~uӏ3_֧[4t?+9둞slk}6wTm7s&rA8鑴ʽ:c d5~QļBK#|,Q`~\矽kۼ=c LB co?>q5xOIB9=q⾝/;d~}[~nXo^ڷ-<{Etl8=l~3\GG⾣U@ 3zq}+9T- 0#OzBV.-qRibk @.| $8ٻ0T;~uG/Àst:d\FDzAgvU6pG2ʽhmu?35Ձo&s_ǼyjH8zEK&#QBr1<[8J]j 3>nڊcvB}~UXYG6Iu!~p01/Ssx[w\pO^9_^\MU39:zZǻrBsOj{u럾 k*.Nj8Ϩyp;n#{Xk]s4p;'N:$ݏpڀ؎z'>j[ʞ8+9ݎA`} Ǟjp>n 烟ZMf-"r9Osz~sx99>+qɓpג8?*<O;~1+7~jh^;g ա{{z6s#5VXd'^_4ۓs p}ҿDȱ-8kf*d.O]k?/ڣ3(Ӿ,K51{ ѼsmA-]+?z~jN[e=HbWd؏qcO~$%iG>isΗ߉0Y>EUd#'T0@ѩ˞Gn&׫F[ӓAEUQ@Q@_ wq&-/?7ټSÚ#(;]#8?@G7 q_яU{c- _SN]v9#tn18ۅ1~C1}?}!͜Fy]pO#3n2@NWck00,@oAQ`A?p:W3˽:z*~nzH?73x-&~j3Ѿ< b.<u5QK. zۙ=~_G1mq4ۆO|y׸i4mEU~?SeXtDPFA}ݤ}M:+Bz4/&eTU?iUҵݢDo3jcUO6t}.Nt[kXm* 4RN˜Ԟ}}MUtPn3GNN›Հa*z_:&5Eprz^WKGRVר!RFWw[y&lBIyElbevIP$yp2GlUE{-6>Qs˃EA-p0H*9ָuғi+$MF:˷uos$k"*+aK(^:~Z2k #n r38oMxȹb@+;y<iRr8R0`pw}kJXr"pNN[ϵU'''fkOFe:(r7@փ?-V8ǽg4]EFLJ oqYՃc\];G髕qp~ 7{k˽+F32Aq=^OIqvI=z6 ƾoJ:mqRq;ָ.,R.5k:t厾i%gsʲw6a4k+ ^-SÚ)%Z;Òtg.mr2?=ǰ3ׯwŗ_+Z?|9kz'جNKWu*yu!C+<}o/|}h@5(gIyZk73隘6-&rK>0gzsR4.=vqf5^/ ͬVKVy r˕kpڲt[he8+Ңu8՜MƜݺ> Ɂ8둷'_Ix?NVhCv댟^ 0NA=bTh~#};Tԥ:c)R7'}%}.6 $m_bx#Èz/ӚjLgf;Wp#y<vd\=qNk̓ ({OO秊y"ĥ6~["b}1֯W-mUcwN}ҪhpY2ʧ#p8[`uϽ~ TUG>oqغQծB0*ѩgO\BpIn0O=ΡǓ&zl'קz֥8-4.**SMu}F#$^4_;XgOO׽}ŏlu,z#sO10C|n0{+SGy~> fO_\t8'+F屃I9;7ҥ̯c98q9 ?7Q{@'V}jb s{WW|00v]6 sm^xߐχx)Q?QNU_? ٭[+)_?C袊>h((n菄w3ywΔy~;x4ǃ|wP4SF,B/xGHb5#'= G_]|jًI_x1\DǧjZ=Sۇk4&>G?x>.ҮkyxOXYaq玴 gӎvz8qz{GI w韥z y=yG4uÆH=^Km>su9#jxHڀ5{"$c F$I: A#z} ߜspq5zPC 3Ϲ!C? <~-;)XGֱk=[)",pד/ sMχA:o[=b7S`@`ѐ@ ib sr>=kyPl~ ~_boпf>+{e<7čf\K};׺radqG`R((((((((((((((((+# Ӧ|OnNOnv&~I;XOWoOm?h}]K #l6K'wb O.9<2G pci|PC>C?/~\Ix IO.Yo< @d'Prbxlfc> E6w^%-V0:^]:+bOM|yh!J"XYNsq_ RxUJ.ު׾9.XGsa^[Ywz[."[Cl +0>S=!|:YռcEUF0zQO7̣ZT(75ukwtԨ<VC) ocwxöWVB]. LH&H tbwrMQB@c}fDAB kMժ>T?MϙP˱3EU()Kڟ?ʹ" bCk/{2lwQcܟ'RIܤ3Z#Iw'^JcPyonor_8U-KZ4KJOC-ŽI5Ԉ K0ڟ ᰸y*Σi5^xUYxs /N: oaɳq``O( WO4d}@>,vM84Y85՟߇%\m}w.As4%N )&.kb*Z[j?>*g,2%ozR_|}B5{ 5k pg~_xৄld&Mi0˩ʸ!29Z|vxW >>Ω\V$>&i')¹ k|eĿ_;1CްӆzqvC 93Yœe}6פTUzs#jӋVim4s⍇oG=ωu3G2}+C;^sǎi٫E{4vw0nׅG%ʒ?uw@?ݔ~9~5엶z.`rpK`.Ns\>w-gͮHWv?)cڽ//5Mw%%R{YMۧݯ?3_q࿄#>Uֹq~HM:.$ RW61x8`\52>vs.Eߊc!co~QwxO<t#?}ScY V.f\F瀵Rpxu m[EU=$wsjOSn֦i~<_Ft9U1I>*#56s-޵By$s3IR a\4S[(p5…^:Y=5ݭw|۫4P#N۳Mzze1;JAFH-1=?h cfpm׫xo.@s:޼C~ /0$!pGO3zvr&ZNͧg+#ybr7R3qz[ FRvg+-C? g[=z ޵|ٯip1)Ll#ue +S_N,L[Qj2e\1Ej'bV03 x (ca>UTgd[ߪ??gcjr* \jN [rud2sǿoֻ"\:ws+l{zvm݄\c?~]BII?47Nk_}A݃I=E}=૰ #=pGNzʾ ''8v89|V>qgZSPN _^'lv#/_A9.~M?G9E5ÞÏ\ǵu`/TOp9^gZ17z9Ǩ # 8EJ[ugJ==7׮AgFO8?Fl #ğ]~vY9=ys;12};+U.4oü`N> W?##9>=s^}5 j>b9Ө$d{`W <]HpG$Oo|ǭp?=Ԝg>ܟ^-<U,1/z {?p: {`vڋw<@Cׁןo t@N=sU?"j;O]{6U:~u( 1a\,Ҽ$pzӮFW}VZit֏-ӹ!uοk t~b=jA?^<K啯>J{h5(tYX462e:,'YN1ӂ:rH.~7O(ߏ_\Y}h:mSRMoGpȈ鴝^Ί~T Ij~%*8It{ERu-_OtۈJPsg{\DѼFz®׮~|QEQEʿ:W {k⭏&)ykUѼ)FX6=&}+/kV6R'-̄]}?~=+xcLÿԼ+ ]Xj>#$˕@ $C8Oed ^vdaGQ99{O {{ -FfCGčkU?g̒YWmti|+P-5Kkoύ k2!1ܡA0zhK?<#Cf{}w#az y_+i(/s>ldOһ=ss@Ap[R~Uy( 2p8<:y zx| {{th7G;K`LW9l[ smq+T_Ži_|*#HU2 KXI&]G6r28MjHG< ^_=nR21^N x{^5 DEbemf CM Y!R z+hڗ4'oo q'-r啼GDkC5-*?:m_NcndD9JZ( ( ( ( ( ( ( ( ( ( ( ( ( +C j^: UM-B >[epWAF_ \j^2|?VmrD;FUxP:O4Э@?o@>$'>&o:ޮ#a@^Va#""Ugr+G3]j& eMȚKsnZcr%/j3K?YY5xUֵ9Y$IoY#;`$qdtF08Q;@?hi"5!,s?zׁ&meO.[ Km`>x['#Wc#:.fY$;f,y$5;"Q9'#Ө$A@ xq OQzU)5h>LD(w3NA9qp8+dtP{/0GxG^yp, 1a36MWj`8n~5:Π>'g0O+ϊKx3*=ߌ |UHBvZG]wKw>rMjǼ_wxqM(/ݨstq[I" }{>E)M|a(Wmn м?Bd.0lBW"ʔNG + _.]M#Ð[Y2*4灀Zb.ꐀk1YŻwfOj9f9v ft30rPWBqzu];?$Ox_wIJ,D^=*lܐD_|"MI&'y.$O$?'Z񾓠O|CwmA+iems!Bp>fŻxBExwl];N8*F{zW⸳3 ,Ny;'k5/ hկ*[S_|1[[H9l-.7(˘U@u_>5KsƂvndm'M75ڗ?~#U~!xXo!t1a n8B3ޱ[B&{( eQjs_\JbVn-n{'c|GK*Jh~Z?,W%ncmm`jzRÓ`(:W_WE.a6+ix2iEg̓<a_W<9GN80X"A'W$Zs u!`"F7Ԯ8*SҿFH[\.px;|\q_R+\ͬ)u>emgL]6 yeڪp 譗ckپyW"H[ zT0xZ^<݇ީo'>|ua7r;g2{ye;pp{SfψD4PlCQF<9oX?$SSL퍬v#j޺^}t8l+Q)IayKUkٵ?FmR_u1T?ٿޕת?˞(c ~|6c'#ɷۑs\"Z y?k`0?3I۝gOGƢBI³ dOĂUӬwݙaIz2)rºy}*VRpOܩ~g<-"ruvm_}h4m1i,!B@#=}hOi $0Z >@A5XʔD3GjyiGAuC\~o7+H%j+S]ȹf=nW8}B]XB9ǡ'Y3 B0CQQ.zN|_C+D#,[{|ɯX1pr8~39(bVr'kt[;laM[;VtKi7=|Wm*_-aY#Uݵ 8Gp2H+w@ObA^-ERqG?t1 3\uE\|,#i?9~.i]cN{~U<7?)\b).><O|)Vd<8'@NϜ#ql3ce'.i#kx>+=ҿQ碞[2 8OQ~p0qv>ˤx`JA@t;s<_gϹb-ӣ? jWW}ursqwy$(l'=W̓(cog}{\FJy2U}ߡ'ʝjmk}CY!'2 0~~'e,rs5x2$|R0~;#w|fe:IJ?8#VͭnlR6*I$u"d}Mmk$=:dkʵKziJ'v 'q޹siyνJ0ß bwC*NwA9緮+'8$@9No`HP^z!~g繦#I&敏}&7AOLwkdxqǾH>¼WN_>kL$,~rFi<|UNmOCׅSɩY.zDᇈ'ݍK]^h7`3 WUD|[&^K]#-p_'wQkO2cU⽣0(((_EqBxJſxdDU[_Hswo~0%OD񆄌CkMD4#KGIkړZeCJ?؋mKJԡ_ii~ 5n++Z^[K (Ό/Dsty5z_C<Yo"$khrcb_`/|+.&|Rߥs^1E c[Pkʹ=Os:rKߎx׌n>a7p@JGA{E a8$s9Q$bpT8+5? bgnz׎0.7Hq>Rկ5]VKM6hE3\~c*yrZ>Oj;"[ZȎN&*xekwc8Icp7n1A_zG_T4m_N_.[NRUvE߃s_G2fTs*0j2I8-bM+[G?MZJ9ź$٩5fY-^?jҤԄlͫ:0' Zvq^cb*[i֑̾wA!UTN0zc=1\$]|1cZYE :ig%®Ⱥ `9[Ve*G'w{:xGN.=7m;m*"mLc*0RAO!,O9<תxo4)!VZ?mt .~ܔ-0œF1n>zMwVN&Q$f,vM%bA\mSd?Z?G$F$F;7Nïo׽t^:ֽ\dp4:5&nrQ/%k|=vvy=-<湭Oe sJFcܑ<5>&#(' 2err|y~MHae+qt> I\ȓr#AƾԴ頋nۑwx?7ǭy6hLCNv:}+D嶞qYW> c'p|0=ҩs <ф+O/CuO3e8$㷯5溶[$ I؜*/u8s9:yJT''{GN!ϵxt{;??.MrZyͻ/؞X9nqKOw7 {0ֹ۞''ާ@lqyrw_{XrrsG\q%uo5' q  N8_ƹݒq u7'N:zۛ9x:4kGcRĒ3rrs=kGC}j̸wq鍠~۹22}OIsg9 k~pGB:+ӡَ*ɽ {@sӯ\8O֭Ü6I'8~rqӞ&Zßxik`ퟧ8?θAV'\qxn\8;3P;G${4 6į{_/s'?)G\g*N\G\=cWUOC\{kfN:gq㞟7{Xm}v?6{O]'Wv̸'EFx$gyF/d^p#'I+vN@z|]q={Fs|W&7$H~uv,S]~#H3`ʽ[ŒJCzc#)'ӹtޜN3ƾ-MAimCK*OeT5M7^ntkCԬStSLO6 7P$lU+f|?fN;9=wþ-mWD4}B6W!9dX_&oGv[Kv04#b+k?x'sxV}BbXst7W~-xſ $cF|wO.,m-]еY, >&+l2 -#8#:WiZ I# gڿI?Ks woxᖆ/?k>| FRO>O3^5Λ${ic7m^\K'88$w޹P0+я$2O{߅u F%y_A^)^lq{{qҾo $d/͍p?&pԒLA玤q'+-l^Dh< `灏5 ][Xcz{/ 0ng 199㷚*Ht@pqqJEП/⇈e]5dž|OoIX%uEe.!i"Y';CQEew8=3ͪ"6 $ ?]$g/G~њm6H~|\6se!3h;Fk G k]\]ƝivYK%se}iq+xHexՁf!6_ۣzoQ| ҭ-|O<< 武hxCaD]H}3((((((((? bojI>/w/ >bo(ܦм-uGr^0vjGˏAh5;7~*^`<34{+x@D8lC MC^υPaȶдhJuL;xހ7BZmMUHQ{{WxmHTsOJ/,2:Z_gt 8}V)@CW?b+6Ny1Ӂӽ|W|]X5$=x {ToKxo~ !,|07 A"k)-#$_O, }ⱦXcr:緭}w;pA|gp8\ߏr־Jbaס>~]yl$qhkpxy<};'RLèbr88_5 1あpy=4/?uGxoZ>/=tidv)ڍ+IWuFwm8Mv@z%vwzߏe!~_'{q x>bi(kxV9̡G=yI өyu Gד,tmݨ̤b6DH!C(ߪ fx2k #Eʶb-@aSL\']4o-'e:%3OTO ij:! N/_ZM OLҞ= Z}z~ڨKUC H|D%9?KK%TUUx+}b٣MBیИn9 ŘN1|o(\*U#u|=-bk`+a{?jdmi+;3szlvshVڝ.6Lao*H#Í'K>LvpƆ!BcMx`bE,-B}/Lds:ھ=,;zu } IG e^ѳϬ Ssܟ7/VIFeA9Ru̥V3)#ˊ|ssY)e y+#yz e5ө+eP">XRM_V’n<~ 1=G:޷l#eߍ܁I]"]rTqX[,pr O@zB\koSޤ8iQӧȳvftR]0y?t_ܪNq E\QGXc$z9)ºkUѴȥQԧK{H-mY;bq*(,BmBxu$•%qzcN9WTj1NRm$onfä!ۀ<y$ߊM{NՏs.\gzSLXdI!p.xr AA]Al[#bI=O?eҥIF7oNΪ>Ik5gOlPϼqz~&-R;"c7ӹ&k=Kd8?0As|WXhWcOan-Jeo#u%ٚHLϽeɣm,E=Jz^ PJcyO+'X&3PP:y3UdټD;~['(/">es~$Zf9gV$CyfCFH1^ʥ,#H$h .F|5zZZ[H[[[Jz+42)7B>ߋ{g8,3 *2}Y?N9Y|Ix ]ZQnX\|}Zdo62H'x@'qI~U^==:ԫ7>G?~Né:op@zwxu 9}h9uJGA#8[³K]WvXDZ*19ǡ[ڷg<smX%p;,^IINsc==%sg*b:y<^5܇0>=m7Adgt=2['ۊ̚[`q܁sԫ}/_ynKH2~ 27w7Xr3z=+<8$:T(5R:qW_֚uu9 \c\d̀r>]]c5uqy0I5Nc1ڿQ7J2I#Ȯ~$'{ *}Hsߊ?RskЧJc##vI$l9kpy3Msq%8b˫$98+ѥJn]^!q, 9$~&3tl ?JytFH$ qj#ӣO__>1/z߁Rr29#ҹ[ GQUˎ89{z^pGSOz)i7}q: F}@k'=A#sZ9$^snH=.vNH>~_Zp~m~-1u.}r9#{ 5) q~J5 =qמ=Mp/c9ϧl^au;i%w r ЀrH;OOj]vsu8 ^\?:>]~oN=OS_Mߡc~iݲ @f?E|c|M8v)rFN?g&DGܞk9+qp?b'{}~h-JU8@kؿb?w/zok鶾%eyxb)$Լ/Rȱ,wB7ݯ0b' =rH#zf[ $u2=9p8#%O~̾1,?g? R(.-uků }el$,x ِ1Uo߂_V'[o:+-yz)ŝͧ#HR"Fvl*bTwK].OAf}-)I d׋,('Py pC1@cXv{iX]&"p$vI?2UZ'σ7+:^*|)o=giCˎVM\GN F+3O~|(XzWOH1'o }kh 4py:ۋ 2Ae`lg95_/g}i#}F O~{֕bk;-0 !i z%!T_ p?5ApE NxkCRʚ4H5(w #rM4 H,Qy$G "*)$9 (_ U ڮ]o׋t"\ 4xGfl$O^Zhҁ|B=9eۮ*|AHk j3ެmgq>!ǹw!/>cHƣkOz"7M'W4Z6#ƥtt`xU!d?Ж v2󯬼7rBm p@xnȎ$EP<լ/n2ps?MaMQ 81tԟvVXWnG\F9U[Eg᳑n3ץyVaB`i xN`UJ`d:kݵ! g$~q^K\,h%xSmu#ka?lC ?'"xV{߅>!iiOhGkH_҇((((((3?P~~|; ;x| yVy|i]  JV(2R?ƾ/qNgew.hcqY+,'x l̿ǯ|W-ď~$Լa^ɩk3\^]\¢F" 1ƱƊ1x^!wPW|[ϭx_euBI#bdqEpE"jr@s g. MÆ3ھ^K_8 n,@xׯ~ 4E;ǰ<z 59H|vF=8:P$\K$d ׁk_vo2'89In6Ԭ䘐1'q*={q^5ij1y$fII$cjϊNY~N}H+Or1#r889'@$@'8?Hpp =s}h;S0DbCHkٓ44#?d?ǃųm.J`njYtHQ ay#hXIx$&c6}&@7sNPs @9r@?6ۿ$zsq~U*ݸy˛m<7cU G<`G١vFнS]N|-O/jv5o 1&ywh^+PqF*$Rd?gW=iֶIhFv^4[Ӧ:Yk?|a|K-'nΗ_j7Dȍ~0Oxs%yNtM>riDsrrk[hXUp' l?J-u* *9=ڸRSo{:ce|Igxf$ˑ@xp;]kh[ܶ3MbFՐASxOv* o+?.{9m!c  $@ 9FqϮ1g}>cIm{so# 's/cN:#1gP8lʑ{WҿmPkrd)䝼 x_:j1C*LDT9\\^ \~-sJMF$IRDS#8?\ W᷅a'( w _$x[[[,P"@pL+/^|1[E[ ƥ `s  ^6Q*i_}jzԡ)Ú뢷?aq*+Hc=s_G麌񥽷;W L|=ɨK$7ێ rs٫1\Gr۱Ƿ{kgҔeG峲OC Uq|isIFEiZ?ƺ巃]U "2I>Ͻ! ب}rO޵T+OJMԭ:IV;8'; x?0sq>;^;@$ӼIiw%L?i+9)HF z7/ឃ3s߰- @g$pb)ЇIr׼ef; ,N*ikBQZM&o؇~xf-cKhW>L\a}FY.n$.Iۂpؾ=2fuy`I+)$ǹn>kӺF=62zڹK7!^c*JR~P8?rZ[omSIBM_|,=U40K"XI]~]QN $ 8?\3+Hw "RHS8dt?qy62XN\4*NݷRUZ%3IaWxviCP@##`ھ xV`ANp{;^od22xcxJVУ onT*sSM:xif]b` -4'ӑ_PJh#*@$cuWxI[ D81{ZӒPmsqWe2 BˎseL59%3a1|M4&c"gi8gPGtZi{ ڔbW%']Ɉi[?(/d_R 2Iׯ> _?f~ {4]2KɹL摺33w oK(!O3ʾKF&«ߦ\4`yIN4mgʄ xWH,5&`atzeXZ}Ki'G?Ljp&q ڋҶ'=R|˾/<sS rc\]c/=9Iyqq\uw.Ғc}d>9{fuۿ^qy,c=`jO͓c/yk&cZq$N~c^8< >ÿpIP9{jRz'r(F<'=yPێ=z1tw;qNJUJ2vmR5-!uֲg@p~S 9YFIPs}y?et~bx8ߩ?cO |ZJ_~{'dg#:99:cԞCd;g;c5qt9;;=x]Tmd'-<xܓCsAQ]䎀9`\݌݂Nz^*I)Z_xAH==i< N^:rE`]]g'pv=ztF+oVur $=\ynq<_W|Xt~}}>]d TnrmrǡӮqfrp Km t=*Ďq~ $$@q0<5j9p@=??ʯ_ޅϿB89^y_'9@%?wzq^c^z5_a'<8ԯA r Aǭsec<}+ļNDH9 _Pz Jr@sH85dH:R=(_& PFaw1x#Es^m1)o5xYw,6W๟|o |)M vHԼ[ u-@[9i.`1`hs ʹsm:<3*I8u_%g$GK V2Hn*H€?' :WZW`+GOjk[X{mUYcq7pD o %i%H0Ð$2RA'(|M/ _{kˢ _ڏɪ\;5,(/'ٚ[ h \$>((((/Ox{\_uKMþүsWEei:]̇2c' '>`k~_u+XMz͢ *9`q_~jpA_b:*h F4H\$|_s3-r屍ĂsպWMƚ=#=>'l8O<' afk9YyUb0X]7t rTǨ&9c_sxVԞJx>ѿ@gF;J\~?9O?N}zKEWOE_l{֞$=kCEfڏy1@僒~O_ٮs3 @??໿NXD0%¤jz*3|kǼ_,w+O?3?c^DM]VZZ4KIw:!Iv 1 qڨͥ@co##gCVⷃ_W5[ꖺfoq{pZH^{k tVVd;3叿A:-) }: V!A#{zZr(`01qߞ3UU'ԎO?^Y:0n\RIY;nx E^ƉWᎃr:jڃAh]GX} rzO(~+G⮓cIY\/5*f^9F2"C&&W"38ĜI@N8?x_ ̄sz tPjYN%|U_'1i)#cn6WkWEo&3${]b=??krΫ{Dhdөƻ7k8a>ưt䮞;>g"1X#$m9^-8h : fW8ʒnǶ+t7ϊWZ3W.|HY7`s`רiiOh%G]_k*%m$qs /STI!d [,k ${HHdEps־L#;\* $1}cD'_IybA 2 `q_f5cʥoag5&ٮ]}w6.T#gQFmw;w,cB#Pd sEl)L!:qӮxׇ.$wG sWXF$"gdQUimYki~uRrR^s# )#OP'+ZO2 8ϧYDw0d^ҽRE.%ss?z挞?ݧkfZkAk4nH㈰%rFH2?j:^X1qG.,=6 sgc6 >&*ŧxSG$B2mmP痒Wxx69Յ&FWn=/b9^70N(GYNY(F*׻ri/t?ocOjϊuK F,c\]2t m@;QcExlA< Ƕzk+/SxZ9;Kf`O_Lzb?' ~~r\Q@BHnvJH<=*:%'V|ֽڿm0|TOYSP?GV6i]ߌzgiuKĊGHQXzŬ҂Wf gEvWZ*$`p 6u]Jx 9&Vտ>2gN\^<c9t`2ߧ9ntkǷ$lc".ֱ鎧IlyP8 g^v cjn~ԌnV]4MpNs_<N}}^429#޹jHfNX-۹rBX(ϩ<gs.⚘ `86{iO#.+gHYcRJt^ZޖBF3GO%Oy֓sAF#;^qӤ8&L=Mz15cXz,*O S_{=62ּk}ŵ˴pP ~Rr85hLrQ^;*q=XHŽ'pi]STK-Vs_FVRT.xc~s9#s rA\69ڽ\ei0ѐ\pHn `qc~-ǚO#}?½ ڜ/iꗗҒ\۶l|o+fE(71`@O$q־PKs y#''NGJWƶ#̝g^0 |%;LDwNr:}BiӬӌZ;^Pۿ'Ó/ƿ\V7ua*S]U.bIyH^w#?j4|+&ak hz1+mfC,ffGFEvg9ǮxM%b0V)J.4q8i`3<%e[ QZB#84]nπ3\:xSXs'Jw鑜sje=K q8abog |Psק?o~s]OSGڳpi{/&SVRk?w8#MdsNV,}rǡ0^]c<\iZL}[F'}$}Y ydvnN{qqtXAm -˯HqwsXyzc;zUI[==>cHVrwgh>qk/Ϝcҿ勫gd`\8<מz:uzH'WB_|Fccoo[: {k䌎1p=/o0g8W'yy1S8Zv3正zg9yG+K#c~-֣kۅa [@|'j)%CI8c[8VLv22k1mC񝌗wlU*Z+&UR$d>O}1A#6]$,IL_Yx_R1Ycp={`P%[᭍N5+u N09q_MW'kġq1nFe| bOjm\¨2z}ӌ?[k!7ds鞘>,[nb8``suV^(Gp>8k/: r@$wPFy$28=םj9lӎHt5;H q=A8xp:9c̀G9<~}sqW>?<6 =y:?Nxwg$9OG(8 u ƾ:w4g,i/۪ۘ # ϑ|iន /[>2,z9+m=x"GRereD`qЎ 9'~߲;KCm=_NO4{ xGx&&k*~Ǖ$k]/o[Won[(> x>ǹ#jKSI-tgkWx|yo& ( ( (q_gǹѴ~&Re3^[Jx_j`wo5 [~|]Ꮓ |w_S>_WFѴKX>8y5jװ#篸Ww<88p9ݞ#<_8!2H;qӧzq?=jz#'psfi*\έ|ړe?j~3Dot)d K_ܠ$24rJ 9q_[:ߊMj5WU/%iGs76 *\(k1t:ҕjֺ{пFuQOp_nFrIg۩:͉8($1Iu 'X$rkJ ( # 2qԨ aǭm[MЅYU+ے9'5`x; [0YE^m6}usI‡")[<UTN0=v}}+ȯC+mRA_Ĝ~~u M2$m1$}z_!aюx?޼P }kKx,<<#T+8E͝a*d(¯J+ۢopY畣ʲڹ&Z4rQKVFݮo+u#71lp=sWxGңf[1pfA7^ح?j4޻ ZF_Gwq[ZGiNOٖY<ʌrI>_S_(R:IG{ZݽL ^&jL4eN3+j+jrZx^W\dyG0iLc{~5Ep-Ȫd@\<<3׼)#Dyodgק5GS J~KVjJUS{t>y~1Ls3Uӧ 7UG=zW_C Pe2!SW뺀wuUFNO=^ ᰊYNVɜJE(.q~#"b[j(mWx {K9V_1$x?} Y]+,nFA.VX9yaNZ}J>o*tCŶc(?. i~vKaF;{ZňH$fu-v8h gW\N.K??{N ҜܚMk~&+q$qH3rҿ<*|q"$r0[c_:c5F3Op;: ▚W$1>u ̲Z;E_0rͥ{|@_5b!$@ o0q Osxoϋw;i{k~K(6}Vfn2l^N~%={uO1 -y|DeŞ|V̂ͽSIBֶfJd/H:@$u58ϯd\W$N`~ W>n=;dg<~5݌s:q>뚕|?V?S^{9qU%A<|ӭsNXG_@ $rzU*cS3O_nKv:9zOҲ s}+{q}pyG1qyɪ77I8=?`\ޓ 䞝?뾕 v>?n`qy1|=wz9;䊫u}A#\|0H6pG޽TuE~i7> wsqӜb 9ק`<A`tZ=_\WF[CsBKцܞ`t%{}pAq|7͑s3Gz/-SWCyl+N^<{ oZodv9lc׏OaW渭BOg OOoN]1o?}܇QFpG?#Hy,38:q \R8'Z_T`9SrkkMgʌfuo1D'-L~9JF kp>A#8q}?* Y[~!7V1/{cFGS*[b#)Y샑ӎ`O'F:$|iJ|[l 0s_f$_$dt'GlN<3˧օ9xL_ǺXhT9ݓsӥ|{ P&+>yTh淔J<`uk|?3ccξ@ظ`AnG~ }+x _J9]4anaA;uk(9't~uⷋAּ'<~՚"pZ3w̄:ހ=z=IxęNO#TA>d}ѕeKa8S]rKXϷm^69ڞ ߮:q_J7Q>P9$3!%${޾*9@_ϥ} jLq$d׭w6zzwon~pv3###Qƒ=|]MW#QI6~|G'?R8 rsۂ1zo)81J۹FQ;=oo $d#qq~5Vl1\_A#jdpr{qQ<ݎIq8~us9=L=gbGON8tj7yz_\rH?Ōs$Nj>z`5_M'#FOs:P-'9<Z%oNI8kRb ǧAבQ\̤'^(Xzgæs:oE #9 FxI'W8#tϮNxҼR^!錜O| 9QASOZ}_(J<LQ8>'J|_6!úwHfǓI/HguF8OlcP;ɇςIFj/pcp1}8H< @3R1'=s@zp:z>z qvIc>=+D)8<}h֯ϖ{{zȵC峒;åok; N}ur,ɉN 0?_Ҁ9]sxOOZ\9$F:v=׵` $9qׯ&_1A?@Ky7Vl8럩ѯ!w1Uc?Imk4_^#To,Z _<6?/s1Xpđc^y?ozҵ Su}6{ GJ,>gxZ 'FRY^.co;Ix/m@˥-=yv "O QK Se-Y3-g"5K؋j|X{ײ` =F"!㬶\JK1NXE^O7][fk2jb8O9ۏ}AVTƒ=dttH +,6dwE})KM%RU+$TB ^@~qbتQu= nKfz=T(sUjo@i'1 W28"xvmOYhbdΧ4nZF(TpV5j7Ҽ+S. <35-Jo8Lj ;*I~?/?j >Y| y&ml̞\֣nc[4iȉ,{P{Wi-znПGs7ѯ|N2q:4zJ[ZVv ʟ?<[BHּyg CIZK/,M#,YY?_7-/2ATUp$G[o!r<_GZO'e&Q[c2s=Fʴ=#qd>-]7:\q~cD##]] $1BFI.kvw?/9'<KUGQ&Ij>ozu>4+C!M4T򭬬l KkKh"qih +IL ne@~.sq+hPf=۞s]Z x#F5 D1YY[Bie@ $$שK2VWkۭe)iܿ<)TBMK2RI])I6qWjzƯE$<*"1b('$u-mNk {V%Q\̪0[2\p>HՈ5sHY9BZ_h& bJS'4[!?i?L_m -\ծnWĹk_YL,v( %zס^/؝ѐdp1*(~QegkUǏ|DOksuw{$iN(̪+޾~9MºUi+Uo5/5+79sp.{6!vy p?"zuWS;)84UlD%udn|_?yGNԜ,ѥ\~-J{IRd{v -SI݂s־O{iPO)~TgvHNzN\bakeo cd?7;7 fI Xq7dWIO:TiaR¾_zm{ӯGk`0sԩRUz-my!I%Lr 9'zYK.n4In@GR+`uNBHY8 9dҼ50!ג_#Ros wO/bI9lu9A1β eW'9nLڶFmg*798י \<*iN}k-Jek+y=>^Y%9Ėç!4%A灂qϊ4(BX99u+f;- pzWJՄ1r8F:?t)YU .cП*?=_יb ǵԐ l}?|oRI"Ct  73L\玞?xQnBx>={V p︨Ef8rw'Vyr76p}NVdfޙc_4dǨ$aA޾2+p<9澋,=7*2WGO'_X-XYS>cg~hMAA xD6^UA[5QL7O8\Мzsڿd5~~4=3W}[GOט.,r8O׉y䓥7X qxς+մ+*YNhچ"}Ey}2spy8je9c}oҸ1c1 r8#x0A-2X ?߿HƠ8לGw<>vb`LqQ gdHN-T-~2Fz 󎇐zWڏ$9#yȪjC1'$r:Tm#K}mG[1ۏX[ sϠ. Onp6nR8#zNg17wW'#g#r׷nygk6R=NW1ycw 0H#w$Ax/R;gKzal_p = G;Ӟr@}r~_j`xs=8^u?:sĔ=KHr}H$ɮR9y'"ۯ_޽6h~Y܊~. $rO|}+f1b3}rpAq}w؜G#p:[׷J?.cb)>Nd6윜{uZ 5?lCo Y">*VI/eBFlʪi^[K4;+KX֯4+Nu{:Z[A4_oI+imqoO:H|IyKBi8 2NU o>kOޗ}$QD(c8,h1FF Wjg#$d$Wꑃ;;>暼@n98+ѼA-3:~m~-L.2>a(P%؆Y?=;_*aF0{zksoqzXHg >+a['9ߓ׸hc:n<9'8U7:wX$8dsw:wy?JdCcU 8c灂; ''P;{g^}$cp^sg+oFyGL?ʯJybOsFns@^{|#Œ=wWeHx߯⸭J VE#䜑Zx8<S:d =|^ai b`v^^Q# g#ֿ">*|Z&o4iw(0߽}?olM"̤+@FZc 1/f}$Gm_8,X0B v O;xZÚar觌t1@En &%#@W&vI$I'c7gg?xw.zq~lڀfr9'צqVφ?~k%}oJe&[W[-:1I/.EKpּAw74z߇>>)׼)(ּ%nƟnT~'Ҧ1\E%0jcg}uК[]'~% m<-#ر?1 ,y `9\ǥS?"@<k 1g$^,.öJ-Ğ ^ZXb@$2IWx/>8!x1u'E fI&?hT,*5S%yE|O&}뉣U] qcB3zsͤ~;I&ՍeٸUI$|M& `e4$# j> 4O ?#i|OZKxo#C5 ,ʨx5'OUWmZ|gkF6(3#~-|K?&}z'%r'n|`h@KȈ++žw *pPHԜzO Z=u¨7{ykmt3\IW^,:TEJMz8ܘ\`=ģbCU,U\ni+4y="xըҫĜ_Ua QmYkP᫓a;SS?%?50?"ӦoJiH@[g )~~&Y˥j;d| ]O[r 5 @Fk{;B)^1k>0xYO&.s$Wʰ6#mƊ?'6l>.WӃxy+ZYdC"xD kʥ*t0 8}V./W7S~?XqR+J7,4mdr~߲?QӾ#Wft ܤ]xY!Umlm*O|cXZ[v6Coio[mo *E FbQB 8Gs% H*F" ңҭdIu#%z^.,+֝|e7J+emUsƞ${?oMa0P8jm얊Sj~d^7j3L"RȠg`Ul7,dʺKf8CO$uHé[Dm 7$cn=:Ya0XT:wuzUJaFjk$ IG@^E8v e;fU8#W2*XB^W9'-s955B; I OC^#+X8zzju]Zxf:^Zlu<  Bϻ#⻴*Kj6) rs^seø))Th`z_o[)XleW%{5uqkk5~ YpHsN;ԟ#=NGΨ;18''~ݫV#8sNk}WǜӒz籮XGGc8/MT~aqө  ƧI yeڨ 'Q:GZ5 Xoy^<~jV;81q7HΨ?8 lga=}4?3855?_Ե}ŐO'<מkG3H۾O֣%b~'A$:@׈l_k:gO[_A $ Wc EĺLmm<ى2ʹ"8N->>~j7Ľ7u;_[ǒE44PbNnqe'/$ ӓӧ^i I燴='Bt=F`[k-;Lm[oh@+c۶Mv$>zsI9Iݳϵx#@0z7^8=?:}^.N2H$チʽKP_2:s^yFIlu۞M2 aaO o@?yuWj qF?μ\r1O|l(sl^7 ';qA};n$sӾ~lx<{7kFC}8=|}qq,;,r2 F,NFx~|I 30^gx_ xJ%s්I'V)P-, b@&9$U;Ty?( W$xN<1  Ȥ ؑt'*>U%|-~zV>,e 6Ϋپ|C6: ޱwMk`5U8Hc @U(P:*?i_ F+6=SJ'*]Wl莎ed 0G<9pIum8HBiPP[itRT3.L&E<2ŶDC)V0npCyҀ$;Y#o|(p;t5kK+<fusBFŠZ{hH!O{g ŊsV0i:Ui„BS_G"ӧõ2H0}3_K|kǤ;A$XxW 31$cy_8me8I"D$0DDPYو A$jzWe|}յ {Sqmöx{[]Eּ;N!g# 㯋 # >*6 Wd -t8y^*ec41ܬ@ $(ϷoZK=&cTdm.x j{d–HOyVHśq9$CE}Bm'ZiquwHi 0_={ƻqX=r }3_f,ƀڠ0#۞PI 8~30jھ0r2@Ǩ=8ϽRF‘g'L$G<|ßZ2xǧ|Ag9<)p8=LzdSǰss=8}= r pz1_TfN#Z?29= "r?h*I9\@AwӢ@lg:u8>~u41#נ 1Ҁ<^ڼ7P\#):F\n7W͞6x7]GÚeĄ(oc RtEp:0y>|(>hW//;kSi)y;՛;muZcfpX,ǒ']'w̗ċl߇!ISeěϱ'8\TЎg#q?JJ1J=BF%K3rĪ]"_vzßT)<'%P5a?~a$lwf'޽Qg#Z: c^q\.x'1^G`,Ḣ`^ֽ?U؁ӭx.شrq6G~=Y>&g'/ďjj|;Ocu!SSgU1]Y)db+?iW!as.~|}sqZԓ/il 'з4 t́kO*ZtPR_;z/-W/O]Zx`2%LI&(:;|J|GgS9aӕ^uu$w̓|)|?\GxpfO'S"?yο1l0vykOɩŧz"UjaqT[R8PiJWaԴ7Ssj6#Ewcq~\s{1WʟPGgL`Yb6׷L+a^unGОF8E~y] Uz-YSK~5x'#WaNVz)rG۳R_+ux8=9?J89=N_LmWgON}\z6?5bIsۮOl}?:zdp-O$:qns<8-_Bn{MWӯ~8N91*]Y@gӌ;Vtگx3WE<&nyX!lh~']>c?#L`gz{B}W?u dMH/=N@Lc!oC9:ˍO`rqZȟSnHdr@{+>oQձG<Gbjx_8O\~_vS­4>oh{EƧ9:u8ajy;q W1u#y' 8X:sd 'nwR½4$ΖUrıjXH8{W;u}ORzo5r=^#vÈhS$2@u5jol=XzH]U$1XO#Hۛ^yO>uF)7|cԮiȷsy$pX+q0:N|Qց~''G@ 9ZIEY#'RR|ӕH\Q5]לr1q}@2Ix߲gWa᥏m2shM꺴;mmPrHBMi^nHG>#؟IX/|qmG<6bSH-y3U? -ᦓ X,M3GMOҀڽi%l=,HU|-gvEs\A$>2yQF<]aʶl0PK{]l:c]qOiVޑ[#:nW~|}sy=r9O$}zӯ\}a}2:`ʨ5$9af-V18'2vC1?J0r^Iv;W-xS|+Nۜ3g$;CU?g?KX ^FMhƱmqg3C.d$Ag23%i;@ /;?4jxFX&|c*x:9aOsXKdF9^ ['Ӎu⿽/! o? <yk?Kh7$4|< 5ljo>}~5j#R6;InC@)D7rI=:Wi#2Ǖ\ aHW~ֈ 3j-_qڹ;_֭z{uutj(\:+M}y8u?7!=zqʀ=zmt !0?\v+F 4?183\0?9sH$D!'I8QҀ5}YfRVg^uyp88$u|9G`F{grw׃$n=zǷ W@8I8=xc[y Չ \.t99du<jӃOoBW?698Rs9TI|p}z{yƧ?\ux'8sjduN=qWnF~{Qs0A#8QF@nF=1!ypI :{}/^?8ao%|3O0X Eb?Y~.D>W8qׯ_0;#fegyw#pœz7ߊmZ[$fe,*$~dlq^a<gQsy999F01ww۾9鑌{~7KM~Ӟ4us/t gM~;uXgo< y~x rx`Y=W&5|#DқIRG㯌~, ӾWPIQX_!Ԯwm+?_Ɵ' ?n?xR+٦ ?þd%`/!(VF_>KVd *(Y_ R[_o3BFrټ=[m1xkr{r1=mgs_źUB8Lƴ5b$;q $GYK}MV.'"pA9M9#@U>\j@5q#UA:y@Q`Ƿ'p{(Y89$g==*YPO4b-*fAl^ bFt (vTN}n=+b>dTÏoH$w c~"'Oԏw;[fTݞmI&~H=Aqmu!ʌgnC~kk'f(>܂A$q}+ô+M[JBٕ?63_Mx.<޾b񞱫Hf@},y\⽷~DLNx8`N=^IyyT9$1g|SfcNu'8a(Ee+BJ):ξ^ Hn u'bx6̬'IZ.TKT vz}KO{6)Pw'dFsea(ҊQk'XER9.w}sfn#y66 x;>(d!8 s,'?+ݮ-6i|I x?zmkQ)%] $gjsy U{Zi} U{;+lVULpP$99c{UoxrM@RHْF  ҽE+%jߥ 8Tu*ZY}I(h_d_W:zz9^Gm[89+r܏. |=8izGpFCגol~.&Jt^}t=-bO'`{URMWu3/I089=3g9y?WjGzi uP@˒r3Ǐֳ}Ry}낗Xw{p~^''9ӥo %ç1'gi>u>y\qԊɟU'8n'nq"ycxzpsvi9錜קz16={g[\r78铒sxx=?}8Y;WKNz{}Հ?||I>?k.Ke?3ێxTu]j9(7n| 8[aKs,%\qy9=_nqSbkWoZ~b{ϐ;(<`Gn94vwgnN՜W]IYO {{$w1QI7e'%#M~:?hi|6!u-+C.㿉0YO x^Me>p%}-cNSע>n?.y-EON)jVRګ+ϦhѯxH,6>2lSc,ICiVKڵ6Ymη-Mc}|(lG abm{W>_ |-x;~M4-l->ѺG$Y^iy]8v~1QVVv3_;=xg22A I眜k⟈nM! 'L~@|ef3=L}?Z&&!@;Oˌ=4SlW#Bg ׆>>xRً_3(NKeA_?S_ɿRVg:׌| "A/%%/ }fK$62H3ؒ7Q_C//7 !Bόq{[JN>ǣ_x]Kk]?\մ=WaeТ@ѱY?eG_gWD=I+֞*𼺗| @!92b?A比#(2N=Hkm\L$L¾=ƺ8 8x<{׶v8^H9뜌g#oū6 dNz-`="G {2=9 PL!8#O˩r zs.1?9>}>ʀ:Dsۜ`瞼9#`:ƸԲ>sX7:9;HON88 iu'$dz`ʸF*#NOR_>@3+[<8s:689=:9jF`A瑞? _^8\,W uϧ\s(ԥH;*-QY# [+j7G<1c Q'O?{bh͝_Ake3-,m:5k>.>UVL' Tp,GQ5_2 :x9+֥mCw&Z{d6s8S,4 N3>^]rO=Aq^oGujw*9gA ]EIszUzw#nzյdg ZH.ՀF}pHkEp00q<1@"Pp8{y8*M-eCӹ98֦p b#}C뎝AS'Yq38T|pr9 O=LLA= fI#gӯ'CSP}}FspySМOrqA NN3܁Je=rF{;ꏘ$c9>d⑤y3yx pg' qV毨 N}}9Uڶ|75@7#+Cv:zq[|mߥxuEz#;D瓞NHZ_گ-ɴ.yVU!ۺ;ݪ`;uC.$@?ֲ|3KwĐ3$p:grMjVL"B'H}魋g -Qx >HkcRйɓVӶ#h|뺁q?O||]'Ķ0ah+Efp 5ZV6GYetppV@AY|GćFĺMa-qmJ3ȒE^lEF.F''_C#n%ˈ1*+SNt]*jpjp_ no:6tR "?.)u?$IHJ#k%FS8~~ѷ>x6QcZurJZT Fe1±[Ly*bFc_{-\~oNH` z^W?Dlˀ:ڛfzUƤ~vz;n*xWt/< :]ZK9s%MO'8pf`UЕte!FA QUԡc!]al`c_W+w[GM&ukx*=VF,ڶ&͓5 &.dFe_v]+&iͥ{ZOCpx_8EZ;R^Swxj4?zJ2mKib8H8bx8>+{Gֵ RB;嵼E= YXFssR-ݕΝ\Xj3mygw [ l Eu ڭ' K{Ϳ$xRN˭ފެ RP i 㟘ҼG0XP cSzLyK'/ vE;>dOwm'ϊk_ [imKFDסq a1}E}2'UuR}즴Uxr>*1xiE깖y)Pds?0{^³^?c -|7D6&z&^Wf+14L̰Ra qӸ9exk(VjFP}Jkz9*|-JMnjpI9cג]]\tO$=?}xy/4IsFcc6$QK[h€0pq:OC5;f&n f4I-_m!|DYgn\#8-s {6y+wƶ;9-~n~"&z>U(^r蕺+~GI?ѹTd3*Ҹ{e#'ܸ1ԚG;Ae2s _jLʤ3&lnBWOMk}VO#ekWwWAO[ܞ 0=9pwv' ڼr;ɇs ơ>>f1ԣqEfռ[mon}Px?ϽU}`)t ~J>INS2@?7lOFA#?J7^CjݼwsS93YkC$ u#̇s2j2ǒ9'$֫ q+=w&ֹpqIY0s$z*c~BOdtӶ2:~fTGL~"K-:-w;Iqq}*fl$ rztgdϧ>g$~^$߹q嬧gGj"'L~Tp^r}{{2u"(F8zڣgL U{u=zJE_|E]ш.&PkHCީsy:Md N 犸r9b"nVK<^=xU￳~ XꚺDl/e[x-r,Ym壕 C|%?CƗoowx&GRnYl1淍$+c7k쬺/_>8W7"7 𶍨kvMJ! pO͓`y^;%x}dqV%NM;sBzv#׭t75s x#{AA⹛<R8Quщ#Aqyng9F:p9#VpO.;pIqチ?Jז : u|1p}Z/$nO(D\8G<`ǭyzq5꺢`pp0O㓞?Ͻy<Ǧrq5K 6x'`> ;A9'z*Zr<@29xaoH6Yxd=215OEqAW>*OБ'^+o\n,}1|ĺ?h,nd+#<W W )|qO |;a/*>NshVyiZ‘EQC{5 I.-?f?2?߱o|9Cqma5pxDž?^խo4w `U 5b^189ϧtkϗqr+H~0&}qk 7UM,o*Kiv2Îk>/W+t286U}A9ON9@I#N5={ TuA0v"p?('4jxNG96Q=ϣbAYA  qJږF71~c$@-ơ;G@O$b9?N}p? ͚9' &n.g#E}u{I~:\Fu:䜎9l^Hsgֹ IAQO16(nnQ mi$W%#ym`q??sNI ,# n q 󫚓43׎0Of+ezəb^1 Z#^Y?qu=vs^iCo}մK,UIhv0R=3 W`mnujv"=e=;PހUth.3r+|yQ lqz^{>ʀ='#L$ǓLzr93kN9gcm<9㎸ǯ"$O󬴔|xDlAҀ48=韭H\``q+; NOu@΀4<÷z1NGnHJ܌ wƔܾ:r@^Q'99<yfbydu>I6ВzVlב鎸ϯJmӧ5sqGHzR\y Ǧs 20Hp Z{src9\6zF?F? .N86o{pvNI3UԂ^NWcח:P|HקQ֪vjdV 翮H?H!.%X@@M̪#?^?xwfeG'?XYHgiܱȉAwJmG2g$vg8׽{^|>I낤qּJ%wA0A둏ҸۍB&Y!,''Ҩd?)8 P42N9߷~ED1F\cpy?z'#I$=LJ_jz^esz嶟6_LvVv!{n%#D PI% Is~ݥĎۙtk4[KH/ 'ÿg?@%ԭ&UCuau2ZjlA1!ܧ?!|w]s_i.+߂ 6^ wQ}!begFhݢd5똚HY! &H3;zf,yƯjK]\ףZvxs2^4֖tRi¤,[;^no9odm61%դI, sY /^Si}qjD%xo⏅>Wn+{)Omof**H ZiyDv(@8_-S{>9[f[ɸ8 Δ :' Sg'f{h|]E¾ u{o#i'US%"?[£vG34`3=:x]txvK g~V\K9=+hnl,DsC/y_aM~\Z?[hԼGzg]K+8De6 F &.wO2xgkNԽ焭J$&eg+τ8 ޝ~!D|swi:wij:F6Ţ#.|,e⿌>оx6ϫktUKӣ+V.OVeA_xo:J^]#I-BR%5;kg# 8[' {I%ﯧ/nI<:֎#>NUiwC Nf>άkKExNx w,[~:cX^a4Sk-W{`|G &Eʔ}۫N;nzlҝhi}u[[NKƍhKk-^kh~+My421 Ah\+E#A<|#WCk:d,.[3Aeouy! e,$k>:]OfV؜G8Q^QaP @NH9xWTF. :UB5dܫRw{>^Y <ʮ?,_3\)*pii}/6b˧|SaCek[ o} ?y+|\a Φ$lВomLKO24 >cJ_~FSG<.*hϡWK.EX*Bwd8c=⾗ xiOO1û9ҭtk:UiϖזPm륛m5~6p]d7STte'ʰϯ}? x~d. 'filW9hX܅H}[;W|5h:W ig$fH&"YVxܨ3^C; W6I? aUms/~׺d&Ѥ[ƫl4~YG~']Zj=UXfMrH#kXO6,0ĭyt*e>^Itwv,. g1(-L$+(e"m`/C1ԋc=O]H|Ȗ3|;:sӯa1*I]5שRvOϋ:.ĸgvf@9jo3Om>"xQԬueoVH$KmB٘-c{I$X⦔I9Rqz?*[~|hC|1_CO=k]٤>KOg ;vn]*ܑV^~]|W+EM;J'Y@2?oف-V4M>_\YJI|"𨼶MrbQ"$WFVFh6(ࣣ** :qg_ xH)M[k;;'Z]\ΙKy, xe]X085?i5 ύkkrJ~8, xTYjyĉG,w!kt[qԎM g>I'> 4~ ӂ&=3uRUpyby_iFONǚf4O|3s3ǣہc>38I1n:qddw_ҏ?opIs߳g%Dv(׆ ; +(か'W7n7*kK^ nUn/eG>_b6i2{(z בjO7k d1o|^gubOiZǯ]|4.1-޿&R߯G jr;z_oI}G98q͂FWזNzz| Q9~)~׾#FVy^03o[ľ!~õXa_/_m|Vx& ~ѣc#NM ,PcqJFr[&8Oyqw2=Ғ@ HfEg$Hsπ~&χu(/|MD{-) *J5VVN3?b?p; ϟ j6rYE-'Zl0ajϪݤzx 4P(Q@*VG,%~Uʟ-_e+xP֑-n+ x"ė~"fMh҃8krJ~g?A_ %|1iqY5Uծ@#ϼyB*Ʈ#DU ckKcS&ٍ?Sp3ֱn;L涮2X#b䁃;v8E2LK9qn8øS[?# 93^d{P?sXLv0A\b8ጒN:r}9*׃H'8#xlvu<| C8t:P)``Wjq 2;^'Quxםj[91H9@MGNN}xD^䓞;{z=V>9?/~:kȵ:g@:x2H0${u#| 0|0w3s⾻0 lw sukZg8u=WE|Nf9 ίM_e_WD~ :uGue[[ xcf B+a#`dӮN?J?d)}C8B],¾.+Rݺ!aʩ;{c*wW0`zQL!9(h^9bC,nH2A@O|Nѿi hZG/4OHj} ÚhفK_Z],ms0).G1lºg]FHJIIonQn摭&?h?&h_8|S~Nx[n--*{>oްWs_ʀ<_xI<9xw. SN]ʨ dkωO_ZCuP, L86~2܀9{O⥺CpI$`~t>:V]nH#%'E8q_FS.) W_~O֣#Kq[M)%I ko,p\4l>Z_4z~껭u>Ok:lZj&W7\ *?{ sgxOR~~;g5m}a|m.Y^Yj[p:A[&5nIw(˃d:C mIj7>wq&; ;M~Oj0[;I|K;aUiXvcmKjARzp\|E۶[Z&D%=9R:W7jv1D(Ӟg;A98_>#EއAX˲."cpYYAٍ~ GC6< dV EB0G^>b >?ƾUCN>4lnb;=:.CȊ9@M}Atɉ"!qegι#ꮬAR~~ڞM4l{ .) 3__: |TO) q?ր,I6 p}YW~n{``gӭ>I:'qϭgKINzϻ}Hrg;s2}zVNx~}Ed\6'q j30ROZn4 r qrx{WkMpIO5ŏ xvr[h6/0(UURn}Z{'ŨKky~vűo~Q=I}Kq_|5YMZIUǏ{yW69TNB%?߲-Ơ,ViSjnÖV; OCǟo?Yڽ#rt׹'4JtE4,ѣ*N-B\⤹~/+~͟Ɲ͢x7Zm-¶罃CXaT |փ8 xcBЭ]YXFxWaklc[-y]skA34j>ԙgy30#q|♵,Ŵb(H6NI0XkRTj GĻjs-H.b}8Lz܊|7>/u>𶳩[J %Y6qw6|6nsXXJua7vt7s\JS}B4P`} ^yαǏLd~Qw~*xj#vιOHkx|K]Gތ5*a} U-ed';[<=W]x¾♼_]IyJ[X 0L 5;Ը<6tsYV-WWTE-oh+b%OüGֵz5I0NmG܇3Nז)gpai*ͺNIkyKkiɯ.qfoxzω<VjWM厡kեHz#5|75].;gE{8 kr3^a rOp۰@ zO/,+Ҕqk2Z4^,66 T*PuMJ2Viѭg/̾3mF_?gOM jMkm^ Nȵ?<>Q\/ĒL*c#xMd%yÜWkn"kQn;A8`0)UEkMiq?g|jfXh)TqqT&Q:i4{IENVVkE @g)?~c]{:uz`<k>"{9TȴO3HV?8W:6|8Qh4{PH ^]/41lܻ93$s$Zep)׊n|iYM{zutc}I;trYktٍ9k]WVNwv?IsO lo֦#˨Ta5T^%Bj0^JIYFL_/O?g "Cx_x! lIӤJR@1#v 2@>ef^ dKχ7z'hv?u% GB Xf Οl=Mz|;9s|"nVP9tӖ*_~_ c7x373)իRVKc p`^Gi*q21>f&=6~暶_s`,I$g_O_ x '|; ωVyH}^_a!jzfxfޢ>&3xwBgOW^#vV?.(Q4܃}JhheܾM4//g~kZV?KԚUy"4kkkz_IQn CGXK3*ۦ~t|}fz 2'8 cv߁5 -lBFp8'z\[:a2rz{|hҖO (˒)l)JOlV,[3vk%䒲F߈ԯ ҼXݐ@#/\/?ZVn >DIsj񸦾0$;۞kc+CZj_]8PNZm,vgxݠc@qqھg\]޺#fb@b=d;Nz¼)-?pT^N#mQ,\3&J0"5emߡ߅TႫQM5މ-[?<76OO +Hu\&̊H4a9gIOֿ|Ip(ǎ$1ߜq_d^k`C7ÖIv%BYAy 2qoŏkZ.fIVbe% [*%B.0\-9Ż7Zj]it\V}jQNQ+'visxo'o"0ɥs)GmU*HFt9|CEu+I3#vAWK0PTl^&Jwc2⿘Ix^"Ur/aT)aѧ&RO#oi)m$\t2zzXӅ$B<8D3#=1^ iv-G<Cc5[R̖;<El9\!P?` 8g^5x5+^8RZ$Ϋe_+0]~&S¨HܳyjO>`5\Ljϡ1?AIT| H>{u8 rܞx' ~Gʗa}b3e3{ Ys7OxiNp1ױ#Lz{ΘG#sֲf}*xiJA93 d)1={q2cqpG~yr}*ssN9nkN~!~zɟG?\wd~t?װ=:k"|e#xlMj\A#{v? Ȝpq`g(8ztd\:9.Z֜y3Yv$uG ŹA9:@~U9= lc'{w>?˞22NO;N899'>Ջ?9sAV##Aұ9xO<`@G9P vqA~5rI1Ёqk~6NxB28NsszvNߟ4s<~czGSں+9לuM`Q\z=E sw9F1׮H݀7z`:8q\9!~~?*oPӮG#pN{^ tsJp89 s S@r{d=qڬy,'נ`w+HrOL u#?y~sq8=_?/JA3r??W>/ $x\n3w_!RpzvGoj?چY^s|]Nv$vھd'M,RI$L]` Cghgp =#_|CȺR0Q8@_j'/k L~:D2oxJ#VGE27$ھb 0b@ ;hɾ%: uc}~ͿCi"O|kggmꮹQ_;7N|S#IgGQ]ՄFxƝko/a)$aO{vaWO*C$9s֯:$gkai/ =j_^O/|4 4$Ymڶ,`y2xh.Y-n.x- xGGFP U>iq7s[]ܤ8w?{_3"j@<һx5eܕ x@q9@7۲n\$ֲ9qKc3ӟҹeB]Gg vRx8@ m,w(''9=:yjĶr8'sލw r_ `ڼŞ07!m% rsxP>/2Ēa0'wцNz+X|m= ㏉ ˻ۙ1 j?^"/Ǻ:7- a\䂶ZeI1Z<ČEB߇JK9о!~4"it{o_n:\sCj5=Kl26BO* d /;)|Vxk+c x.yGlZn khfV(((Wzfs$Z:V9=ԲIW/ԾYnnjx#ZE|/~B?kkVhkt oօXƑqh… n>U=xQp1ޙde Ԟ9#cT|-WZZ+nmG:#qq[djty$CG?{('qqӆ&?W>aȻ&Hv88_HAj1 mITyzW3m"K C$x$lt5qG"BN 3 =}')C\? ڂ"R# o2$>8 1` M|aYj.pY&C{ 9#֬/K=Zk}3GAaX+^JZF\I;qHۛ ٴ]U^ٲXwP9& rs9N3_Ii9nԏ k8|8>7?g}o~ 1gk1u]cN{K^XxF!1Ӛ5kf>|_/x? ^x+?o iΟ$7T|;y ~e|:2oz.O=;֎^;{דRCd#LpJ`Qץw+q9'~2nǮxG=\^9 dtgnO@: c铜h2#V \qN~e.:rG^G_s@"A8#38Oօűh+|vh/?ZF8R<8q[sJ@$fKs=1qo{ӎOኯ,pGr ;R"1yz랻1cs<@7q uMqZ܀I鞣tA'׸P9jsq8Ij?{ 2A9'8+ʵPa{3+zqumkۑ*kXʰ݌1c< P$SM&䗶|AmbXnlu+9kmZMZ,hꪪq0_͏|5᭮]wK C2ȹ89"_'Cc<7B%垴zJBM.I _1\a,q.rU6Rϝ)4i86՗e]֨t~䚏Gkۮg,f2fDl$)n$XF灜לwiNIj5w{"@Hs }G :LS"Kdc k{C_exJi9:6iQFTohRKWdNE ThxDŽ;?ݮ'W0ď3G/i{(_3M0:Wkd^xO.-4} chV1 ^~>.1o-n;mHA!9>+.Lӎ<@ʜ 1RiYN?Cic]>MT^M(g<ͤj>"%-- [@IեO(r3{W~*M~z,EJyMNZA[c9F= |S"Gyh*n\IkG:k?~2[OݫeαvXgu@P~RǎK7/1׼W5jYEТk3i3%_lf4=&`1>SF@ܲa3⻫Z2UK省G҄nv$dw%XC`gߧ_IMqdy$8c` ܤQr HQ~mIThQW{^s:KKMun $l\FO9䎝?+h`G[F@9~X9HR6$ {ּGƞ7<3_ZXeE (j.LQAf'gVoJjxYⱕNb9MmRU'*&&[sL47[y;Gyd5@Ē@s__5xox"z5۽4kMF%HݦD@#~ ]Abxㆦ ~iڴ3)gG+k>(\ԼmteG9W)nmQ~T~I|m#=nNmnHNHwnVxSnBFD͂˓PҥEwm{Fs,FE,vwQ[/KE._~ M^;msx2ڵg[Zijyy ')%?^_|9t/M Q-$ ;Ğs_Bh^<7mkkk CQ T(P0Q*cuUU d`{+縧<_x؏c skdd{(CD֯vWuy 3o#cּ ۯ 0@lqB n+ ׅQr.@'t=oR!SSv=wi7ʑ^26߀ x==Jwp09bG 2sɯ"6oA\4iKZŶՔ>VOfRT~ 5:qIGQZL2bypOÃ~3`gG_^OZ@ۥfLORrN21G3:r0Nz9޲8'1g8zћ> '=t~@3F;`eVdN9<~hs#>̛<@s}x0y$qZNnsTtx8neNrqbI8>@ִADq(2H8n8dO܏NA=:םH=$#d 4q۞ZƘr@{l\u8QX2;G^;P5~1NkpNNs}GB [3$y@Ď03X#9g\p[-+xCǸ5r9n㎸b\tm_`\ O|$V=\uu\==k w']p}_Sv>ݯ z;w⺛A䓂G=}NkO />{b;3 J3'׸ T< <"q_ǧ޸}I099y0s]8qß\NG;Z-V,w$u߷^iŹ_c+9~Uڤy,Fq08>?OZ}Z0CxqkЃy:¼3İIFH r1=A_C8=c y  <qӞhڂf[9 6dvo;03ӯ_u~`xA+O6Y<BgO ~C>5~:[C|ԵIn^92AïYZ ;xGZ|˪xyp M~%t'1N#Rx;ǒ\|> h<1V 18$u,i,nG"+"ꬮ:hC`3Poz>!goڸUD` >$UK-@ @ pz@(dgx 43&hdE2HYXz(t8]+'?ok:]Oz/ܓ]&,oA;`Ob1pF~-e^">KJK3w?/{D7RXS$ZMIVS( ( ( ( (?; ? #}& ])Vs\:;!$#xQ$I'ϸ'ľ?xO xKJZ~1\?.-}B, M,xPeG\p9  o44Qv_o:M ~6Ky.noxUQQT* U^(@tv=9?*7̾ֆ்;=).u Cd/涷K2j[K~Fh>8||_׾~ў '/8cO#$HMMf5kX 0c"$h"tFY#G=:zb+uQqx焼cC[|O~#|8 hmdz}n-H /6i%׏#*i59>|~Νw^) /!>1l,n1Lk|;8q zE 89;㌌_8h5Nᑗ91\ 8<ǩX8b}qWcGБt7U'WU|Ã##8ǷZ!{z:?5ОNG<9~#.1sIǷ$gK0h0\ #:}#Ͽ-\p$dkԵ̝81OSְdc8SWj]88P 瑞F~Oß? (/tU_ Gˬw@tGIt*.P+k5H4 xOW&" o*F yE(_՗|ox+{h u03[ZKiM˵3I(©ϙc3cqբ:q8GR}~UnJfҊjvIz_C7kIj .kr! psj߲{ k{9` .yevnYӮ2=O^)b`pp/=s~>YO1q Ѩ-{{dYDaOUDrt^M{ KҴEh,4;( 1ƠνXtF( Q`Wx@QH#܇$u_GxwIoq^'ti|rU\9JrnM_ ([MIvZh Onmn0q]< `wqQW9iࣣ5=. qk 74\(r~7e5GWoUf*N4g}pggt!Gh*蜒pf9[ y+ŦA ` 89-.b>R3?z% Ꚕ"<_{mٸ;iT*3";_%sšd4+o?ڥ]ȯ_> FUCZs]Y-/jTuqN!txR{F|^}O޿ j>"Oj+i@uJXv#8+۫Y;kUln̟)9kx##U~ ?aiq Vԑ(Zhbp[  }[7fo_&> ,6\K#H3rN9_ ?9CDJhvRfѼ9^_%'.B9qX ~77 }SxV-SLØ+Y!=V_qn-:8c0*MF4dw-Os)Ք'ЧJ͹T ]mDkoE!ob[ Ga\i(V s֢< vO 9lgMKN,vEѿy:V]~8|~qK(̨HKKK=5bAA{{:׈m5%hx+q@p@=V8=p3N8+bs|37w)MR~w=,4iB:Y+/F],,0$=}y[1qp'~O0FJO^/ UT9NNj*_+x'H۸1 vL_&եnR w'ɯE4LgH^<_-ɔ*x{ףk*nNg.ed?;>#icml37#plG ~#^0#Z%jvujg>%V(g $ $÷_#lw Tn q9;'QgT 1BO ,`>ݔp,a"3^O8Ty`` їAprO'usveA8탞$z֌ǮO=%cz̙{~z}Μ#=?zʔdׂ~qZRL<ǓYsN1?f#=xdp =ZSd>8>V\PsМ<^J˟c#Xw?.zּy'#Ս1 @:r@SHr:Nq488<+^p2Hӎ18{ cț<#iI2p:gxQ~}+]I(=b9q#bszxl\p z< V<}O=89c\c'cy;=1q=r:97uBxvMvҳ}:±/Ŕ̦+eqy?AhYK߃w/.5m-mȐmO7C^Cx,UTN $((q}((((((()`r=AԴP_j@5;Xaொ<Lg\uKdw IHS|`#yn~Iol}AlNl7>.O~v菻#q@G2O?3zfGxWlm)Zv~L>^Q:' ocՠKo=u ukxW͔:ms{$EUU TUUT`::jZ((??|)7|5OC?w;Hb4}Z[{vBAY#a(3~ff/kz¯jHtk*4YXy @xGďHjyj-5|A0ݥc5PaKX/=K?4e:iqC *,񕈋S2}(*\G4ca'}7GY eF"A3ӣ{οۏ 0ٵ?<>3Eo::,|&? |S/ro7U-ݩFe}]ڏW Qwu o j2Z$WmL˔,܎U ?ִk}@s|M|V% 'z5Aݗ d3:sӥ}~#^w[ċ:pZʹ*1gjp(9z w=_Qisv &`GQ={({|ޢGqc?Vj7J0s̸=Ng6~2XY$s:p1@\j~1nOs^ox$-K2<u~m^YGͫGlc{maI'4%JL̤Nk=z5Yd&"-.˹6a(BQ=pYșN0Qs˵˻tI0}sڼSɻd!9'>+49xWi_ w>pkk.\ ] ץ~hlt{ߴnvuOez(yqW,xs6pdZ?)M}wJφtc^oӴ2'ˆ(bLwKtU1 'K֕:.cPL#Xy̑9uD.x_Pּi{h_|y}o/ fMm9Hl_UO%>qU2)sJ.jrWR(Ĵ@WIRexў&j۴*CNh֭qHG)_]{wn.䐫ur5'<(+>${cf 5#wbM@`}?8<1iB6Mi-n_O1ܚ/'9lzXIZRK۩\0 +7w*}{{ydn 6*t[UV[Q(̻Oe'v5x9񞟥#a[B q0,rNs_ Ѭ4'-j1B~xcߎ+>0m!@ 9$rxt2<>&7)ՊWQ^Sʛ+Em=Y/ױ'aΖ2-'$~Wն>-PY[[AX(!T8B'"FېH ki4KbK`?)nx9'x濕sN'.8α9&uQMHžXR0fWQK N?Vݿ6:Nd¡ PHprA`NkuM>/be8d2N;ck9`g,':q^ F/ z8M6Z[]~tMNT*ۙ#uC F/!O ׋kJ9e†Fu9Ԍ3'#<3Ve쒘BXۈ;x^",›rۗi.MzqzoBqOS:=n]J .2N:r0?J-|GpM(`ŽnI@l7XSF8;A#<~9|8IKvPNeGXTuRt8$;qs ':VLZ+2O%ۯRFZT H^|z$Ӻ#D%3A$p{ׯO6D9WgAsZӱ6&5_:8==ǀxQx\2IIܹ=kž+ :S o(P*=˚U\nA=O޼ű"[ב{u?5ﺖ^cKN^5Dl p<]<'C %ʧz\\:|mkI;Wv8#<^;P` ./wfEmFՐkq Iz=2Fr8|i(z4g%L~ИNdg9?eH'BsN~Ny>&l:1ziLy$qJ˘v^ߡeNIAL^=qg\Vr31tVD䌞:}3 ydFxi3g<`֘1_F:zwYF3gր2gy9r:9Ob9 z=+bt ucOLG@N8<{ǘNy'8ε=A;I\2N>q r?ax9]F2zuV;s۞MaH9KN 瞸=}{?}OO€9lFGq"pFG\ߡu7#RA{}kgd΀8#lN>ރOv׃9~ /W{ =ԓ9Gdd皢}pz <zv8gZ9-sNsʸq? a 9T Iϯb0;feuVlOc;_ù%ק"kuӴ=#lP>ǟG?ON]_gK\ڴak@\_ϊ-|7ǞZɷooVr-]UIIbeʃ_E>!_[մOzfK>$vkݸ[hA ikckj,@c?_ \E ΆFGbԼM sp*v+(u`?;;ş>>xsGg(OK+a}졶I<Ua!7?ȭfѼiF ,<[ĮNT@ҿ8<Y4qe8A i:ɐ cXH|sfDT[ Sq@ο?__L"fLY~*x5!H $pA~ >8^* 51 xYp.e|W eoc ݔYUD6 ~sglc<1nqyө?_%Ûky> ?;k=~ Ϣm&M=6S aM~LO'co]'iþ!XvMm@Sv}k z،v9g!'ğ|q=v}xSYmt=oEO3I:SRGX_u_֙⯈6OêY9.̒x[Ǣ23DnCFaQ<{H8s_󪺎^agiwvmmŭoʹ3+++EIY8c?fmަ0b u+`;w+֘yXIb>տc|Eo&EեgWhj;Fugg,4DNXSI?_/md$S$X#VG7  ?Nm?l߀^,{AH·T$`$d '#A8 L"e؊&]_3:BB*ij̹[[.$)єH)]6~yv aױGyv-pH0P$'#+^~ΚTu #-5iX N캗[gzѮՊv3Ij&𿍳 h8kjeKݭu_ۊL ZqSc_\4vSձʆA%O܌gF&㈪29=kZhk4 Y4>Uω,].Mp.N1~1j"Ooh^ܨд7*y{$ rI:xpxi`eTւkŸl擁_ο'xO}oZg3j]$FLtT(M3 dzkǕ4_usN’Z^>Nsk{4S*RUfOFCw$xFizꚎџ- *[~1)gď D|Eu.'e*0[c܀8JqP4(D8ZYF8Tbp5?f-ƕ9;Oms&M&cl$pv"dcU[#㞥!o>]]hHjjc|m7c5&>x<~;򢻥&9tWvpA$_igN`N+x+x-H-lqJ4 P3aV3ODՍnU<⼚?D/BQc:Nqr~ZG\  -"y2csXƣkt@$prøkFuy[s7H?2_>Ӝ_`Z:QY]}ϩ }zpnˬ@ێIdUTNQ';'ksj3]FT19cn=7mdr gs랣^uH)Oh%GiZ 2 _gXY^uxB4hΛȬ^Y갬Hr>խ>0~^&V]xW=ƟF%Ht [saB\7L{rW2,YU KУ/z\'&{7gt[US)$9]V>!x/뗗֋-V:nR>m|cRO8-.dSsrs<? I(-m!"*!yٹwl~U]z=/qwwv!,<&ܳ <\҅ QJZ*RR\ڊҡʊ&ݺ.:kaWڠ0>t+[DwV*A,p$a98kQ?~KOxNk,"q$Qܠ+6n9i>嘼CQ3B]9ff:88JMA6۵ li"#I$.H#899s?Ҽj@ *O :_VtM/a0=qӏnM|FtU oc'_[Uj]1Km*VN[ots9z~;㑈Wv@gI$`c|-c" =98UepNqʒUӯ+]kՏϦ~_4J1"oǸQ>yx>oc{g'qԿ1__^XsEcKopz_;dTR1u[x29G *<'s>hly[gOYxO^qL׎F+.byQ_oNՁ)=sa9'fMQpzp=*u;V\ێxu>(J~=3ӷk*s`c qǷiM8qֲ#$p@'fMz sy'$;88ֵ&N$gXrx79c4qsߒx{~>}OBzێqZl8C߁X=}yڀ2 ;cץc\wGs~ֵrFrx<yXc9$8< 8h&O<ߎʲ.03O@ry=;8y\cM߿_Sc# !8P$$xc `LvI_ {=~pA$c}'8/Ր p39G?xc#qӠ캢2H' ӱ85zYNH<gր<1n3c<1veOS==_Nkdz2 Ͼ3޾eo7o8=x>21p0Xߓn}k}z_(2,Nγe[ aN __̴S3g<}g@8=hxO&P~!5ӥY.O?Y{9P%-(A z=~`?_ o k|Es! E?,dyXp5@@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@j)CO@?$uiF7$1 / lԄco\cȘ3Puh i~#,2b h1_U W/=$6/D=NJ5Ppq#?SҾ ,`Wx6 *0=p+ŵAӟԎzj( Զyg=@ ӌq@'ip灂s8ڨ'<q4tN)ӨIsch9~ ~+>_#V2owHryA',ZjKl kG7%}uet\iMYo7cyJA?~(<5-7?ß'Ϩi b~" FMf.y O j+F^#/E>~)x:+I澼-ƥ6ddǍYUpNNGJT$[6KGڶZ|G𵬺jV1 H t;w@?68_FY7.UvsA85S|-Ӿ~_4o*״*Cma[;;WHm+ٳeV3\0g^1`yhRG<~߉¼qaɨTҩ wIJIlՕɘ<Ҫaj$+Ż+֩џ:r?`n+11ӝ~x{*)yl˦R#F0zz6_Q'ѯJ& }[QF-׽}(Ѕ_au~X7kvOpFi99Ӎwɮ[Gy+こ[AD33m ^(a8_ ?e ׇnnCX 0ֽVtMӴ>PYZZ+xQh8^w0Yl^Qnbc*_CW/%̼pNNOp9⏤?gmO(I8ri[,r,!}e<[Ms+U3wkm>BjZ{@o+8 ҾKXŔ =1<Ҽ;F  3gz?ʶtJXI)bNp84[7S֭IR{nޖ1ɰj_찌)\7/\A݌uY7גs?/ZYPq#rs<`kԼ ۠w&Vʂ4 O"DHkªʴa*U٥ɿ%IN\S yݝ̫4BRv![$?j_F6'ʥI8$Ǒ^ |,UI|bB6iůkR`񭆒03_?>ץ|>#jvI[z,}g,_2Hܙ$ֲ?RxwR,Z4֛Tq_CW#{}o DdtN_>149Są,TXB)$_[yw>]܍rLJ$wG\d8]C~^Mo^ɇ"a<6s|׳\xr{Wၗx|A>|(\w>e,6]߼ 0a1ό?Mn5y#[xo̗VjAs r"9 Os,ҽLz|Kpj$F6l4#ZӒ殷Ꟊ|nP]$& B䥒n_v\g'_C[/A?l,dt*?_,O/O9fHi|ڵ0Sdc|*5KNGӭmQ"C;BbfbOzeE4ޚˡ*}8ǯei1S]~۷ZgttH3>>ytUDWP0[ڌ @#p{ϦwXѤ6Á8[Cp3ksLV6#^u?;wwwտDZ8ҍ:1QPJKlyg'2Ix0:ssڼlArČIϷ}[HJQFT ٯ{Ur<{~/[> s:NkaPp =:sW~#FG|pNLty5݂ϞkV^~:֤3I]_0;u.x[:W4[~Ylm SNpE_wFƿ\Iu|U]Z=nÖwjW7\ f =)oɂL_wZ| -Sx Υgp1o!ɸ[Zբm5p9#ʜT[]Y3q 2yVd鎘>hJxcqp: gx51#98֌2H#þ:J̘qp8qߨ6`>p+"c$ۯ\ZuyӎՏpxppz˘NG#pryұ-=zpIVH`nyu9#'RrO ր28gl +"c'7Oɜg{c G>?bH9|*ٜN8=I|[m9 rCqǶt`ry p?ís_eoǫo/y5Mÿ~,|@uۍx6O8ޅgu-^6=|^dO |y=Z|9I|F $k߫ .⦗o5/x r3uup>Z^w"!4KMDby6ʊE OWYGKm:pO~.~Ǿ m.ƣ5a%HhH8|!mFUqל`r=+} "#N dzrz {*{֑/\w~3Ns9z]m\^: x={xz-LqǠu E=t8qN((L#gڢv1s |)wo~g!jPZ͡j6 Vi^@PqAWo6 Hm>ď΍4b$.i' q,^:=x_?G\M;ŚT,5mVِn$b^^FuyeUegnZM98_X>dnV5a|B['[5k? ,ђ| N 8y$5^kK"?{j3}8k?mKs) #iI#Aq$|7{!cC9uGOg__5eL.[5{%u^ '.9)RVdϿd*(;Wpբ.4F,@+hA>[jz61$VfmW 0ӴO"{@v^³x~kx,>{j7.pWYBWݏڭ Ly9bg!+:f_EP/I ͩ_&@E8JpCgjc_ޝm!xrXnG˰ W/rxiK+̉sqV]%/i+A7|#MML)C͇1QXHfIY umL:E3dh>K*ĄD68 n J'e5k7IybAmrr:O蜨#_ x>YfZ[ (B1f$Q?<5ʎ ̱b15oz.uEsfЖʓ^YzݿCg]$w4VCi_nyYn6S$g_զPsj/IgpLH=q5wZJc\``c2\`MG^’aH3O<9ךI9}omfM Y"TA;&^*uN\5*9f\u$3\iѡ(X;S^}kêX5F岿{[tE/MRD v@cs83۟jZH<8Z_jy8(IBv^%#;Kg `'N&j[7-B4<ǝ7],݈`sʼW9Yby緮׶\ZZ  HpzrG^lڼ[*IO=Ц`Ҟ*j]v9FHwO^h.<{p+Hr=;WQ8I=x^ idbA,Ip98׆S=f]?S3>TŚ2ͅ$Tx= 0~ϺmogU/t kq5ǎ~%/]mAfO FUƶ[ČOa]oٟ/ |S:s(_Þ sdyVGoZ3c?xL瑜8GP\$scd\$֬>qdJx`>s11Xr388<ԜאF1FY3ss@s/n599lwzui؏L<(.svdX#s9`=:gOX><Oc\X8amO3î;,9\ZĹr3OV_G#FNS8Z[ls'yOO/R\r{\>`7<dw=μW*y'ߓۏo+u%6GBGgkεTgv: t{_z]r.qSP| |'ר{ֹCt$ׯ^3@8vq4m֜9=>~?\pG$3_}GK`zsʞ9 rpx׭z37/)4çh?kn7|3㫉xR h&c8 uMW~&|S\5kO4P^U/`tSգeZoK⭧Oُzcv5 Ox|WYk0cݳ@EPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEP+k|<A7P4𮓠ZYLO"9+xu[5Y.>|bDZ +\񯉵zB]q\d!wàGm?w%TZgeY[69?zHl@RN ~ Golc}%X1z)0O;t}+3R03¨ztLzqP qں[pp1np#Y sа'=8kݹCMh.00rN}~Ϡ펟: ( (''sPwA=='Lg8'< hc(eZzYKm>7;KY-%[9 B񢟲lO4t3&gg~?X߇7 GiWZ|;xAS#Ax#ZW42Z0H  [Oڋ> ?&MgCXEd򖋃X(TÚJ-QkG(*ꓺ%K.2J/eC+i9}rWK/'C?|>sj3= ae9]1>bq޽Kg"-ʎѩxso) "p%޿4<2,znч 6ƝD_qKok:;H xk^J3㡂* O.V\hu=hmX0b##Dw`׸дŶowV0oXĀfY巷Wդh@8{>/omhi+ L%@2q?\}ž*ɮxX8,%U=Wf! N*/5wu'nxoў55;_-,Tc?'ꖷs@MCZ F%J+&ʑ׷ּş4>CY0V-F]I$HG>"^ݲ S,N!qqgiڭH6u}Nw19=NzWO-,X0u)҅}N8=~]*G;Kiv.#~аb&߼q+{ nh3p@d=>k"cG'$ノZ'#czdȜ۩;z~9$zd#?dB:@)B?SץeMrp v ɉ!{gMdG89ۮ֜ǒ288=Jɜuj˜8L>089ε&\z{VLeH8=9g=+7n7\ir9cr t=GӠ?P iwt=s=OscNI9=緦kf  dG?b#s P=7ЃzpsX7\F{t[ܞ$ Ұs>?P=sC#'+ #89>$w1qA=xl8l5~ːI\j 3'O'7Rixz߄twko^* X:*r8g}+*9l|g;i /k|3,T?( ( ( ( ( ( ( ( ( ( ( ( ( ( ( (qa_x/TڧĶڶe >nDpxC"Z k&W^x: եQg 3dv)"kVct§pG8+O:nmq遜`q֯O@BG?*wb#=W飅#kͼ>$g|^P3ߟp8P_d>[rz?":X{GrO~G^qmC@Fq_ZjG?ӧ>()GO1uD=3#(6'=rsUv=#?Ly5+'sӥWr:퓞=;lI_>5c>CNd*Dv𝞟{ijF$Nessvdr+~G9gSG-|#↙i[?7[/))rƋ/o}v M_24 *ucx,/t;nsM `>^5h#O\`(-94Z5$8Bwβ4jIyǸֿ9mdGUj~>yY'7м5 \cUlI{gÚc ?KD*># 1ovgRW<P1zWTY`!NH\sKg# < 2ppp sXG':WSwUd7r 知gk$'',TP} -ʅFюӓ:`Zh#9g_Ae&wW3ϖ!*w;E?gk:W wr~>$A0ẁ3~}znAZRwǩ#-M! p;^y9#bp%RQRkEcV<[[rxA*m,ʹwʬ9?xc\{%(Wy?>+WrH=2J {'N:zs'5+uڝݵ$c;+$( Ms+>T"?3<}Zg8 su⽪X_K쵵/q<1T _!)y+i'\1 S]NuwHq$nv@?JA'dz0N:Z8ƕ/?%:Rcee 9y85j:A<swEӧG͜dG=Rզf9i99>م(.jvcV\N-b 2`Cqy6 H?{csG_^Z9C=O@#Wjw]z2=+Ft^pԨz#lNG ~qzs?5Toŋߵ_%o|YN9"͏\V F5p8 l7PZ[^yo $IxhQki'~2$A #1^yH9$dY Z+ sRs eA'~uquk/ Ņ{q@ߢFh2y㞝k48QHF{q\Q<ס0Ih< :lDxv<Ԍペ ??*s oLIy'DO9R*$#=z *)@;W; c8<=䘺tgW['}mu(۸rAm'?){kU,c gok3F\`^/;T"$. `{d~TE51.QzEyOVMi!VyDj;I-y]%xV003 sMpDmYK`c8V.k+v)H%}Lg[幦39իTRVZ퓈ЬT眷l][^"EF$ Ss^{? yMJWM&؜ 9n5$?I#\t,]Y{XAЖɧ,(.YK%z%dwA=UX#8鎕ʛH w|Pgo1 ^Lk8'IwNyW5,֭y{:ug>~$T~Bkq5s {q9+2N1mF Fvz'$_zuY<`n:9Sʏ&9#0H)Hq+*go$v53g9zI9T9錌=93n8<;{VDĎ0=>Fcס8'3dr3H霌zP|pAzҲ&lg<9ZҙǷ'u1I:dwҀ3c'VDNcZS\qӐ;wq3^; 0x8lZʟ$1sVČg92}MeNz2=3T0xny9?sX`'>r}Gp{ǟ:cA ^NzdI<u.qЎukbsc <\g02`]r9qsk䎄AY랇 r3sV93#n\qb{Xwߕt^Iz~ÌErW`z8R=rsGO]upz'83\2FO^QSsM݌āӭz.9$8<޸-ErH(̵dy s&hO9;vײjdxWkQד(Q_E_v_ěmFU-rVo0;HkIy$WQEQEQEQEQEQEQEQEQEQEQEQEQEQEQE2?r_&teOc mq$9$~u{p4|4Oa୞ylQZxǞ,0H4  ԩwp pq˳q._]xZ#.003q8=P1 9=st|3! (B܀R3qϩ烑ָ-1F3⻻@^S{tvt2A`sҵ"y<+2#y{#pG^@?IP𮹥OsaO`ePBGkEUP%jr&wV{Hw"tnN9xMKs}`,s@*×&X!8'_5g&I9R=>_PQxw6ݫmڟ[Afl}maseaQ s^TA~WhRjh.GU+gc]kI`s8'Mz>c/gOKDF9;EMf+m'!I8=:ϊqtJ~p8:dzzq^YeI [hӽvvz2m`r{ڼ CO~Gsn+[z<9 as88Uw4dA1Jg&X1ϓֵ-/^@1\dpOA))ʤ ŦάTzj4'=@$7Cz,( A܌roD cy=j{:yUPs*G|z^^Ҕ1hIOhwZƔ6  /\Wm!3 #ۑdYj2چ!J)ICɸ0HNx'w39>cӹ?šʊU=.oPwmOO5/" -Hu;u\ISx_#ϸ'I둃~=k ֪;<>n7NiVۘms9;yu5ar0SK+y?Dzt*Fɻhm~%,?9'z-;?hKdd1\뗛4[Po2߲#HRN+O~~ P8">ɠC \R9!u,5J޶*hL qLʪO~H'ީ|I%?g_}ViƬxXb<7k-Z8o [H?M{>RJ09Qpo4ߌ:Ku\I#,oh2+Fc{q;sǯ ˂A<=z>9䃜89'ָX#=LG +s#=:zV#<9nytր1.yݓrs۩a\c8NAs[wdc=Vǩz~ a95]`gNr89]%nzϨW;yHq33ہP-v:0y5ޅ9vqWy28G^\by `g'?q8='## R8:<qCIҀQRSIմ³m$7REPEPEPEPEPEPEPEPEPEPEPEPEPEPHFFzZ(I,Xh{vgKR|Ktgc+9dzMvd?,\c0<5Iw>)4,k=]̞Zx`d>\~  p/no L!#`1ϦAϹ78j=;{w=5! В9P\Fpk'=:߷\f0t#gkwp8  Ở}v0x {gzz##<քg8z`t@*z?,fAzT@`:^421NNxc8_qR1O@8'ӊy'?#D[N>]~ r=:֥b}f9Xk61ch|qv1V񦁦ČoX@A5x6&Wi#n{z q\JŶsWM|M{JOkg VRR #'ajI 3 :dA^`ұۑ99ϯFꚃo˱rA\ 㰴ӠywNUc$xu U }8xkψVpJ&ˎ eW9¤q_Si_W^06ΏA]hwBy™~=_ m :7tfHZۄ }R p1$ tyqfSUn\oO''˯s TIǺ^GZ~*xѼ#{ei*yh#'hms$N;_ٶώe=*_z (e_Jc $*"K/$}KS3$@zO~Ο|X/t_r?0~x)Z5cM57"9vy@++PlapDG|UcskOv2a5 ۱B=z{5- 2SG( qj1XΝ)E}.Xӯml~Oz^>,Jn"`y AO~iS, O’ÀA MhN'Hdּ^b#̓ aї8XNqާ|ӭ4??h/u*(uy3_oW{FryS"H$Dud/.oQs62'a7Zvij2N7Ԭ]ڬ0!dA9#ҾX+{Mr@)U9#k^yqJժ6JOEӺIO!ON[m.?c~6.5j6ڍ-q[Y>> NN*>Q%ӮoJݱq@LL _K'MCLgxgL6ײ}:yhC\%Ҽ@=Psdp '9AZS69@TH9C~1G$$uβg+3Ϧ?ýix zqq=Xx=ۯZ̜Ө##gyuVz kc ds\c2.HasXW,Gsy=kj9:nOx'Zĸ#pF;m@9땼$A#+'=O?Ӛz}8N x\&zg'z8? ![0skA;LրpRÌsOҾFհ >: dv?}Ȱ%pNs&Jrpzq׎?' ?ि]%_f\K(AkNWxJ/_n8jgn8ӧ>€-Nyg'S@s9^??ʝAP;I
    3*zN3֜נA7<;u?c#xC~jF=HO#*8s\~6L9#8B1Ov:8 j9ǡ19',YyѾ!ŧAi|iQfBoW~֍+M,bx" aĪ6I6q_x7;'e٣^|cgi]k~)mxÚ5գKmFv Ŵ^cƚeE,RI#$c]X2*A+SJ]IEzLB5_kmx_Sq!?6c߂F 8ݜ`^3,XfdÜ eLʙSg~p^ :I߻zҬ|/Uo%ctZ"'i$AZkA26p2瑒:O% Hǹj[H$r=}3\riOEƷ-Um58*/tזe#cך!C~Ang_Y=oaOO'מkվ2hDo?8cU[:/Ԫ8F]^G*QPGP 8p9ץ,zyz`u=hmjw>Nj-!>Y/Ozӥn[SOڌdlt 5[[Fa}%R7cRvMèk)WNq~l uzd<?Ȯrĝ@Rռ9ɜ6+pvu1qڰ%pYxxK~YLn!~!L,fn4)k%SZ[xt@#t9 .=ZuωTyP$|A &X#:M{5_K0_NbI㍓ءum6`lmK=D-탁j`9'"^$du [,6>9Yƻ,EnU0i'%wK~##ϥl¶O{s #H.կna#/ڔS~ =&2|+V+=|tkmL'5q}6 +c^H󝮰NJ2S(NhԨ).T:T,^"tbVyCE(aѭCy|$>m^㋨hf.neSqv(Y+Sbro,~svGM]UXFNpxg5\"<9۵Eʴn ӛr޿ʞ#p=OfSPG>d'۾knU 2~<12)91v#{\C}$;v0`sz5iI(8B8~n5'?T`cp8gs!8ՊSQ]⚞A`p\q01ןָ-CF90y}}2:eG9>Udgӧ^V3 zǿ&#9Cqad<8漳^/%نv`C+Vy N=i͌c9Ϡ+"r0>n~9^r;Wq{9:~n=2A;0O^0_yޮuSyuq9Fz9^{𧁒[Ou=y=p9xLjS1Ls;^ٮrԂ}zry21߶x2?x8־Ryx9 g'܇ 5^ ׋ؒzۓy;`G81 c<}q=Nʀ,#9#_F:wOQM3 3Ӟ}HN9' usz w$f#9MG~cinx=tj7y֧'9j#@ h7ny#_÷NVF#=z2y~3'#89OyVFcN8<\R08:UW`Kt <+^5Q8'Ԟ;PR02AA#g~ 5 |f7TIi_<[igQDo位 Ki3]|$ld\ÿ=fym;ŽlF.+W<_umsZ=eEb16_#Ưǜx2=9r~'G\ۦO\fkB15oq]i]ᥭ*% IìPHQ=M߈uBpC_nW:||Z7RasʁD\  ,n؜Najx)$~ˉ֌?}A4+Tv#oTpzq]^wg枡S^p0_CiJ]D:7=toHctm=! =:q٢}w-h),%cwCG]Of[[吏_|;bٍ\D$+%o8LWO$]m{dl$6̑,)W~?|E? |%n.]:BFͱԶ^/ᧃ㶏A?"iV&;,|nj x!`RvKȰ^ĺβ0*sd\?~ V<==a!uUEy^Cե'oiyYOFH=7_'W{0 >1{czT=ZM_NI3bX9p^?+n3$B8#*~]pIK=9A¸.Q;W-,i({J m);(=j8ԲEƒ=W#Դo [Mq{rcݒ̣$p| C㖡 xﮋΤ+&#i3ȉ2I7uY2h^S\:|?ĸ;[i֬GgnU_9h;^IO)~{ <=$ھmXAFD p _}¼US>$=7ag8\;ZmiItv~F~O?_G#g2~o!k5)Ӽ;&zǗ!DHk#^-[ςLM3GݾReu+g!eR$D^K4&i6CcZUiv,6vvѤvĊK4=Gl=k7kFU?fb:Y(>JqZB ?3sٔ-pzBi?/;=Ǚ;H^z<{yk"g8sӞ1Vg p8=:cN=k"f?182==>7s:Fk2V=:ǿg@fcrq8$. r{;#9 I?˕2HP9=z}q۟eOӞ2|pr \0:jts8nkI܎ˌB;i;{ ($c*wyk^6zw?a6{3~x-[Ӏ89{˵P{f8{dI;cGktw$:#8_Z =1zp~W/bA s<vǿ@gzt 9' OyL3ߎqGOh ~( 3qߥG㓖=S|!cqgjV`pIЃ>P܎F3RnoZ$ڀx@19@9{vɧpsۦq:8Jy gۑE1۟2>8<zUV~Hשc=O5QϰuE#{ 'zJ'~<9J>[~-<=76|2D5Ok]'Ú$30@2#EgQ; qU**T(RnEj.9ש TRI%o>~V?_ j00__b߆LG ۠GHS_YrΩsssyuq;\]]\\#I݉gf$I5cO_ojԑ,;i4oi1䭝PXJM&^C_ү [ak. X;r+3us]m oNo5j+.f^|<%;K%_kΟu׵4A d ykZ[ƯFࣅaxp?*<_-0D_@n<=y4U$|O}kN#*JӲEt]4g`0&.^Mnw~"nBq?P*$jPXJ; XW 98^O^0Ui;Ӌ3ӔLo"[Ԍ?{WgF6=ZYfFs#<A^ ی8ε%+8Fqߞo'g|{.9_$qV^2DOp;9|oݞ1cڵS]#pO8l翽y&ݻ{D7%#kz#O?:ϟŒIy= ׅxrNs3ӯqϠklc=z_\b }ayҼ83݉=?fCp; rj:$zOO{ j,Cy#g?s!B2[' 9nF rz7?4 7I/OQI뎾F=?aI;d`7\1W)yA'inͫ˵|<8ny\9b] ǷǦp=z KInp'$dqG-kEySNAzpOO55?8G2(`ǯִ-|/,A;#FO#]?NɹJ\ʸ.]z2N9MBiXg<ͫ'7&:tjUiFEKg_ќ;u% Ò:zՈ-)B>c=ӆjگTVZW#9p2?#sl=_J*J(ѧe$JS'9VۻomO׹Y?P0 ܏`U\3aК͕8:v )'8#=3޲qg` 8'~2sNG<SۏUR#AO9=T̀y?OP)[sq}2v:jמzǽf8q#@n  ~3 t#zɟ|I y擌g9)N$x93?3{~?Uߩ9:LԟB21N?,}ÂIzIz8d~b'# ĝP}G;g=zPUˎ~'+'$2=/ʵn}0Cøo^zgӒ:0Ob]1ӓё}z0 $`n0q]Aqsb蜜 tǭsgLc#~z8N'sq֮F9Nqqq\ߠϡֻC9`<W x=yfݎ0[<(g5zڌ7#<N8\+ص7{8ӧ^Ҽ{]r =G'4*^%v^_1>Y=3W)v9>AUG`3t<0|u"g?퓓~ Wp?e /.=Wե.&̧K89'Qk ʯOߵ$sxOuH.͠ HiQEQEQEQEQEQEQEQEQEQEQEQEQEQE!~/)eA13<%c9m[7t{׎ߟ^?ϭ\~x(w\q#?@JheS% '~c"{K9yG#ryzΙ?n4 篶Mtt>sV_u~+Lƀ5'}'U8} ``}tUl v㞙z,>qiϷ_cty}灟q9>@ NA##9Lx= z#7=H8gIjFncj`3sc +6 ?OUg8z` H<#c##UfG$rqZs=vϿj~u/:ƭL/CO<-,VpytUm+%$g2 ?63ac1uU=JOd]ٵ 5СRGdW]Ri?߉?gOyX!N+JѢ;WԘV _[#P\_EWkLLRZ\x# '6Hl^~??jO.Vf3Ǡ~ a׃wBƒҔӭJ5̃͸IGNjg!dR8$'+|31,/RroIUI9꠾l?)0$c^֝}{c3ĚΧd]3bmlE_Z^Jӭ ciŎ2I'kk4Kt1&p+yTgW՞SX'ǧ+6N0?s [Ni-g:D|9#EU2WG^=hY?co~ ][ *1JNJz)B6#aWr:zʺ_/~gkn+ Nr0;:,V|G}]q9<mydʅZ"5d;sktV(xLtҏ3|nMZk|aמ=7p[v^wcpsLg5ɮ(02;9!rw#pOQ5TKCө QOLF{@aq{ׯּ O8 @d`˟ &U F0V%rZk^x08=N?+&` ־s1*>9Ewpq Wnʫ9=8Iezw^0<\ߋ?;Fx16-t (Ty:׫So"] 6R@?p ?Nk?a);Two Om:Ns cy#דnO'  $=A_oWJ;žLo*u(9䃁GjKFt׬N-joI6M,.Af%&w^mҊ=_т {95'~xV~<0 gi%LQO=+࿈RF};MkIJPߋJUe7X[TcڔW.td[/^MVˀ\ CceA^$<װx CTMcΤ=A<|I{%}}:6 N'1+ s@ƙ,vo}?E4U"ӭ5 1}j899=2kœFxtIZF;lU}%~Nj.09{Vq I=|>KY[6 }UO %En)f\{ 5?{&_xo:rM{-d+M<\U $6>gjsljY$^99J̚\88ϽC,pYSI ?ƹ[($7$ד-}y:zߩ=IrO##PkOcAZ<ae?mL/c-|?}nfh\ԈNQEQEQEQEQEQEQEQEQEQEQEQEQEQEzZ.lbE HYYm(xYJۂfб(,*,T I0k?fmz_x^7.>&T+4"JY@[̼b@:Pp!8{uzF|0daxc(pgG=kմ?A'J49폨+4ÐGCs>h# 0quֹ&Tx?Z!c=N{P7F7syF3դax sӁր&݌t:s BsF:w$zS20I1:{Snq׎9P#un3b{\8'V(;7FOn:RE!߹>)b+al\+ngmSx*:"7^ؿg~\a"F`,A!1@<`fm!c3F"%w`#_=Vk3K[ 7`#,>pqZNCB0R4g#1vC_f،:UҷWR^k^hF[Ķ-/-l͹IxןzޔH#t%jYj*H.ᑰy|ױh/e+F7qο0*UN^֕H]M{>G]Mha xWCysұt unm~yHz&;L<'^GWbp1z +2^#PӣRLׁڽgA ٙ٫c?hՠ X ʊ4Tq$t>aMf<bqb ҃_$-R~PQ$~ONvw>d:[T:ɬY_O}I/~: qM?ZʠRJqvGЌWI{cҔտ3ͫ OivK8.=rH=sֻ]+}up[ 9  Ͽz&/ -8nTgd}}~ Zh|9]+;1ѪjK"8ۥ[wT,K(,IPB;fU@*iVt|hO*ͣL=s޹7o/$|2HHOMk: ЦkM3<'s%S o{%oFחCTxM/ޏީ[_SI ݒh#61؞`եoX;`pey*u4~3oFb|k?(xW÷ ]Huq}%\_\$KNju?|@ULAapMm"˕=O|\ rF:̖N8zg#Hp>p R:XγvI>[yr*7^4'c [@mt 2zP{xNI=IH@Uxҟ,`s00=q8٤lҎ}pst_Zls9+:YzӒycNN|u2}jΖ\dgA<ɐpyIGk.Yz=>ҥPIxylOp3>9K&O^r2NA$utzVTg$=3A48< wz`ӵfJr3*ysrs׎3#̖A$w9P2sʳf~ǿ׭O+#߸8J͚N1H~`?@L真|tclD\AVlsn3#.W'$vӵUO9xgn+&frCqx39\sgTOS9v4Vv89=s:ǝs=Gݸ2FO|3¶9AǯJ殜s<8Z¹~O?9$F1|8϶1At$FN#۵r <qʀ9AN b0q=OW ?G?]GS:{\>NzdeI=? 5zq<{qk#wא돝8r1`O^OdstXI20Al ss^$oݿP2r#؞+g2 pY˜g@'x,$ö{t⿪3S6PHꟲxP'GH%xww6NH l\yS^dqsQEQEQEQEQEQEQEQEQEQEQEQEQEQE|CSþψdEk2J[g޼`'=_C۪h3L1sk?lIo+gItnet{'FG^UD0G +[bn<$3@ Kc'|>X ;:@_\YA 9#T=G㧿iP`^GPIS^]<` ^=+tF==y#^ -cas-r;0q9f#>'߯Zޅdy'בӎ7c$u8*P{}s۽gFӌO#=}ҿ@9s@w#'lgM,:ێF8scҡsAM-ǧ^:{>Aʢg}G`0OҚπA3Wcqq@9{c9's#9<:һu'SHޫ;H88sqszo|a_z}ݎnn|eg..1y i ^ Z96K\6{y~>VF9=:kz#8f .,6|En̥ØΕ: VPA85RHFp8뜖* sո qw?`qOT5(NetL?f⣉K-7J#u?YYq 4U7"b!P:V:#4ƒ%m6.Bc1I) /nNL9,=GmťGI'g>KRieu9tDZI'SoV٫qv<̑펿z2|^+x'ΥӅ6?-:b#wQQ*"UU?Lӧx;RZz]F B|{4 y<-~ 4o?!po[$ovϧ5z8lim-bS *9Ee9zgJ;N=8}+zK6ꔡf9gxg->VwK/`uTq"h?mtlv+:Wxg x_0_Mv8;X4"8'=@瓞2y9>]gJc'۩*p6Z\וVSsB(~/wX$o,[pBѭ4uqBqֽßKkA}GKO2KNOzG +6Y #c~^8CӥQ֢u~v.gXL¥E.UX7'h>(V]sAL^9;Mhz&-2O(UR+XQU@0+rIPA '#3YI9 r~},˰iG pR<1]VߚMlI>R8x>YJ1=54O9#OfL3Nqʨ'^'6IH۹jX~1"ۦ<8\}O8'=8z`v~̞CO\*YzN~󬩧'=()x}+.w$`x5$pN=~^~eK1}{GOjlr2q1>z54@#z4G *˚Q ӹiӜIY82s,Aqӏ_ %y#󎜚I=8#:ɖA0>=*iy1{L9>#=@/l׿_Ck&YS'?ƥ\OsU4q8#s@O.@x{V5ÜH= Sq9遜zi1s< 3ڹ'+|8? { _Z/\ls#9e랃2؞<f]FC9~_\WNyIۓs׮Pssj8:3S^E8; tq+[:ߓ^I7q=>'>$l3>++NOq#qxq=ks&[=hw~G}p8C~$aSSܸ7\d-_OcHۚȉTGHQ N89<tQEQEQEQEQEQEQEQEQEQEQEQEQEQE|N ׷1;y#8߿C-~z)aG9WK߶HZn}XrWN?p3_ĿzB{CF0NLPwN~^دrc*Oߧ~<¿\}~\`J'Cp?h ?w׌Ͽz18 rȇ|{zק{xͲ=:psߧ?η!nW9\ͫ<矦xn87F9q~5a[#ӟ˚d=@ typr9ׁQnLf=Gb9^r(qנqz.޼sNȦ##{u@$c:{{>~ZF뎽w`#8:}y@s8Ncӑ;zpI;7qq9?Ϛl>\gΩ njprrx=y63g'79IA=3@ su<䑟sj`y9{dۨs=ϧ$89{7^}@NO#}?֨'{vY0I<#~0x ?OYy<럯o\Vd<q23Ma=ǩ?f>p:zy@ 4zzk6YNI>8'I㏨K099\sG=k6Y9#u9(FrA8ӌ Κ^=r@2i #9dfs܎>i-rCLr3?ʲrG|=)N9<\rs54:u`3 <8&% t#}j9àxgI?=zsZyps^x~$9pcO=Izu$d9^I$A<=?N+:Y#'{d~4fz`p@9Yq:I,2O\s49OTrMG9p81٧u۟jINO9=pj`p@#ߧ=@y^>U)'q M9$?^yRJG_NLҢaqpy?/ʳ}<(i&f9'+; ܜ|Jϸ fbH瞝E,Ӓ d1=AtD* /H? pQEQEQEQEQEQEQEQEQEQEQEQEQEQE~wY 3$Kc9)??#ăBa}0lUHN5* 7>^Iڇ"dh[{gOrcjs+(j"ry󯁾k 9=?ZzGO=@K诅?80}kcc'~l&e¡ ۠N=zUcdp鎄}h@N{pޟ?*܉<``ys6p2Au::܅=pzۍNÓ$c=Sסzՠ \^ğ\MHs vc!;`L/?۟ʀ'g ~GUw~gN3Qsڠy<=;'zUdr3{R9Qp>lǵPN!Ns>9S9`O~_G\d O^:I rHϡ9'^A8<ֳd$g>4٥s,yz~u,׶OM/lzuk6Yx\wh˜#=@$86i8<ǯsOLgN0s܃߃Z&` };sK1g+2Yq84<= `G1$wYM9=t`@8LTϡXLOS'>dy-ГGαчQԒC:S盃'0:nqp;:Ju7x䌑篽s2`cc_Sר^rI=뚺8#y8%֥Iݖ#O(G!0N=zsdOS8׿MO8xOҾnTNq0d(/Z@zu89ҿ/2W@|N:ß־dۖ/rq?x4I8tnxN 1~9{E*m~zc*FAz(8\Az #JL=38o'x0098It#a3=;gq߷N?YQ9xVN@` ~.^rA'?›s>bUIlp}iN=s?T+93;qP;wnd cz,p/s^sDu ^?J$H\ $~O;qϒN OFxJGtx$'8=8{8,ž0;r $nlv8Ȏ_I/$` ǵf/Qqy$JqבϿJΒa< ~4rznnF:qYϞr8=0x=9:Y9 ld\p)K:ӞJ̚osׯ^3g9 s2y1YN0FqFH⣚bA9^׸+.ycqYt<Y3L}A< cӷ@8{88=+.Y3Igy85c'k.k9N08 q@秿VTӯ8#?E5`ֲ8nxn=Ox@&zq=9+2Y{O?W=3ӏҳ&<pI=GziG̞aӞPMq޽zT9c=pz=NrbYOdvcgI8@9UYnspF99QY]`Gn:ǡ9翽gM8|cuvk{tے7pOYu<=8?R ܐq@::˚x׊5=1\=zVt<#TafprNsϸ \9zoΩ=^#8׹'<9'ԜzUI.aq[m :/r? }j8q큏_̚?'@grTt8L9 s۵Vs}qYS\vw9뜑3w_YS\uO?ӥVrsYRsր-Mq8'Ay#nsԌ'Ue<FqϠ>ֳf>=n:3p@a>-G\OAsUe ؜s%_ '8(=FF1߮1:>-=~CⲦtǡf,I?'zgfK81:11U8zfg'8*{qǥZp g:=k:=q#p3ybzH g=rGur0ҼW|##=@kե9lz::bRsb<IJ-p9#S &^8{WxRCß_9x^%y{slO@籯2?Nb?jwH+ѤaܛKtl;ۦ9v?qzt?I<w# O|ac۾>,[9ooG@z@UQ@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@_G_:\_"~լz'#Ӛ6$:Jn?|z Wjj6QjVu ͔A@A6HxΙk}Jotr77r[!xH# |͍I 8>g%!9I28=NO<κyQ=x#s@r09>Ȑ{=qȊLӾ}~mezg_2z}y$4=gzw1cWy>Or d`d*d|c]9C $Iz:#ΛpI93z~u1Z$nsd| zdNH#קSe;$nyP!=JϿ8㜓Yɍ#sx|ק9`esyQtY@Ϯ9@9eV9 ӥ,^sfM>Ct\积րi=FqyT?׎{sӥc|q.i<<I8 ϯfM?|M1nzC{Trs^3{Ps0854r{lxazxeK0^Hƀ4zger{%;Lw:dA83׾?ϥ9ngoֳ&^y@~5r7O9x~Ѓ}ɪ#=yn<JǞc8=rzrTvk#$Fx*k8?\ N=ez#8VD׃Lr~`?45$[gֿG B?0~CNwb܆qt]G +z/쑰 p:cd|1> ;b:i/gw`cV4 j2 a45Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@?_憚]kڷlBMKCq|SU_(+.C=z~5nn'?߷fm[^6@59߂7- |~\证n *gG$+]{_q3;`?J"dSzLޅ8ڜp^sÿ^kIBrGbHk|?6V1TH^L/ qߞy#vOm@ Rcv~L_B1=ꌓz=|>=zVls}ey9zl~{~YuSLt ~=8?zIrO~u4g=I=GS@fxzȚn 89@I8=:Y  $  dO6 G?|9YSպzp9眎>3Ǯ_ZȚ|ĀpG%'@U53v=:TS\`q:+q N9'O59u'<1YS\HgpsOl V{N}[OךȞx<@G9=ϸ$gdq*=p dw#ׯ="{ g0O==g#xG'댙pNkp;g=z+&{zd ?hKs@3O5=z|ׄ7_a9?Jɞ9ןBk;uzc?J͚ ²`N#}xϮ(Nk:O^ du؀zӧfOysNzy<ߍd{v翩#4-8rx#_ewY2G|?N}+.k9c(ZkG8=;*ʚc##?Ϡ?Ս5R ~ڲI9pxy%w HǠ9U)/AqZ# yҩ=8}ox!p!|j;g$du SҰwzgypz??LPsgPH =1T:rON;3X_09y#DF@=< ךzƞI=Y3rG^>5=^z8@ސIGר稬'$t9#dOzIn@ JȚpFxǯҀ68NNqGonZ˒9;Cz/lӧ ۸y鞇ܜڱg'l6z ɬi't?N?J˒+ˀ=0}G@^ fyq89+k:>GSc'H93@n.:HZŸ{g?θO|GqD%I82}EhrI'1k zltXnX3nFprlg"+]JNIx$sr|\u8qW&1by-08 Ec^9xS܃ЌrJu9 H㌎{θEs<6>'#'sm۞3:?p#x[pIIgs־r y޽O'#JĬ1 R}rOϨ Ʋb6;_gď 0τ1<_ܡI* : >4d#6Tfێc?%ob05mGQh{z~f4<9G' ~t'Ƿ_T2 #:L$s:#=H8$cԞSAx=zݩ&2NꔒN9*p IO<֪//$ޙ$F8)$ԃЎ?_Ӟhf>2qY#rN91R6 rHY3L9u݃>N݇>YR8ہ\| ;ɧl'd8@3A@O8gX܌ 01{u=܎H'c%#'#5=A= x'w`,3۩95=<}> ݎr q韯?JƞgTvHy>k{cH<Zўd8OsY݃0 ~g^:VlFF 8dMx e<\u#y$GVE%G 3sg^Qxp8=0:z{VDy<5s88ﳟ3Zʚ<9=:V< x=zP@ {-ssߎ@ǩDxgIϡ~u- Cs@3$Iez:y: ƞNS:*Ǟ =:3@sޒNp.Z̚`v9zk k8/גF}eM~:Qd=s_jޚY?0>б8kk7 Tڀ瑜;pA#^h~k3m'fM~2FW9^q\ק{.1~=:~I| <1}jÜ? sߟ_ҹy5'9~ u8נKHO*}Nӷ?ҹY5~˩H#tq'&gԸ$ӡ=}\gwr2}Kw&98*x?00^JƛR'Òyg'+6XMg GtӽL{=U p1}:ν'n{v׷r^=`s rc`9|Y6##Rx# W~(/#62:W,9=N~?5C$?-j.aĒ!T!'#toeVH՗`k?_Ŕ ^uKY]&ZHc4% ]S_S@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@sG.O(!U/~o|<5sv[GS`+^9nb О+4W8;ûnqI7Ë&)#P22x8?ZAn #$>_=Zqcpq8=1{19sϭz֝'9=2rxg[H0 r2Fqθ]6^8={]]8=zsZ顐8#<s8\#Xи8z#}ZAs<2g #p:DdNz}ƪ$H'L&yH:NqRcrN1ۧ$~3ǩp}*pH#?>I@LU fzNGl_ʒY0 0͑9%?N08oZI999~O^ȚaNgS?O\80x ƞ|A3ߜPM7'N0N {Ȟ|=zAJKc73#iI+߃M:}lcs3'<~k{N[ \] ><}k  G={Dnc g$Vy9#Мq?Z 3}`zV$C'x3߮@.n#N XWF@~>xc1nw?:8`p 8xLPۋ ss- RyҨ\^s^OOq'=qu +~{s`H}C<}?nQ4l/-G\gAYaHrsߟơck}C=Æz/I cqI0;@Ͽ\PI> ǓV<;W> > ~9&1Cp܌Ps&u3TeF{cdpjqjw<GӱH :<1#͓T8=S#vyuuq3zV|=u?\j|y 9qg P2c1\uƴ'ps׾Ұnu'yu;[Pm??bsӌIN0X$p:'~y9~]9?:GGz4z;^>odrFWkd'N?k6]dsg瞔N܂I8>>Cdm99uμs:ũ {c$P}6OzpsלgO%yy^h9 ỎG ^ObO?ʀ=MS<3c u59s?ͫXQwOTK89#=ʀ;uP m#^H8q" I'瞤iyO6r9'}stUk|Ǿ?99sy$Hמ}vH3=z1^Ѭù$9;XBǃӶq{.[,0G_lBs qӠҀ,Ǟ8ԟʐ)8{ssǥ*GÀ:wӚ8FqvJǼA$rӃ]+FV3q7c9߰+ CӜt6q}?HR ;x;@񍐍@K r[u _,~~ XF c|-W\sL~ *ksa܇L-O5S>dR9~< s9:=z}z{v=rxIG-pá `L 8a'HNךe Hc"ۛA'0 |gA\r$>Pno 9nxx'^?n8l6I9W5uuw 77gp뜓Ns;=uz9;I7 g=Vup3˭sWn/qܞO^z錰:M`\~a<ܟP1'ӟoz㌒{~9@7-3뷓538Nq9O=@< gƢ;22z z>QXW:F17qO]`]j$3cs?7ֹۭK<NA PIsX8߯˭a]j]r9ӧ\ƫcp8x+TsrG8?t@dPp8'9aϩ'w$dy$?ꜰ3p{s:I;8_q~q'=IGӁX9_6W~p8$}F}?a\w=zcPgq0{zŸFH,}ۦ+x 2B0KocNuq~gg sxMpw0un<Ƹy>`9Sxt{?%ή8qqמ\kcw'רCX:_tz$ҌԌscIRApH9_¼\v䜂FCù@ yǨpp^nRNSx8$w& yI2v;r1;0='gӁ:g:1뛷rzsǿqNs cHƀ7U pG9Z̳8888t$c}H8sS-hNO_ϐ894aO\yP9G8}(2xʡ,C:*#};ӿucv s28rO8ހ8Qm$`pFs:,Py98_3.H?1 t<Ο5 D8>=3_fdW q&|:|o6_~!H4X#kG +h{qPrG\`c&[Hpqu>jػ9k.CFϯ^1\߈H$}09z5δ?0qI+֔88k.IH9ҹ 8'es1^=J\?:W=q(Σ3Sy5$y?ӓ\ߊy?'R/\d?{ELjg2);uN3H?W2FIoҀ=˃s>= I;ק:O?²fZ둞1܌~-?eU?-:ǦM} ?XN22y3ӓX;Osd<`(<ğƑٛ###84<+Y3pCzc`G|p?K?r<@P*<(?0$3߷|wbؗy`\b~~=:P^+Pxw|qW?s>oluZei=NqL*z$d\.F /g8=~^vĎqp{tGP7jגÂNpF9yZLg? ~u8LI8#''{ʀ= b0N@'8m%T q%c8ci'נ͉x9ֺUQuXENqq;dG?-ٰvI:d3j,Hp2N0999KohHi<קa[p[x8鏡(8`灎32x:W!}x0v<`r ')  OָgG-3<O}(fs4' 8o0I /uqsׯr‚{lo+5o;89?^*_a Ga=hqp77Nsֹ+sۧJ/DF13#< q9݂8=_8ӓ\2J8syoy~P7as;z52̀u{ pG@{>blcֹN% ޿^9[ s뎿xrCzxA?I\犓\2srFq'P7p{g}0_t8 dB+tc$H9`~n>vx $5xنT~x'/|cOppO@k.A>ƾk)-@$xFg9~=#ׯ^5^<7c%w9|}`&'c$rW)w9dFqrޟ@Q^x ߽ݓqc|q;IQVֲn1$v?}sN'lm=ҥW8qހ4I'py dҨ+dsҤ I=A}\svz}xL)> 9UN(LKrFx=3:t{WId@LO5ip;s=6Ɉ_9SH]!]z8߽6 #tϿ^[(1בܜzrƀ*61x5dzQV!?'s܊Ҋz@=/PdFN3ӯ8?sro;2A'ПtS\ qc=kԮ> x>9}Rp;^KCɂLrA}滝bP;n^2pzpx~9Be'psh?xux.8cx|O5 1O"-F 3*@=ycl?"&`t߈%fcey{g n+J6*H.rsogb?/?|{csmַe2[-]ƒ[\gRjI%ka#G vZIo1(X`HU@UU@ ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( (8ψ~'|>oCĞ /:O4{QhL',Gf ms_*g@<0zӭzy89`;>n6=z{Vy\$ 9ʏʀ=өsֺ;{G$xgϿyn\v'$QҺK sק@ q`pI}})|O<`P7q@R{Ғ]Þy9gO.p3g1?*8 8[P'9=ONA9yZn#8<{㩬;G#=>^9HO8$r?ְf$Cנ΀*@lЃ?r7cOUu0 pLNW#8H,;2npFOnnL~&_\~RwprH=G{tۛ-s#׏Ҁ)j{K|FO'{\5Pp8 8ڴϔÜ $w=kϵ;θ`0=xqԎh = ϸ  $zRjWo}$sq\,PG?yP:'}=2?Z-Qranߐ'TzqrNF &Uw.j:aI rqߊ5=]@acn3zVN݇sߌr}>+5=pٓ ~|jZx 3ou yo8''5CR9ӎW7yb00FOBhԼBIoSH ~t=yҸ=W"A =993|LT%Cۊ}Kh'NO=NO^=ԼT`~OSU座q#=['k͵o`e$|#S^/w# y8$Hzp ^7^zrk5zp~o"{P~4 v99yt'$v#^p20bxڼRr0ry9&>{%=18<^}A)Ǎ^y{F_\=52Ob[\9Cw.+28luFw铑\\wUV9%Xy%?\@<着#GR{YR3gt>>Rok13? &kM3G*cpT _ه tts~ |olώè,gyeuk4#U͎*pр-vONľ1|=k,#P׵fX;M3J{feG9*?c!}KiXw/ 2W|tXbeFR dq|~߲ˡ7<~ 4776 ~x?ZD3:I/)g+Ix#G lm|MHGZ]4KY[]_ͶUvYa] eh'~o_58mFY\j:-m5% *3B/rI:c?~ϱwŵ߉ߴ)`N[$`l/p?{nү ?E }<٬`\Ɵ|J-#̻ӵoIe31$#ex??kuO7ڔ]6oI-'F~:8+T#@R~z^$m!xK<5gk2[^AK2$ČmP|g/1|iǥ7,m{-+KkGֵkU^t H͜!iq)?f(D,9oöKǾь$`=ҟ1퓑®Em+Cqg<|zm{,<>YZ1(1!}}-':u#?B;< =_xWc rszz; aI=h%NGn6=9MHA#ߞ?Vt9o^]!$Q2}@θ2pGQw:~T$1ƗOܑ=;v@1:p@;/j]?G$.9OJ!]s9PMs1;s]N@=`YHnv6jp?{{ g=OG몳]0#zg=B`N"80@ <Vzj։B$@XۃI<ޙ r23ӽk $*ͧ1yClxÒHG̥Gr96u)GP'cʼY@ 7@۞ߥrsnAO}wdY`$pgӚ|WmPO`=8ۯ K^6Vuh'\K$-i\M6:\D4/.J q@Ϊ0r^99$O_zSTc>/k"D79kj;{}h;Q̹OOuv9$c^/jG 9_Ju Sz(#><7LS 9tS"%TPy889zzs=y#8:28 R?*q9 d~g 9s8ی~_,3c8+^A^^>뛀3}H0sSX7:㑌w.xb0F1F:WyH<<?Ѻ:qʸF; 6yOQy^##G*vT=:}koN_ :7#@ 3n:uzpH=֞}rz``^gߟ8#G4KUԓ$܂^ok:<}D61t vy`< ʡTï81|p9')ƱaA=t(ˌ|=?\s-յedgԏXִAodg>z^C~d` =tBxݎ9$gZg!w׌[~mò79}uk5ꃂ͜x8<}Ҁ;Mk eOqq^Oxe 7Sד{5F zxοy 7?Pּf`d;S*=oƧ!q*Mwd,'އחj"f SQύ[^ܳlŏBqg+5ûw,@'G ʨ>3A$sqi}<3u<8gq9#X4_x]Ҽ-YO/5kTMdHјpkwQkEu_[Zݏ$Ef 2Z'vZZB2hJe@6[d< C olc?fW+B~[j d&M͑&VfXȍ$vUo/%dFMov[.xV>/D<1{kk,ut;OҬ.M!("Eomnƪ PMi~*?i8Ctg8/t[kq]Awo-4;..bčZ~_Io'ycV4KQ-'?Ũj5SK62Xj#"aE(bE(@#4" (((((((_F5>Ht;Zo#1^izsey;/5il{s/:΢S>藒fsmke$M+$(of?>Y4'㇓(JOzٴM V6@+ŏ.'xo4>:mb&YRV-~F) ?vHg,L#O߶ǁ~~~dexl.|WO.<%eojM?-٣%4UwmmrqoOu\YY_k<}yeh KՂo.  XmAc$P:g4zN ;Wi<͹ʐy1 A<>1܂etAݾc9q8 pc]uln=zd{x50VQb@-ԡ - EmX.9-eP~xg+<} n76ckw d|䯷n?Nv.PǠTn8k0>_|N֔%=G`zʲ.~)s9'8GQZrL鞕]=/*UdqF:|y 9#==k/'νFb5b@ >IzvҤq&GI"Ai$z' C} ` jR,>;jx7Rә.1|k+-# >пW w}~œkA`|m഻o|^.~3_?O4wmeYmA& ?M6%9V@Ƞߏ̎%ع9J>_89Ӑ}3Wg?ͭv!##<) "9QzG΀>ud`T$gӭz=y<ξh5W$Oy=f00Ϣru9q*^߆(gc$sޠ' ݲqs@{Hddd7+scx3>n 39U.o d{zu?sW 98<`u>Ow{`8'{+u>Vnq1Qr3Ӄv\Ny|Àx8 F`1 oʼSAǯjw׎}Gy֩9Gcsq@5]DlF99=9߭y. ǿPN8*msV29kǵi3pHOZMs\ 0{uϨku 7sk d8czb+>-8sw/Ogg'_?xrdf ܞ@<^HDǀGW%$Nyp2~j5 fT$|ݸe FF;@%v,c< $Fxr{g8<ګKsGN'+k ਿg/tXwƫh | g; 4i׉75_xZM=U5]F6:ve ^I#HGw<*_O Ek_G~"N =HYxSG~FG-uYG$:](?_&KO?h?3kVRtφDhx~Kn\B;tq9Mm!=|gs.~eG]-ey|Xnj3,g 5ؾD>Rc*B?:([n$/ ߩ +?Y^kiO'm6vڄ>.+R>EI=3lG}!1<Onߥ^iŔvae(Pt0YncdwpF@5^lεXW1otE+wmKT7z˙*P(yQ~!L1sQ6yw_k; Y5_WƟo<im6m>]L 0f98Z>!(~&>U{$.Ix'8@»jgI p99qT 8=C|0/?aY)~_?ċңg4׺ ohWAVIajVۿ#-ῌrK/S>+vQ*EmnqdqI4vF@?cu<M š;x E՞=1$~~n_M"C=_a:Opx~n}r8#=kTK)9<KՂԀ>cv¸rpFyhR`{>*C~pmF+U\g~y:5"r7wy@]΢rx yydsZ xw^H㞕sqgORy=+ s*ӻ@qpA;z~9ꚆrǷ_jQo^{+յA%1Wp}{ WSa ux<יڠau߸V}G`9漯X'=8 ά1ʼw\H3ǧ_j:p2Xm܎xҸ9gv,XprO$9$`^. p$G$1jY'?Q^O"d7|O(Zk ծO|$vK;*G ࡓh>$X-̷BP *xKE&߼uQ4Ս[1=߱_?+ٿVkMONAmYܖWqi&,zeg-bҰ)B\pFG3^7k`oĀ[8I Z}I0?a# qh'_ EAxGQi|-B#uKj*,i=!.eR!|? |@/4+~񖇧xÚޝuE=wF67 -B(%exհ ޣ<:WPǛ 3w=Uonu߉M_u./uY?g:?o>WtTp5~e&?j؛|-xybzlo~-XxkFk+* 0$?J:yw6p=~;A5򃄔`ЌM'Юyz.@όdFϽ~Z|SWR>#S뻊Z~2>Nxk׭~ai6uDnF+rտ?vEaz0`}y-2@'p{+INI8gNQ_9yBrWboӡ9?@fapq6:cڼW:ҳ>ҾKƽ.?*!d'z7J?g|Tǘpyqq(x)3|aG S_2@c#=q6l$KVi$?~~?>:YwO~'h_ | kq41kqjXDx7)gT|kR$89QBG_з h>!ZK.~BQo>ү=.M(TƥaS -忐c)HAũGy|:$^|A=t5$NE?A6omVACƱC 1*qEƱ{*c&Ÿg.z0 ]s⿏&RA|[qo[i"y' 2}N̐I_p:v ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( g?ڗC!;xZg-mf!]KGi n%[{i1-Hۨ/>=MwVE]k^! rgc|GwZuwRh+di#g3R0xžy|sR~k*'ڦ5D}ckpc<(U 4*`C`F @o7iԴBg#6+-եY-WB]U]ӚEU!Hls_)T3?`WL>|JM:Ʒ^O:5ӈt?>\`NeaXe@ğ3 Y[>E.h/tV^%Y K%;.$F14r?_%n #'sX?fY;8?ޯ:mσmߌWq`|-Om8?J״iqs|Mci)o-)3 vܹҀ?'(Չg&[6l_MEdVo`Dqdڿk~ ωlw$8Sv =M]dg8@'vFsӭ}}!~'_/V|ᦟ/m:f pv? !L|3<;xDB|y)|)q t /-2(H%IS|'9O_~?ڭχ|!6,H4+8 I^GaY%y$gwf o O8? 9/-򠿺Q4?\"I?yVZNj'ҭ.#D,ESi? ~/)φ5U Ҧ9ɒWwfcPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPmaven-war-plugin-2.1.1/src/it/MWAR-143/war-common/src/main/resources/0000755000175000017500000000000011641142610024720 5ustar twernertwernermaven-war-plugin-2.1.1/src/it/MWAR-143/war-common/src/main/resources/filter.properties0000644000175000017500000000015010772000266030323 0ustar twernertwernertitle.main=Prototype ${pom.name} title.version=version ${pom.version} debug.test = ${my.filter.value} maven-war-plugin-2.1.1/src/it/MWAR-143/war-filter-overlay/0000755000175000017500000000000011641142610022647 5ustar twernertwernermaven-war-plugin-2.1.1/src/it/MWAR-143/war-filter-overlay/pom.xml0000644000175000017500000000415610772000266024176 0ustar twernertwerner 4.0.0 debug.war MWAR-143 1.0-SNAPSHOT custom-manifest war debug.war common-overlay 1.0-SNAPSHOT war runtime org.apache.maven.plugins maven-war-plugin debug.war common-overlay true hello world ! maven-war-plugin-2.1.1/src/it/MWAR-143/war-filter-overlay/src/0000755000175000017500000000000011641142610023436 5ustar twernertwernermaven-war-plugin-2.1.1/src/it/MWAR-143/war-filter-overlay/src/main/0000755000175000017500000000000011641142610024362 5ustar twernertwernermaven-war-plugin-2.1.1/src/it/MWAR-143/war-filter-overlay/src/main/webapp/0000755000175000017500000000000011641142610025640 5ustar twernertwernermaven-war-plugin-2.1.1/src/it/MWAR-143/war-filter-overlay/src/main/webapp/WEB-INF/0000755000175000017500000000000011641142610026667 5ustar twernertwernermaven-war-plugin-2.1.1/src/it/MWAR-143/war-filter-overlay/src/main/webapp/WEB-INF/web.xml0000644000175000017500000000045711431607526030205 0ustar twernertwerner maven-war-plugin-2.1.1/src/it/MWAR-143/goals.txt0000644000175000017500000000001510771710445020770 0ustar twernertwernerclean installmaven-war-plugin-2.1.1/src/it/MWAR-143/verify.bsh0000644000175000017500000000712011431607526021127 0ustar twernertwerner /* * 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 java.io.*; import org.codehaus.plexus.util.*; boolean result = true; filesAreIdentical( File expected, File current ) throws IOException { if ( expected.length() != current.length() ) { return false; } FileInputStream expectedIn = new FileInputStream( expected ); FileInputStream currentIn = new FileInputStream( current ); try { byte[] expectedBuffer = IOUtil.toByteArray( expectedIn ); byte[] currentBuffer = IOUtil.toByteArray( currentIn ); if (expectedBuffer.length != currentBuffer.length) { return false; } for (int i = 0,size = expectedBuffer.length;i it-repo true local.central @localRepositoryUrl@ true true local.central @localRepositoryUrl@ true true maven-war-plugin-2.1.1/src/it/MWAR-62/0000755000175000017500000000000011641142610017034 5ustar twernertwernermaven-war-plugin-2.1.1/src/it/MWAR-62/pom.xml0000644000175000017500000000363510772000266020364 0ustar twernertwerner 4.0.0 testwar MWAR-62 war 1.0-SNAPSHOT MWAR-62 Maven Webapp http://maven.apache.org junit junit 3.8.1 test maven-war-plugin @pom.version@ ${project.build.directory}/webAppDirectory src/main/webapp **/*dev.properties,**/*test.properties maven-war-plugin-2.1.1/src/it/MWAR-62/src/0000755000175000017500000000000011641142610017623 5ustar twernertwernermaven-war-plugin-2.1.1/src/it/MWAR-62/src/main/0000755000175000017500000000000011641142610020547 5ustar twernertwernermaven-war-plugin-2.1.1/src/it/MWAR-62/src/main/webapp/0000755000175000017500000000000011641142610022025 5ustar twernertwernermaven-war-plugin-2.1.1/src/it/MWAR-62/src/main/webapp/test.properties0000644000175000017500000000000710771710445025131 0ustar twernertwernerfoo devmaven-war-plugin-2.1.1/src/it/MWAR-62/src/main/webapp/dev.properties0000644000175000017500000000000710771710445024730 0ustar twernertwernerfoo devmaven-war-plugin-2.1.1/src/it/MWAR-62/src/main/webapp/web.xml0000644000175000017500000000172210772000266023332 0ustar twernertwerner Archetype Created Web Application maven-war-plugin-2.1.1/src/it/MWAR-62/goals.txt0000644000175000017500000000002310771710445020707 0ustar twernertwernerclean war:exploded maven-war-plugin-2.1.1/src/it/MWAR-62/verify.bsh0000644000175000017500000000355011431607526021052 0ustar twernertwerner /* * 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 java.io.*; import org.codehaus.plexus.util.*; boolean result = true; try { File target = new File( basedir, "target" ); if ( !target.exists() || !target.isDirectory() ) { System.err.println( "target file is missing or not a directory." ); return false; } File webAppDirectory = new File ( target, "webAppDirectory" ); if ( !webAppDirectory.exists() || !webAppDirectory.isDirectory() ) { System.err.println( "webAppDirectory is missing or a not directory." ); return false; } File devProperties = new File ( webAppDirectory, "dev.properties" ); if ( devProperties.exists() ) { System.err.println( "dev.properties has not been excluded." ); return false; } File testProperties = new File ( webAppDirectory, "test.properties" ); if ( testProperties.exists() ) { System.err.println( "test.properties has not been excluded." ); return false; } } catch( Throwable e ) { e.printStackTrace(); result = false; } return result; maven-war-plugin-2.1.1/src/it/MWAR-139/0000755000175000017500000000000011641142610017121 5ustar twernertwernermaven-war-plugin-2.1.1/src/it/MWAR-139/pom.xml0000644000175000017500000000334110772000266020443 0ustar twernertwerner 4.0.0 testwar MWAR-139 war 1.0-SNAPSHOT MWAR-139 Maven Webapp http://maven.apache.org maven-war-plugin @pom.version@ src/main/webapp src/main/webresources true maven-war-plugin-2.1.1/src/it/MWAR-139/src/0000755000175000017500000000000011641142610017710 5ustar twernertwernermaven-war-plugin-2.1.1/src/it/MWAR-139/src/main/0000755000175000017500000000000011641142610020634 5ustar twernertwernermaven-war-plugin-2.1.1/src/it/MWAR-139/src/main/webapp/0000755000175000017500000000000011641142610022112 5ustar twernertwernermaven-war-plugin-2.1.1/src/it/MWAR-139/src/main/webapp/WEB-INF/0000755000175000017500000000000011641142610023141 5ustar twernertwernermaven-war-plugin-2.1.1/src/it/MWAR-139/src/main/webapp/WEB-INF/web.xml0000644000175000017500000000172210772000266024446 0ustar twernertwerner Archetype Created Web Application maven-war-plugin-2.1.1/src/it/MWAR-139/src/main/webresources/0000755000175000017500000000000011641142610023344 5ustar twernertwernermaven-war-plugin-2.1.1/src/it/MWAR-139/src/main/webresources/filterme.xml0000644000175000017500000000014410772000266025700 0ustar twernertwerner ${foo.url} hallo @@ hallo start-${}-end maven-war-plugin-2.1.1/src/it/MWAR-139/verify.bsh0000644000175000017500000000431711431607526021141 0ustar twernertwerner /* * 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 java.io.*; import org.codehaus.plexus.util.*; boolean result = true; try { File target = new File( basedir, "target" ); if ( !target.exists() || !target.isDirectory() ) { System.err.println( "target file is missing or not a directory." ); return false; } File webappDirectory = new File( target, "MWAR-139-1.0-SNAPSHOT" ); if ( !webappDirectory.exists() || !webappDirectory.isDirectory() ) { System.err.println( "webappDirectory is missing or not a directory." ); return false; } File param = new File ( webappDirectory, "filterme.xml" ); if ( !param.exists() || param.isDirectory() ) { System.err.println( "filterme.xml file is missing or a directory." ); return false; } FileInputStream fis = new FileInputStream ( param ); String paramContent = IOUtil.toString ( fis ); int indexOf = paramContent.indexOf( "hallo @@ hallo" ); if ( indexOf < 0) { System.err.println( "filterme.xml does not contains hallo @@ hallo" ); return false; } indexOf = paramContent.indexOf( "start-${}-end" ); if ( indexOf < 0) { System.err.println( "filterme.xml does not contains start-${}-end" ); return false; } } catch( Throwable e ) { e.printStackTrace(); result = false; } return result; maven-war-plugin-2.1.1/src/it/default/0000755000175000017500000000000011641142610017465 5ustar twernertwernermaven-war-plugin-2.1.1/src/it/default/pom.xml0000644000175000017500000000366311063504402021011 0ustar twernertwerner 4.0.0 org.apache.maven.its.it0016 maven-it-it0016 1.0 war Maven Integration Test :: it0016 Test a WAR generation UTF-8 javax.servlet servlet-api 2.4 provided commons-logging commons-logging 1.0.3 junit junit 3.8.2 test org.apache.maven.plugins maven-war-plugin @project.version@ maven-war-plugin-2.1.1/src/it/default/src/0000755000175000017500000000000011641142610020254 5ustar twernertwernermaven-war-plugin-2.1.1/src/it/default/src/main/0000755000175000017500000000000011641142610021200 5ustar twernertwernermaven-war-plugin-2.1.1/src/it/default/src/main/webapp/0000755000175000017500000000000011641142610022456 5ustar twernertwernermaven-war-plugin-2.1.1/src/it/default/src/main/webapp/index.html0000644000175000017500000000006211063504402024450 0ustar twernertwerner Hello World maven-war-plugin-2.1.1/src/it/default/src/main/webapp/WEB-INF/0000755000175000017500000000000011641142610023505 5ustar twernertwernermaven-war-plugin-2.1.1/src/it/default/src/main/webapp/WEB-INF/web.xml0000644000175000017500000000027311063504402025005 0ustar twernertwerner maven-war-plugin-2.1.1/src/it/default/src/main/java/0000755000175000017500000000000011641142610022121 5ustar twernertwernermaven-war-plugin-2.1.1/src/it/default/src/main/java/org/0000755000175000017500000000000011641142610022710 5ustar twernertwernermaven-war-plugin-2.1.1/src/it/default/src/main/java/org/apache/0000755000175000017500000000000011641142610024131 5ustar twernertwernermaven-war-plugin-2.1.1/src/it/default/src/main/java/org/apache/maven/0000755000175000017500000000000011641142610025237 5ustar twernertwernermaven-war-plugin-2.1.1/src/it/default/src/main/java/org/apache/maven/it0016/0000755000175000017500000000000011641142610026162 5ustar twernertwernermaven-war-plugin-2.1.1/src/it/default/src/main/java/org/apache/maven/it0016/Person.java0000644000175000017500000000034711063504402030276 0ustar twernertwernerpackage org.apache.maven.it0016; public class Person { private String name; public void setName( String name ) { this.name = name; } public String getName() { return name; } } maven-war-plugin-2.1.1/src/it/default/verify.bsh0000644000175000017500000000377711063504402021504 0ustar twernertwernerimport java.io.*; import java.util.*; import java.util.jar.*; import java.util.regex.*; try { File explodedDir = new File( basedir, "target/maven-it-it0016-1.0" ); System.out.println( "Checking for existence of exploded directory " + explodedDir ); if ( !explodedDir.isDirectory() ) { System.out.println( "FAILURE!" ); return false; } String[] expectedPaths = { "index.html", "WEB-INF/classes/org/apache/maven/it0016/Person.class", "WEB-INF/lib/commons-logging-1.0.3.jar", }; for ( String path : expectedPaths ) { File file = new File( explodedDir, path ); System.out.println( "Checking for existence of " + file ); if ( !file.exists() ) { System.out.println( "FAILURE!" ); return false; } } String[] unexpectedPaths = { "WEB-INF/lib/servlet-api-2.4.jar", }; for ( String path : unexpectedPaths ) { File file = new File( explodedDir, path ); System.out.println( "Checking for absence of " + file ); if ( file.exists() ) { System.out.println( "FAILURE!" ); return false; } } File warFile = new File( basedir, "target/maven-it-it0016-1.0.war" ); System.out.println( "Checking for existence of " + warFile ); if ( !warFile.isFile() ) { System.out.println( "FAILURE!" ); return false; } JarFile war = new JarFile( warFile ); String[] includedEntries = { "WEB-INF/classes/org/apache/maven/it0016/Person.class", "WEB-INF/lib/commons-logging-1.0.3.jar", }; for ( String included : includedEntries ) { System.out.println( "Checking for existence of " + included ); if ( war.getEntry( included ) == null ) { System.out.println( "FAILURE!" ); return false; } } war.close(); } catch( Throwable t ) { t.printStackTrace(); return false; } return true; maven-war-plugin-2.1.1/src/it/scoped-dependency-same-artifact/0000755000175000017500000000000011641142610024150 5ustar twernertwernermaven-war-plugin-2.1.1/src/it/scoped-dependency-same-artifact/pom.xml0000644000175000017500000000347610772000266025503 0ustar twernertwerner 4.0.0 test scope-depdency-same-artifact war 1.0-SNAPSHOT Maven Simple War Project Test maven-war-plugin @pom.version@ org.codehaus.plexus plexus-utils 1.4.7 org.codehaus.plexus plexus-utils sources 1.4.7 maven-war-plugin-2.1.1/src/it/scoped-dependency-same-artifact/src/0000755000175000017500000000000011641142610024737 5ustar twernertwernermaven-war-plugin-2.1.1/src/it/scoped-dependency-same-artifact/src/main/0000755000175000017500000000000011641142610025663 5ustar twernertwernermaven-war-plugin-2.1.1/src/it/scoped-dependency-same-artifact/src/main/webapp/0000755000175000017500000000000011641142610027141 5ustar twernertwernermaven-war-plugin-2.1.1/src/it/scoped-dependency-same-artifact/src/main/webapp/WEB-INF/0000755000175000017500000000000011641142610030170 5ustar twernertwernermaven-war-plugin-2.1.1/src/it/scoped-dependency-same-artifact/src/main/webapp/WEB-INF/web.xml0000644000175000017500000000221410772000266031472 0ustar twernertwerner Maven Simple War Project Test maven-war-plugin-2.1.1/src/it/scoped-dependency-same-artifact/src/main/webapp/index.jsp0000644000175000017500000000162011045075710030771 0ustar twernertwerner<%-- ~ 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. --%> <% response.sendRedirect( request.getContextPath() + "/groupSummary.action" ); %> maven-war-plugin-2.1.1/src/it/scoped-dependency-same-artifact/goals.txt0000644000175000017500000000001510772000266026016 0ustar twernertwernerclean packagemaven-war-plugin-2.1.1/src/it/scoped-dependency-same-artifact/verify.bsh0000644000175000017500000000566310772000266026170 0ustar twernertwerner /* * 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 java.io.*; boolean result = true; try { File target = new File( basedir, "target" ); if ( !target.exists() || !target.isDirectory() ) { System.err.println( "target file is missing or a directory." ); return false; } File webappDirectory = new File( target, "scope-depdency-same-artifact-1.0-SNAPSHOT" ); if ( !webappDirectory.exists() || !webappDirectory.isDirectory() ) { System.err.println( "webappDirectory is missing or not a directory." ); return false; } File webInfFile = new File( webappDirectory, "WEB-INF/web.xml" ); if ( !webInfFile.exists() || webInfFile.isDirectory() ) { System.err.println( "webInfFile is missing or a directory." ); return false; } File indexJsp = new File( webappDirectory, "index.jsp" ); if ( !indexJsp.exists() || indexJsp.isDirectory() ) { System.err.println( "indexJsp is missing or a directory." ); return false; } File warFile = new File (target, "scope-depdency-same-artifact-1.0-SNAPSHOT.war" ); if ( !warFile.exists() || warFile.isDirectory() ) { System.err.println( "warFile is missing or a directory." ); return false; } File libDir = new File ( webappDirectory, "WEB-INF/lib" ); if ( !libDir.exists() || !libDir.isDirectory() ) { System.err.println( "WEB-INF/lib is missing or not a directory." ); return false; } File plexusUtilsDependency = new File ( libDir, "plexus-utils-1.4.7.jar" ); if ( !plexusUtilsDependency.exists() || plexusUtilsDependency.isDirectory() ) { System.err.println( "plexus-utils-1.4.7.jar is missing or a directory." ); return false; } File plexusUtilsSourceDependency = new File ( libDir, "plexus-utils-1.4.7-sources.jar" ); if ( !plexusUtilsSourceDependency.exists() || plexusUtilsSourceDependency.isDirectory() ) { System.err.println( "plexus-utils-1.4.7-sources.jar is missing or a directory." ); return false; } } catch( IOException e ) { e.printStackTrace(); result = false; } return result; maven-war-plugin-2.1.1/src/it/MWAR-96/0000755000175000017500000000000011641142610017043 5ustar twernertwernermaven-war-plugin-2.1.1/src/it/MWAR-96/pom.xml0000644000175000017500000000362010771710445020373 0ustar twernertwerner 4.0.0 testwar MWAR-96 war 1.0-SNAPSHOT MWAR-96 MWAR-144 Tests http://maven.apache.org maven-war-plugin @pom.version@ src/main/webapp src/main/filters/filter.properties true src/main/webapp index.jsp maven-war-plugin-2.1.1/src/it/MWAR-96/src/0000755000175000017500000000000011641142610017632 5ustar twernertwernermaven-war-plugin-2.1.1/src/it/MWAR-96/src/main/0000755000175000017500000000000011641142610020556 5ustar twernertwernermaven-war-plugin-2.1.1/src/it/MWAR-96/src/main/webapp/0000755000175000017500000000000011641142610022034 5ustar twernertwernermaven-war-plugin-2.1.1/src/it/MWAR-96/src/main/webapp/WEB-INF/0000755000175000017500000000000011641142610023063 5ustar twernertwernermaven-war-plugin-2.1.1/src/it/MWAR-96/src/main/webapp/WEB-INF/web.xml0000644000175000017500000000172210771710445024376 0ustar twernertwerner Archetype Created Web Application maven-war-plugin-2.1.1/src/it/MWAR-96/src/main/webapp/index.jsp0000755000175000017500000000176010756133373023704 0ustar twernertwerner java versionjava version : ${java.version} Project${pom.name} Version${pom.version} custom filter${warPluginFilterConfigurationProperty}maven-war-plugin-2.1.1/src/it/MWAR-96/src/main/filters/0000755000175000017500000000000011641142610022226 5ustar twernertwernermaven-war-plugin-2.1.1/src/it/MWAR-96/src/main/filters/filter.properties0000644000175000017500000000155110771710445025645 0ustar twernertwerner#/* # * 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. # */ warPluginFilterConfigurationProperty=okitworksmaven-war-plugin-2.1.1/src/it/MWAR-96/verify.bsh0000644000175000017500000000437611431607526021070 0ustar twernertwerner /* * 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 java.io.*; import org.codehaus.plexus.util.*; boolean result = true; try { File target = new File( basedir, "target" ); if ( !target.exists() || !target.isDirectory() ) { System.err.println( "target file is missing or not a directory." ); return false; } File webappDirectory = new File( target, "MWAR-96-1.0-SNAPSHOT" ); if ( !webappDirectory.exists() || !webappDirectory.isDirectory() ) { System.err.println( "webappDirectory is missing or not a directory." ); return false; } File param = new File ( webappDirectory, "index.jsp" ); if ( !param.exists() || param.isDirectory() ) { System.err.println( "index.jsp file is missing or a directory." ); return false; } FileInputStream fis = new FileInputStream ( param ); String paramContent = IOUtil.toString ( fis ); String javaVersion = System.getProperty("java.version"); int indexOf = paramContent.indexOf( "java version : " + javaVersion + "" ); if ( indexOf < 0) { System.err.println( "index.jsp not contains java version : " + javaVersion + "" ); return false; } indexOf = paramContent.indexOf("okitworks"); if ( indexOf < 0) { System.err.println( "index.jsp not contains okitworks" ); return false; } } catch( Throwable e ) { e.printStackTrace(); result = false; } return result; maven-war-plugin-2.1.1/src/it/MWAR-129/0000755000175000017500000000000011641142610017120 5ustar twernertwernermaven-war-plugin-2.1.1/src/it/MWAR-129/pom.xml0000644000175000017500000000726610772000266020454 0ustar twernertwerner 4.0.0 testwar MWAR-129 war 1.0-SNAPSHOT MWAR-129 Maven Webapp http://maven.apache.org junit junit 3.8.1 test package true src/main/resources src/main/java **/*.xml src/test/resources src/main/webapp **/*.xml src/test/webapp **/*.xml ${project.artifactId} maven-war-plugin @pom.version@ src/main/webapp true src/main/webapp . param.jsp profile1 profile1 profile1 profile1.css profile2 true profile2 profile2 profile2.css maven-war-plugin-2.1.1/src/it/MWAR-129/src/0000755000175000017500000000000011641142610017707 5ustar twernertwernermaven-war-plugin-2.1.1/src/it/MWAR-129/src/main/0000755000175000017500000000000011641142610020633 5ustar twernertwernermaven-war-plugin-2.1.1/src/it/MWAR-129/src/main/webapp/0000755000175000017500000000000011641142610022111 5ustar twernertwernermaven-war-plugin-2.1.1/src/it/MWAR-129/src/main/webapp/param.jsp0000755000175000017500000000204711431607526023746 0ustar twernertwerner maven-war-plugin-2.1.1/src/it/MWAR-129/src/main/webapp/WEB-INF/0000755000175000017500000000000011641142610023140 5ustar twernertwernermaven-war-plugin-2.1.1/src/it/MWAR-129/src/main/webapp/WEB-INF/web.xml0000644000175000017500000000172210772000266024445 0ustar twernertwerner Archetype Created Web Application maven-war-plugin-2.1.1/src/it/MWAR-129/src/main/webapp/index.jsp0000755000175000017500000000146010722071206023743 0ustar twernertwerner

    Hello World!

    maven-war-plugin-2.1.1/src/it/MWAR-129/src/main/resources/0000755000175000017500000000000011641142610022645 5ustar twernertwernermaven-war-plugin-2.1.1/src/it/MWAR-129/goals.txt0000644000175000017500000000002310771710445020773 0ustar twernertwernerclean war:exploded maven-war-plugin-2.1.1/src/it/MWAR-129/verify.bsh0000644000175000017500000000407711431607526021143 0ustar twernertwerner /* * 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 java.io.*; import org.codehaus.plexus.util.*; boolean result = true; try { File target = new File( basedir, "target" ); if ( !target.exists() || !target.isDirectory() ) { System.err.println( "target file is missing or not a directory." ); return false; } File webappDirectory = new File( target, "profile2" ); if ( !webappDirectory.exists() || !webappDirectory.isDirectory() ) { System.err.println( "webappDirectory is missing or not a directory." ); return false; } File param = new File ( webappDirectory, "param.jsp" ); if ( !param.exists() || param.isDirectory() ) { System.err.println( "param.jsp file is missing or a directory." ); return false; } System.out.println (" before reading param " ); FileInputStream fis = new FileInputStream ( param ); String paramContent = IOUtil.toString ( fis ); int indexOf = paramContent.indexOf( "" ); if ( indexOf < 0) { System.err.println( "param.jsp not contains " ); return false; } } catch( Throwable e ) { e.printStackTrace(); result = false; } return result; maven-war-plugin-2.1.1/src/it/simple-war-no-webxml/0000755000175000017500000000000011641142610022027 5ustar twernertwernermaven-war-plugin-2.1.1/src/it/simple-war-no-webxml/pom.xml0000644000175000017500000000325610772000266023356 0ustar twernertwerner 4.0.0 test simple-war-no-webxml war 1.0-SNAPSHOT Maven Simple War Project Test maven-war-plugin @pom.version@ false org.codehaus.plexus plexus-utils 1.4.6 maven-war-plugin-2.1.1/src/it/simple-war-no-webxml/src/0000755000175000017500000000000011641142610022616 5ustar twernertwernermaven-war-plugin-2.1.1/src/it/simple-war-no-webxml/src/main/0000755000175000017500000000000011641142610023542 5ustar twernertwernermaven-war-plugin-2.1.1/src/it/simple-war-no-webxml/src/main/webapp/0000755000175000017500000000000011641142610025020 5ustar twernertwernermaven-war-plugin-2.1.1/src/it/simple-war-no-webxml/src/main/webapp/index.jsp0000644000175000017500000000162011045075710026650 0ustar twernertwerner<%-- ~ 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. --%> <% response.sendRedirect( request.getContextPath() + "/groupSummary.action" ); %> maven-war-plugin-2.1.1/src/it/simple-war-no-webxml/goals.txt0000644000175000017500000000002010771710445023677 0ustar twernertwernerclean package -Xmaven-war-plugin-2.1.1/src/it/simple-war-no-webxml/verify.bsh0000644000175000017500000000510710772000266024040 0ustar twernertwerner /* * 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 java.io.*; boolean result = true; try { File target = new File( basedir, "target" ); if ( !target.exists() || !target.isDirectory() ) { System.err.println( "target file is missing or a directory." ); return false; } File webappDirectory = new File( target, "simple-war-no-webxml-1.0-SNAPSHOT" ); if ( !webappDirectory.exists() || !webappDirectory.isDirectory() ) { System.err.println( "webappDirectory is missing or not a directory." ); return false; } File webInfFile = new File( webappDirectory, "WEB-INF/web.xml" ); if ( webInfFile.exists()) { System.err.println( "web.xml should not be there." ); return false; } File indexJsp = new File( webappDirectory, "index.jsp" ); if ( !indexJsp.exists() || indexJsp.isDirectory() ) { System.err.println( "indexJsp is missing or a directory." ); return false; } File warFile = new File (target, "simple-war-no-webxml-1.0-SNAPSHOT.war" ); if ( !warFile.exists() || warFile.isDirectory() ) { System.err.println( "warFile is missing or a directory." ); return false; } File libDir = new File ( webappDirectory, "WEB-INF/lib" ); if ( !libDir.exists() || !libDir.isDirectory() ) { System.err.println( "WEB-INF/lib is missing or not a directory." ); return false; } File plexusUtilsDependency = new File ( libDir, "plexus-utils-1.4.6.jar" ); if ( !plexusUtilsDependency.exists() || plexusUtilsDependency.isDirectory() ) { System.err.println( "plexus-utils-1.4.6.jar is missing or a directory." ); return false; } } catch( IOException e ) { e.printStackTrace(); result = false; } return result; maven-war-plugin-2.1.1/src/it/simple-war-project/0000755000175000017500000000000011641142610021565 5ustar twernertwernermaven-war-plugin-2.1.1/src/it/simple-war-project/pom.xml0000644000175000017500000000343611015343033023105 0ustar twernertwerner 4.0.0 test simple-war-project war 1.0-SNAPSHOT Maven Simple War Project Test maven test it maven-war-plugin @pom.version@ true org.codehaus.plexus plexus-utils 1.4.6 maven-war-plugin-2.1.1/src/it/simple-war-project/src/0000755000175000017500000000000011641142610022354 5ustar twernertwernermaven-war-plugin-2.1.1/src/it/simple-war-project/src/main/0000755000175000017500000000000011641142610023300 5ustar twernertwernermaven-war-plugin-2.1.1/src/it/simple-war-project/src/main/webapp/0000755000175000017500000000000011641142610024556 5ustar twernertwernermaven-war-plugin-2.1.1/src/it/simple-war-project/src/main/webapp/WEB-INF/0000755000175000017500000000000011641142610025605 5ustar twernertwernermaven-war-plugin-2.1.1/src/it/simple-war-project/src/main/webapp/WEB-INF/web.xml0000644000175000017500000000220111015343033027074 0ustar twernertwerner ${pom.description} maven-war-plugin-2.1.1/src/it/simple-war-project/src/main/webapp/index.jsp0000755000175000017500000000162110705241604026411 0ustar twernertwerner<%-- ~ 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. --%> <% response.sendRedirect( request.getContextPath() + "/groupSummary.action" ); %> maven-war-plugin-2.1.1/src/it/simple-war-project/goals.txt0000644000175000017500000000001510771710445023441 0ustar twernertwernerclean packagemaven-war-plugin-2.1.1/src/it/simple-war-project/verify.bsh0000644000175000017500000000601111015343033023562 0ustar twernertwerner /* * 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 java.io.*; import org.codehaus.plexus.util.*; boolean result = true; try { File target = new File( basedir, "target" ); if ( !target.exists() || !target.isDirectory() ) { System.err.println( "target file is missing or a directory." ); return false; } File webappDirectory = new File( target, "simple-war-project-1.0-SNAPSHOT" ); if ( !webappDirectory.exists() || !webappDirectory.isDirectory() ) { System.err.println( "webappDirectory is missing or not a directory." ); return false; } File webInfFile = new File( webappDirectory, "WEB-INF/web.xml" ); if ( !webInfFile.exists() || webInfFile.isDirectory() ) { System.err.println( "webInfFile is missing or a directory." ); return false; } FileInputStream fis = new FileInputStream ( webInfFile ); String paramContent = IOUtil.toString ( fis ); int indexOf = paramContent.indexOf( "maven test it" ); if ( indexOf < 0) { System.err.println( "web.xml not contains maven test it" ); return false; } File indexJsp = new File( webappDirectory, "index.jsp" ); if ( !indexJsp.exists() || indexJsp.isDirectory() ) { System.err.println( "indexJsp is missing or a directory." ); return false; } File warFile = new File (target, "simple-war-project-1.0-SNAPSHOT.war" ); if ( !warFile.exists() || warFile.isDirectory() ) { System.err.println( "warFile is missing or a directory." ); return false; } File libDir = new File ( webappDirectory, "WEB-INF/lib" ); if ( !libDir.exists() || !libDir.isDirectory() ) { System.err.println( "WEB-INF/lib is missing or not a directory." ); return false; } File plexusUtilsDependency = new File ( libDir, "plexus-utils-1.4.6.jar" ); if ( !plexusUtilsDependency.exists() || plexusUtilsDependency.isDirectory() ) { System.err.println( "plexus-utils-1.4.6.jar is missing or a directory." ); return false; } } catch( IOException e ) { e.printStackTrace(); result = false; } return result; maven-war-plugin-2.1.1/src/it/MWAR-131/0000755000175000017500000000000011641142610017111 5ustar twernertwernermaven-war-plugin-2.1.1/src/it/MWAR-131/mwar131-webapp2/0000755000175000017500000000000011641142610021642 5ustar twernertwernermaven-war-plugin-2.1.1/src/it/MWAR-131/mwar131-webapp2/pom.xml0000644000175000017500000000210111045075710023155 0ustar twernertwerner mwar131 com.example 1.0-SNAPSHOT 4.0.0 com.example mwar131-webapp2 war Maven Webapp Archetype Webapp that declares the attached jar from mwar131-webapp as a dependency, which should show up in WEB-INF/lib along with its transitive dependencies. 1.0-SNAPSHOT http://maven.apache.org ${project.artifactId} junit junit 3.8.1 test com.example mwar131-webapp 1.0-SNAPSHOT classes maven-war-plugin-2.1.1/src/it/MWAR-131/mwar131-webapp2/src/0000755000175000017500000000000011641142610022431 5ustar twernertwernermaven-war-plugin-2.1.1/src/it/MWAR-131/mwar131-webapp2/src/main/0000755000175000017500000000000011641142610023355 5ustar twernertwernermaven-war-plugin-2.1.1/src/it/MWAR-131/mwar131-webapp2/src/main/webapp/0000755000175000017500000000000011641142610024633 5ustar twernertwernermaven-war-plugin-2.1.1/src/it/MWAR-131/mwar131-webapp2/src/main/webapp/WEB-INF/0000755000175000017500000000000011641142610025662 5ustar twernertwernermaven-war-plugin-2.1.1/src/it/MWAR-131/mwar131-webapp2/src/main/webapp/WEB-INF/web.xml0000644000175000017500000000032711045075710027167 0ustar twernertwerner Archetype Created Web Application maven-war-plugin-2.1.1/src/it/MWAR-131/mwar131-webapp2/src/main/webapp/index.jsp0000644000175000017500000000006411045075710026464 0ustar twernertwerner

    Hello World!

    maven-war-plugin-2.1.1/src/it/MWAR-131/mwar131-webapp2/src/main/resources/0000755000175000017500000000000011641142610025367 5ustar twernertwernermaven-war-plugin-2.1.1/src/it/MWAR-131/pom.xml0000644000175000017500000000144111045075710020432 0ustar twernertwerner 4.0.0 com.example mwar131 pom 1.0-SNAPSHOT MWAR-131 Integration Test http://maven.apache.org maven-war-plugin @pom.version@ mwar131-webapp mwar131-test mwar131-webapp2 maven-war-plugin-2.1.1/src/it/MWAR-131/mwar131-webapp/0000755000175000017500000000000011641142610021560 5ustar twernertwernermaven-war-plugin-2.1.1/src/it/MWAR-131/mwar131-webapp/pom.xml0000644000175000017500000000243411047136167023112 0ustar twernertwerner 4.0.0 com.example mwar131 1.0-SNAPSHOT mwar131-webapp war MWAR-131 Webapp Web application with classes that get installed as an attached artifact with a classifier (mwar131-webapp-1.0-SNAPSHOT-classes.jar) http://maven.apache.org junit junit 3.8.1 test org.apache.struts struts-core 1.3.9 mwar131-webapp maven-war-plugin true maven-war-plugin-2.1.1/src/it/MWAR-131/mwar131-webapp/src/0000755000175000017500000000000011641142610022347 5ustar twernertwernermaven-war-plugin-2.1.1/src/it/MWAR-131/mwar131-webapp/src/main/0000755000175000017500000000000011641142610023273 5ustar twernertwernermaven-war-plugin-2.1.1/src/it/MWAR-131/mwar131-webapp/src/main/webapp/0000755000175000017500000000000011641142610024551 5ustar twernertwernermaven-war-plugin-2.1.1/src/it/MWAR-131/mwar131-webapp/src/main/webapp/WEB-INF/0000755000175000017500000000000011641142610025600 5ustar twernertwernermaven-war-plugin-2.1.1/src/it/MWAR-131/mwar131-webapp/src/main/webapp/WEB-INF/web.xml0000644000175000017500000000032711045075710027105 0ustar twernertwerner Archetype Created Web Application maven-war-plugin-2.1.1/src/it/MWAR-131/mwar131-webapp/src/main/webapp/index.jsp0000644000175000017500000000006411045075710026402 0ustar twernertwerner

    Hello World!

    maven-war-plugin-2.1.1/src/it/MWAR-131/mwar131-webapp/src/main/resources/0000755000175000017500000000000011641142610025305 5ustar twernertwernermaven-war-plugin-2.1.1/src/it/MWAR-131/mwar131-webapp/src/main/java/0000755000175000017500000000000011641142610024214 5ustar twernertwernermaven-war-plugin-2.1.1/src/it/MWAR-131/mwar131-webapp/src/main/java/com/0000755000175000017500000000000011641142610024772 5ustar twernertwernermaven-war-plugin-2.1.1/src/it/MWAR-131/mwar131-webapp/src/main/java/com/example/0000755000175000017500000000000011641142610026425 5ustar twernertwernermaven-war-plugin-2.1.1/src/it/MWAR-131/mwar131-webapp/src/main/java/com/example/Util.java0000644000175000017500000000016311123544663030216 0ustar twernertwernerpackage com.example; public class Util { public static boolean isPresent() { return true; } } maven-war-plugin-2.1.1/src/it/MWAR-131/goals.txt0000644000175000017500000000001511045075710020757 0ustar twernertwernerclean installmaven-war-plugin-2.1.1/src/it/MWAR-131/verify.bsh0000644000175000017500000000510211045075710021115 0ustar twernertwerner /* * 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 java.io.*; import org.codehaus.plexus.util.*; boolean result = true; try { // Make sure the -classes jar from the first webapp is installed into the local repo File localRepoClassesJar = new File( basedir, "../../../target/local-repo/com/example/mwar131-webapp/1.0-SNAPSHOT/mwar131-webapp-1.0-SNAPSHOT-classes.jar"); if ( !localRepoClassesJar.exists() || localRepoClassesJar.isDirectory() ) { System.err.println( "The -classes jar file is missing or is a directory." ); return false; } // Make sure the -classes jar is included in WEB-INF/lib of the second webapp File classesJar = new File( basedir, "mwar131-webapp2/target/mwar131-webapp2/WEB-INF/lib/mwar131-webapp-1.0-SNAPSHOT-classes.jar"); if ( !classesJar.exists() || classesJar.isDirectory() ) { System.err.println( "The -classes jar file is missing or is a directory." ); return false; } // Make sure dependencies of the -classes jar are included in WEB-INF/lib of the second webapp File strutsJar = new File( basedir, "mwar131-webapp2/target/mwar131-webapp2/WEB-INF/lib/struts-core-1.3.9.jar"); if ( !strutsJar.exists() || strutsJar.isDirectory() ) { System.err.println( "The Struts 1.3.9 jar file is missing or is a directory." ); return false; } // Make sure transitive dependencies of the -classes jar are included in WEB-INF/lib of the second webapp File digesterJar = new File( basedir, "mwar131-webapp2/target/mwar131-webapp2/WEB-INF/lib/commons-digester-1.8.jar"); if ( !digesterJar.exists() || digesterJar.isDirectory() ) { System.err.println( "The Commons Digester 1.8 jar file is missing or is a directory." ); return false; } } catch( Throwable e ) { e.printStackTrace(); result = false; } return result; maven-war-plugin-2.1.1/src/it/MWAR-131/mwar131-test/0000755000175000017500000000000011641142610021261 5ustar twernertwernermaven-war-plugin-2.1.1/src/it/MWAR-131/mwar131-test/pom.xml0000644000175000017500000000164411045075710022607 0ustar twernertwerner mwar131 com.example 1.0-SNAPSHOT 4.0.0 com.example mwar131-test Maven Quick Start Archetype Example project that expects the attached jar from mwar131-webapp to be on the compile and test classpath. 1.0-SNAPSHOT http://maven.apache.org junit junit 3.8.1 test com.example mwar131-webapp 1.0-SNAPSHOT classes maven-war-plugin-2.1.1/src/it/MWAR-131/mwar131-test/src/0000755000175000017500000000000011641142610022050 5ustar twernertwernermaven-war-plugin-2.1.1/src/it/MWAR-131/mwar131-test/src/test/0000755000175000017500000000000011641142610023027 5ustar twernertwernermaven-war-plugin-2.1.1/src/it/MWAR-131/mwar131-test/src/test/java/0000755000175000017500000000000011641142610023750 5ustar twernertwernermaven-war-plugin-2.1.1/src/it/MWAR-131/mwar131-test/src/test/java/com/0000755000175000017500000000000011641142610024526 5ustar twernertwernermaven-war-plugin-2.1.1/src/it/MWAR-131/mwar131-test/src/test/java/com/example/0000755000175000017500000000000011641142610026161 5ustar twernertwernermaven-war-plugin-2.1.1/src/it/MWAR-131/mwar131-test/src/test/java/com/example/AppTest.java0000644000175000017500000000131711123544663030417 0ustar twernertwernerpackage com.example; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; /** * Unit test for simple App. */ public class AppTest extends TestCase { /** * Create the test case * * @param testName name of the test case */ public AppTest( String testName ) { super( testName ); } /** * @return the suite of tests being tested */ public static Test suite() { return new TestSuite( AppTest.class ); } /** * Rigourous Test :-) */ public void testApp() { assertTrue( true ); } public void testUtil() { assertTrue( Util.isPresent() ); } } maven-war-plugin-2.1.1/src/it/MWAR-131/mwar131-test/src/main/0000755000175000017500000000000011641142610022774 5ustar twernertwernermaven-war-plugin-2.1.1/src/it/MWAR-131/mwar131-test/src/main/java/0000755000175000017500000000000011641142610023715 5ustar twernertwernermaven-war-plugin-2.1.1/src/it/MWAR-131/mwar131-test/src/main/java/com/0000755000175000017500000000000011641142610024473 5ustar twernertwernermaven-war-plugin-2.1.1/src/it/MWAR-131/mwar131-test/src/main/java/com/example/0000755000175000017500000000000011641142610026126 5ustar twernertwernermaven-war-plugin-2.1.1/src/it/MWAR-131/mwar131-test/src/main/java/com/example/App.java0000644000175000017500000000030411123544663027517 0ustar twernertwernerpackage com.example; /** * Hello world! * */ public class App { public static void main( String[] args ) { System.out.println( "Hello World is " + Util.isPresent() ); } } maven-war-plugin-2.1.1/src/it/web-resources-filtering/0000755000175000017500000000000011641142610022607 5ustar twernertwernermaven-war-plugin-2.1.1/src/it/web-resources-filtering/pom.xml0000644000175000017500000000272511105663705024142 0ustar twernertwerner 4.0.0 com.edb.finance.example example-parent 1.0.0-SNAPSHOT parent/pom.xml example pom Example Maven Multi-module project http://maven.apache.org parent web maven-war-plugin-2.1.1/src/it/web-resources-filtering/parent/0000755000175000017500000000000011641142610024100 5ustar twernertwernermaven-war-plugin-2.1.1/src/it/web-resources-filtering/parent/pom.xml0000644000175000017500000000403011431607526025423 0ustar twernertwerner 4.0.0 Company Parent Parent that handles dependencyManagement com.edb.finance.example example-parent 1.0.0-SNAPSHOT pom 2008 1 Valeriy Molyakov valeriy.molyakov@infopulse.com.ua EDB Business Partner http://www.edb.com developer +2 sample.website ${website.url}/${project.name} jdbc:oracle:thin:@localhost:1521:orcl scp://www.yourcompany.com/www/docs/project maven-war-plugin-2.1.1/src/it/web-resources-filtering/verify.bsh0000644000175000017500000000377611105662411024627 0ustar twernertwerner /* * 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 java.io.*; import org.codehaus.plexus.util.*; boolean result = true; try { File target = new File( basedir, "web/target/example-web/WEB-INF" ); if ( !target.exists() || !target.isDirectory() ) { System.err.println( "web/target/example-web/WEB-INF file is missing or a directory." ); return false; } File jettyEnv = new File( target, "jetty-env.xml" ); if ( !jettyEnv.exists() || jettyEnv.isDirectory() ) { System.err.println( "jetty-env.xml is missing or a directory." ); return false; } FileInputStream fis = new FileInputStream ( jettyEnv ); String paramContent = IOUtil.toString ( fis ); int indexOf = paramContent.indexOf( "jdbc:oracle:thin:@localhost:1521:orcl" ); if ( indexOf < 0) { System.err.println( "jdbc.url not filtered correctly" ); return false; } indexOf = paramContent.indexOf( "${jdbc.password}" ); if ( indexOf < 0) { System.err.println( "jdbc.password has been filtered" ); return false; } } catch( IOException e ) { e.printStackTrace(); result = false; } return result; maven-war-plugin-2.1.1/src/it/web-resources-filtering/web/0000755000175000017500000000000011641142610023364 5ustar twernertwernermaven-war-plugin-2.1.1/src/it/web-resources-filtering/web/pom.xml0000644000175000017500000000417111123542071024704 0ustar twernertwerner 4.0.0 com.edb.finance.example example-parent 1.0.0-SNAPSHOT ../parent/pom.xml example-web war example-web Maven Webapp http://maven.apache.org junit junit 3.8.1 test example-web org.apache.maven.plugins maven-war-plugin @pom.version@ \ ${basedir}/src/main/webresources true maven-war-plugin-2.1.1/src/it/web-resources-filtering/web/src/0000755000175000017500000000000011641142610024153 5ustar twernertwernermaven-war-plugin-2.1.1/src/it/web-resources-filtering/web/src/main/0000755000175000017500000000000011641142610025077 5ustar twernertwernermaven-war-plugin-2.1.1/src/it/web-resources-filtering/web/src/main/webapp/0000755000175000017500000000000011641142610026355 5ustar twernertwernermaven-war-plugin-2.1.1/src/it/web-resources-filtering/web/src/main/webapp/WEB-INF/0000755000175000017500000000000011641142610027404 5ustar twernertwernermaven-war-plugin-2.1.1/src/it/web-resources-filtering/web/src/main/webapp/WEB-INF/web.xml0000644000175000017500000000177211123542071030712 0ustar twernertwerner Archetype Created Web Application maven-war-plugin-2.1.1/src/it/web-resources-filtering/web/src/main/webapp/index.jsp0000755000175000017500000000153411105663705030220 0ustar twernertwerner/* * 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. */

    Hello World!

    maven-war-plugin-2.1.1/src/it/web-resources-filtering/web/src/main/webresources/0000755000175000017500000000000011641142610027607 5ustar twernertwernermaven-war-plugin-2.1.1/src/it/web-resources-filtering/web/src/main/webresources/WEB-INF/0000755000175000017500000000000011641142610030636 5ustar twernertwerner././@LongLink0000000000000000000000000000014600000000000011566 Lustar rootrootmaven-war-plugin-2.1.1/src/it/web-resources-filtering/web/src/main/webresources/WEB-INF/jetty-env.xmlmaven-war-plugin-2.1.1/src/it/web-resources-filtering/web/src/main/webresources/WEB-INF/jetty-env.xm0000644000175000017500000000106311123542071033131 0ustar twernertwerner jdbc/EventdialogDS ${jdbc.url} ${jdbc.user} \${jdbc.password} maven-war-plugin-2.1.1/src/it/web-resources-filtering/web/src/main/resources/0000755000175000017500000000000011641142610027111 5ustar twernertwernermaven-war-plugin-2.1.1/src/main/0000755000175000017500000000000011641142606016356 5ustar twernertwernermaven-war-plugin-2.1.1/src/main/java/0000755000175000017500000000000011641142606017277 5ustar twernertwernermaven-war-plugin-2.1.1/src/main/java/org/0000755000175000017500000000000011641142606020066 5ustar twernertwernermaven-war-plugin-2.1.1/src/main/java/org/apache/0000755000175000017500000000000011641142606021307 5ustar twernertwernermaven-war-plugin-2.1.1/src/main/java/org/apache/maven/0000755000175000017500000000000011641142606022415 5ustar twernertwernermaven-war-plugin-2.1.1/src/main/java/org/apache/maven/plugin/0000755000175000017500000000000011641142606023713 5ustar twernertwernermaven-war-plugin-2.1.1/src/main/java/org/apache/maven/plugin/war/0000755000175000017500000000000011641142607024505 5ustar twernertwernermaven-war-plugin-2.1.1/src/main/java/org/apache/maven/plugin/war/WarManifestMojo.java0000644000175000017500000000643611431721024030417 0ustar twernertwernerpackage org.apache.maven.plugin.war; /* * 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.maven.archiver.MavenArchiver; import org.apache.maven.artifact.DependencyResolutionRequiredException; import org.apache.maven.plugin.MojoExecutionException; import org.codehaus.plexus.archiver.jar.Manifest; import org.codehaus.plexus.archiver.jar.ManifestException; import org.codehaus.plexus.archiver.war.WarArchiver; import org.codehaus.plexus.util.IOUtil; import org.codehaus.plexus.util.WriterFactory; import java.io.File; import java.io.IOException; import java.io.PrintWriter; /** * Generate a manifest for this webapp. The manifest file is created in the * warSourceDirectory. * * @author Mike Perham * @version $Id: WarManifestMojo.java 985625 2010-08-15 08:15:16Z dennisl $ * @goal manifest * @phase process-resources * @threadSafe * @requiresDependencyResolution runtime */ public class WarManifestMojo extends AbstractWarMojo { /** * The WAR archiver. * * @component role="org.codehaus.plexus.archiver.Archiver" roleHint="war" */ private WarArchiver warArchiver; /** * Executes this mojo on the current project. * * @throws MojoExecutionException if an error occurred while building the webapp */ public void execute() throws MojoExecutionException { File manifestDir = new File( getWarSourceDirectory(), "META-INF" ); if ( !manifestDir.exists() ) { manifestDir.mkdirs(); } File manifestFile = new File( manifestDir, "MANIFEST.MF" ); MavenArchiver ma = new MavenArchiver(); ma.setArchiver( warArchiver ); ma.setOutputFile( manifestFile ); PrintWriter printWriter = null; try { Manifest mf = ma.getManifest( getProject(), getArchive() ); printWriter = new PrintWriter( WriterFactory.newWriter( manifestFile, WriterFactory.UTF_8 ) ); mf.write( printWriter ); } catch ( ManifestException e ) { throw new MojoExecutionException( "Error preparing the manifest: " + e.getMessage(), e ); } catch ( DependencyResolutionRequiredException e ) { throw new MojoExecutionException( "Error preparing the manifest: " + e.getMessage(), e ); } catch ( IOException e ) { throw new MojoExecutionException( "Error preparing the manifest: " + e.getMessage(), e ); } finally { IOUtil.close( printWriter ); } } } maven-war-plugin-2.1.1/src/main/java/org/apache/maven/plugin/war/Overlay.java0000644000175000017500000001535011431614336026775 0ustar twernertwernerpackage org.apache.maven.plugin.war; /* * 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.maven.artifact.Artifact; import java.util.ArrayList; import java.util.Arrays; import java.util.List; /** * An overlay is a skeleton WAR added to another WAR project in order to inject a * functionality, resources or any other shared component. *

    * Note that a particular WAR dependency can be added multiple times as an overlay * with different includes/excludes filter; this allows building a fine grained * overwriting policy. *

    * The current project can also be described as an overlay and can not be specified * twice. An overlay with no groupId and no artifactId represents the * current project. * * @author Stephane Nicoll * @version $Id: Overlay.java 985595 2010-08-14 22:29:50Z dennisl $ */ public class Overlay { public static final String[] DEFAULT_INCLUDES = new String[]{"**/**"}; public static final String[] DEFAULT_EXCLUDES = new String[]{"META-INF/MANIFEST.MF"}; private String id; private String groupId; private String artifactId; private String classifier = null; private String[] includes = DEFAULT_INCLUDES; private String[] excludes = DEFAULT_EXCLUDES; private boolean filtered = false; private boolean skip = false; private Artifact artifact; private String targetPath; /** default overlay type is war */ private String type = "war"; public Overlay() { super(); } public Overlay( String groupId, String artifactId ) { this(); this.groupId = groupId; this.artifactId = artifactId; } /** * Specify whether this overlay represents the current project or not. * * @return true if the overlay represents the current project, false otherwise */ public boolean isCurrentProject() { return ( groupId == null && artifactId == null ); } public static Overlay createInstance() { Overlay overlay = new Overlay(); overlay.setId( "currentBuild" ); return overlay; } // Getters and Setters public String getId() { if ( id == null ) { final StringBuffer sb = new StringBuffer(); sb.append( getGroupId() ).append( ":" ).append( getArtifactId() ); if ( getClassifier() != null ) { sb.append( ":" ).append( getClassifier() ); } id = sb.toString(); } return id; } public void setId( String id ) { this.id = id; } public String getGroupId() { return groupId; } public void setGroupId( String groupId ) { this.groupId = groupId; } public String getArtifactId() { return artifactId; } public void setArtifactId( String artifactId ) { this.artifactId = artifactId; } public String getClassifier() { return classifier; } public void setClassifier( String classifier ) { this.classifier = classifier; } public String[] getIncludes() { return includes; } public void setIncludes( String includes ) { this.includes = parse( includes ); } public void setIncludes( String[] includes ) { this.includes = includes; } public String[] getExcludes() { return excludes; } public void setExcludes( String excludes ) { this.excludes = parse( excludes ); } public void setExcludes( String[] excludes ) { this.excludes = excludes; } public boolean isFiltered() { return filtered; } public void setFiltered( boolean filtered ) { this.filtered = filtered; } public boolean shouldSkip() { return skip; } public void setSkip( boolean skip ) { this.skip = skip; } public Artifact getArtifact() { return artifact; } public void setArtifact( Artifact artifact ) { this.artifact = artifact; } public String getTargetPath() { return targetPath; } public void setTargetPath( String targetPath ) { this.targetPath = targetPath; } public String getType() { return type; } public void setType( String type ) { this.type = type; } public String toString() { return " id " + getId(); } public boolean equals( Object o ) { if ( this == o ) { return true; } if ( o == null || getClass() != o.getClass() ) { return false; } Overlay overlay = (Overlay) o; if ( excludes != null ? !Arrays.equals( excludes, overlay.excludes ) : overlay.excludes != null ) { return false; } if ( getId() != null ? !getId().equals( overlay.getId() ) : overlay.getId() != null ) { return false; } if ( includes != null ? !Arrays.equals( includes, overlay.includes ) : overlay.includes != null ) { return false; } return true; } public int hashCode() { int result; result = ( getId() != null ? getId().hashCode() : 0 ); result = 31 * result + ( includes != null ? includes.hashCode() : 0 ); result = 31 * result + ( excludes != null ? excludes.hashCode() : 0 ); return result; } private String[] parse( String s ) { final List result = new ArrayList(); if ( s == null ) { return (String[]) result.toArray( new String[result.size()] ); } else { String[] tokens = s.split( "," ); for ( int i = 0; i < tokens.length; i++ ) { String token = tokens[i]; result.add( token.trim() ); } return (String[]) result.toArray( new String[result.size()] ); } } } maven-war-plugin-2.1.1/src/main/java/org/apache/maven/plugin/war/util/0000755000175000017500000000000011641142607025462 5ustar twernertwernermaven-war-plugin-2.1.1/src/main/java/org/apache/maven/plugin/war/util/DependencyInfo.java0000644000175000017500000000523411045160162031215 0ustar twernertwernerpackage org.apache.maven.plugin.war.util; /* * 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.maven.model.Dependency; /** * Holds a dependency and packaging information. * * @author Stephane Nicoll * @version $Id: DependencyInfo.java 682073 2008-08-02 22:32:18Z dennisl $ */ public class DependencyInfo { private final Dependency dependency; private String targetFileName; /** * Creates a new instance. * * @param dependency the dependency */ public DependencyInfo( Dependency dependency ) { this.dependency = dependency; } /** * Returns the dependency. * * @return the dependency */ public Dependency getDependency() { return dependency; } /** * Returns the target filen ame of the dependency. If no target file name * is associated, returns null. * * @return the target file name or null */ public String getTargetFileName() { return targetFileName; } /** * Sets the target file name. * * @param targetFileName the target file name */ public void setTargetFileName( String targetFileName ) { this.targetFileName = targetFileName; } public boolean equals( Object o ) { if ( this == o ) { return true; } if ( o == null || getClass() != o.getClass() ) { return false; } DependencyInfo that = (DependencyInfo) o; if ( dependency != null ? !dependency.equals( that.dependency ) : that.dependency != null ) { return false; } return true; } public int hashCode() { int result; result = ( dependency != null ? dependency.hashCode() : 0 ); result = 31 * result + ( targetFileName != null ? targetFileName.hashCode() : 0 ); return result; } } maven-war-plugin-2.1.1/src/main/java/org/apache/maven/plugin/war/util/WarUtils.java0000644000175000017500000001200611144561523030076 0ustar twernertwernerpackage org.apache.maven.plugin.war.util; /* * 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.maven.artifact.Artifact; import org.apache.maven.model.Dependency; import org.apache.maven.project.MavenProject; import org.codehaus.plexus.util.StringUtils; import java.util.Iterator; /** * * @author Stephane Nicoll * @version $Id: WarUtils.java 743348 2009-02-11 14:40:19Z dennisl $ */ public class WarUtils { public static Artifact getArtifact( MavenProject project, Dependency dependency ) { final Iterator it = project.getArtifacts().iterator(); while ( it.hasNext() ) { Artifact artifact = (Artifact) it.next(); if ( artifact.getGroupId().equals( dependency.getGroupId() ) && artifact.getArtifactId().equals( dependency.getArtifactId() ) && artifact.getType().equals( dependency.getType() ) ) { if ( artifact.getClassifier() == null && dependency.getClassifier() == null ) { return artifact; } else if ( dependency.getClassifier() != null && dependency.getClassifier().equals( artifact.getClassifier() ) ) { return artifact; } } } return null; } public static boolean isRelated( Artifact artifact, Dependency dependency ) { if ( artifact == null || dependency == null ) { return false; } if ( !StringUtils.equals( artifact.getGroupId(), dependency.getGroupId() ) ) { return false; } if ( !StringUtils.equals( artifact.getArtifactId(), dependency.getArtifactId() ) ) { return false; } if ( artifact.getVersion() != null ? !artifact.getVersion().equals( dependency.getVersion() ) : dependency.getVersion() != null ) { return false; } if ( artifact.getType() != null ? !artifact.getType().equals( dependency.getType() ) : dependency.getType() != null ) { return false; } if ( artifact.getClassifier() != null ? !artifact.getClassifier().equals( dependency.getClassifier() ) : dependency.getClassifier() != null ) { return false; } if ( artifact.getScope() != null ? !artifact.getScope().equals( dependency.getScope() ) : dependency.getScope() != null ) { return false; } if ( artifact.isOptional() != dependency.isOptional() ) { return false; } return true; } public static boolean dependencyEquals( Dependency first, Dependency second ) { if ( first == second ) { return true; } if ( first.isOptional() != second.isOptional() ) { return false; } if ( !StringUtils.equals( first.getArtifactId(), second.getArtifactId() ) ) { return false; } if ( first.getClassifier() != null ? !first.getClassifier().equals( second.getClassifier() ) : second.getClassifier() != null ) { return false; } if ( first.getExclusions() != null ? !first.getExclusions().equals( second.getExclusions() ) : second.getExclusions() != null ) { return false; } if ( !StringUtils.equals( first.getGroupId(), second.getGroupId() ) ) { return false; } if ( first.getScope() != null ? !first.getScope().equals( second.getScope() ) : second.getScope() != null ) { return false; } if ( first.getSystemPath() != null ? !first.getSystemPath().equals( second.getSystemPath() ) : second.getSystemPath() != null ) { return false; } if ( first.getType() != null ? !first.getType().equals( second.getType() ) : second.getType() != null ) { return false; } if ( first.getVersion() != null ? !first.getVersion().equals( second.getVersion() ) : second.getVersion() != null ) { return false; } return true; } } maven-war-plugin-2.1.1/src/main/java/org/apache/maven/plugin/war/util/PathSet.java0000644000175000017500000001723311224274273027705 0ustar twernertwernerpackage org.apache.maven.plugin.war.util; /* * 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.codehaus.plexus.util.DirectoryScanner; import org.codehaus.plexus.util.StringUtils; import java.io.File; import java.util.Collection; import java.util.HashSet; import java.util.Iterator; import java.util.LinkedHashSet; import java.util.Set; /** * Set of file's paths. *

    * The class extends functionality of a "normal" set of strings by a process of * the paths normalization. All paths are converted to unix form (slashes) and * they don't start with starting /. * * @author Piotr Tabor * @version $Id: PathSet.java 791368 2009-07-06 04:08:27Z snicoll $ */ public class PathSet { /** * Set of normalized paths */ private Set/* */pathsSet = new LinkedHashSet(); /** * The method normalizes the path. *

    *

      *
    • changes directory separator to unix's separator(/)
    • *
    • deletes all trailing slashes
    • *
    * * @param path to normalization * @return normalized path */ protected String normalizeFilePath( String path ) { return normalizeFilePathStatic( path ); } /*-------------------- Business interface ------------------------------*/ /** * Creates an empty paths set */ public PathSet() { /*Empty default constructor*/ } /** * Creates paths set and normalizate and adds all 'paths'. * The source 'paths' will not be changed * * @param paths to be added */ public PathSet( Collection/*String>*/ paths ) { addAll( paths ); } /** * Creates paths set and normalizate and adds all 'paths'. * The source 'paths' will not be changed * * @param paths to be added */ public PathSet( String[] paths ) { addAll( paths ); } /** * Normalizes and adds given path to the set. * * @param path to be added */ public void add( String path ) { pathsSet.add( normalizeFilePath( path ) ); } /** * Normalizes and adds given paths (collection of strings) * to the set. The source collection will not be changed * * @param paths - collection of strings to be added * @param prefix added to all given paths */ public void addAll( Collection/**/ paths, String prefix ) { for ( Iterator iter = paths.iterator(); iter.hasNext(); ) { add( prefix + iter.next() ); } } /** * Normalizes and adds given paths to the set. * The source collection will not be changed * * @param paths to be added * @param prefix added to all given paths */ public void addAll( String[] paths, String prefix ) { for ( int i = 0; i < paths.length; i++ ) { add( prefix + paths[i] ); } } /** * Adds given paths to the set. * The source collection will not be changed * * @param paths to be added * @param prefix added to all given paths */ public void addAll( PathSet paths, String prefix ) { for ( Iterator iter = paths.iterator(); iter.hasNext(); ) { add( prefix + iter.next() ); } } /** * Normalizes and adds given paths (collection of strings) * to the set. The source collection will not be changed * * @param paths - collection of strings to be added */ public void addAll( Collection/**/ paths ) { addAll( paths, "" ); } /** * Normalizes and adds given paths to the set. * The source collection will not be changed * * @param paths to be added */ public void addAll( String[] paths ) { addAll( paths, "" ); } /** * Adds given paths to the set. * The source collection will not be changed * * @param paths to be added */ public void addAll( PathSet paths ) { addAll( paths, "" ); } /** * Checks if the set constains given path. The path is normalized * before check. * * @param path we are looking for in the set. * @return information if the set constains the path. */ public boolean contains( String path ) { return pathsSet.contains( normalizeFilePath( path ) ); } /** * Removes the specified path if it exists. * * @param path the path to remove * @return true if the path was removed, false if it did not existed */ boolean remove( String path ) { final String normalizedPath = normalizeFilePath( path ); return pathsSet.remove( normalizedPath ); } /** * Returns iterator of normalized paths (strings) * * @return iterator of normalized paths (strings) */ public Iterator iterator() { return pathsSet.iterator(); } /** * Adds given prefix to all paths in the set. *

    * The prefix should be ended by '/'. The generated paths are normalized. * * @param prefix to be added to all items */ public void addPrefix( String prefix ) { final Set/**/ newSet = new HashSet(); for ( Iterator iter = pathsSet.iterator(); iter.hasNext(); ) { String path = (String) iter.next(); newSet.add( normalizeFilePath( prefix + path ) ); } pathsSet = newSet; } /** * Returns count of the paths in the set * * @return count of the paths in the set */ public int size() { return pathsSet.size(); } /** * Adds to the set all files in the given directory * * @param directory that will be searched for file's paths to add * @param prefix to be added to all found files */ public void addAllFilesInDirectory( File directory, String prefix ) { DirectoryScanner scanner = new DirectoryScanner(); scanner.setBasedir( directory ); scanner.scan(); addAll( scanner.getIncludedFiles(), prefix ); } /*-------------------- Universal static mathods ------------------------*/ /** * The method normalizes the path. *

    *

      *
    • changes directory separator to unix's separator(/)
    • *
    • deletes all trailing slashes
    • *
    * * @param path to normalization * @return normalized path */ public static String normalizeFilePathStatic( String path ) { return trimTrailingSlashes( StringUtils.replace( path, '\\', '/' ) ); } /** * The method deletes all trailing slashes from the given string * * @param str a string * @return trimed string */ public static String trimTrailingSlashes( String str ) { int i; for ( i = 0; i < str.length() && str.charAt( i ) == '/'; i++ ) { // just calculate i } return str.substring( i ); } } maven-war-plugin-2.1.1/src/main/java/org/apache/maven/plugin/war/util/WebappStructure.java0000644000175000017500000005441111453717203031472 0ustar twernertwernerpackage org.apache.maven.plugin.war.util; /* * 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.maven.artifact.Artifact; import org.apache.maven.model.Dependency; import org.codehaus.plexus.util.StringUtils; import java.io.IOException; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; /** * Represents the structure of a web application composed of multiple * overlays. Each overlay is registered within this structure with the * set of files it holds. *

    * Note that this structure is persisted to disk at each invocation to * store which owner holds which path (file). * * @author Stephane Nicoll * @version $Id: WebappStructure.java 1006058 2010-10-08 22:43:15Z dennisl $ */ public class WebappStructure { private Map registeredFiles; private List dependenciesInfo; private transient PathSet allFiles = new PathSet(); private transient WebappStructure cache; /** * Creates a new empty instance. * * @param dependencies the dependencies of the project */ public WebappStructure( List dependencies ) { this.dependenciesInfo = createDependenciesInfoList( dependencies ); this.registeredFiles = new HashMap(); this.cache = null; } /** * Creates a new instance with the specified cache. * * @param dependencies the dependencies of the project * @param cache the cache */ public WebappStructure( List dependencies, WebappStructure cache ) { this.dependenciesInfo = createDependenciesInfoList( dependencies ); this.registeredFiles = new HashMap(); if ( cache == null ) { this.cache = new WebappStructure( dependencies ); } else { this.cache = cache; } } /** * Returns the list of {@link DependencyInfo} for the project. * * @return the dependencies information of the project */ public List getDependenciesInfo() { return dependenciesInfo; } /** * Returns the dependencies of the project. * * @return the dependencies of the project */ public List getDependencies() { final List result = new ArrayList(); if ( dependenciesInfo == null ) { return result; } final Iterator it = dependenciesInfo.iterator(); while ( it.hasNext() ) { DependencyInfo dependencyInfo = (DependencyInfo) it.next(); result.add( dependencyInfo.getDependency() ); } return result; } /** * Specify if the specified path is registered or not. * * @param path the relative path from the webapp root directory * @return true if the path is registered, false otherwise */ public boolean isRegistered( String path ) { return getFullStructure().contains( path ); } /** * Registers the specified path for the specified owner. Returns true * if the path is not already registered, false otherwise. * * @param id the owner of the path * @param path the relative path from the webapp root directory * @return true if the file was registered successfully */ public boolean registerFile( String id, String path ) { if ( !isRegistered( path ) ) { doRegister( id, path ); return true; } else { return false; } } /** * Forces the registration of the specified path for the specified owner. If * the file is not registered yet, a simple registration is performed. If the * file already exists, the owner changes to the specified one. *

    * Beware that the semantic of the return boolean is different than the one * from {@link #registerFile(String, String)}; returns true if an * owner replacement was made and false if the file was simply registered * for the first time. * * @param id the owner of the path * @param path the relative path from the webapp root directory * @return false if the file did not exist, true if the owner was replaced */ public boolean registerFileForced( String id, String path ) { if ( !isRegistered( path ) ) { doRegister( id, path ); return false; } else { // Force the switch to the new owner getStructure( getOwner( path ) ).remove( path ); getStructure( id ).add( path ); return true; } } /** * Registers the specified path for the specified owner. Invokes * the callback with the result of the registration. * * @param id the owner of the path * @param path the relative path from the webapp root directory * @param callback the callback to invoke with the result of the registration * @throws IOException if the callback invocation throws an IOException */ public void registerFile( String id, String path, RegistrationCallback callback ) throws IOException { // If the file is already in the current structure, rejects it with the current owner if ( isRegistered( path ) ) { callback.refused( id, path, getOwner( path ) ); } else { doRegister( id, path ); // This is a new file if ( cache.getOwner( path ) == null ) { callback.registered( id, path ); } // The file already belonged to this owner else if ( cache.getOwner( path ).equals( id ) ) { callback.alreadyRegistered( id, path ); } // The file belongs to another owner and it's known currently else if ( getOwners().contains( cache.getOwner( path ) ) ) { callback.superseded( id, path, cache.getOwner( path ) ); } // The file belongs to another owner and it's unknown else { callback.supersededUnknownOwner( id, path, cache.getOwner( path ) ); } } } /** * Returns the owner of the specified path. If the file is not * registered, returns null * * @param path the relative path from the webapp root directory * @return the owner or null. */ public String getOwner( String path ) { if ( !isRegistered( path ) ) { return null; } else { final Iterator it = registeredFiles.keySet().iterator(); while ( it.hasNext() ) { final String owner = (String) it.next(); final PathSet structure = getStructure( owner ); if ( structure.contains( path ) ) { return owner; } } throw new IllegalStateException( "Should not happen, path [" + path + "] is flagged as being registered but was not found." ); } } /** * Returns the owners. Note that this the returned {@link Set} may be * inconsistent since it represents a persistent cache across multiple * invocations. *

    * For instance, if an overlay was removed in this execution, it will be * still be there till the cache is cleaned. This happens when the clean * mojo is invoked. * * @return the list of owners */ public Set getOwners() { return registeredFiles.keySet(); } /** * Returns all paths that have been registered so far. * * @return all registered path */ public PathSet getFullStructure() { return allFiles; } /** * Returns the list of registered files for the specified owner. * * @param id the owner * @return the list of files registered for that owner */ public PathSet getStructure( String id ) { PathSet pathSet = (PathSet) registeredFiles.get( id ); if ( pathSet == null ) { pathSet = new PathSet(); registeredFiles.put( id, pathSet ); } return pathSet; } /** * Analyze the dependencies of the project using the specified callback. * * @param callback the callback to use to report the result of the analysis */ public void analyseDependencies( DependenciesAnalysisCallback callback ) { if ( callback == null ) { throw new NullPointerException( "Callback could not be null." ); } if ( cache == null ) { // Could not analyze dependencies without a cache return; } final List currentDependencies = new ArrayList( getDependencies() ); final List previousDependencies = new ArrayList( cache.getDependencies() ); final Iterator it = currentDependencies.listIterator(); while ( it.hasNext() ) { Dependency dependency = (Dependency) it.next(); // Check if the dependency is there "as is" final Dependency matchingDependency = matchDependency( previousDependencies, dependency ); if ( matchingDependency != null ) { callback.unchangedDependency( dependency ); // Handled so let's remove it.remove(); previousDependencies.remove( matchingDependency ); } else { // Try to get the dependency final Dependency previousDep = findDependency( dependency, previousDependencies ); if ( previousDep == null ) { callback.newDependency( dependency ); it.remove(); } else if ( !dependency.getVersion().equals( previousDep.getVersion() ) ) { callback.updatedVersion( dependency, previousDep.getVersion() ); it.remove(); previousDependencies.remove( previousDep ); } else if ( !dependency.getScope().equals( previousDep.getScope() ) ) { callback.updatedScope( dependency, previousDep.getScope() ); it.remove(); previousDependencies.remove( previousDep ); } else if ( dependency.isOptional() != previousDep.isOptional() ) { callback.updatedOptionalFlag( dependency, previousDep.isOptional() ); it.remove(); previousDependencies.remove( previousDep ); } else { callback.updatedUnknown( dependency, previousDep ); it.remove(); previousDependencies.remove( previousDep ); } } } final Iterator previousDepIt = previousDependencies.iterator(); while ( previousDepIt.hasNext() ) { Dependency dependency = (Dependency) previousDepIt.next(); callback.removedDependency( dependency ); } } /** * Registers the target file name for the specified artifact. * * @param artifact the artifact * @param targetFileName the target file name */ public void registerTargetFileName( Artifact artifact, String targetFileName ) { final Iterator it = dependenciesInfo.iterator(); while ( it.hasNext() ) { DependencyInfo dependencyInfo = (DependencyInfo) it.next(); if ( WarUtils.isRelated( artifact, dependencyInfo.getDependency() ) ) { dependencyInfo.setTargetFileName( targetFileName ); } } } /** * Returns the cached target file name that matches the specified * dependency, that is the target file name of the previous run. *

    * The dependency object may have changed so the comparison is * based on basic attributes of the dependency. * * @param dependency a dependency * @return the target file name of the last run for this dependency */ public String getCachedTargetFileName( Dependency dependency ) { if ( cache == null ) { return null; } final Iterator it = cache.getDependenciesInfo().iterator(); while ( it.hasNext() ) { DependencyInfo dependencyInfo = (DependencyInfo) it.next(); final Dependency dependency2 = dependencyInfo.getDependency(); if ( StringUtils.equals( dependency.getGroupId(), dependency2.getGroupId() ) && StringUtils.equals( dependency.getArtifactId(), dependency2.getArtifactId() ) && StringUtils.equals( dependency.getType(), dependency2.getType() ) && StringUtils.equals( dependency.getClassifier(), dependency2.getClassifier() ) ) { return dependencyInfo.getTargetFileName(); } } return null; } // Private helpers private void doRegister( String id, String path ) { getFullStructure().add( path ); getStructure( id ).add( path ); } /** * Find a dependency that is similar from the specified dependency. * * @param dependency the dependency to find * @param dependencies a list of dependencies * @return a similar dependency or null if no similar dependency is found */ private Dependency findDependency( Dependency dependency, List dependencies ) { final Iterator it = dependencies.iterator(); while ( it.hasNext() ) { Dependency dep = (Dependency) it.next(); if ( dependency.getGroupId().equals( dep.getGroupId() ) && dependency.getArtifactId().equals( dep.getArtifactId() ) && dependency.getType().equals( dep.getType() ) && ( ( dependency.getClassifier() == null && dep.getClassifier() == null ) || ( dependency.getClassifier() != null && dependency.getClassifier().equals( dep.getClassifier() ) ) ) ) { return dep; } } return null; } private Dependency matchDependency( List dependencies, Dependency dependency ) { final Iterator it = dependencies.iterator(); while ( it.hasNext() ) { Dependency dep = (Dependency) it.next(); if ( WarUtils.dependencyEquals( dep, dependency ) ) { return dep; } } return null; } private List createDependenciesInfoList( List dependencies ) { if ( dependencies == null ) { return Collections.EMPTY_LIST; } final List result = new ArrayList(); final Iterator it = dependencies.iterator(); while ( it.hasNext() ) { Dependency dependency = (Dependency) it.next(); result.add( new DependencyInfo( dependency ) ); } return result; } private Object readResolve() { // the full structure should be resolved so let's rebuild it this.allFiles = new PathSet(); final Iterator it = registeredFiles.values().iterator(); while ( it.hasNext() ) { PathSet pathSet = (PathSet) it.next(); this.allFiles.addAll( pathSet ); } return this; } /** * Callback interface to handle events related to filepath registration in * the webapp. */ public interface RegistrationCallback { /** * Called if the targetFilename for the specified ownerId * has been registered successfully. *

    * This means that the targetFilename was unknown and has been * registered successfully. * * @param ownerId the ownerId * @param targetFilename the relative path according to the root of the webapp * @throws IOException if an error occurred while handling this event */ void registered( String ownerId, String targetFilename ) throws IOException; /** * Called if the targetFilename for the specified ownerId * has already been registered. *

    * This means that the targetFilename was known and belongs to the * specified owner. * * @param ownerId the ownerId * @param targetFilename the relative path according to the root of the webapp * @throws IOException if an error occurred while handling this event */ void alreadyRegistered( String ownerId, String targetFilename ) throws IOException; /** * Called if the registration of the targetFilename for the * specified ownerId has been refused since the path already * belongs to the actualOwnerId. *

    * This means that the targetFilename was known and does not * belong to the specified owner. * * @param ownerId the ownerId * @param targetFilename the relative path according to the root of the webapp * @param actualOwnerId the actual owner * @throws IOException if an error occurred while handling this event */ void refused( String ownerId, String targetFilename, String actualOwnerId ) throws IOException; /** * Called if the targetFilename for the specified ownerId * has been registered successfully by superseding a deprecatedOwnerId, * that is the previous owner of the file. *

    * This means that the targetFilename was known but for another * owner. This usually happens after a project's configuration change. As a * result, the file has been registered successfully to the new owner. * * @param ownerId the ownerId * @param targetFilename the relative path according to the root of the webapp * @param deprecatedOwnerId the previous owner that does not exist anymore * @throws IOException if an error occurred while handling this event */ void superseded( String ownerId, String targetFilename, String deprecatedOwnerId ) throws IOException; /** * Called if the targetFilename for the specified ownerId * has been registered successfully by superseding a unknownOwnerId, * that is an owner that does not exist anymore in the current project. *

    * This means that the targetFilename was known but for an owner that * does not exist anymore. Hence the file has been registered successfully to * the new owner. * * @param ownerId the ownerId * @param targetFilename the relative path according to the root of the webapp * @param unknownOwnerId the previous owner that does not exist anymore * @throws IOException if an error occurred while handling this event */ void supersededUnknownOwner( String ownerId, String targetFilename, String unknownOwnerId ) throws IOException; } /** * Callback interface to handle events related to dependencies analysis. */ public interface DependenciesAnalysisCallback { /** * Called if the dependency has not changed since the last build. * * @param dependency the dependency that hasn't changed */ void unchangedDependency( Dependency dependency ); /** * Called if a new dependency has been added since the last build. * * @param dependency the new dependency */ void newDependency( Dependency dependency ); /** * Called if the dependency has been removed since the last build. * * @param dependency the dependency that has been removed */ void removedDependency( Dependency dependency ); /** * Called if the version of the dependency has changed since the last build. * * @param dependency the dependency * @param previousVersion the previous version of the dependency */ void updatedVersion( Dependency dependency, String previousVersion ); /** * Called if the scope of the dependency has changed since the last build. * * @param dependency the dependency * @param previousScope the previous scope */ void updatedScope( Dependency dependency, String previousScope ); /** * Called if the optional flag of the dependency has changed since the * last build. * * @param dependency the dependency * @param previousOptional the previous optional flag */ void updatedOptionalFlag( Dependency dependency, boolean previousOptional ); /** * Called if the dependency has been updated for unknown reason. * * @param dependency the dependency * @param previousDep the previous dependency */ void updatedUnknown( Dependency dependency, Dependency previousDep ); } } maven-war-plugin-2.1.1/src/main/java/org/apache/maven/plugin/war/util/ClassesPackager.java0000644000175000017500000000717211046130275031364 0ustar twernertwernerpackage org.apache.maven.plugin.war.util; /* * 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.maven.archiver.MavenArchiveConfiguration; import org.apache.maven.archiver.MavenArchiver; import org.apache.maven.artifact.DependencyResolutionRequiredException; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.war.packaging.AbstractWarPackagingTask; import org.apache.maven.project.MavenProject; import org.codehaus.plexus.archiver.ArchiverException; import org.codehaus.plexus.archiver.jar.JarArchiver; import org.codehaus.plexus.archiver.jar.ManifestException; import java.io.File; import java.io.IOException; /** * Packages the content of the classes directory. * * @author Stephane Nicoll * @version $Id: ClassesPackager.java 682908 2008-08-05 19:57:49Z hboutemy $ */ public class ClassesPackager { /** * Creates a new instance. */ public ClassesPackager() { super(); } /** * Package the classes * * @param classesDirectory the classes directory * @param targetFile the target file * @param jarArchiver the jar archiver to use * @param project the related project * @param archiveConfiguration the archive configuration to use * @throws MojoExecutionException if an error occurred while creating the archive */ public void packageClasses( File classesDirectory, File targetFile, JarArchiver jarArchiver, MavenProject project, MavenArchiveConfiguration archiveConfiguration ) throws MojoExecutionException { try { final MavenArchiver archiver = new MavenArchiver(); archiver.setArchiver( jarArchiver ); archiver.setOutputFile( targetFile ); archiver.getArchiver().addDirectory( classesDirectory ); archiver.createArchive( project, archiveConfiguration ); } catch ( ArchiverException e ) { throw new MojoExecutionException( "Could not create classes archive", e ); } catch ( ManifestException e ) { throw new MojoExecutionException( "Could not create classes archive", e ); } catch ( IOException e ) { throw new MojoExecutionException( "Could not create classes archive", e ); } catch ( DependencyResolutionRequiredException e ) { throw new MojoExecutionException( "Could not create classes archive", e ); } } /** * Returns the classes directory from the specified webapp directory. * * @param webappDirectory the webapp directory * @return the classes directory of the specified webapp directory */ public File getClassesDirectory( File webappDirectory ) { return new File( webappDirectory, AbstractWarPackagingTask.CLASSES_PATH ); } } maven-war-plugin-2.1.1/src/main/java/org/apache/maven/plugin/war/util/MappingUtils.java0000644000175000017500000001015311376451113030741 0ustar twernertwernerpackage org.apache.maven.plugin.war.util; /* * 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 java.util.Collections; import java.util.List; import java.util.Properties; import org.apache.maven.artifact.Artifact; import org.codehaus.plexus.interpolation.InterpolationException; import org.codehaus.plexus.interpolation.ObjectBasedValueSource; import org.codehaus.plexus.interpolation.PropertiesBasedValueSource; import org.codehaus.plexus.interpolation.RegexBasedInterpolator; import org.codehaus.plexus.interpolation.ValueSource; /** * Utilities used to evaluate expression. *

    * TODO: this comes from the assembly plugin; refactor when it's shared. *

    * The expression might use any field of the {@link Artifact} interface. Some * examples might be: *

      *
    • @{artifactId}@-@{version}@@{dashClassifier?}@.@{extension}@
    • *
    • @{artifactId}@-@{version}@.@{extension}@
    • *
    • @{artifactId}@.@{extension}@
    • *
    * * @author Stephane Nicoll * @version $Id: MappingUtils.java 947587 2010-05-24 10:17:47Z dennisl $ */ public class MappingUtils { /** * Evaluates the specified expression for the given artifact. * * @param expression the expression to evaluate * @param artifact the artifact to use as value object for tokens * @return expression the evaluated expression */ public static String evaluateFileNameMapping( String expression, Artifact artifact ) throws InterpolationException { String value = expression; // FIXME: This is BAD! Accessors SHOULD NOT change the behavior of the object. artifact.isSnapshot(); RegexBasedInterpolator interpolator = new RegexBasedInterpolator( "\\@\\{(", ")?([^}]+)\\}@" ); interpolator.addValueSource( new ObjectBasedValueSource( artifact ) ); interpolator.addValueSource( new ObjectBasedValueSource( artifact.getArtifactHandler() ) ); Properties classifierMask = new Properties(); classifierMask.setProperty( "classifier", "" ); // Support for special expressions, like @{dashClassifier?}@, see MWAR-212 String classifier = artifact.getClassifier(); if ( classifier != null ) { classifierMask.setProperty( "dashClassifier?", "-" + classifier ); classifierMask.setProperty( "dashClassifier", "-" + classifier ); } else { classifierMask.setProperty( "dashClassifier?", "" ); classifierMask.setProperty( "dashClassifier", "" ); } interpolator.addValueSource( new PropertiesBasedValueSource ( classifierMask ) ); value = interpolator.interpolate( value, "__artifact" ); return value; } /** * Internal implementation of {@link ValueSource} */ static class PropertiesInterpolationValueSource implements ValueSource { private final Properties properties; public PropertiesInterpolationValueSource( Properties properties ) { this.properties = properties; } public Object getValue( String key ) { return properties.getProperty( key ); } public void clearFeedback() { // nothing here } public List getFeedback() { // nothing here just NPE free return Collections.EMPTY_LIST; } } } ././@LongLink0000000000000000000000000000014500000000000011565 Lustar rootrootmaven-war-plugin-2.1.1/src/main/java/org/apache/maven/plugin/war/util/WebappStructureSerializer.javamaven-war-plugin-2.1.1/src/main/java/org/apache/maven/plugin/war/util/WebappStructureSerializer.java0000644000175000017500000000703211431612271033514 0ustar twernertwernerpackage org.apache.maven.plugin.war.util; /* * 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 com.thoughtworks.xstream.XStream; import com.thoughtworks.xstream.io.xml.DomDriver; import org.apache.maven.model.Dependency; import org.codehaus.plexus.util.IOUtil; import org.codehaus.plexus.util.ReaderFactory; import org.codehaus.plexus.util.WriterFactory; import java.io.File; import java.io.IOException; import java.io.Reader; import java.io.Writer; /** * Serializes {@link WebappStructure} back and forth. * * @author Stephane Nicoll * @version $Id: WebappStructureSerializer.java 985593 2010-08-14 22:12:09Z dennisl $ */ public class WebappStructureSerializer { private static final XStream xStream; static { xStream = new XStream( new DomDriver() ); // Register aliases xStream.alias( "webapp-structure", WebappStructure.class ); xStream.alias( "path-set", PathSet.class ); xStream.alias( "dependency", Dependency.class ); } /** * Creates a new instance of the serializer. */ public WebappStructureSerializer() { } /** * Reads the {@link WebappStructure} from the specified file. * * @param file the file containing the webapp structure * @return the webapp structure * @throws IOException if an error occurred while reading the structure */ public WebappStructure fromXml( File file ) throws IOException { Reader reader = null; try { reader = ReaderFactory.newXmlReader( file ); return (WebappStructure) xStream.fromXML( reader ); } finally { IOUtil.close( reader ); } } /** * Saves the {@link WebappStructure} to the specified file. * * @param webappStructure the structure to save * @param targetFile the file to use to save the structure * @throws IOException if an error occurred while saving the webapp structure */ public void toXml( WebappStructure webappStructure, File targetFile ) throws IOException { Writer writer = null; try { if ( !targetFile.getParentFile().exists() && !targetFile.getParentFile().mkdirs() ) { throw new IOException( "Could not create parent [" + targetFile.getParentFile().getAbsolutePath() + "]" ); } if ( !targetFile.exists() && !targetFile.createNewFile() ) { throw new IOException( "Could not create file [" + targetFile.getAbsolutePath() + "]" ); } writer = WriterFactory.newXmlWriter( targetFile ); xStream.toXML( webappStructure, writer ); } finally { IOUtil.close( writer ); } } } maven-war-plugin-2.1.1/src/main/java/org/apache/maven/plugin/war/WarInPlaceMojo.java0000644000175000017500000000271111431721024030154 0ustar twernertwernerpackage org.apache.maven.plugin.war; /* * 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.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.MojoFailureException; /** * Generate the webapp in the WAR source directory. * * @goal inplace * @requiresDependencyResolution runtime * @threadSafe * @version $Id: WarInPlaceMojo.java 985625 2010-08-15 08:15:16Z dennisl $ */ public class WarInPlaceMojo extends AbstractWarMojo { public void execute() throws MojoExecutionException, MojoFailureException { getLog().info( "Generating webapp in source directory [" + getWarSourceDirectory() + "]" ); buildExplodedWebapp( getWarSourceDirectory() ); } }maven-war-plugin-2.1.1/src/main/java/org/apache/maven/plugin/war/packaging/0000755000175000017500000000000011641142607026431 5ustar twernertwernermaven-war-plugin-2.1.1/src/main/java/org/apache/maven/plugin/war/packaging/WarPackagingTask.java0000644000175000017500000000316711046130275032461 0ustar twernertwernerpackage org.apache.maven.plugin.war.packaging; /* * 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.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.MojoFailureException; /** * The base packaging task. * * @author Stephane Nicoll * @version $Id: WarPackagingTask.java 682908 2008-08-05 19:57:49Z hboutemy $ */ public interface WarPackagingTask { /** * Performs the packaging for the specified task. *

    * The task is responsible to update the packaging context, namely * with the files that have been copied. * * @param context the packaging context * @throws MojoExecutionException if an error occurred * @throws MojoFailureException if the project configuration is invalid */ void performPackaging( WarPackagingContext context ) throws MojoExecutionException, MojoFailureException; } ././@LongLink0000000000000000000000000000015000000000000011561 Lustar rootrootmaven-war-plugin-2.1.1/src/main/java/org/apache/maven/plugin/war/packaging/WarProjectPackagingTask.javamaven-war-plugin-2.1.1/src/main/java/org/apache/maven/plugin/war/packaging/WarProjectPackagingTask.j0000644000175000017500000003465411431614336033330 0ustar twernertwernerpackage org.apache.maven.plugin.war.packaging; /* * 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.maven.model.Resource; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.MojoFailureException; import org.apache.maven.plugin.war.Overlay; import org.apache.maven.plugin.war.util.PathSet; import org.apache.maven.shared.filtering.MavenFilteringException; import org.codehaus.plexus.util.DirectoryScanner; import org.codehaus.plexus.util.StringUtils; import org.codehaus.plexus.util.xml.XmlStreamReader; import java.io.File; import java.io.IOException; import java.util.Iterator; /** * Handles the project own resources, that is: *

      The list of web resources, if any *
    • The content of the webapp directory if it exists
    • *
    • The custom deployment descriptor(s), if any
    • *
    • The content of the classes directory if it exists
    • *
    • The dependencies of the project
    • *
    * * @author Stephane Nicoll * @version $Id: WarProjectPackagingTask.java 985595 2010-08-14 22:29:50Z dennisl $ */ public class WarProjectPackagingTask extends AbstractWarPackagingTask { private final Resource[] webResources; private final File webXml; private final File containerConfigXML; private final String id; private Overlay currentProjectOverlay; public WarProjectPackagingTask( Resource[] webResources, File webXml, File containerConfigXml, Overlay currentProjectOverlay ) { if ( webResources != null ) { this.webResources = webResources; } else { this.webResources = new Resource[0]; } this.webXml = webXml; this.containerConfigXML = containerConfigXml; this.currentProjectOverlay = currentProjectOverlay; this.id = currentProjectOverlay.getId(); } public void performPackaging( WarPackagingContext context ) throws MojoExecutionException, MojoFailureException { context.getLog().info( "Processing war project" ); // Prepare the INF directories File webinfDir = new File( context.getWebappDirectory(), WEB_INF_PATH ); webinfDir.mkdirs(); File metainfDir = new File( context.getWebappDirectory(), META_INF_PATH ); metainfDir.mkdirs(); handleWebResources( context ); handeWebAppSourceDirectory( context ); // Debug mode: dump the path set for the current build PathSet pathSet = context.getWebappStructure().getStructure( "currentBuild" ); context.getLog().debug( "Dump of the current build pathSet content -->" ); for ( Iterator iterator = pathSet.iterator(); iterator.hasNext(); ) { context.getLog().debug( "" + iterator.next() ); } context.getLog().debug( "-- end of dump --" ); handleDeploymentDescriptors( context, webinfDir, metainfDir ); handleClassesDirectory( context ); handleArtifacts( context ); } /** * Handles the web resources. * * @param context the packaging context * @throws MojoExecutionException if a resource could not be copied */ protected void handleWebResources( WarPackagingContext context ) throws MojoExecutionException { for ( int i = 0; i < webResources.length; i++ ) { Resource resource = webResources[i]; if ( !( new File( resource.getDirectory() ) ).isAbsolute() ) { resource.setDirectory( context.getProject().getBasedir() + File.separator + resource.getDirectory() ); } // Make sure that the resource directory is not the same as the webappDirectory if ( !resource.getDirectory().equals( context.getWebappDirectory().getPath() ) ) { try { copyResources( context, resource ); } catch ( IOException e ) { throw new MojoExecutionException( "Could not copy resource [" + resource.getDirectory() + "]", e ); } } } } /** * Handles the webapp sources. * * @param context the packaging context * @throws MojoExecutionException if the sources could not be copied */ protected void handeWebAppSourceDirectory( WarPackagingContext context ) throws MojoExecutionException { if ( !context.getWebappSourceDirectory().exists() ) { context.getLog().debug( "webapp sources directory does not exist - skipping." ); } else if ( !context.getWebappSourceDirectory().getAbsolutePath().equals( context.getWebappDirectory().getPath() ) ) { context.getLog().info( "Copying webapp resources [" + context.getWebappSourceDirectory() + "]" ); final PathSet sources = getFilesToIncludes( context.getWebappSourceDirectory(), context.getWebappSourceIncludes(), context.getWebappSourceExcludes() ); try { copyFiles( id, context, context.getWebappSourceDirectory(), sources, false ); } catch ( IOException e ) { throw new MojoExecutionException( "Could not copy webapp sources [" + context.getWebappDirectory().getAbsolutePath() + "]", e ); } } } /** * Handles the webapp artifacts. * * @param context the packaging context * @throws MojoExecutionException if the artifacts could not be packaged */ protected void handleArtifacts( WarPackagingContext context ) throws MojoExecutionException { ArtifactsPackagingTask task = new ArtifactsPackagingTask( context.getProject().getArtifacts(), currentProjectOverlay ); task.performPackaging( context ); } /** * Handles the webapp classes. * * @param context the packaging context * @throws MojoExecutionException if the classes could not be packaged */ protected void handleClassesDirectory( WarPackagingContext context ) throws MojoExecutionException { ClassesPackagingTask task = new ClassesPackagingTask( currentProjectOverlay ); task.performPackaging( context ); } /** * Handles the deployment descriptors, if specified. Note that the behavior * here is slightly different since the customized entry always win, even if * an overlay has already packaged a web.xml previously. * * @param context the packaging context * @param webinfDir the web-inf directory * @param metainfDir the meta-inf directory * @throws MojoFailureException if the web.xml is specified but does not exist * @throws MojoExecutionException if an error occurred while copying the descriptors */ protected void handleDeploymentDescriptors( WarPackagingContext context, File webinfDir, File metainfDir ) throws MojoFailureException, MojoExecutionException { try { if ( webXml != null && StringUtils.isNotEmpty( webXml.getName() ) ) { if ( !webXml.exists() ) { throw new MojoFailureException( "The specified web.xml file '" + webXml + "' does not exist" ); } // Making sure that it won't get overlayed context.getWebappStructure().registerFileForced( id, WEB_INF_PATH + "/web.xml" ); if ( context.isFilteringDeploymentDescriptors() ) { context.getMavenFileFilter().copyFile( webXml, new File( webinfDir, "web.xml" ), true, context.getFilterWrappers(), getEncoding( webXml ) ); } else { copyFile( context, webXml, new File( webinfDir, "web.xml" ), "WEB-INF/web.xml", true ); } } else { // the webXml can be the default one File defaultWebXml = new File( context.getWebappSourceDirectory(), WEB_INF_PATH + "/web.xml" ); // if exists we can filter it if ( defaultWebXml.exists() && context.isFilteringDeploymentDescriptors() ) { context.getWebappStructure().registerFile( id, WEB_INF_PATH + "/web.xml" ); context.getMavenFileFilter().copyFile( defaultWebXml, new File( webinfDir, "web.xml" ), true, context.getFilterWrappers(), getEncoding( defaultWebXml ) ); } } if ( containerConfigXML != null && StringUtils.isNotEmpty( containerConfigXML.getName() ) ) { String xmlFileName = containerConfigXML.getName(); context.getWebappStructure().registerFileForced( id, META_INF_PATH + "/" + xmlFileName ); if ( context.isFilteringDeploymentDescriptors() ) { context.getMavenFileFilter().copyFile( containerConfigXML, new File( metainfDir, xmlFileName ), true, context.getFilterWrappers(), getEncoding( containerConfigXML ) ); } else { copyFile( context, containerConfigXML, new File( metainfDir, xmlFileName ), "META-INF/" + xmlFileName, true ); } } } catch ( IOException e ) { throw new MojoExecutionException( "Failed to copy deployment descriptor", e ); } catch ( MavenFilteringException e ) { throw new MojoExecutionException( "Failed to copy deployment descriptor", e ); } } /** * Get the encoding from an XML-file. * * @param webXml the XML-file * @return The encoding of the XML-file, or UTF-8 if it's not specified in the file * @throws IOException if an error occurred while reading the file */ private String getEncoding( File webXml ) throws IOException { XmlStreamReader xmlReader = new XmlStreamReader( webXml ); return xmlReader.getEncoding(); } /** * Copies webapp webResources from the specified directory. * * @param context the WAR packaging context to use * @param resource the resource to copy * @throws IOException if an error occurred while copying the resources * @throws MojoExecutionException if an error occurred while retrieving the filter properties */ public void copyResources( WarPackagingContext context, Resource resource ) throws IOException, MojoExecutionException { if ( !context.getWebappDirectory().exists() ) { context.getLog().warn( "Not copying webapp webResources [" + resource.getDirectory() + "]: webapp directory [" + context.getWebappDirectory().getAbsolutePath() + "] does not exist!" ); } context.getLog().info( "Copying webapp webResources [" + resource.getDirectory() + "] to [" + context.getWebappDirectory().getAbsolutePath() + "]" ); String[] fileNames = getFilesToCopy( resource ); for ( int i = 0; i < fileNames.length; i++ ) { String targetFileName = fileNames[i]; if ( resource.getTargetPath() != null ) { //TODO make sure this thing is 100% safe // MWAR-129 if targetPath is only a dot . or ./ // and the Resource is in a part of the warSourceDirectory the file from sources will override this // that's we don't have to add the targetPath yep not nice but works if ( !StringUtils.equals( ".", resource.getTargetPath() ) && !StringUtils.equals( "./", resource.getTargetPath() ) ) { targetFileName = resource.getTargetPath() + File.separator + targetFileName; } } if ( resource.isFiltering() && !context.isNonFilteredExtension( fileNames[i] ) ) { copyFilteredFile( id, context, new File( resource.getDirectory(), fileNames[i] ), targetFileName ); } else { copyFile( id, context, new File( resource.getDirectory(), fileNames[i] ), targetFileName ); } } } /** * Returns a list of filenames that should be copied * over to the destination directory. * * @param resource the resource to be scanned * @return the array of filenames, relative to the sourceDir */ private String[] getFilesToCopy( Resource resource ) { DirectoryScanner scanner = new DirectoryScanner(); scanner.setBasedir( resource.getDirectory() ); if ( resource.getIncludes() != null && !resource.getIncludes().isEmpty() ) { scanner.setIncludes( (String[]) resource.getIncludes().toArray( new String[resource.getIncludes().size()] ) ); } else { scanner.setIncludes( DEFAULT_INCLUDES ); } if ( resource.getExcludes() != null && !resource.getExcludes().isEmpty() ) { scanner.setExcludes( (String[]) resource.getExcludes().toArray( new String[resource.getExcludes().size()] ) ); } scanner.addDefaultExcludes(); scanner.scan(); return scanner.getIncludedFiles(); } } ././@LongLink0000000000000000000000000000014500000000000011565 Lustar rootrootmaven-war-plugin-2.1.1/src/main/java/org/apache/maven/plugin/war/packaging/WarPostPackagingTask.javamaven-war-plugin-2.1.1/src/main/java/org/apache/maven/plugin/war/packaging/WarPostPackagingTask.java0000644000175000017500000000317011046130275033321 0ustar twernertwernerpackage org.apache.maven.plugin.war.packaging; /* * 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.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.MojoFailureException; /** * Defines tasks that should be performed after the packaging. * * @author Stephane Nicoll * @version $Id: WarPostPackagingTask.java 682908 2008-08-05 19:57:49Z hboutemy $ */ public interface WarPostPackagingTask { /** * Executes the post packaging task. *

    * The packaging context hold all information regarding the webapp that * has been packaged. * * @param context the packaging context * @throws MojoExecutionException if an error occurred * @throws MojoFailureException if a failure occurred */ void performPostPackaging( WarPackagingContext context ) throws MojoExecutionException, MojoFailureException; } ././@LongLink0000000000000000000000000000015100000000000011562 Lustar rootrootmaven-war-plugin-2.1.1/src/main/java/org/apache/maven/plugin/war/packaging/AbstractWarPackagingTask.javamaven-war-plugin-2.1.1/src/main/java/org/apache/maven/plugin/war/packaging/AbstractWarPackagingTask.0000644000175000017500000003576111431612271033307 0ustar twernertwernerpackage org.apache.maven.plugin.war.packaging; /* * 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 java.io.File; import java.io.IOException; import java.util.Iterator; import org.apache.maven.artifact.Artifact; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.war.AbstractWarMojo; import org.apache.maven.plugin.war.util.MappingUtils; import org.apache.maven.plugin.war.util.PathSet; import org.apache.maven.plugin.war.util.WebappStructure; import org.apache.maven.shared.filtering.MavenFilteringException; import org.codehaus.plexus.archiver.ArchiverException; import org.codehaus.plexus.archiver.UnArchiver; import org.codehaus.plexus.archiver.manager.NoSuchArchiverException; import org.codehaus.plexus.interpolation.InterpolationException; import org.codehaus.plexus.util.DirectoryScanner; import org.codehaus.plexus.util.FileUtils; /** * @author Stephane Nicoll * @version $Id: AbstractWarPackagingTask.java 985593 2010-08-14 22:12:09Z dennisl $ */ public abstract class AbstractWarPackagingTask implements WarPackagingTask { public static final String[] DEFAULT_INCLUDES = {"**/**"}; public static final String WEB_INF_PATH = "WEB-INF"; public static final String META_INF_PATH = "META-INF"; public static final String CLASSES_PATH = "WEB-INF/classes/"; public static final String LIB_PATH = "WEB-INF/lib/"; /** * Copies the files if possible with an optional target prefix. *

    * Copy uses a first-win strategy: files that have already been copied by previous * tasks are ignored. This method makes sure to update the list of protected files * which gives the list of files that have already been copied. *

    * If the structure of the source directory is not the same as the root of the * webapp, use the targetPrefix parameter to specify in which particular * directory the files should be copied. Use null to copy the files with * the same structure * * @param sourceId the source id * @param context the context to use * @param sourceBaseDir the base directory from which the sourceFilesSet will be copied * @param sourceFilesSet the files to be copied * @param targetPrefix the prefix to add to the target file name * @throws IOException if an error occurred while copying the files */ protected void copyFiles( String sourceId, WarPackagingContext context, File sourceBaseDir, PathSet sourceFilesSet, String targetPrefix, boolean filtered ) throws IOException, MojoExecutionException { for ( Iterator iter = sourceFilesSet.iterator(); iter.hasNext(); ) { final String fileToCopyName = (String) iter.next(); final File sourceFile = new File( sourceBaseDir, fileToCopyName ); String destinationFileName; if ( targetPrefix == null ) { destinationFileName = fileToCopyName; } else { destinationFileName = targetPrefix + fileToCopyName; } if ( filtered && !context.isNonFilteredExtension( sourceFile.getName() ) ) { copyFilteredFile( sourceId, context, sourceFile, destinationFileName ); } else { copyFile( sourceId, context, sourceFile, destinationFileName ); } } } /** * Copies the files if possible as is. *

    * Copy uses a first-win strategy: files that have already been copied by previous * tasks are ignored. This method makes sure to update the list of protected files * which gives the list of files that have already been copied. * * @param sourceId the source id * @param context the context to use * @param sourceBaseDir the base directory from which the sourceFilesSet will be copied * @param sourceFilesSet the files to be copied * @throws IOException if an error occurred while copying the files */ protected void copyFiles( String sourceId, WarPackagingContext context, File sourceBaseDir, PathSet sourceFilesSet, boolean filtered ) throws IOException, MojoExecutionException { copyFiles( sourceId, context, sourceBaseDir, sourceFilesSet, null, filtered ); } /** * Copy the specified file if the target location has not yet already been used. *

    * The targetFileName is the relative path according to the root of * the generated web application. * * @param sourceId the source id * @param context the context to use * @param file the file to copy * @param targetFilename the relative path according to the root of the webapp * @throws IOException if an error occurred while copying */ protected void copyFile( String sourceId, final WarPackagingContext context, final File file, String targetFilename ) throws IOException { final File targetFile = new File( context.getWebappDirectory(), targetFilename ); context.getWebappStructure().registerFile( sourceId, targetFilename, new WebappStructure.RegistrationCallback() { public void registered( String ownerId, String targetFilename ) throws IOException { copyFile( context, file, targetFile, targetFilename, false ); } public void alreadyRegistered( String ownerId, String targetFilename ) throws IOException { copyFile( context, file, targetFile, targetFilename, true ); } public void refused( String ownerId, String targetFilename, String actualOwnerId ) throws IOException { context.getLog().debug( " - " + targetFilename + " wasn't copied because it has " + "already been packaged for overlay [" + actualOwnerId + "]." ); } public void superseded( String ownerId, String targetFilename, String deprecatedOwnerId ) throws IOException { context.getLog().info( "File [" + targetFilename + "] belonged to overlay [" + deprecatedOwnerId + "] so it will be overwritten." ); copyFile( context, file, targetFile, targetFilename, false ); } public void supersededUnknownOwner( String ownerId, String targetFilename, String unknownOwnerId ) throws IOException { context.getLog() .warn( "File [" + targetFilename + "] belonged to overlay [" + unknownOwnerId + "] which does not exist anymore in the current project. It is recommended to invoke " + "clean if the dependencies of the project changed." ); copyFile( context, file, targetFile, targetFilename, false ); } } ); } /** * Copy the specified file if the target location has not yet already been * used and filter its content with the configured filter properties. *

    * The targetFileName is the relative path according to the root of * the generated web application. * * @param sourceId the source id * @param context the context to use * @param file the file to copy * @param targetFilename the relative path according to the root of the webapp * @return true if the file has been copied, false otherwise * @throws IOException if an error occurred while copying * @throws MojoExecutionException if an error occurred while retrieving the filter properties */ protected boolean copyFilteredFile( String sourceId, final WarPackagingContext context, File file, String targetFilename ) throws IOException, MojoExecutionException { if ( context.getWebappStructure().registerFile( sourceId, targetFilename ) ) { final File targetFile = new File( context.getWebappDirectory(), targetFilename ); try { // fix for MWAR-36, ensures that the parent dir are created first targetFile.getParentFile().mkdirs(); // TODO: add encoding support (null mean platform encoding) context.getMavenFileFilter().copyFile( file, targetFile, true, context.getFilterWrappers(), null ); } catch ( MavenFilteringException e ) { throw new MojoExecutionException( e.getMessage(), e ); } // Add the file to the protected list context.getLog().debug( " + " + targetFilename + " has been copied (filtered)." ); return true; } else { context.getLog().debug( " - " + targetFilename + " wasn't copied because it has already been packaged (filtered)." ); return false; } } /** * Unpacks the specified file to the specified directory. * * @param context the packaging context * @param file the file to unpack * @param unpackDirectory the directory to use for th unpacked file * @throws MojoExecutionException if an error occurred while unpacking the file */ protected void doUnpack( WarPackagingContext context, File file, File unpackDirectory ) throws MojoExecutionException { String archiveExt = FileUtils.getExtension( file.getAbsolutePath() ).toLowerCase(); try { UnArchiver unArchiver = context.getArchiverManager().getUnArchiver( archiveExt ); unArchiver.setSourceFile( file ); unArchiver.setDestDirectory( unpackDirectory ); unArchiver.setOverwrite( true ); unArchiver.extract(); } catch ( ArchiverException e ) { throw new MojoExecutionException( "Error unpacking file [" + file.getAbsolutePath() + "]" + "to [" + unpackDirectory.getAbsolutePath() + "]", e ); } catch ( NoSuchArchiverException e ) { context.getLog().warn( "Skip unpacking dependency file [" + file.getAbsolutePath() + " with unknown extension [" + archiveExt + "]" ); } } /** * Copy file from source to destination. The directories up to destination * will be created if they don't already exist. if the onlyIfModified flag * is false, destination will be overwritten if it already exists. If the * flag is true destination will be overwritten if it's not up to date. *

    * * @param context the packaging context * @param source an existing non-directory File to copy bytes from * @param destination a non-directory File to write bytes to (possibly overwriting). * @param targetFilename the relative path of the file from the webapp root directory * @param onlyIfModified if true, copy the file only if the source has changed, always copy otherwise * @return true if the file has been copied/updated, false otherwise * @throws IOException if source does not exist, destination cannot * be written to, or an IO error occurs during copying */ protected boolean copyFile( WarPackagingContext context, File source, File destination, String targetFilename, boolean onlyIfModified ) throws IOException { if ( onlyIfModified && destination.lastModified() >= source.lastModified() ) { context.getLog().debug( " * " + targetFilename + " is up to date." ); return false; } else { FileUtils.copyFile( source.getCanonicalFile(), destination ); // preserve timestamp destination.setLastModified( source.lastModified() ); context.getLog().debug( " + " + targetFilename + " has been copied." ); return true; } } /** * Returns the file to copy. If the includes are null or empty, the * default includes are used. * * @param baseDir the base directory to start from * @param includes the includes * @param excludes the excludes * @return the files to copy */ protected PathSet getFilesToIncludes( File baseDir, String[] includes, String[] excludes ) { final DirectoryScanner scanner = new DirectoryScanner(); scanner.setBasedir( baseDir ); if ( excludes != null ) { scanner.setExcludes( excludes ); } scanner.addDefaultExcludes(); if ( includes != null && includes.length > 0 ) { scanner.setIncludes( includes ); } else { scanner.setIncludes( DEFAULT_INCLUDES ); } scanner.scan(); return new PathSet( scanner.getIncludedFiles() ); } /** * Returns the final name of the specified artifact. *

    * If the outputFileNameMapping is set, it is used, otherwise * the standard naming scheme is used. * * @param context the packaging context * @param artifact the artifact * @return the converted filename of the artifact */ protected String getArtifactFinalName( WarPackagingContext context, Artifact artifact ) throws InterpolationException { if ( context.getOutputFileNameMapping() != null ) { return MappingUtils.evaluateFileNameMapping( context.getOutputFileNameMapping(), artifact ); } String classifier = artifact.getClassifier(); if ( ( classifier != null ) && !( "".equals( classifier.trim() ) ) ) { return MappingUtils.evaluateFileNameMapping( AbstractWarMojo.DEFAULT_FILE_NAME_MAPPING_CLASSIFIER, artifact ); } else { return MappingUtils.evaluateFileNameMapping( AbstractWarMojo.DEFAULT_FILE_NAME_MAPPING, artifact ); } } } maven-war-plugin-2.1.1/src/main/java/org/apache/maven/plugin/war/packaging/WarPackagingContext.java0000644000175000017500000001227211144576221033204 0ustar twernertwernerpackage org.apache.maven.plugin.war.packaging; /* * 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 java.io.File; import java.util.List; import org.apache.maven.archiver.MavenArchiveConfiguration; import org.apache.maven.artifact.factory.ArtifactFactory; import org.apache.maven.plugin.logging.Log; import org.apache.maven.plugin.war.util.WebappStructure; import org.apache.maven.project.MavenProject; import org.apache.maven.shared.filtering.MavenFileFilter; import org.codehaus.plexus.archiver.jar.JarArchiver; import org.codehaus.plexus.archiver.manager.ArchiverManager; import org.codehaus.plexus.util.FileUtils.FilterWrapper; /** * The packaging context. * * @author Stephane Nicoll * @version $Id: WarPackagingContext.java 743374 2009-02-11 16:28:01Z dennisl $ */ public interface WarPackagingContext { /** * Returns the maven project. * * @return the project */ MavenProject getProject(); /** * Returns the webapp directory. Packaging tasks should use this * directory to generate the webapp. * * @return the webapp directory */ File getWebappDirectory(); /** * Returns the main webapp source directory. * * @return the webapp source directory */ File getWebappSourceDirectory(); /** * Returns the webapp source includes. * * @return the webapp source includes */ String[] getWebappSourceIncludes(); /** * Returns the webapp source excludes. * * @return the webapp source excludes */ String[] getWebappSourceExcludes(); /** * Returns the directory holding generated classes. * * @return the classes directory */ File getClassesDirectory(); /** * Specify whether the classes resources should be archived in * the WEB-INF/lib of the generated web app. * * @return true if the classes should be archived, false otherwise */ boolean archiveClasses(); /** * Returns the logger to use to output logging event. * * @return the logger */ Log getLog(); /** * Returns the directory to unpack dependent WARs into if needed. * * @return the overlays work directory */ File getOverlaysWorkDirectory(); /** * Returns the archiver manager to use. * * @return the archiver manager */ ArchiverManager getArchiverManager(); /** * The maven archive configuration to use. * * @return the maven archive configuration */ MavenArchiveConfiguration getArchive(); /** * Returns the Jar archiver needed for archiving classes directory into * jar file under WEB-INF/lib. * * @return the jar archiver to user */ JarArchiver getJarArchiver(); /** * Returns the output file name mapping to use, if any. Returns null * if no file name mapping is set. * * @return the output file name mapping or null */ String getOutputFileNameMapping(); /** * Returns the list of filter files to use. * * @return a list of filter files */ List getFilters(); /** * Returns the {@link WebappStructure}. * * @return the webapp structure */ WebappStructure getWebappStructure(); /** * Returns the list of registered overlays for this session. This list might * differ from the one returned by the cache; in this case, it means that the * project's configuration has changed. The plugin will handle thos cases nicely * but it would be better in general to invoke the clean goal. * * @return the list of registered overlays, including the current project */ List getOwnerIds(); /** * Returns the {@link MavenFileFilter} instance to use. * * @return the maven file filter to use * @since 2.1-alpha-2 */ MavenFileFilter getMavenFileFilter(); /** * @return {@link List} of {@link FilterWrapper} * @since 2.1-alpha-2 */ List getFilterWrappers(); /** * Specify if the given fileName belongs to the list of extensions * that must not be filtered * * @param fileName the name of file * @return true if it should not be filtered, false otherwise * @since 2.1-alpha-2 */ boolean isNonFilteredExtension( String fileName ); boolean isFilteringDeploymentDescriptors(); ArtifactFactory getArtifactFactory(); } ././@LongLink0000000000000000000000000000014500000000000011565 Lustar rootrootmaven-war-plugin-2.1.1/src/main/java/org/apache/maven/plugin/war/packaging/OverlayPackagingTask.javamaven-war-plugin-2.1.1/src/main/java/org/apache/maven/plugin/war/packaging/OverlayPackagingTask.java0000644000175000017500000001246711431612271033353 0ustar twernertwernerpackage org.apache.maven.plugin.war.packaging; /* * 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.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.war.Overlay; import org.apache.maven.plugin.war.util.PathSet; import org.codehaus.plexus.util.FileUtils; import java.io.File; import java.io.IOException; /** * Handles an overlay. * * @author Stephane Nicoll * * @version $Id: OverlayPackagingTask.java 985593 2010-08-14 22:12:09Z dennisl $ */ public class OverlayPackagingTask extends AbstractWarPackagingTask { private final Overlay overlay; public OverlayPackagingTask( Overlay overlay, Overlay currentProjectOverlay ) { if ( overlay == null ) { throw new NullPointerException( "overlay could not be null." ); } if ( overlay.equals( currentProjectOverlay ) ) { throw new IllegalStateException( "Could not handle the current project with this task." ); } this.overlay = overlay; } public void performPackaging( WarPackagingContext context ) throws MojoExecutionException { context.getLog().debug( "OverlayPackagingTask performPackaging overlay.getTargetPath() " + overlay.getTargetPath() ); if ( overlay.shouldSkip() ) { context.getLog().info( "Skipping overlay [" + overlay + "]" ); } else { try { context.getLog().info( "Processing overlay [" + overlay + "]" ); // Step1: Extract if necessary final File tmpDir = unpackOverlay( context, overlay ); // Step2: setup final PathSet includes = getFilesToIncludes( tmpDir, overlay.getIncludes(), overlay.getExcludes() ); // Copy if ( null == overlay.getTargetPath() ) { copyFiles( overlay.getId(), context, tmpDir, includes, overlay.isFiltered() ); } else { // overlay.getTargetPath() must ended with / // if not we add it String targetPath = overlay.getTargetPath(); if ( !targetPath.endsWith( "/" ) ) { targetPath = targetPath + "/"; } copyFiles( overlay.getId(), context, tmpDir, includes, targetPath, overlay.isFiltered() ); } } catch ( IOException e ) { throw new MojoExecutionException( "Failed to copy file for overlay [" + overlay + "]", e ); } } } /** * Unpacks the specified overlay. *

    * Makes sure to skip the unpack process if the overlay has * already been unpacked. * * @param context the packaging context * @param overlay the overlay * @return the directory containing the unpacked overlay * @throws MojoExecutionException if an error occurred while unpacking the overlay */ protected File unpackOverlay( WarPackagingContext context, Overlay overlay ) throws MojoExecutionException { final File tmpDir = getOverlayTempDirectory( context, overlay ); // TODO: not sure it's good, we should reuse the markers of the dependency plugin if ( FileUtils.sizeOfDirectory( tmpDir ) == 0 || overlay.getArtifact().getFile().lastModified() > tmpDir.lastModified() ) { doUnpack( context, overlay.getArtifact().getFile(), tmpDir ); } else { context.getLog().debug( "Overlay [" + overlay + "] was already unpacked" ); } return tmpDir; } /** * Returns the directory to use to unpack the specified overlay. * * @param context the packaging context * @param overlay the overlay * @return the temp directory for the overlay */ protected File getOverlayTempDirectory( WarPackagingContext context, Overlay overlay ) { final File groupIdDir = new File( context.getOverlaysWorkDirectory(), overlay.getGroupId() ); if ( !groupIdDir.exists() ) { groupIdDir.mkdir(); } String directoryName = overlay.getArtifactId(); if ( overlay.getClassifier() != null ) { directoryName = directoryName + "-" + overlay.getClassifier(); } final File result = new File( groupIdDir, directoryName ); if ( !result.exists() ) { result.mkdirs(); } return result; } } ././@LongLink0000000000000000000000000000016500000000000011567 Lustar rootrootmaven-war-plugin-2.1.1/src/main/java/org/apache/maven/plugin/war/packaging/SaveWebappStructurePostPackagingTask.javamaven-war-plugin-2.1.1/src/main/java/org/apache/maven/plugin/war/packaging/SaveWebappStructurePostPa0000644000175000017500000000435511015345234033464 0ustar twernertwernerpackage org.apache.maven.plugin.war.packaging; /* * 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.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.MojoFailureException; import org.apache.maven.plugin.war.util.WebappStructureSerializer; import java.io.File; import java.io.IOException; /** * Saves the webapp structure cache. * * @author Stephane Nicoll * * @version $Id: SaveWebappStructurePostPackagingTask.java 659222 2008-05-22 19:33:48Z olamy $ */ public class SaveWebappStructurePostPackagingTask implements WarPostPackagingTask { private final File targetFile; private final WebappStructureSerializer serialier; public SaveWebappStructurePostPackagingTask( File targetFile ) { this.targetFile = targetFile; this.serialier = new WebappStructureSerializer(); } public void performPostPackaging( WarPackagingContext context ) throws MojoExecutionException, MojoFailureException { if ( targetFile == null ) { context.getLog().debug( "Cache usage is disabled, not saving webapp structure." ); } else { try { serialier.toXml( context.getWebappStructure(), targetFile ); context.getLog().debug( "Cache saved successfully." ); } catch ( IOException e ) { throw new MojoExecutionException( "Could not save webapp structure", e ); } } } } ././@LongLink0000000000000000000000000000014700000000000011567 Lustar rootrootmaven-war-plugin-2.1.1/src/main/java/org/apache/maven/plugin/war/packaging/ArtifactsPackagingTask.javamaven-war-plugin-2.1.1/src/main/java/org/apache/maven/plugin/war/packaging/ArtifactsPackagingTask.ja0000644000175000017500000001457711453733464033343 0ustar twernertwernerpackage org.apache.maven.plugin.war.packaging; /* * 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.maven.artifact.Artifact; import org.apache.maven.artifact.resolver.filter.ScopeArtifactFilter; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.war.Overlay; import org.codehaus.plexus.interpolation.InterpolationException; import java.io.IOException; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Set; /** * Handles the artifacts that needs to be packaged in the web application. * * @author Stephane Nicoll * * @version $Id: ArtifactsPackagingTask.java 1006083 2010-10-09 00:28:36Z snicoll $ */ public class ArtifactsPackagingTask extends AbstractWarPackagingTask { public static final String TLD_PATH = "WEB-INF/tld/"; public static final String SERVICES_PATH = "WEB-INF/services/"; public static final String MODULES_PATH = "WEB-INF/modules/"; private final Set artifacts; private final String id; public ArtifactsPackagingTask( Set artifacts, Overlay currentProjectOverlay ) { this.artifacts = artifacts; this.id = currentProjectOverlay.getId(); } public void performPackaging( WarPackagingContext context ) throws MojoExecutionException { try { final ScopeArtifactFilter filter = new ScopeArtifactFilter( Artifact.SCOPE_RUNTIME ); final List duplicates = findDuplicates( context, artifacts ); for ( Iterator iter = artifacts.iterator(); iter.hasNext(); ) { Artifact artifact = (Artifact) iter.next(); String targetFileName = getArtifactFinalName( context, artifact ); context.getLog().debug( "Processing: " + targetFileName ); if ( duplicates.contains( targetFileName ) ) { context.getLog().debug( "Duplicate found: " + targetFileName ); targetFileName = artifact.getGroupId() + "-" + targetFileName; context.getLog().debug( "Renamed to: " + targetFileName ); } context.getWebappStructure().registerTargetFileName( artifact, targetFileName ); if ( !artifact.isOptional() && filter.include( artifact ) ) { try { String type = artifact.getType(); if ( "tld".equals( type ) ) { copyFile( id, context, artifact.getFile(), TLD_PATH + targetFileName ); } else if ( "aar".equals( type ) ) { copyFile( id, context, artifact.getFile(), SERVICES_PATH + targetFileName ); } else if ( "mar".equals( type ) ) { copyFile( id, context, artifact.getFile(), MODULES_PATH + targetFileName ); } else if ( "jar".equals( type ) || "ejb".equals( type ) || "ejb-client".equals( type ) || "test-jar".equals( type ) ) { copyFile( id, context, artifact.getFile(), LIB_PATH + targetFileName ); } else if ( "par".equals( type ) ) { targetFileName = targetFileName.substring( 0, targetFileName.lastIndexOf( '.' ) ) + ".jar"; copyFile( id, context, artifact.getFile(), LIB_PATH + targetFileName ); } else if ( "war".equals( type ) ) { // Nothing to do here, it is an overlay and it's already handled context.getLog().debug( "war artifacts are handled as overlays, ignoring [" + artifact + "]" ); } else if ( "zip".equals( type ) ) { // Nothing to do here, it is an overlay and it's already handled context.getLog().debug( "zip artifacts are handled as overlays, ignoring [" + artifact + "]" ); } else { context.getLog().debug( "Artifact of type [" + type + "] is not supported, ignoring [" + artifact + "]" ); } } catch ( IOException e ) { throw new MojoExecutionException( "Failed to copy file for artifact [" + artifact + "]", e ); } } } } catch ( InterpolationException e ) { throw new MojoExecutionException( e.getMessage(), e ); } } /** * Searches a set of artifacts for duplicate filenames and returns a list * of duplicates. * * @param context the packaging context * @param artifacts set of artifacts * @return List of duplicated artifacts as bundling file names */ private List findDuplicates( WarPackagingContext context, Set artifacts ) throws InterpolationException { List duplicates = new ArrayList(); List identifiers = new ArrayList(); for ( Iterator iter = artifacts.iterator(); iter.hasNext(); ) { Artifact artifact = (Artifact) iter.next(); String candidate = getArtifactFinalName( context, artifact ); if ( identifiers.contains( candidate ) ) { duplicates.add( candidate ); } else { identifiers.add( candidate ); } } return duplicates; } } ././@LongLink0000000000000000000000000000016200000000000011564 Lustar rootrootmaven-war-plugin-2.1.1/src/main/java/org/apache/maven/plugin/war/packaging/DependenciesAnalysisPackagingTask.javamaven-war-plugin-2.1.1/src/main/java/org/apache/maven/plugin/war/packaging/DependenciesAnalysisPacka0000644000175000017500000002453011431612271033406 0ustar twernertwernerpackage org.apache.maven.plugin.war.packaging; /* * 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.maven.artifact.Artifact; import org.apache.maven.model.Dependency; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.MojoFailureException; import org.apache.maven.plugin.war.util.WebappStructure; import java.io.File; /** * Analyzes the dependencies of the project with its previous state and update * the target directory accordingly. * * @author Stephane Nicoll * * @version $Id: DependenciesAnalysisPackagingTask.java 985593 2010-08-14 22:12:09Z dennisl $ */ public class DependenciesAnalysisPackagingTask extends AbstractWarPackagingTask { public void performPackaging( final WarPackagingContext context ) throws MojoExecutionException, MojoFailureException { context.getWebappStructure().analyseDependencies( new DependenciesAnalysisCallbackImpl( context ) ); } protected void handleDependency( WarPackagingContext context, Dependency dependency, String notBundledMessage, String warOrZipMessage, String standardMessage, boolean removeFile ) { if ( Artifact.SCOPE_PROVIDED.equals( dependency.getScope() ) || Artifact.SCOPE_TEST.equals( dependency.getScope() ) || dependency.isOptional() ) { context.getLog().debug( notBundledMessage ); } else if ( "war".equals( dependency.getType() ) || "zip".equals( dependency.getType() ) ) { context.getLog().warn( warOrZipMessage ); } else if ( "tld".equals( dependency.getType() ) || "aar".equals( dependency.getType() ) || "jar".equals( dependency.getType() ) || "ejb".equals( dependency.getType() ) || "ejb-client".equals( dependency.getType() ) || "test-jar".equals( dependency.getType() ) || "par".equals( dependency.getType() ) ) { context.getLog().info( standardMessage ); if ( removeFile ) { removeDependency( context, dependency ); } } } protected void handleDependencyScope( WarPackagingContext context, Dependency dependency, String warOrZipMessage, String standardMessage, boolean removeFile ) { if ( "war".equals( dependency.getType() ) || "zip".equals( dependency.getType() ) ) { context.getLog().warn( warOrZipMessage ); } else if ( "tld".equals( dependency.getType() ) || "aar".equals( dependency.getType() ) || "jar".equals( dependency.getType() ) || "ejb".equals( dependency.getType() ) || "ejb-client".equals( dependency.getType() ) || "test-jar".equals( dependency.getType() ) || "par".equals( dependency.getType() ) ) { context.getLog().info( standardMessage ); if ( removeFile ) { removeDependency( context, dependency ); } } } private void removeDependency( WarPackagingContext context, Dependency dependency ) { final String targetFileName = context.getWebappStructure().getCachedTargetFileName( dependency ); if ( targetFileName != null ) { final String type = dependency.getType(); File targetFile = null; if ( "tld".equals( type ) ) { targetFile = new File( context.getWebappDirectory(), ArtifactsPackagingTask.TLD_PATH + targetFileName ); } else if ( "aar".equals( type ) ) { targetFile = new File( context.getWebappDirectory(), ArtifactsPackagingTask.SERVICES_PATH + targetFileName ); } else if ( "jar".equals( type ) || "ejb".equals( type ) || "ejb-client".equals( type ) || "test-jar".equals( type ) ) { targetFile = new File( context.getWebappDirectory(), LIB_PATH + targetFileName ); } else if ( "par".equals( type ) ) { String targetFileName2 = targetFileName.substring( 0, targetFileName.lastIndexOf( '.' ) ) + ".jar"; targetFile = new File( context.getWebappDirectory(), LIB_PATH + targetFileName2 ); } // now remove if ( targetFile == null ) { context.getLog().error( "Could not get file from dependency [" + dependency + "]" ); } else if ( targetFile.exists() ) { context.getLog().debug( "Removing file [" + targetFile.getAbsolutePath() + "]" ); targetFile.delete(); } else { context.getLog().warn( "File to remove [" + targetFile.getAbsolutePath() + "] has not been found" ); } } else { context.getLog().warn( "Could not retrieve the target file name of dependency [" + dependency + "]" ); } } class DependenciesAnalysisCallbackImpl implements WebappStructure.DependenciesAnalysisCallback { private final WarPackagingContext context; DependenciesAnalysisCallbackImpl( WarPackagingContext context ) { this.context = context; } public void unchangedDependency( Dependency dependency ) { context.getLog().debug( "Dependency [" + dependency + "] has not changed since last build." ); } public void newDependency( Dependency dependency ) { context.getLog().debug( "New dependency [" + dependency + "]." ); } public void removedDependency( Dependency dependency ) { handleDependency( context, dependency, "Dependency [" + dependency + "] has been removed from the project but it was not bundled anyway.", "Dependency [" + dependency + "] has been removed from the project. If it was included in the build as an overlay, " + "consider cleaning the target directory of the project (mvn clean)", "Dependency [" + dependency + "] has been removed from the project.", true ); } public void updatedVersion( Dependency dependency, String previousVersion ) { handleDependency( context, dependency, "Version of dependency [" + dependency + "] has changed (" + previousVersion + " -> " + dependency.getVersion() + ") but it was not bundled anyway.", "Version of dependency [" + dependency + "] has changed (" + previousVersion + " -> " + dependency.getVersion() + "). If it was included in the build as an overlay, " + "consider " + "cleaning the target directory of the project (mvn clean)", "Version of dependency [" + dependency + "] has changed (" + previousVersion + " -> " + dependency.getVersion() + ").", true ); } public void updatedScope( Dependency dependency, String previousScope ) { if ( Artifact.SCOPE_PROVIDED.equals( dependency.getScope() ) || Artifact.SCOPE_TEST.equals( dependency.getScope() ) && ( !Artifact.SCOPE_PROVIDED.equals( previousScope ) && !Artifact.SCOPE_TEST.equals( previousScope ) ) ) { // It's now provided or test so it should be removed handleDependencyScope( context, dependency, "Scope of dependency [" + dependency + "] has changed (" + previousScope + " -> " + dependency.getScope() + "). If it was included in the build as an overlay, " + "consider cleaning the target directory of the project (mvn clean)", "Scope of dependency [" + dependency + "] has changed (" + previousScope + " -> " + dependency.getScope() + ").", true ); } } public void updatedOptionalFlag( Dependency dependency, boolean previousOptional ) { if ( !previousOptional && dependency.isOptional() ) { // It wasn't optional but now it is anymore handleDependency( context, dependency, "Dependency [" + dependency + "] is now optional but it was not bundled anyway.", "Dependency [" + dependency + "] is now optional. If it was included in the build as an overlay, " + "consider cleaning the target directory of the project (mvn clean)", "Dependency [" + dependency + "] is now optional", true ); } } public void updatedUnknown( Dependency dependency, Dependency previousDep ) { handleDependency( context, dependency, "Dependency [" + dependency + "] has changed (was " + previousDep + ") but it was not bundled anyway.", "Dependency [" + dependency + "] has changed (was " + previousDep + "). If it was included in the build as an overlay, " + "consider " + "cleaning the target directory of the project (mvn clean)", "Dependency [" + dependency + "] has changed (was " + previousDep + ").", true ); } } } ././@LongLink0000000000000000000000000000014500000000000011565 Lustar rootrootmaven-war-plugin-2.1.1/src/main/java/org/apache/maven/plugin/war/packaging/ClassesPackagingTask.javamaven-war-plugin-2.1.1/src/main/java/org/apache/maven/plugin/war/packaging/ClassesPackagingTask.java0000644000175000017500000001135611431612271033323 0ustar twernertwernerpackage org.apache.maven.plugin.war.packaging; /* * 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.maven.artifact.Artifact; import org.apache.maven.artifact.factory.ArtifactFactory; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.war.Overlay; import org.apache.maven.plugin.war.util.ClassesPackager; import org.apache.maven.plugin.war.util.PathSet; import org.apache.maven.project.MavenProject; import org.codehaus.plexus.interpolation.InterpolationException; import java.io.File; import java.io.IOException; /** * Handles the classes directory that needs to be packaged in the web application. *

    * Based on the {@link WarPackagingContext#archiveClasses()} flag the resources * either copied into to WEB-INF/classes directory or archived in a jar * within the WEB-INF/lib directory. * * @author Stephane Nicoll * * @version $Id: ClassesPackagingTask.java 985593 2010-08-14 22:12:09Z dennisl $ */ public class ClassesPackagingTask extends AbstractWarPackagingTask { private final Overlay currentProjectOverlay; public ClassesPackagingTask( Overlay currentProjectOverlay ) { this.currentProjectOverlay = currentProjectOverlay; } public void performPackaging( WarPackagingContext context ) throws MojoExecutionException { final File webappClassesDirectory = new File( context.getWebappDirectory(), CLASSES_PATH ); if ( !webappClassesDirectory.exists() ) { webappClassesDirectory.mkdirs(); } if ( context.getClassesDirectory().exists() && !context.getClassesDirectory().equals( webappClassesDirectory ) ) { if ( context.archiveClasses() ) { generateJarArchive( context ); } else { final PathSet sources = getFilesToIncludes( context.getClassesDirectory(), null, null ); try { copyFiles( currentProjectOverlay.getId(), context, context.getClassesDirectory(), sources, CLASSES_PATH, false ); } catch ( IOException e ) { throw new MojoExecutionException( "Could not copy webapp classes [" + context.getClassesDirectory().getAbsolutePath() + "]", e ); } } } } protected void generateJarArchive( WarPackagingContext context ) throws MojoExecutionException { MavenProject project = context.getProject(); ArtifactFactory factory = context.getArtifactFactory(); Artifact artifact = factory.createBuildArtifact( project.getGroupId(), project.getArtifactId(), project.getVersion(), "jar" ); String archiveName = null; try { archiveName = getArtifactFinalName( context, artifact ); } catch ( InterpolationException e ) { throw new MojoExecutionException( "Could not get the final name of the artifact [" + artifact.getGroupId() + ":" + artifact.getArtifactId() + ":" + artifact.getVersion() + "]", e ); } final String targetFilename = LIB_PATH + archiveName; if ( context.getWebappStructure().registerFile( currentProjectOverlay.getId(), targetFilename ) ) { final File libDirectory = new File( context.getWebappDirectory(), LIB_PATH ); final File jarFile = new File( libDirectory, archiveName ); final ClassesPackager packager = new ClassesPackager(); packager.packageClasses( context.getClassesDirectory(), jarFile, context.getJarArchiver(), project, context.getArchive() ); } else { context.getLog().warn( "Could not generate archive classes file [" + targetFilename + "] has already been copied." ); } } } maven-war-plugin-2.1.1/src/main/java/org/apache/maven/plugin/war/WarMojo.java0000644000175000017500000002773511446464325026753 0ustar twernertwernerpackage org.apache.maven.plugin.war; /* * 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.maven.archiver.MavenArchiver; import org.apache.maven.artifact.Artifact; import org.apache.maven.artifact.DependencyResolutionRequiredException; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.MojoFailureException; import org.apache.maven.plugin.war.util.ClassesPackager; import org.apache.maven.project.MavenProjectHelper; import org.codehaus.plexus.archiver.ArchiverException; import org.codehaus.plexus.archiver.jar.ManifestException; import org.codehaus.plexus.archiver.war.WarArchiver; import org.codehaus.plexus.util.StringUtils; import java.io.File; import java.io.IOException; import java.util.Arrays; /** * Build a WAR file. * * @author Emmanuel Venisse * @version $Id: WarMojo.java 1000203 2010-09-22 20:36:37Z dennisl $ * @goal war * @phase package * @threadSafe * @requiresDependencyResolution runtime */ public class WarMojo extends AbstractWarMojo { /** * The directory for the generated WAR. * * @parameter default-value="${project.build.directory}" * @required */ private String outputDirectory; /** * The name of the generated WAR. * * @parameter default-value="${project.build.finalName}" * @required */ private String warName; /** * Classifier to add to the generated WAR. If given, the artifact will be an attachment instead. * The classifier will not be applied to the JAR file of the project - only to the WAR file. * * @parameter */ private String classifier; /** * The comma separated list of tokens to exclude from the WAR before * packaging. This option may be used to implement the skinny WAR use * case. * * @parameter * @since 2.1-alpha-2 */ private String packagingExcludes; /** * The comma separated list of tokens to include in the WAR before * packaging. By default everything is included. This option may be used * to implement the skinny WAR use case. * * @parameter * @since 2.1-beta-1 */ private String packagingIncludes; /** * The WAR archiver. * * @component role="org.codehaus.plexus.archiver.Archiver" roleHint="war" */ private WarArchiver warArchiver; /** * @component */ private MavenProjectHelper projectHelper; /** * Whether this is the main artifact being built. Set to false if you don't want to install or * deploy it to the local repository instead of the default one in an execution. * * @parameter expression="${primaryArtifact}" default-value="true" */ private boolean primaryArtifact = true; /** * Whether or not to fail the build if the web.xml file is missing. Set to false * if you want you WAR built without a web.xml file. * This may be useful if you are building an overlay that has no web.xml file. * * @parameter expression="${failOnMissingWebXml}" default-value="true" * @since 2.1-alpha-2 */ private boolean failOnMissingWebXml = true; /** * Whether classes (that is the content of the WEB-INF/classes directory) should be attached to the * project. * * @parameter default-value="false" * @since 2.1-alpha-2 */ private boolean attachClasses = false; /** * The classifier to use for the attached classes artifact. * * @parameter default-value="classes" * @since 2.1-alpha-2 */ private String classesClassifier = "classes"; // ---------------------------------------------------------------------- // Implementation // ---------------------------------------------------------------------- /** * Executes the WarMojo on the current project. * * @throws MojoExecutionException if an error occurred while building the webapp */ public void execute() throws MojoExecutionException, MojoFailureException { File warFile = getTargetWarFile(); try { performPackaging( warFile ); } catch ( DependencyResolutionRequiredException e ) { throw new MojoExecutionException( "Error assembling WAR: " + e.getMessage(), e ); } catch ( ManifestException e ) { throw new MojoExecutionException( "Error assembling WAR", e ); } catch ( IOException e ) { throw new MojoExecutionException( "Error assembling WAR", e ); } catch ( ArchiverException e ) { throw new MojoExecutionException( "Error assembling WAR: " + e.getMessage(), e ); } } /** * Generates the webapp according to the mode attribute. * * @param warFile the target WAR file * @throws IOException if an error occurred while copying files * @throws ArchiverException if the archive could not be created * @throws ManifestException if the manifest could not be created * @throws DependencyResolutionRequiredException * if an error occurred while resolving the dependencies * @throws MojoExecutionException if the execution failed * @throws MojoFailureException if a fatal exception occurred */ private void performPackaging( File warFile ) throws IOException, ArchiverException, ManifestException, DependencyResolutionRequiredException, MojoExecutionException, MojoFailureException { getLog().info( "Packaging webapp" ); buildExplodedWebapp( getWebappDirectory() ); MavenArchiver archiver = new MavenArchiver(); archiver.setArchiver( warArchiver ); archiver.setOutputFile( warFile ); getLog().debug( "Excluding " + Arrays.asList( getPackagingExcludes() ) + " from the generated webapp archive." ); getLog().debug( "Including " + Arrays.asList( getPackagingIncludes() ) + " in the generated webapp archive." ); warArchiver.addDirectory( getWebappDirectory(), getPackagingIncludes(), getPackagingExcludes() ); final File webXmlFile = new File( getWebappDirectory(), "WEB-INF/web.xml" ); if ( webXmlFile.exists() ) { warArchiver.setWebxml( webXmlFile ); } if ( !failOnMissingWebXml ) { getLog().debug( "Build won't fail if web.xml file is missing." ); // The flag is wrong in plexus-archiver so it will need to be fixed at some point warArchiver.setIgnoreWebxml( false ); } // create archive archiver.createArchive( getProject(), getArchive() ); // create the classes to be attached if necessary if ( isAttachClasses() ) { ClassesPackager packager = new ClassesPackager(); final File classesDirectory = packager.getClassesDirectory( getWebappDirectory() ); if ( classesDirectory.exists() ) { getLog().info( "Packaging classes" ); packager.packageClasses( classesDirectory, getTargetClassesFile(), getJarArchiver(), getProject(), getArchive() ); projectHelper.attachArtifact( getProject(), "jar", getClassesClassifier(), getTargetClassesFile() ); } } String classifier = this.classifier; if ( classifier != null ) { projectHelper.attachArtifact( getProject(), "war", classifier, warFile ); } else { Artifact artifact = getProject().getArtifact(); if ( primaryArtifact ) { artifact.setFile( warFile ); } else if ( artifact.getFile() == null || artifact.getFile().isDirectory() ) { artifact.setFile( warFile ); } } } protected static File getTargetFile( File basedir, String finalName, String classifier, String type ) { if ( classifier == null ) { classifier = ""; } else if ( classifier.trim().length() > 0 && !classifier.startsWith( "-" ) ) { classifier = "-" + classifier; } return new File( basedir, finalName + classifier + "." + type ); } protected File getTargetWarFile() { return getTargetFile( new File( getOutputDirectory() ), getWarName(), getClassifier(), "war" ); } protected File getTargetClassesFile() { return getTargetFile( new File( getOutputDirectory() ), getWarName(), getClassesClassifier(), "jar" ); } // Getters and Setters public String getClassifier() { return classifier; } public void setClassifier( String classifier ) { this.classifier = classifier; } public String[] getPackagingExcludes() { if ( StringUtils.isEmpty( packagingExcludes ) ) { return new String[0]; } else { return StringUtils.split( packagingExcludes, "," ); } } public void setPackagingExcludes( String packagingExcludes ) { this.packagingExcludes = packagingExcludes; } public String[] getPackagingIncludes() { if ( StringUtils.isEmpty( packagingIncludes ) ) { return new String[]{"**"}; } else { return StringUtils.split( packagingIncludes, "," ); } } public void setPackagingIncludes( String packagingIncludes ) { this.packagingIncludes = packagingIncludes; } public String getOutputDirectory() { return outputDirectory; } public void setOutputDirectory( String outputDirectory ) { this.outputDirectory = outputDirectory; } public String getWarName() { return warName; } public void setWarName( String warName ) { this.warName = warName; } public WarArchiver getWarArchiver() { return warArchiver; } public void setWarArchiver( WarArchiver warArchiver ) { this.warArchiver = warArchiver; } public MavenProjectHelper getProjectHelper() { return projectHelper; } public void setProjectHelper( MavenProjectHelper projectHelper ) { this.projectHelper = projectHelper; } public boolean isPrimaryArtifact() { return primaryArtifact; } public void setPrimaryArtifact( boolean primaryArtifact ) { this.primaryArtifact = primaryArtifact; } public boolean isAttachClasses() { return attachClasses; } public void setAttachClasses( boolean attachClasses ) { this.attachClasses = attachClasses; } public String getClassesClassifier() { return classesClassifier; } public void setClassesClassifier( String classesClassifier ) { this.classesClassifier = classesClassifier; } public boolean isFailOnMissingWebXml() { return failOnMissingWebXml; } public void setFailOnMissingWebXml( boolean failOnMissingWebXml ) { this.failOnMissingWebXml = failOnMissingWebXml; } } maven-war-plugin-2.1.1/src/main/java/org/apache/maven/plugin/war/WarExplodedMojo.java0000644000175000017500000000265311374304707030425 0ustar twernertwernerpackage org.apache.maven.plugin.war; /* * 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.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.MojoFailureException; /** * Create an exploded webapp in a specified directory. * * @goal exploded * @phase package * @threadSafe * @requiresDependencyResolution runtime * @version $Id: WarExplodedMojo.java 945283 2010-05-17 18:24:07Z krosenvold $ */ public class WarExplodedMojo extends AbstractWarMojo { public void execute() throws MojoExecutionException, MojoFailureException { getLog().info( "Exploding webapp" ); buildExplodedWebapp( getWebappDirectory() ); } }maven-war-plugin-2.1.1/src/main/java/org/apache/maven/plugin/war/AbstractWarMojo.java0000644000175000017500000006332311431721024030412 0ustar twernertwernerpackage org.apache.maven.plugin.war; /* * 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 java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Iterator; import java.util.List; import org.apache.maven.archiver.MavenArchiveConfiguration; import org.apache.maven.artifact.factory.ArtifactFactory; import org.apache.maven.execution.MavenSession; import org.apache.maven.model.Resource; import org.apache.maven.plugin.AbstractMojo; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.MojoFailureException; import org.apache.maven.plugin.logging.Log; import org.apache.maven.plugin.war.overlay.OverlayManager; import org.apache.maven.plugin.war.packaging.DependenciesAnalysisPackagingTask; import org.apache.maven.plugin.war.packaging.OverlayPackagingTask; import org.apache.maven.plugin.war.packaging.SaveWebappStructurePostPackagingTask; import org.apache.maven.plugin.war.packaging.WarPackagingContext; import org.apache.maven.plugin.war.packaging.WarPackagingTask; import org.apache.maven.plugin.war.packaging.WarPostPackagingTask; import org.apache.maven.plugin.war.packaging.WarProjectPackagingTask; import org.apache.maven.plugin.war.util.WebappStructure; import org.apache.maven.plugin.war.util.WebappStructureSerializer; import org.apache.maven.project.MavenProject; import org.apache.maven.shared.filtering.MavenFileFilter; import org.apache.maven.shared.filtering.MavenFilteringException; import org.apache.maven.shared.filtering.MavenResourcesExecution; import org.apache.maven.shared.filtering.MavenResourcesFiltering; import org.codehaus.plexus.archiver.jar.JarArchiver; import org.codehaus.plexus.archiver.manager.ArchiverManager; import org.codehaus.plexus.util.StringUtils; /** * Contains common jobs for WAR mojos. * * @version $Id: AbstractWarMojo.java 985625 2010-08-15 08:15:16Z dennisl $ */ public abstract class AbstractWarMojo extends AbstractMojo { public static final String DEFAULT_FILE_NAME_MAPPING = "@{artifactId}@-@{version}@.@{extension}@"; public static final String DEFAULT_FILE_NAME_MAPPING_CLASSIFIER = "@{artifactId}@-@{version}@-@{classifier}@.@{extension}@"; private static final String[] EMPTY_STRING_ARRAY = {}; private static final String META_INF = "META-INF"; private static final String WEB_INF = "WEB-INF"; /** * The Maven project. * * @parameter default-value="${project}" * @required * @readonly */ private MavenProject project; /** * The directory containing compiled classes. * * @parameter default-value="${project.build.outputDirectory}" * @required * @readonly */ private File classesDirectory; /** * Whether a JAR file will be created for the classes in the webapp. Using this optional configuration * parameter will make the compiled classes to be archived into a JAR file * and the classes directory will then be excluded from the webapp. * * @parameter expression="${archiveClasses}" default-value="false" * @since 2.0.1 */ private boolean archiveClasses; /** * The JAR archiver needed for archiving the classes directory into a JAR file under WEB-INF/lib. * * @component role="org.codehaus.plexus.archiver.Archiver" role-hint="jar" * @required */ private JarArchiver jarArchiver; /** * The directory where the webapp is built. * * @parameter default-value="${project.build.directory}/${project.build.finalName}" * @required */ private File webappDirectory; /** * Single directory for extra files to include in the WAR. This is where * you place your JSP files. * * @parameter default-value="${basedir}/src/main/webapp" * @required */ private File warSourceDirectory; /** * The list of webResources we want to transfer. * * @parameter */ private Resource[] webResources; /** * Filters (property files) to include during the interpolation of the pom.xml. * @parameter */ private List filters; /** * The path to the web.xml file to use. * * @parameter expression="${maven.war.webxml}" */ private File webXml; /** * The path to a configuration file for the servlet container. Note that * the file name may be different for different servlet containers. * Apache Tomcat uses a configuration file named context.xml. The file will * be copied to the META-INF directory. * * @parameter expression="${maven.war.containerConfigXML}" */ private File containerConfigXML; /** * Directory to unpack dependent WARs into if needed. * * @parameter default-value="${project.build.directory}/war/work" * @required */ private File workDirectory; /** * The file name mapping to use when copying libraries and TLDs. If no file mapping is * set (default) the files are copied with their standard names. * * @parameter * @since 2.1-alpha-1 */ private String outputFileNameMapping; /** * The file containing the webapp structure cache. * * @parameter default-value="${project.build.directory}/war/work/webapp-cache.xml" * @required * @since 2.1-alpha-1 */ private File cacheFile; /** * Whether the cache should be used to save the status of the webapp * across multiple runs. Experimental feature so disabled by default. * * @parameter expression="${useCache}" default-value="false" * @since 2.1-alpha-1 */ private boolean useCache = false; /** * @component role="org.apache.maven.artifact.factory.ArtifactFactory" * @required * @readonly */ private ArtifactFactory artifactFactory; /** * To look up Archiver/UnArchiver implementations. * * @component role="org.codehaus.plexus.archiver.manager.ArchiverManager" * @required */ private ArchiverManager archiverManager; /** * @component role="org.apache.maven.shared.filtering.MavenFileFilter" role-hint="default" * @required */ private MavenFileFilter mavenFileFilter; /** * @component role="org.apache.maven.shared.filtering.MavenResourcesFiltering" role-hint="default" * @required */ private MavenResourcesFiltering mavenResourcesFiltering; /** * The comma separated list of tokens to include when copying the content * of the warSourceDirectory. * * @parameter alias="includes" default-value="**" */ private String warSourceIncludes; /** * The comma separated list of tokens to exclude when copying the content * of the warSourceDirectory. * * @parameter alias="excludes" */ private String warSourceExcludes; /** * The comma separated list of tokens to include when doing * a WAR overlay. * Default is '**' * * @parameter * @deprecated Use <overlay>/<includes> instead */ private String dependentWarIncludes = "**/**"; /** * The comma separated list of tokens to exclude when doing * a WAR overlay. * * @parameter * @deprecated Use <overlay>/<excludes> instead */ private String dependentWarExcludes = "META-INF/**"; /** * The overlays to apply. * * @parameter * @since 2.1-alpha-1 */ private List overlays = new ArrayList(); /** * A list of file extensions that should not be filtered. * Will be used when filtering webResources and overlays. * * @parameter * @since 2.1-alpha-2 */ private List nonFilteredFileExtensions; /** * @parameter default-value="${session}" * @readonly * @required * @since 2.1-alpha-2 */ private MavenSession session; /** * To filter deployment descriptors. Disabled by default. * * @parameter expression="${maven.war.filteringDeploymentDescriptors}" default-value="false" * @since 2.1-alpha-2 */ private boolean filteringDeploymentDescriptors = false; /** * To escape interpolated values with Windows path * c:\foo\bar will be replaced with c:\\foo\\bar. * * @parameter expression="${maven.war.escapedBackslashesInFilePath}" default-value="false" * @since 2.1-alpha-2 */ private boolean escapedBackslashesInFilePath = false; /** * Expression preceded with this String won't be interpolated. * \${foo} will be replaced with ${foo}. * * @parameter expression="${maven.war.escapeString}" * @since 2.1-beta-1 */ protected String escapeString; /** * The archive configuration to use. * See Maven Archiver Reference. * * @parameter */ private MavenArchiveConfiguration archive = new MavenArchiveConfiguration(); private final WebappStructureSerializer webappStructureSerialier = new WebappStructureSerializer(); private final Overlay currentProjectOverlay = Overlay.createInstance(); public Overlay getCurrentProjectOverlay() { return currentProjectOverlay; } /** * Returns a string array of the excludes to be used * when copying the content of the WAR source directory. * * @return an array of tokens to exclude */ protected String[] getExcludes() { List excludeList = new ArrayList(); if ( StringUtils.isNotEmpty( warSourceExcludes ) ) { excludeList.addAll( Arrays.asList( StringUtils.split( warSourceExcludes, "," ) ) ); } // if webXML is specified, omit the one in the source directory if ( webXml != null && StringUtils.isNotEmpty( webXml.getName() ) ) { excludeList.add( "**/" + WEB_INF + "/web.xml" ); } // if contextXML is specified, omit the one in the source directory if ( containerConfigXML != null && StringUtils.isNotEmpty( containerConfigXML.getName() ) ) { excludeList.add( "**/" + META_INF + "/" + containerConfigXML.getName() ); } return (String[]) excludeList.toArray( EMPTY_STRING_ARRAY ); } /** * Returns a string array of the includes to be used * when assembling/copying the WAR. * * @return an array of tokens to include */ protected String[] getIncludes() { return StringUtils.split( StringUtils.defaultString( warSourceIncludes ), "," ); } /** * Returns a string array of the excludes to be used * when adding dependent WAR as an overlay onto this WAR. * * @return an array of tokens to exclude */ protected String[] getDependentWarExcludes() { String[] excludes; if ( StringUtils.isNotEmpty( dependentWarExcludes ) ) { excludes = StringUtils.split( dependentWarExcludes, "," ); } else { excludes = EMPTY_STRING_ARRAY; } return excludes; } /** * Returns a string array of the includes to be used * when adding dependent WARs as an overlay onto this WAR. * * @return an array of tokens to include */ protected String[] getDependentWarIncludes() { return StringUtils.split( StringUtils.defaultString( dependentWarIncludes ), "," ); } public void buildExplodedWebapp( File webappDirectory ) throws MojoExecutionException, MojoFailureException { webappDirectory.mkdirs(); try { buildWebapp( project, webappDirectory ); } catch ( IOException e ) { throw new MojoExecutionException( "Could not build webapp", e ); } } /** * Builds the webapp for the specified project with the new packaging task * thingy *

    * Classes, libraries and tld files are copied to * the webappDirectory during this phase. * * @param project the maven project * @param webappDirectory the target directory * @throws MojoExecutionException if an error occurred while packaging the webapp * @throws MojoFailureException if an unexpected error occurred while packaging the webapp * @throws IOException if an error occurred while copying the files */ public void buildWebapp( MavenProject project, File webappDirectory ) throws MojoExecutionException, MojoFailureException, IOException { WebappStructure cache; if ( useCache && cacheFile.exists() ) { cache = new WebappStructure( project.getDependencies(), webappStructureSerialier.fromXml( cacheFile ) ); } else { cache = new WebappStructure( project.getDependencies(), null ); } final long startTime = System.currentTimeMillis(); getLog().info( "Assembling webapp [" + project.getArtifactId() + "] in [" + webappDirectory + "]" ); final OverlayManager overlayManager = new OverlayManager( overlays, project, dependentWarIncludes, dependentWarExcludes, currentProjectOverlay ); final List packagingTasks = getPackagingTasks( overlayManager ); List defaultFilterWrappers = null; try { MavenResourcesExecution mavenResourcesExecution = new MavenResourcesExecution(); mavenResourcesExecution.setEscapeString( escapeString ); defaultFilterWrappers = mavenFileFilter.getDefaultFilterWrappers( project, filters, escapedBackslashesInFilePath, this.session, mavenResourcesExecution ); } catch ( MavenFilteringException e ) { getLog().error( "fail to build filering wrappers " + e.getMessage() ); throw new MojoExecutionException( e.getMessage(), e ); } final WarPackagingContext context = new DefaultWarPackagingContext( webappDirectory, cache, overlayManager, defaultFilterWrappers, getNonFilteredFileExtensions(), filteringDeploymentDescriptors, this.artifactFactory ); final Iterator it = packagingTasks.iterator(); while ( it.hasNext() ) { WarPackagingTask warPackagingTask = (WarPackagingTask) it.next(); warPackagingTask.performPackaging( context ); } // Post packaging final List postPackagingTasks = getPostPackagingTasks(); final Iterator it2 = postPackagingTasks.iterator(); while ( it2.hasNext() ) { WarPostPackagingTask task = (WarPostPackagingTask) it2.next(); task.performPostPackaging( context ); } getLog().info( "Webapp assembled in [" + ( System.currentTimeMillis() - startTime ) + " msecs]" ); } /** * Returns a List of the {@link org.apache.maven.plugin.war.packaging.WarPackagingTask} * instances to invoke to perform the packaging. * * @param overlayManager the overlay manager * @return the list of packaging tasks * @throws MojoExecutionException if the packaging tasks could not be built */ private List getPackagingTasks( OverlayManager overlayManager ) throws MojoExecutionException { final List packagingTasks = new ArrayList(); if ( useCache ) { packagingTasks.add( new DependenciesAnalysisPackagingTask() ); } final List resolvedOverlays = overlayManager.getOverlays(); final Iterator it = resolvedOverlays.iterator(); while ( it.hasNext() ) { Overlay overlay = (Overlay) it.next(); if ( overlay.isCurrentProject() ) { packagingTasks.add( new WarProjectPackagingTask( webResources, webXml, containerConfigXML, currentProjectOverlay ) ); } else { packagingTasks.add( new OverlayPackagingTask( overlay, currentProjectOverlay ) ); } } return packagingTasks; } /** * Returns a List of the {@link org.apache.maven.plugin.war.packaging.WarPostPackagingTask} * instances to invoke to perform the post-packaging. * * @return the list of post packaging tasks */ private List getPostPackagingTasks() { final List postPackagingTasks = new ArrayList(); if ( useCache ) { postPackagingTasks.add( new SaveWebappStructurePostPackagingTask( cacheFile ) ); } // TODO add lib scanning to detect duplicates return postPackagingTasks; } /** * WarPackagingContext default implementation */ private class DefaultWarPackagingContext implements WarPackagingContext { private final ArtifactFactory artifactFactory; private final WebappStructure webappStructure; private final File webappDirectory; private final OverlayManager overlayManager; private final List filterWrappers; private List nonFilteredFileExtensions; private boolean filteringDeploymentDescriptors; public DefaultWarPackagingContext( File webappDirectory, final WebappStructure webappStructure, final OverlayManager overlayManager, List filterWrappers, List nonFilteredFileExtensions, boolean filteringDeploymentDescriptors, ArtifactFactory artifactFactory ) { this.webappDirectory = webappDirectory; this.webappStructure = webappStructure; this.overlayManager = overlayManager; this.filterWrappers = filterWrappers; this.artifactFactory = artifactFactory; this.filteringDeploymentDescriptors = filteringDeploymentDescriptors; this.nonFilteredFileExtensions = nonFilteredFileExtensions == null ? Collections.EMPTY_LIST : nonFilteredFileExtensions; // This is kinda stupid but if we loop over the current overlays and we request the path structure // it will register it. This will avoid wrong warning messages in a later phase final Iterator it = overlayManager.getOverlayIds().iterator(); while ( it.hasNext() ) { String overlayId = (String) it.next(); webappStructure.getStructure( overlayId ); } } public MavenProject getProject() { return project; } public File getWebappDirectory() { return webappDirectory; } public File getClassesDirectory() { return classesDirectory; } public Log getLog() { return AbstractWarMojo.this.getLog(); } public String getOutputFileNameMapping() { return outputFileNameMapping; } public File getWebappSourceDirectory() { return warSourceDirectory; } public String[] getWebappSourceIncludes() { return getIncludes(); } public String[] getWebappSourceExcludes() { return getExcludes(); } public boolean archiveClasses() { return archiveClasses; } public File getOverlaysWorkDirectory() { return workDirectory; } public ArchiverManager getArchiverManager() { return archiverManager; } public MavenArchiveConfiguration getArchive() { return archive; } public JarArchiver getJarArchiver() { return jarArchiver; } public List getFilters() { return filters; } public WebappStructure getWebappStructure() { return webappStructure; } public List getOwnerIds() { return overlayManager.getOverlayIds(); } public MavenFileFilter getMavenFileFilter() { return mavenFileFilter; } public List getFilterWrappers() { return filterWrappers; } public boolean isNonFilteredExtension( String fileName ) { return !mavenResourcesFiltering.filteredFileExtension( fileName, nonFilteredFileExtensions ); } public boolean isFilteringDeploymentDescriptors() { return filteringDeploymentDescriptors; } public ArtifactFactory getArtifactFactory() { return this.artifactFactory; } } public MavenProject getProject() { return project; } public void setProject( MavenProject project ) { this.project = project; } public File getClassesDirectory() { return classesDirectory; } public void setClassesDirectory( File classesDirectory ) { this.classesDirectory = classesDirectory; } public File getWebappDirectory() { return webappDirectory; } public void setWebappDirectory( File webappDirectory ) { this.webappDirectory = webappDirectory; } public File getWarSourceDirectory() { return warSourceDirectory; } public void setWarSourceDirectory( File warSourceDirectory ) { this.warSourceDirectory = warSourceDirectory; } public File getWebXml() { return webXml; } public void setWebXml( File webXml ) { this.webXml = webXml; } public File getContainerConfigXML() { return containerConfigXML; } public void setContainerConfigXML( File containerConfigXML ) { this.containerConfigXML = containerConfigXML; } public String getOutputFileNameMapping() { return outputFileNameMapping; } public void setOutputFileNameMapping( String outputFileNameMapping ) { this.outputFileNameMapping = outputFileNameMapping; } public List getOverlays() { return overlays; } public void setOverlays( List overlays ) { this.overlays = overlays; } public void addOverlay( Overlay overlay ) { overlays.add( overlay ); } public boolean isArchiveClasses() { return archiveClasses; } public void setArchiveClasses( boolean archiveClasses ) { this.archiveClasses = archiveClasses; } public JarArchiver getJarArchiver() { return jarArchiver; } public void setJarArchiver( JarArchiver jarArchiver ) { this.jarArchiver = jarArchiver; } public Resource[] getWebResources() { return webResources; } public void setWebResources( Resource[] webResources ) { this.webResources = webResources; } public List getFilters() { return filters; } public void setFilters( List filters ) { this.filters = filters; } public File getWorkDirectory() { return workDirectory; } public void setWorkDirectory( File workDirectory ) { this.workDirectory = workDirectory; } public File getCacheFile() { return cacheFile; } public void setCacheFile( File cacheFile ) { this.cacheFile = cacheFile; } public String getWarSourceIncludes() { return warSourceIncludes; } public void setWarSourceIncludes( String warSourceIncludes ) { this.warSourceIncludes = warSourceIncludes; } public String getWarSourceExcludes() { return warSourceExcludes; } public void setWarSourceExcludes( String warSourceExcludes ) { this.warSourceExcludes = warSourceExcludes; } public boolean isUseCache() { return useCache; } public void setUseCache( boolean useCache ) { this.useCache = useCache; } public MavenArchiveConfiguration getArchive() { return archive; } public List getNonFilteredFileExtensions() { return nonFilteredFileExtensions; } public void setNonFilteredFileExtensions( List nonFilteredFileExtensions ) { this.nonFilteredFileExtensions = nonFilteredFileExtensions; } public ArtifactFactory getArtifactFactory() { return this.artifactFactory; } public void setArtifactFactory( ArtifactFactory artifactFactory ) { this.artifactFactory = artifactFactory; } } maven-war-plugin-2.1.1/src/main/java/org/apache/maven/plugin/war/overlay/0000755000175000017500000000000011641142606026165 5ustar twernertwernermaven-war-plugin-2.1.1/src/main/java/org/apache/maven/plugin/war/overlay/OverlayManager.java0000644000175000017500000002220111431614336031742 0ustar twernertwernerpackage org.apache.maven.plugin.war.overlay; /* * 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.maven.artifact.Artifact; import org.apache.maven.artifact.resolver.filter.ScopeArtifactFilter; import org.apache.maven.plugin.war.Overlay; import org.apache.maven.project.MavenProject; import org.codehaus.plexus.util.StringUtils; import java.util.ArrayList; import java.util.Arrays; import java.util.Iterator; import java.util.List; import java.util.ListIterator; import java.util.Set; /** * Manages the overlays. * * @author Stephane Nicoll * * @version $Id: OverlayManager.java 985595 2010-08-14 22:29:50Z dennisl $ */ public class OverlayManager { private final List overlays; private final MavenProject project; private final List artifactsOverlays; /** * Creates a manager with the specified overlays. *

    * Note that the list is potentially updated by the * manager so a new list is created based on the overlays. * * @param overlays the overlays * @param project the maven project * @param defaultIncludes the default includes to use * @param defaultExcludes the default excludes to use * @param currentProjectOverlay the overlay for the current project * @throws InvalidOverlayConfigurationException * if the config is invalid */ public OverlayManager( List overlays, MavenProject project, String defaultIncludes, String defaultExcludes, Overlay currentProjectOverlay ) throws InvalidOverlayConfigurationException { this.overlays = new ArrayList(); if ( overlays != null ) { this.overlays.addAll( overlays ); } this.project = project; this.artifactsOverlays = getOverlaysAsArtifacts(); // Initialize initialize( defaultIncludes, defaultExcludes, currentProjectOverlay ); } /** * Returns the resolved overlays. * * @return the overlays */ public List getOverlays() { return overlays; } /** * Returns the id of the resolved overlays. * * @return the overlay ids */ public List getOverlayIds() { final Iterator it = overlays.iterator(); final List result = new ArrayList(); while ( it.hasNext() ) { Overlay overlay = (Overlay) it.next(); result.add( overlay.getId() ); } return result; } /** * Intializes the manager and validates the overlays configuration. * * @param defaultIncludes the default includes to use * @param defaultExcludes the default excludes to use * @param currentProjectOverlay the overlay for the current project * @throws InvalidOverlayConfigurationException * if the configuration is invalid */ void initialize( String defaultIncludes, String defaultExcludes, Overlay currentProjectOverlay ) throws InvalidOverlayConfigurationException { // Build the list of configured artifacts and makes sure that each overlay // refer to a valid artifact final List configuredWarArtifacts = new ArrayList(); final ListIterator it = overlays.listIterator(); while ( it.hasNext() ) { Overlay overlay = (Overlay) it.next(); if ( overlay == null ) { throw new InvalidOverlayConfigurationException( "overlay could not be null." ); } // If it's the current project, return the project instance if ( overlay.isCurrentProject() ) { overlay = currentProjectOverlay; it.set( overlay ); } // default includes/excludes - only if the overlay uses the default settings if ( Arrays.equals( Overlay.DEFAULT_INCLUDES, overlay.getIncludes() ) && Arrays.equals( Overlay.DEFAULT_EXCLUDES, overlay.getExcludes() ) ) { overlay.setIncludes( defaultIncludes ); overlay.setExcludes( defaultExcludes ); } final Artifact artifact = getAssociatedArtifact( overlay ); if ( artifact != null ) { configuredWarArtifacts.add( artifact ); overlay.setArtifact( artifact ); } } // Build the list of missing overlays final Iterator it2 = artifactsOverlays.iterator(); while ( it2.hasNext() ) { Artifact artifact = (Artifact) it2.next(); if ( !configuredWarArtifacts.contains( artifact ) ) { // Add a default overlay for the given artifact which will be applied after // the ones that have been configured overlays.add( new DefaultOverlay( artifact, defaultIncludes, defaultExcludes ) ); } } // Final validation, make sure that the current project is in there. Otherwise add it first final Iterator it3 = overlays.iterator(); while ( it3.hasNext() ) { Overlay overlay = (Overlay) it3.next(); if ( overlay.equals( currentProjectOverlay ) ) { return; } } overlays.add( 0, currentProjectOverlay ); } /** * Returns the Artifact associated to the specified overlay. *

    * If the overlay defines the current project, null is * returned. If no artifact could not be found for the overlay * a InvalidOverlayConfigurationException is thrown. * * @param overlay an overlay * @return the artifact associated to the overlay * @throws org.apache.maven.plugin.war.overlay.InvalidOverlayConfigurationException * if the overlay does not have an associated artifact */ Artifact getAssociatedArtifact( final Overlay overlay ) throws InvalidOverlayConfigurationException { if ( overlay.isCurrentProject() ) { return null; } for ( Iterator iterator = artifactsOverlays.iterator(); iterator.hasNext(); ) { // Handle classifier dependencies properly (clash management) Artifact artifact = (Artifact) iterator.next(); if ( compareOverlayWithArtifact( overlay, artifact ) ) { return artifact; } } // maybe its a project dependencies zip or an other type Set projectArtifacts = this.project.getDependencyArtifacts(); if ( projectArtifacts != null ) { for ( Iterator iterator = projectArtifacts.iterator(); iterator.hasNext(); ) { Artifact artifact = (Artifact) iterator.next(); if ( compareOverlayWithArtifact( overlay, artifact ) ) { return artifact; } } } throw new InvalidOverlayConfigurationException( "overlay [" + overlay + "] is not a dependency of the project." ); } /** * compare groupId && artifactId && Type && classifier * @param overlay the overlay * @param artifact the artifact * @return boolean true if equals */ private boolean compareOverlayWithArtifact( Overlay overlay, Artifact artifact ) { return ( StringUtils.equals( overlay.getGroupId(), artifact.getGroupId() ) && StringUtils.equals( overlay.getArtifactId(), artifact.getArtifactId() ) && StringUtils.equals( overlay.getType(), artifact.getType() ) && StringUtils.equals( overlay.getClassifier(), artifact.getClassifier() ) ); } /** * Returns a list of WAR {@link org.apache.maven.artifact.Artifact} describing * the overlays of the current project. * * @return the overlays as artifacts objects */ private List getOverlaysAsArtifacts() { ScopeArtifactFilter filter = new ScopeArtifactFilter( Artifact.SCOPE_RUNTIME ); final Set artifacts = project.getArtifacts(); final Iterator it = artifacts.iterator(); final List result = new ArrayList(); while ( it.hasNext() ) { Artifact artifact = (Artifact) it.next(); if ( !artifact.isOptional() && filter.include( artifact ) && ( "war".equals( artifact.getType() ) ) ) { result.add( artifact ); } } return result; } } ././@LongLink0000000000000000000000000000016300000000000011565 Lustar rootrootmaven-war-plugin-2.1.1/src/main/java/org/apache/maven/plugin/war/overlay/InvalidOverlayConfigurationException.javamaven-war-plugin-2.1.1/src/main/java/org/apache/maven/plugin/war/overlay/InvalidOverlayConfiguration0000644000175000017500000000262411015345234033571 0ustar twernertwernerpackage org.apache.maven.plugin.war.overlay; /* * 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.maven.plugin.MojoExecutionException; /** * Thrown if the overlay configuration is invalid. * * @author Stephane Nicoll * * @version $Id: InvalidOverlayConfigurationException.java 659222 2008-05-22 19:33:48Z olamy $ */ public class InvalidOverlayConfigurationException extends MojoExecutionException { public InvalidOverlayConfigurationException( String string ) { super( string ); } public InvalidOverlayConfigurationException( String string, Throwable throwable ) { super( string, throwable ); } } maven-war-plugin-2.1.1/src/main/java/org/apache/maven/plugin/war/overlay/DefaultOverlay.java0000644000175000017500000000356311015345234031762 0ustar twernertwernerpackage org.apache.maven.plugin.war.overlay; /* * 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.maven.artifact.Artifact; import org.apache.maven.plugin.war.Overlay; /** * A default overlay implementation based on an {@link Artifact}. * * @author Stephane Nicoll * * @version $Id: DefaultOverlay.java 659222 2008-05-22 19:33:48Z olamy $ */ public class DefaultOverlay extends Overlay { /** * Creates an overlay for the specified artifact. * * @param a the artifact */ public DefaultOverlay( Artifact a ) { super(); setGroupId( a.getGroupId() ); setArtifactId( a.getArtifactId() ); setClassifier( a.getClassifier() ); setArtifact( a ); setType( a.getType() ); } /** * Creates an overlay for the specified artifact. * * @param a the artifact * @param includes the includes to use * @param excludes the excludes to use */ public DefaultOverlay( Artifact a, String includes, String excludes ) { this( a ); setIncludes( includes ); setExcludes( excludes ); } }