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.security.CodeSource;
27  import java.util.Enumeration;
28  import java.util.Properties;
29  import java.util.jar.JarEntry;
30  import java.util.jar.JarFile;
31  
32  import org.junit.Test;
33  
34  public class MainTest {
35  
36      private static boolean hasMainMethod(String name) {
37          name = name.replace(".class", "");
38          try {
39              final Class<?> clazz = Class.forName(name, false, MainTest.class.getClassLoader());
40              clazz.getMethod("main", String[].class);
41              return true;
42          } catch (final ClassNotFoundException e) {
43              System.out.println("Cannot find " + name);
44              return false;
45          } catch (final NoSuchMethodException e) {
46              return false;
47          } catch (final SecurityException e) {
48              e.printStackTrace();
49          }
50          return true;
51      }
52  
53      private static void processFileName(String name, final Properties p) {
54          name = name.replace(File.separatorChar, '.');
55          if (!name.endsWith(".class") || name.contains("$") // subclasses
56                  || name.endsWith("examples.Main.class") // the initial class, don't want to add that
57                  || !hasMainMethod(name)) {
58              return;
59          }
60          name = name.replace(".class", "");
61          final int lastSep = name.lastIndexOf('.');
62          final String alias = name.substring(lastSep + 1);
63          if (p.containsKey(alias)) {
64              System.out.printf("Duplicate alias: %-25s %s %s %n", alias, name, p.getProperty(alias));
65          } else {
66              p.setProperty(alias, name);
67          }
68      }
69  
70      private static void scanForClasses(final int rootLength, final File current, final Properties p) {
71          final File[] files = current.listFiles();
72          if (files != null) {
73              for (final File file : files) {
74                  if (file.isDirectory()) {
75                      scanForClasses(rootLength, file, p);
76                  } else {
77                      processFileName(file.getPath().substring(rootLength), p);
78                  }
79              }
80          }
81      }
82  
83      @Test
84      public void checkExamplesPropertiesIsComplete() throws Exception {
85          final Properties cp = scanClasses();
86          final Properties fp = new Properties();
87          try (final InputStream inputStream = this.getClass().getResourceAsStream("examples.properties")) {
88              fp.load(inputStream);
89          }
90          @SuppressWarnings("unchecked") // OK
91          final Enumeration<String> propertyNames = (Enumeration<String>) cp.propertyNames();
92          while (propertyNames.hasMoreElements()) {
93              final String c = propertyNames.nextElement();
94              final String fv = fp.getProperty(c);
95              final String cv = cp.getProperty(c);
96              if (fv == null) {
97                  System.out.printf("%-25s %s - missing from examples.properties%n", c, cv);
98              } else if (!fv.equals(cv)) {
99                  System.out.printf("%-25s %s - expected value %s %n", c, fv, cv);
100             }
101         }
102     }
103 
104     private Properties scanClasses() throws IOException {
105         final CodeSource codeSource = Main.class.getProtectionDomain().getCodeSource();
106         // ensure special characters are decoded OK by uing the charset
107         // Use canonical path to ensure consistency with Windows
108         final String sourceFile = new File(URLDecoder.decode(codeSource.getLocation().getFile(), "UTF-8")).getCanonicalPath();
109         final Properties p = new Properties();
110         if (sourceFile.endsWith(".jar")) {
111             try (final JarFile jf = new JarFile(sourceFile)) {
112                 final Enumeration<JarEntry> e = jf.entries();
113                 while (e.hasMoreElements()) {
114                     final JarEntry je = e.nextElement();
115                     final String name = je.getName();
116                     processFileName(name, p);
117                 }
118             }
119         } else {
120             final File examples = new File(sourceFile, "org/apache/commons/net/examples"); // must match top level examples package name
121             if (examples.exists()) {
122                 // need to add 1 to allow for path separator between root and file
123                 scanForClasses(sourceFile.length() + 1, examples, p);
124             } else {
125                 fail("Could not find examples classes: " + examples.getCanonicalPath());
126             }
127         }
128         return p;
129     }
130 }