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.shared.dependency.analyzer;
20  
21  import java.io.BufferedReader;
22  import java.io.IOException;
23  import java.io.InputStream;
24  import java.io.InputStreamReader;
25  import java.net.URL;
26  import java.nio.charset.StandardCharsets;
27  import java.nio.file.Files;
28  import java.nio.file.Path;
29  import java.util.ArrayList;
30  import java.util.List;
31  import java.util.jar.JarOutputStream;
32  import java.util.zip.ZipEntry;
33  
34  import org.junit.jupiter.api.Test;
35  import org.junit.jupiter.api.io.TempDir;
36  
37  import static org.assertj.core.api.Assertions.assertThat;
38  import static org.assertj.core.api.Assertions.fail;
39  
40  /**
41   * Tests <code>ClassFileVisitorUtils</code>.
42   *
43   * @author <a href="mailto:markhobson@gmail.com">Mark Hobson</a>
44   * @see ClassFileVisitorUtils
45   */
46  class ClassFileVisitorUtilsTest {
47  
48      @TempDir
49      private Path tempDir;
50  
51      private TestVisitor visitor = new TestVisitor();
52  
53      private static class TestVisitor implements ClassFileVisitor {
54          final List<String> classNames = new ArrayList<>();
55  
56          final List<String> data = new ArrayList<>();
57  
58          @Override
59          public void visitClass(String className, InputStream in) {
60              classNames.add(className);
61              BufferedReader reader = new BufferedReader(new InputStreamReader(in, StandardCharsets.UTF_8));
62              reader.lines().forEach(data::add);
63          }
64      }
65  
66      @Test
67      void testAcceptJar() throws IOException {
68          Path path = Files.createTempFile(tempDir, "test", ".jar");
69  
70          try (JarOutputStream out = new JarOutputStream(Files.newOutputStream(path))) {
71              addZipEntry(out, "a/b/c.class", "class a.b.c");
72              addZipEntry(out, "x/y/z.class", "class x.y.z");
73          }
74  
75          ClassFileVisitorUtils.accept(path.toUri().toURL(), visitor);
76  
77          assertThat(visitor.classNames).contains("a.b.c");
78          assertThat(visitor.classNames).contains("x.y.z");
79          assertThat(visitor.data).contains("class a.b.c");
80          assertThat(visitor.data).contains("class x.y.z");
81      }
82  
83      @Test
84      void testAcceptJarWithNonClassEntry() throws IOException {
85          Path path = Files.createTempFile(tempDir, "test", ".jar");
86  
87          try (JarOutputStream out = new JarOutputStream(Files.newOutputStream(path))) {
88              addZipEntry(out, "a/b/c.jpg", "jpeg a.b.c");
89          }
90  
91          ClassFileVisitorUtils.accept(path.toUri().toURL(), visitor);
92  
93          assertThat(visitor.classNames).isEmpty();
94      }
95  
96      @Test
97      void testAcceptDir() throws IOException {
98          Path dir = Files.createTempDirectory(tempDir, "d-a-test");
99  
100         Path abDir = Files.createDirectories(dir.resolve("a/b"));
101         writeToFile(abDir, "c.class", "class a.b.c");
102 
103         Path xyDir = Files.createDirectories(dir.resolve("x/y"));
104         writeToFile(xyDir, "z.class", "class x.y.z");
105 
106         ClassFileVisitorUtils.accept(dir.toUri().toURL(), visitor);
107 
108         assertThat(visitor.classNames).contains("a.b.c");
109         assertThat(visitor.classNames).contains("x.y.z");
110         assertThat(visitor.data).contains("class a.b.c");
111         assertThat(visitor.data).contains("class x.y.z");
112     }
113 
114     @Test
115     void testAcceptDirWithNonClassFile() throws IOException {
116         Path dir = Files.createTempDirectory(tempDir, "d-a-test");
117 
118         Path abDir = Files.createDirectories(dir.resolve("a/b"));
119         writeToFile(abDir, "c.jpg", "jpeg a.b.c");
120 
121         ClassFileVisitorUtils.accept(dir.toUri().toURL(), visitor);
122 
123         assertThat(visitor.classNames).isEmpty();
124     }
125 
126     @Test
127     void testAcceptWithFile() throws IOException {
128         Path path = Files.createTempFile(tempDir, "test", ".class");
129         URL url = path.toUri().toURL();
130 
131         try {
132             ClassFileVisitorUtils.accept(url, visitor);
133             fail("expected IllegalArgumentException");
134         } catch (IllegalArgumentException exception) {
135             assertThat(exception).hasMessage("Cannot accept visitor on URL: " + url);
136         }
137     }
138 
139     @Test
140     void testAcceptWithUnsupportedScheme() throws IOException {
141         URL url = new URL("http://localhost/");
142 
143         try {
144             ClassFileVisitorUtils.accept(url, visitor);
145             fail("expected IllegalArgumentException");
146         } catch (IllegalArgumentException exception) {
147             assertThat(exception).hasMessage("Cannot accept visitor on URL: " + url);
148         }
149     }
150 
151     private void writeToFile(Path parent, String file, String data) throws IOException {
152         Files.write(parent.resolve(file), data.getBytes(StandardCharsets.UTF_8));
153     }
154 
155     private void addZipEntry(JarOutputStream out, String fileName, String content) throws IOException {
156         out.putNextEntry(new ZipEntry(fileName));
157         byte[] bytes = content.getBytes(StandardCharsets.UTF_8);
158         out.write(bytes, 0, bytes.length);
159     }
160 }