View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.maven.plugin.resources.remote;
20  
21  import java.io.File;
22  import java.io.InputStream;
23  import java.io.OutputStream;
24  import java.net.URL;
25  import java.nio.charset.StandardCharsets;
26  import java.nio.file.Files;
27  import java.util.ArrayList;
28  import java.util.Arrays;
29  import java.util.Calendar;
30  import java.util.Collections;
31  import java.util.jar.JarOutputStream;
32  import java.util.zip.ZipEntry;
33  
34  import org.apache.maven.artifact.Artifact;
35  import org.apache.maven.artifact.DefaultArtifact;
36  import org.apache.maven.artifact.handler.DefaultArtifactHandler;
37  import org.apache.maven.artifact.repository.MavenArtifactRepository;
38  import org.apache.maven.artifact.repository.layout.DefaultRepositoryLayout;
39  import org.apache.maven.artifact.versioning.VersionRange;
40  import org.apache.maven.execution.DefaultMavenExecutionRequest;
41  import org.apache.maven.execution.DefaultMavenExecutionResult;
42  import org.apache.maven.execution.MavenSession;
43  import org.apache.maven.plugin.resources.remote.stub.MavenProjectBuildStub;
44  import org.apache.maven.plugin.resources.remote.stub.MavenProjectResourcesStub;
45  import org.apache.maven.plugin.testing.AbstractMojoTestCase;
46  import org.apache.maven.project.MavenProject;
47  import org.apache.maven.repository.internal.MavenRepositorySystemUtils;
48  import org.codehaus.plexus.util.FileUtils;
49  import org.codehaus.plexus.util.IOUtil;
50  import org.eclipse.aether.DefaultRepositorySystemSession;
51  import org.eclipse.aether.internal.impl.SimpleLocalRepositoryManagerFactory;
52  import org.eclipse.aether.repository.LocalRepository;
53  
54  /**
55   * RemoteResources plugin Test Case
56   */
57  public class RemoteResourcesMojoTest extends AbstractMojoTestCase {
58      static final String DEFAULT_BUNDLE_POM_PATH = "target/test-classes/unit/rrmojotest/bundle-plugin-config.xml";
59      static final String DEFAULT_PROCESS_POM_PATH = "target/test-classes/unit/rrmojotest/process-plugin-config.xml";
60  
61      private final String LOCAL_REPO = "target/local-repo/";
62  
63      @Override
64      public void setUp() throws Exception {
65          super.setUp();
66      }
67  
68      @Override
69      public void tearDown() throws Exception {}
70  
71      /**
72       * check test environment
73       *
74       * @throws Exception if any exception occurs
75       */
76      public void testTestEnvironment() throws Exception {
77          // Perform lookup on the Mojo to make sure everything is ok
78          lookupProcessMojo();
79      }
80  
81      public void testNoBundles() throws Exception {
82          final MavenProjectResourcesStub project = createTestProject("default-nobundles");
83          final ProcessRemoteResourcesMojo mojo = lookupProcessMojoWithDefaultSettings(project);
84  
85          setupDefaultProject(project);
86  
87          mojo.execute();
88      }
89  
90      public void testCreateBundle() throws Exception {
91          buildResourceBundle("default-createbundle", null, new String[] {"SIMPLE.txt"}, null);
92      }
93  
94      public void testSimpleBundles() throws Exception {
95          final MavenProjectResourcesStub project = createTestProject("default-simplebundles");
96          final ProcessRemoteResourcesMojo mojo = lookupProcessMojoWithSettings(project, new String[] {"test:test:1.0"});
97  
98          setupDefaultProject(project);
99  
100         String path = pathOf(new DefaultArtifact(
101                 "test", "test", VersionRange.createFromVersion("1.0"), null, "jar", "", new DefaultArtifactHandler()));
102 
103         File file = new File(path);
104         file.getParentFile().mkdirs();
105         buildResourceBundle("default-simplebundles-create", null, new String[] {"SIMPLE.txt"}, file);
106 
107         mojo.execute();
108 
109         file = (File) getVariableValueFromObject(mojo, "outputDirectory");
110         file = new File(file, "SIMPLE.txt");
111         assertTrue(file.exists());
112     }
113 
114     public void testSimpleBundlesWithType() throws Exception {
115         final MavenProjectResourcesStub project = createTestProject("default-simplebundles");
116         final ProcessRemoteResourcesMojo mojo =
117                 lookupProcessMojoWithSettings(project, new String[] {"test:test:1.0:war"});
118 
119         setupDefaultProject(project);
120 
121         String path = pathOf(new DefaultArtifact(
122                 "test", "test", VersionRange.createFromVersion("1.0"), null, "war", "", new DefaultArtifactHandler()));
123 
124         File file = new File(path);
125         file.getParentFile().mkdirs();
126         buildResourceBundle("default-simplebundles-create", null, new String[] {"SIMPLE.txt"}, file);
127 
128         mojo.execute();
129 
130         file = (File) getVariableValueFromObject(mojo, "outputDirectory");
131         file = new File(file, "SIMPLE.txt");
132         assertTrue(file.exists());
133     }
134 
135     public void testSimpleBundlesWithClassifier() throws Exception {
136         final MavenProjectResourcesStub project = createTestProject("default-simplebundles");
137         final ProcessRemoteResourcesMojo mojo =
138                 lookupProcessMojoWithSettings(project, new String[] {"test:test:1.0:jar:test"});
139 
140         setupDefaultProject(project);
141 
142         String path = pathOf(new DefaultArtifact(
143                 "test",
144                 "test",
145                 VersionRange.createFromVersion("1.0"),
146                 null,
147                 "jar",
148                 "test",
149                 new DefaultArtifactHandler()));
150 
151         File file = new File(path);
152         file.getParentFile().mkdirs();
153         buildResourceBundle("default-simplebundles-create", null, new String[] {"SIMPLE.txt"}, file);
154 
155         mojo.execute();
156 
157         file = (File) getVariableValueFromObject(mojo, "outputDirectory");
158         file = new File(file, "SIMPLE.txt");
159         assertTrue(file.exists());
160     }
161 
162     public void testVelocityUTF8() throws Exception {
163         final MavenProjectResourcesStub project = createTestProject("default-utf8");
164         final ProcessRemoteResourcesMojo mojo = lookupProcessMojoWithSettings(project, new String[] {"test:test:1.2"});
165 
166         setupDefaultProject(project);
167 
168         String path = pathOf(new DefaultArtifact(
169                 "test", "test", VersionRange.createFromVersion("1.2"), null, "jar", "", new DefaultArtifactHandler()));
170 
171         File file = new File(path);
172         file.getParentFile().mkdirs();
173         buildResourceBundle("default-utf8-create", "UTF-8", new String[] {"UTF-8.bin.vm"}, file);
174 
175         mojo.execute();
176 
177         file = (File) getVariableValueFromObject(mojo, "outputDirectory");
178         file = new File(file, "UTF-8.bin");
179         assertTrue(file.exists());
180 
181         try (InputStream in = Files.newInputStream(file.toPath())) {
182             byte[] data = IOUtil.toByteArray(in);
183             byte[] expected = "\u00E4\u00F6\u00FC\u00C4\u00D6\u00DC\u00DF".getBytes(StandardCharsets.UTF_8);
184             assertTrue(Arrays.equals(expected, data));
185         }
186     }
187 
188     public void testVelocityISO88591() throws Exception {
189         final MavenProjectResourcesStub project = createTestProject("default-iso88591");
190         final ProcessRemoteResourcesMojo mojo = lookupProcessMojoWithSettings(project, new String[] {"test:test:1.3"});
191 
192         setupDefaultProject(project);
193 
194         String path = pathOf(new DefaultArtifact(
195                 "test", "test", VersionRange.createFromVersion("1.3"), null, "jar", "", new DefaultArtifactHandler()));
196 
197         File file = new File(path);
198         file.getParentFile().mkdirs();
199         buildResourceBundle("default-iso88591-create", "ISO-8859-1", new String[] {"ISO-8859-1.bin.vm"}, file);
200 
201         mojo.execute();
202 
203         file = (File) getVariableValueFromObject(mojo, "outputDirectory");
204         file = new File(file, "ISO-8859-1.bin");
205         assertTrue(file.exists());
206 
207         try (InputStream in = Files.newInputStream(file.toPath())) {
208             byte[] data = IOUtil.toByteArray(in);
209             byte[] expected = "\u00E4\u00F6\u00FC\u00C4\u00D6\u00DC\u00DF".getBytes(StandardCharsets.ISO_8859_1);
210             assertTrue(Arrays.equals(expected, data));
211         }
212     }
213 
214     public void testFilteredBundles() throws Exception {
215         final MavenProjectResourcesStub project = createTestProject("default-filterbundles");
216         final ProcessRemoteResourcesMojo mojo = lookupProcessMojoWithSettings(project, new String[] {"test:test:1.1"});
217 
218         setupDefaultProject(project);
219 
220         String path = pathOf(new DefaultArtifact(
221                 "test", "test", VersionRange.createFromVersion("1.1"), null, "jar", "", new DefaultArtifactHandler()));
222 
223         File file = new File(path);
224         file.getParentFile().mkdirs();
225         buildResourceBundle("default-filterbundles-create", null, new String[] {"FILTER.txt.vm"}, file);
226 
227         mojo.execute();
228         // executing a second time (example: forked lifecycle) should still work
229         mojo.execute();
230 
231         file = (File) getVariableValueFromObject(mojo, "outputDirectory");
232         file = new File(file, "FILTER.txt");
233         assertTrue(file.exists());
234 
235         String data = FileUtils.fileRead(file);
236         assertTrue(data.contains("project.name: Test Project default-filterbundles"));
237         assertTrue(data.contains("projectTimespan: 2007-2019"));
238         assertTrue(data.contains("projects: ["));
239         assertTrue(data.contains("projectsSortedByOrganization: {"));
240     }
241 
242     public void testFilteredBundlesWithProjectProperties() throws Exception {
243         final MavenProjectResourcesStub project = createTestProject("default-filterbundles-two");
244         final ProcessRemoteResourcesMojo mojo =
245                 lookupProcessMojoWithSettings(project, new String[] {"test-filtered-bundles:test-filtered-bundles:2"});
246 
247         mojo.includeProjectProperties = true;
248         setupDefaultProject(project);
249 
250         project.addProperty("testingPropertyOne", "maven");
251         project.addProperty("testingPropertyTwo", "rules");
252 
253         String path = pathOf(new DefaultArtifact(
254                 "test-filtered-bundles",
255                 "test-filtered-bundles",
256                 VersionRange.createFromVersion("2"),
257                 null,
258                 "jar",
259                 "",
260                 new DefaultArtifactHandler()));
261 
262         File file = new File(path);
263         file.getParentFile().mkdirs();
264         buildResourceBundle("default-filterbundles-two-create", null, new String[] {"PROPERTIES.txt.vm"}, file);
265 
266         mojo.execute();
267         // executing a second time (example: forked lifecycle) should still work
268         mojo.execute();
269 
270         file = (File) getVariableValueFromObject(mojo, "outputDirectory");
271         file = new File(file, "PROPERTIES.txt");
272 
273         assertTrue(file.exists());
274 
275         String data = FileUtils.fileRead(file);
276         assertTrue(data.contains("maven"));
277         assertTrue(data.contains("rules"));
278     }
279 
280     protected void buildResourceBundle(String id, String sourceEncoding, String[] resourceNames, File jarName)
281             throws Exception {
282         final MavenProjectResourcesStub project = createTestProject(id);
283 
284         final File resourceDir = new File(project.getBasedir() + "/src/main/resources");
285         final BundleRemoteResourcesMojo mojo = lookupBundleMojoWithSettings(project, resourceDir, sourceEncoding);
286 
287         setupDefaultProject(project);
288 
289         for (String resourceName2 : resourceNames) {
290             File resource = new File(resourceDir, resourceName2);
291             URL source = getClass().getResource("/" + resourceName2);
292 
293             FileUtils.copyURLToFile(source, resource);
294         }
295 
296         mojo.execute();
297 
298         File xmlFile = new File(project.getBasedir() + "/target/classes/META-INF/maven/remote-resources.xml");
299         assertTrue(xmlFile.exists());
300 
301         String data = FileUtils.fileRead(xmlFile);
302         for (String resourceName1 : resourceNames) {
303             assertTrue(data.contains(resourceName1));
304         }
305 
306         if (null != jarName) {
307             try (OutputStream fos = Files.newOutputStream(jarName.toPath());
308                     JarOutputStream jar = new JarOutputStream(fos)) {
309                 jar.putNextEntry(new ZipEntry("META-INF/maven/remote-resources.xml"));
310                 jar.write(data.getBytes());
311                 jar.closeEntry();
312 
313                 for (String resourceName : resourceNames) {
314                     File resource = new File(resourceDir, resourceName);
315                     try (InputStream in = Files.newInputStream(resource.toPath())) {
316                         jar.putNextEntry(new ZipEntry(resourceName));
317                         IOUtil.copy(in, jar);
318                         jar.closeEntry();
319                     }
320                 }
321             }
322         }
323     }
324 
325     protected MavenProjectResourcesStub createTestProject(final String testName) throws Exception {
326         // this will automatically create the isolated
327         // test environment
328         return new MavenProjectResourcesStub(testName);
329     }
330 
331     protected void setupDefaultProject(final MavenProjectResourcesStub project) throws Exception {
332         // put this on the root dir
333         project.addFile("pom.xml", MavenProjectBuildStub.ROOT_FILE);
334         project.setInceptionYear("2007");
335         // start creating the environment
336         project.setupBuildEnvironment();
337     }
338 
339     protected BundleRemoteResourcesMojo lookupBundleMojo() throws Exception {
340         File pomFile = new File(getBasedir(), DEFAULT_BUNDLE_POM_PATH);
341         BundleRemoteResourcesMojo mojo = (BundleRemoteResourcesMojo) lookupMojo("bundle", pomFile);
342 
343         assertNotNull(mojo);
344 
345         return mojo;
346     }
347 
348     protected BundleRemoteResourcesMojo lookupBundleMojoWithDefaultSettings(final MavenProject project)
349             throws Exception {
350         File resourceDir = new File(project.getBasedir() + "/src/main/resources");
351         return lookupBundleMojoWithSettings(project, resourceDir, null);
352     }
353 
354     protected BundleRemoteResourcesMojo lookupBundleMojoWithSettings(
355             final MavenProject project, File resourceDir, String sourceEncoding) throws Exception {
356         final BundleRemoteResourcesMojo mojo = lookupBundleMojo();
357 
358         setVariableValueToObject(mojo, "resourcesDirectory", resourceDir);
359         setVariableValueToObject(
360                 mojo, "outputDirectory", new File(project.getBuild().getOutputDirectory()));
361         setVariableValueToObject(mojo, "sourceEncoding", sourceEncoding);
362         return mojo;
363     }
364 
365     protected ProcessRemoteResourcesMojo lookupProcessMojo() throws Exception {
366         File pomFile = new File(getBasedir(), DEFAULT_PROCESS_POM_PATH);
367         ProcessRemoteResourcesMojo mojo = (ProcessRemoteResourcesMojo) lookupMojo("process", pomFile);
368 
369         assertNotNull(mojo);
370 
371         return mojo;
372     }
373 
374     protected ProcessRemoteResourcesMojo lookupProcessMojoWithSettings(final MavenProject project, String[] bundles)
375             throws Exception {
376         return lookupProcessMojoWithSettings(project, new ArrayList<>(Arrays.asList(bundles)));
377     }
378 
379     protected ProcessRemoteResourcesMojo lookupProcessMojoWithSettings(
380             final MavenProject project, ArrayList<String> bundles) throws Exception {
381         final ProcessRemoteResourcesMojo mojo = lookupProcessMojo();
382 
383         DefaultRepositorySystemSession reposession = MavenRepositorySystemUtils.newSession();
384         reposession.setLocalRepositoryManager(new SimpleLocalRepositoryManagerFactory()
385                 .newInstance(reposession, new LocalRepository(new File(LOCAL_REPO))));
386 
387         DefaultMavenExecutionRequest request = new DefaultMavenExecutionRequest();
388         request.setUserProperties(null);
389         // request.setLocalRepository( reposession.getLocalRepository() );
390         request.setGoals(Collections.singletonList("install"));
391         request.setBaseDirectory(project.getBasedir());
392         request.setStartTime(Calendar.getInstance().getTime());
393 
394         // TODO: get rid of this uglyness/legacy
395         MavenArtifactRepository localRepository = new MavenArtifactRepository();
396         localRepository.setId("local");
397         localRepository.setUrl(new File(LOCAL_REPO).toURI().toASCIIString());
398         localRepository.setLayout(new DefaultRepositoryLayout());
399         request.setLocalRepository(localRepository);
400         MavenSession session =
401                 new MavenSession(getContainer(), reposession, request, new DefaultMavenExecutionResult());
402         session.setProjects(Collections.singletonList(project));
403 
404         setVariableValueToObject(
405                 mojo, "outputDirectory", new File(project.getBuild().getOutputDirectory()));
406         setVariableValueToObject(mojo, "resourceBundles", bundles);
407         setVariableValueToObject(mojo, "mavenSession", session);
408         setVariableValueToObject(mojo, "project", project);
409         return mojo;
410     }
411 
412     protected ProcessRemoteResourcesMojo lookupProcessMojoWithDefaultSettings(final MavenProject project)
413             throws Exception {
414         return lookupProcessMojoWithSettings(project, new ArrayList<>());
415     }
416 
417     private String pathOf(Artifact artifact) {
418         String path = LOCAL_REPO + artifact.getGroupId().replace(".", "/") + "/"
419                 + artifact.getArtifactId() + "/"
420                 + artifact.getBaseVersion() + "/"
421                 + artifact.getArtifactId() + "-" + artifact.getVersion();
422         if (artifact.getClassifier() != null && !artifact.getClassifier().isEmpty()) {
423             path = path + "-" + artifact.getClassifier();
424         }
425         String ext = artifact.getArtifactHandler().getExtension();
426         if (ext == null) {
427             ext = artifact.getType();
428         }
429         path = path + "." + ext;
430         return path;
431     }
432 }