View Javadoc

1   package com.atlassian.plugin.osgi.util;
2   
3   import com.atlassian.plugin.osgi.hostcomponents.HostComponentRegistration;
4   import com.atlassian.plugin.osgi.container.PackageScannerConfiguration;
5   import com.atlassian.plugin.util.ClassLoaderUtils;
6   import com.atlassian.plugin.util.ClassUtils;
7   
8   import java.util.*;
9   import java.util.jar.Manifest;
10  import java.io.*;
11  import java.net.MalformedURLException;
12  
13  import org.twdata.pkgscanner.ExportPackage;
14  import org.twdata.pkgscanner.PackageScanner;
15  import static org.twdata.pkgscanner.PackageScanner.jars;
16  import static org.twdata.pkgscanner.PackageScanner.include;
17  import static org.twdata.pkgscanner.PackageScanner.exclude;
18  import static org.twdata.pkgscanner.PackageScanner.packages;
19  import org.osgi.framework.Version;
20  import org.osgi.framework.Constants;
21  import org.apache.commons.logging.Log;
22  import org.apache.commons.logging.LogFactory;
23  import org.apache.commons.io.IOUtils;
24  import aQute.lib.osgi.Analyzer;
25  import aQute.lib.osgi.Jar;
26  
27  import javax.servlet.ServletContext;
28  
29  /**
30   * Utilities to help create OSGi headers
31   */
32  public class OsgiHeaderUtil
33  {
34      static final String JDK_PACKAGES_PATH = "jdk-packages.txt";
35      static final String JDK6_PACKAGES_PATH = "jdk6-packages.txt";
36      static Log log = LogFactory.getLog(OsgiHeaderUtil.class);
37  
38      /**
39       * Finds all referred packages for host component registrations by scanning their declared interfaces' bytecode.
40       *
41       * @param registrations A list of host component registrations
42       * @return The referred packages in a format compatible with an OSGi header
43       * @throws IOException If there are any problems scanning bytecode
44       */
45      public static String findReferredPackages(List<HostComponentRegistration> registrations) throws IOException
46      {
47          StringBuffer sb = new StringBuffer();
48          Set<String> referredPackages = new HashSet<String>();
49          Set<String> referredClasses = new HashSet<String>();
50          if (registrations == null)
51          {
52              sb.append(",");
53          }
54          else
55          {
56              for (HostComponentRegistration reg : registrations)
57              {
58                  Set<Class> classesToScan = new HashSet<Class>();
59  
60                  // Make sure we scan all extended interfaces as well
61                  for (Class inf : reg.getMainInterfaceClasses())
62                      ClassUtils.findAllTypes(inf, classesToScan);
63  
64                  for (Class inf : classesToScan)
65                  {
66                      String clsName = inf.getName().replace('.','/')+".class";
67                      crawlReferenceTree(clsName, referredClasses, referredPackages, 1);
68                  }
69              }
70              for (String pkg : referredPackages)
71              {
72                  sb.append(pkg).append(",");
73              }
74          }
75          return sb.toString();
76      }
77  
78      /**
79       * This will crawl the class interfaces to the desired level.
80       *
81       * @param className name of the class.
82       * @param scannedClasses set of classes that have been scanned.
83       * @param packageImports set of imports that have been found.
84       * @param level depth of scan (recursion).
85       * @throws IOException error loading a class.
86       */
87      static void crawlReferenceTree(String className, Set<String> scannedClasses, Set<String> packageImports, int level) throws IOException
88      {
89          if (level <= 0)
90          {
91              return;
92          }
93  
94          if (className.startsWith("java/"))
95              return;
96  
97          if (scannedClasses.contains(className))
98              return;
99          else
100             scannedClasses.add(className);
101 
102         if (log.isDebugEnabled())
103             log.debug("Crawling "+className);
104 
105         InputStream in = ClassLoaderUtils.getResourceAsStream(className, OsgiHeaderUtil.class);
106         if (in == null)
107         {
108             log.error("Cannot find interface "+className);
109             return;
110         }
111         Clazz clz = new Clazz(className, in);
112         packageImports.addAll(clz.getReferred().keySet());
113 
114         Set<String> referredClasses = clz.getReferredClasses();
115         for (String ref : referredClasses)
116             crawlReferenceTree(ref, scannedClasses, packageImports, level-1);
117 
118     }
119 }