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