1   package com.atlassian.plugins.codegen.annotations.asm;
2   
3   import java.io.File;
4   import java.io.IOException;
5   import java.io.InputStream;
6   import java.net.JarURLConnection;
7   import java.net.URL;
8   import java.util.ArrayList;
9   import java.util.Enumeration;
10  import java.util.List;
11  import java.util.jar.JarEntry;
12  import java.util.jar.JarFile;
13  
14  import org.apache.commons.io.FileUtils;
15  import org.apache.commons.io.IOUtils;
16  import org.objectweb.asm.ClassReader;
17  import org.objectweb.asm.ClassVisitor;
18  
19  /**
20   * @since 3.6
21   */
22  public abstract class AbstractAnnotationParser
23  {
24  
25      public void parse(String basePackage, ClassVisitor classVisitor) throws Exception
26      {
27          ClassLoader classLoader = Thread.currentThread()
28                  .getContextClassLoader();
29  
30          String path = basePackage.replace('.', '/');
31  
32          Enumeration<URL> resources = classLoader.getResources(path);
33          List<File> dirs = new ArrayList<File>();
34          while (resources.hasMoreElements())
35          {
36              URL resource = resources.nextElement();
37              processResource(resource, basePackage, classVisitor);
38          }
39      }
40  
41      protected void processResource(URL resource, String packageName, ClassVisitor classVisitor) throws IOException
42      {
43          if (resource.getProtocol()
44                  .equals("file"))
45          {
46              processFileDirectory(new File(resource.getFile()), packageName, classVisitor);
47          } else if (resource.getProtocol()
48                  .equals("jar"))
49          {
50              JarURLConnection conn = (JarURLConnection) resource.openConnection();
51              processJarDirectory(conn.getJarFile(), packageName, classVisitor);
52          }
53      }
54  
55      protected void processJarDirectory(JarFile jarFile, String packageName, ClassVisitor classVisitor) throws IOException
56      {
57          Enumeration<JarEntry> entries = jarFile.entries();
58          String basePath = packageName.replace('.', '/');
59          while (entries.hasMoreElements())
60          {
61              JarEntry entry = entries.nextElement();
62              String name = entry.getName();
63              if (name.startsWith(basePath) && !entry.isDirectory() && name.endsWith(".class"))
64              {
65                  InputStream is = jarFile.getInputStream(entry);
66                  try
67                  {
68                      processClassFile(is, classVisitor);
69                  } finally
70                  {
71                      IOUtils.closeQuietly(is);
72                  }
73              }
74          }
75      }
76  
77      protected void processFileDirectory(File directory, String packageName, ClassVisitor classVisitor) throws IOException
78      {
79          if (!directory.exists())
80          {
81              return;
82          }
83          File[] files = directory.listFiles();
84          for (File file : files)
85          {
86              if (file.isDirectory())
87              {
88                  assert !file.getName()
89                          .contains(".");
90                  processFileDirectory(file, packageName + "." + file.getName(), classVisitor);
91              } else if (file.getName()
92                      .endsWith(".class"))
93              {
94                  InputStream is = FileUtils.openInputStream(file);
95  
96                  try
97                  {
98                      processClassFile(is, classVisitor);
99                  } finally
100                 {
101                     IOUtils.closeQuietly(is);
102                 }
103 
104             }
105         }
106     }
107 
108     protected void processClassFile(InputStream is, ClassVisitor classVisitor) throws IOException
109     {
110         ClassReader classReader = new ClassReader(is);
111         classReader.accept(classVisitor, ClassReader.SKIP_CODE | ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES);
112     }
113 
114     protected static String normalize(String name)
115     {
116         if (name == null)
117         {
118             return null;
119         }
120 
121         if (name.startsWith("L") && name.endsWith(";"))
122         {
123             name = name.substring(1, name.length() - 1);
124         }
125 
126         if (name.endsWith(".class"))
127         {
128             name = name.substring(0, name.length() - ".class".length());
129         }
130 
131         return name.replace('/', '.');
132     }
133 }