View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  
18  package org.apache.commons.net.examples;
19  
20  import static org.junit.Assert.fail;
21  
22  import java.io.File;
23  import java.io.IOException;
24  import java.io.InputStream;
25  import java.net.URLDecoder;
26  import java.nio.charset.StandardCharsets;
27  import java.security.CodeSource;
28  import java.util.Enumeration;
29  import java.util.Properties;
30  import java.util.jar.JarEntry;
31  import java.util.jar.JarFile;
32  
33  import org.junit.Test;
34  
35  public class MainTest {
36  
37      private static boolean hasMainMethod(String name) {
38          name = name.replace(".class", "");
39          try {
40              final Class<?> clazz = Class.forName(name, false, MainTest.class.getClassLoader());
41              clazz.getMethod("main", String[].class);
42              return true;
43          } catch (final ClassNotFoundException e) {
44              System.out.println("Cannot find " + name);
45              return false;
46          } catch (final NoSuchMethodException e) {
47              return false;
48          } catch (final SecurityException e) {
49              e.printStackTrace();
50          }
51          return true;
52      }
53  
54      private static void processFileName(String name, final Properties p) {
55          name = name.replace(File.separatorChar, '.');
56          if (!name.endsWith(".class") || name.contains("$") // subclasses
57                  || name.endsWith("examples.Main.class") // the initial class, don't want to add that
58                  || !hasMainMethod(name)) {
59              return;
60          }
61          name = name.replace(".class", "");
62          final int lastSep = name.lastIndexOf('.');
63          final String alias = name.substring(lastSep + 1);
64          if (p.containsKey(alias)) {
65              System.out.printf("Duplicate alias: %-25s %s %s %n", alias, name, p.getProperty(alias));
66          } else {
67              p.setProperty(alias, name);
68          }
69      }
70  
71      private static void scanForClasses(final int rootLength, final File current, final Properties p) {
72          final File[] files = current.listFiles();
73          if (files != null) {
74              for (final File file : files) {
75                  if (file.isDirectory()) {
76                      scanForClasses(rootLength, file, p);
77                  } else {
78                      processFileName(file.getPath().substring(rootLength), p);
79                  }
80              }
81          }
82      }
83  
84      private Properties scanClasses() throws IOException {
85          final CodeSource codeSource = Main.class.getProtectionDomain().getCodeSource();
86          // ensure special characters are decoded OK by uing the charset
87          // Use canonical path to ensure consistency with Windows
88          final String sourceFile = new File(URLDecoder.decode(codeSource.getLocation().getFile(), StandardCharsets.UTF_8.name())).getCanonicalPath();
89          final Properties p = new Properties();
90          if (sourceFile.endsWith(".jar")) {
91              try (final JarFile jf = new JarFile(sourceFile)) {
92                  final Enumeration<JarEntry> e = jf.entries();
93                  while (e.hasMoreElements()) {
94                      final JarEntry je = e.nextElement();
95                      final String name = je.getName();
96                      processFileName(name, p);
97                  }
98              }
99          } else {
100             final File examples = new File(sourceFile, "org/apache/commons/net/examples"); // must match top level examples package name
101             if (examples.exists()) {
102                 // need to add 1 to allow for path separator between root and file
103                 scanForClasses(sourceFile.length() + 1, examples, p);
104             } else {
105                 fail("Could not find examples classes: " + examples.getCanonicalPath());
106             }
107         }
108         return p;
109     }
110 
111     @Test
112     public void testCheckExamplesPropertiesIsComplete() throws Exception {
113         final Properties cp = scanClasses();
114         final Properties fp = new Properties();
115         try (final InputStream inputStream = this.getClass().getResourceAsStream("examples.properties")) {
116             fp.load(inputStream);
117         }
118         @SuppressWarnings("unchecked") // OK
119         final Enumeration<String> propertyNames = (Enumeration<String>) cp.propertyNames();
120         while (propertyNames.hasMoreElements()) {
121             final String c = propertyNames.nextElement();
122             final String fv = fp.getProperty(c);
123             final String cv = cp.getProperty(c);
124             if (fv == null) {
125                 System.out.printf("%-25s %s - missing from examples.properties%n", c, cv);
126             } else if (!fv.equals(cv)) {
127                 System.out.printf("%-25s %s - expected value %s %n", c, fv, cv);
128             }
129         }
130     }
131 }