Class Analyzer

All Implemented Interfaces:
Constants, Registry, Report, Reporter, Closeable, AutoCloseable, Iterable<String>
Direct Known Subclasses:
Builder

public class Analyzer extends Processor
  • Field Details

  • Constructor Details

  • Method Details

    • setTypeSpecificPlugins

      protected void setTypeSpecificPlugins(Set<Object> list)
      Overrides:
      setTypeSpecificPlugins in class Processor
    • getManifest

      public static Properties getManifest(File dirOrJar) throws Exception
      Specifically for Maven
      Throws:
      Exception
    • analyze

      public void analyze() throws Exception
      Calculates the data structures for generating a manifest.
      Throws:
      IOException
      Exception
    • getHostPackages

      public Optional<Set<Descriptors.PackageRef>> getHostPackages()
      Get the packages from the host if this is a fragment bundle
      Returns:
      the host packages or an empty set if not a fragment
    • getRequireBundlePackages

      public Optional<Set<Descriptors.PackageRef>> getRequireBundlePackages()
      Find the packages belonging to the required bundles
      Returns:
      the packages from the required bundles, with no Require-Bundle return an empty Optional
    • isNormalPackage

      private boolean isNormalPackage(Descriptors.PackageRef pRef)
    • toJar

      private Jar toJar(Map.Entry<String,Attrs> host)
    • getExportedByAnnotation

      private Parameters getExportedByAnnotation()
    • referencesByAnnotation

      private Set<Descriptors.PackageRef> referencesByAnnotation(Clazz clazz)
    • getPackageInfo

      public Clazz getPackageInfo(Descriptors.PackageRef packageRef)
    • doConditionalPackages

      private void doConditionalPackages() throws Exception
      Throws:
      Exception
    • learnPackage

      private void learnPackage(Jar jar, String prefix, Descriptors.PackageRef packageRef, Packages map) throws Exception
      Throws:
      Exception
    • getName

      protected String getName(Jar jar) throws Exception
      Throws:
      Exception
    • parsePackageinfo

      Attrs parsePackageinfo(Descriptors.PackageRef packageRef, Resource r) throws Exception
      Throws:
      Exception
    • parsePackageInfoClass

      private Attrs parsePackageInfoClass(Resource r) throws Exception
      Throws:
      Exception
    • removeDynamicImports

      void removeDynamicImports(Packages referredAndExported)
      Discussed with BJ and decided to kill the .
      Parameters:
      referredAndExported -
    • getExtra

      protected Jar getExtra() throws Exception
      Throws:
      Exception
    • doPlugins

      void doPlugins()
    • isResourceOnly

      boolean isResourceOnly()
      Returns:
      true if the -resourceonly instruction is set, false otherwise
    • calcManifest

      public Manifest calcManifest() throws Exception
      One of the main workhorses of this class. This will analyze the current setup and calculate a new manifest according to this setup.
      Throws:
      IOException
      Exception
    • findClasspathEntry

      public Jar findClasspathEntry(String bsn, String r)
      Find a class path entry based on bsn and versionrange
      Parameters:
      bsn - The bundle symbolic name
      r - The version range specified like in OSGi (version => [version,infinite))
      Returns:
      first JAR that matches bsn &r or null if not found
    • doEEProfiles

      private String doEEProfiles(Clazz.JAVA highest) throws IOException
      Added for 1.8 profiles. A 1.8 profile is a set of packages so the VM can be delivered in smaller versions. This method will look at the Constants.EEPROFILE option. If it is set, it can be "auto" or it can contain a list of profiles specified as name="a,b,c" values. If we find a package outside the profiles, no profile is set. Otherwise the highest found profile is added. This only works for java packages.
      Throws:
      IOException
    • doHeader

      private void doHeader(Attributes main, String header)
    • doNamesection

      private void doNamesection(Jar dot, Manifest manifest)
      Parse the namesection as instructions and then match them against the current set of resources For example:
        -namesection: *;baz=true,
       abc/def/bar/X.class=3
       
      The raw value of Constants.NAMESECTION is used but the values of the attributes are replaced where @ is set to the resource name. This allows macro to operate on the resource
    • doNameSection

      void doNameSection(Manifest manifest, String header)
      This method is called when the header starts with a @, signifying a name section header. The name part is defined by replacing all the @ signs to a /, removing the first and the last, and using the last part as header name:
        @org@osgi@service@event@Implementation-Title
       
      This will be the header Implementation-Title in the org/osgi/service/event named section.
      Parameters:
      manifest -
      header -
    • getBsn

      public String getBsn()
      Clear the key part of a header. I.e. remove everything from the first ';'
    • _bsn

      public String _bsn(String[] args)
    • calculateExportsFromContents

      public String calculateExportsFromContents(Jar bundle)
      Calculate an export header solely based on the contents of a JAR file
      Parameters:
      bundle - The jar file to analyze
    • getContained

      public Packages getContained()
    • getExports

      public Packages getExports()
    • getImports

      public Packages getImports()
    • getPrivates

      public Set<Descriptors.PackageRef> getPrivates()
    • getJar

      public Jar getJar()
    • getReferred

      public Packages getReferred()
    • getUnreachable

      public Set<Descriptors.PackageRef> getUnreachable()
      Return the set of unreachable code depending on exports and the bundle activator.
    • getUses

    • getAPIUses

    • getClasspathExports

      public Packages getClasspathExports()
    • getBndVersion

      public String getBndVersion()
      Get the version for this bnd
      Returns:
      version or unknown.
    • getBndLastModified

      public long getBndLastModified()
    • getBndInfo

      public String getBndInfo(String key, String defaultValue)
    • mergeManifest

      public void mergeManifest(Manifest manifest) throws IOException
      Merge the existing manifest with the instructions but do not override existing properties.
      Parameters:
      manifest - The manifest to merge with
      Throws:
      IOException
    • setBase

      public void setBase(File file)
      Overrides:
      setBase in class Processor
    • setClasspath

      public void setClasspath(Collection<?> classpath) throws IOException
      Set the classpath for this analyzer by file.
      Parameters:
      classpath -
      Throws:
      IOException
    • setClasspath

      public void setClasspath(File[] classpath) throws IOException
      Throws:
      IOException
    • setClasspath

      public void setClasspath(Jar[] classpath)
    • setClasspath

      public void setClasspath(String[] classpath)
    • setJar

      public Jar setJar(File file) throws IOException
      Set the JAR file we are going to work in. This will read the JAR in memory.
      Parameters:
      file -
      Throws:
      IOException
    • setJar

      public Jar setJar(Jar jar)
      Set the JAR directly we are going to work on.
      Parameters:
      jar -
    • begin

      protected void begin()
      Overrides:
      begin in class Processor
    • getJarFromName

      public Jar getJarFromName(String name, String from)
      Try to get a Jar from a file name/path or a url, or in last resort from the classpath name part of their files.
      Overrides:
      getJarFromName in class Processor
      Parameters:
      name - URL or filename relative to the base
      from - Message identifying the caller for errors
      Returns:
      null or a Jar with the contents for the name
    • getJarsFromName

      public List<Jar> getJarsFromName(String name, String from)
    • merge

      private void merge(Manifest result, Manifest old)
    • verifyManifestHeadersCase

      void verifyManifestHeadersCase(Properties properties)
      Bnd is case sensitive for the instructions so we better check people are not using an invalid case. We do allow this to set headers that should not be processed by us but should be used by the framework.
      Parameters:
      properties - Properties to verify.
    • doExportsToImports

      Packages doExportsToImports(Packages exports)
      We will add all exports to the imports unless there is a -noimport directive specified on an export. This directive is skipped for the manifest. We also remove any version parameter so that augmentImports can do the version policy. The following method is really tricky and evolved over time. Coming from the original background of OSGi, it was a weird idea for me to have a public package that should not be substitutable. I was so much convinced that this was the right rule that I rücksichtlos imported them all. Alas, the real world was more subtle than that. It turns out that it is not a good idea to always import. First, there must be a need to import, i.e. there must be a contained package that refers to the exported package for it to make use importing that package. Second, if an exported package refers to an internal package than it should not be imported. Additionally, it is necessary to treat the exports in groups. If an exported package refers to another exported packages than it must be in the same group. A framework can only substitute exports for imports for the whole of such a group. WHY????? Not clear anymore ...
    • referred

      public boolean referred(Descriptors.PackageRef packageName)
    • getManifestInfoFromClasspath

      private void getManifestInfoFromClasspath(Jar jar, Packages classpathExports, Contracts contracts)
    • fixupOldStyleVersions

      private void fixupOldStyleVersions(Attrs attrs)
    • augmentImports

      void augmentImports(Packages imports, Packages exports) throws Exception
      Find some more information about imports in manifest and other places. It is assumed that the augmentsExports has already copied external attrs from the classpathExports.
      Throws:
      Exception
    • divideRegularAndDynamicImports

      Pair<Packages,Parameters> divideRegularAndDynamicImports()
    • applyVersionPolicy

      String applyVersionPolicy(String exportVersion, String importRange, boolean provider)
    • findProvidedPackages

      Set<Descriptors.PackageRef> findProvidedPackages() throws Exception
      Find the packages we depend on, where we implement an interface that is a Provider Type. These packages, when we import them, must use the provider policy.
      Throws:
      Exception
    • isProvider

      private boolean isProvider(Descriptors.TypeRef t)
    • augmentExports

      void augmentExports(Packages exports) throws IOException
      Provide any macro substitutions and versions for exported packages.
      Throws:
      IOException
    • fixupAttributes

      void fixupAttributes(Descriptors.PackageRef packageRef, Attrs attributes) throws IOException
      Fixup Attributes Execute any macros on an export and
      Throws:
      IOException
    • removeAttributes

      void removeAttributes(Attrs attributes)
      Remove the attributes mentioned in the REMOVE_ATTRIBUTE_DIRECTIVE. You can add a remove-attribute: directive with a regular expression for attributes that need to be removed. We also remove all attributes that have a value of !. This allows you to use macros with ${if} to remove values.
    • calculateVersionRange

      String calculateVersionRange(String version, boolean impl)
      Calculate a version from a version policy.
      Parameters:
      version - The actual exported version
      impl - true for implementations and false for clients
    • doUses

      void doUses(Packages exports, Map<Descriptors.PackageRef,List<Descriptors.PackageRef>> uses, Packages imports)
      Add the uses clauses. This method iterates over the exports and cal
      Parameters:
      exports -
      uses -
      Throws:
      MojoExecutionException
    • doUses

      protected void doUses(Descriptors.PackageRef packageRef, Packages exports, Map<Descriptors.PackageRef,List<Descriptors.PackageRef>> uses, Packages imports)
      Parameters:
      packageRef -
      exports -
      uses -
      imports -
    • removeTransitive

      void removeTransitive(Descriptors.PackageRef name, Set<Descriptors.PackageRef> unreachable)
      Transitively remove all elemens from unreachable through the uses link.
      Parameters:
      name -
      unreachable -
    • verifyAttribute

      private void verifyAttribute(String path, String where, String key, String value) throws IOException
      Throws:
      IOException
    • close

      public void close() throws IOException
      Specified by:
      close in interface AutoCloseable
      Specified by:
      close in interface Closeable
      Overrides:
      close in class Processor
      Throws:
      IOException
    • _findpath

      public String _findpath(String[] args)
      Findpath looks through the contents of the JAR and finds paths that end with the given regular expression ${findpath (; reg-expr (; replacement)? )? }
      Parameters:
      args -
    • _findname

      public String _findname(String[] args)
    • findPath

      String findPath(String name, String[] args, boolean fullPathName)
    • putAll

      public void putAll(Map<String,String> additional, boolean force)
    • getClasspath

      public List<Jar> getClasspath()
    • addClasspath

      public void addClasspath(Jar jar)
    • addClasspath

      public void addClasspath(Collection<?> jars) throws IOException
      Throws:
      IOException
    • addClasspath

      public void addClasspath(File cp) throws IOException
      Throws:
      IOException
    • clear

      public void clear()
      Overrides:
      clear in class Processor
    • forceRefresh

      public void forceRefresh()
      Overrides:
      forceRefresh in class Processor
    • getTarget

      public Jar getTarget()
    • analyzeBundleClasspath

      private void analyzeBundleClasspath() throws Exception
      Throws:
      Exception
    • analyzeJar

      private boolean analyzeJar(Jar jar, String prefix, boolean okToIncludeDirs, String bcpEntry) throws Exception
      We traverse through all the classes that we can find and calculate the contained and referred set and uses. This method ignores the Bundle classpath.
      Throws:
      Exception
    • cleanupVersion

      public static String cleanupVersion(String version)
    • isInteger

      private static boolean isInteger(String minor)
      TRhe cleanup version got confused when people used numeric dates like 201209091230120 as qualifiers. These are too large for Integers. This method checks if the all digit string fits in an integer.
        maxint =
       2,147,483,647 = 10 digits
       
      Returns:
      if this fits in an integer
    • removeLeadingZeroes

      private static String removeLeadingZeroes(String group)
    • cleanupModifier

      static void cleanupModifier(StringBuilder result, String modifier)
    • getVersionPolicy

      public String getVersionPolicy(boolean implemented)
    • _classes

      public String _classes(String... args) throws Exception
      Throws:
      Exception
    • getClasses

      public Collection<Clazz> getClasses(String... args) throws Exception
      Throws:
      Exception
    • _packages

      public String _packages(String... args) throws Exception
      Throws:
      Exception
    • getPackages

      public Collection<Descriptors.PackageRef> getPackages(Packages scope, String... args) throws Exception
      Throws:
      Exception
    • _exporters

      public String _exporters(String[] args) throws Exception
      Get the exporter of a package ...
      Throws:
      Exception
    • getClassspace

      public Map<Descriptors.TypeRef,Clazz> getClassspace()
    • _packageattribute

      public String _packageattribute(String[] args)
      Return an attribute of a package
    • findResource

      public Resource findResource(String path)
      Locate a resource on the class path.
      Parameters:
      path - Path of the reosurce
      Returns:
      A resource or null
    • findResources

      public Stream<Resource> findResources(Predicate<String> matches)
    • findClass

      public Clazz findClass(Descriptors.TypeRef typeRef) throws Exception
      Find a clazz on the class path. This class has been parsed.
      Throws:
      Exception
    • getVersion

      public String getVersion()
      Answer the bundle version.
    • isNoBundle

      public boolean isNoBundle()
    • referTo

      public void referTo(Descriptors.TypeRef ref)
    • nonClassReferTo

      public void nonClassReferTo(Descriptors.TypeRef ref)
    • referToByBinaryName

      public void referToByBinaryName(String binaryClassName)
    • doRequireBnd

      protected void doRequireBnd()
      Ensure that we are running on the correct bnd.
    • _md5

      public String _md5(String[] args) throws Exception
      Throws:
      Exception
    • _sha1

      public String _sha1(String[] args) throws Exception
      Throws:
      Exception
    • getDescriptor

      public Descriptors.Descriptor getDescriptor(String descriptor)
    • getTypeRef

      public Descriptors.TypeRef getTypeRef(String binaryClassName)
    • getPackageRef

      public Descriptors.PackageRef getPackageRef(String binaryName)
    • getTypeRefFromFQN

      public Descriptors.TypeRef getTypeRefFromFQN(String fqn)
    • getTypeRefFromPath

      public Descriptors.TypeRef getTypeRefFromPath(String path)
    • getClassSignature

      public ClassSignature getClassSignature(String signature)
    • getMethodSignature

      public MethodSignature getMethodSignature(String signature)
    • getFieldSignature

      public FieldSignature getFieldSignature(String signature)
    • isImported

      public boolean isImported(Descriptors.PackageRef packageRef)
    • filter

      Packages filter(Instructions instructions, Packages source, Set<Instruction> nomatch)
      Merge the attributes of two maps, where the first map can contain wildcarded names. The idea is that the first map contains instructions (for example *) with a set of attributes. These patterns are matched against the found packages in actual. If they match, the result is set with the merged set of attributes. It is expected that the instructions are ordered so that the instructor can define which pattern matches first. Attributes in the instructions override any attributes from the actual.
      A pattern is a modified regexp so it looks like globbing. The * becomes a .* just like the ? becomes a .?. '.' are replaced with \\. Additionally, if the pattern starts with an exclamation mark, it will remove that matches for that pattern (- the !) from the working set. So the following patterns should work:
      • com.foo.bar
      • com.foo.*
      • com.foo.???
      • com.*.[^b][^a][^r]
      • !com.foo.* (throws away any match for com.foo.*)
      Enough rope to hang the average developer I would say.
      Parameters:
      instructions - the instructions with patterns.
      source - the actual found packages, contains no duplicates
      Returns:
      Only the packages that were filtered by the given instructions
    • setDiagnostics

      public void setDiagnostics(boolean b)
    • getLowestEE

      public Clazz.JAVA getLowestEE()
    • getHighestEE

      public Clazz.JAVA getHighestEE()
    • _ee

      public String _ee(String[] args)
    • getOutputFile

      public File getOutputFile(String output)
      Calculate the output file for the given target. The strategy is:
       parameter given if not null and not directory if directory, this will be
       the output directory based on bsn-version.jar name of the source file if
       exists Untitled-[n]
       
      Parameters:
      output - may be null, otherwise a file path relative to base
    • save

      public boolean save(File output, boolean force) throws Exception
      Utility function to carefully save the file. Will create a backup if the source file has the same path as the output. It will also only save if the file was modified or the force flag is true
      Parameters:
      output - the output file, if null getOutputFile(String) is used.
      force - if it needs to be overwritten
      Throws:
      Exception
    • setDefaults

      public void setDefaults(String bsn, Version version)
      Set default import and export instructions if none are set
    • cleanupUses

      Remove the own references and optional java references from the uses lib
      Parameters:
      apiUses -
      removeJava -
    • getClassspace

      public Set<Clazz> getClassspace(Descriptors.PackageRef source)
      Return the classes for a given source package.
      Parameters:
      source - the source package
      Returns:
      a set of classes for the requested package.
    • getXRef

      public Map<Clazz.Def,List<Descriptors.TypeRef>> getXRef(Descriptors.PackageRef source, Collection<Descriptors.PackageRef> dest, int sourceModifiers) throws Exception
      Create a cross reference from package source, to packages in dest
      Parameters:
      source -
      dest -
      sourceModifiers -
      Throws:
      Exception
    • _exports

      public String _exports(String[] args)
    • _imports

      public String _imports(String[] args)
    • filter

      private <T> Collection<T> filter(Collection<T> list, String[] args)
    • report

      public void report(Map<String,Object> table) throws Exception
      Report the details of this analyzer
      Overrides:
      report in class Processor
      Throws:
      Exception
    • getEEs

      public SortedSet<Clazz.JAVA> getEEs()
      Return the EEs
    • validResourcePath

      public String validResourcePath(String name, String reportIfWrong)
      Parameters:
      name -
    • check

      public boolean check(Analyzer.Check key)
      Check if we have an a check option
    • getSourceFileFor

      public String getSourceFileFor(Descriptors.TypeRef type) throws Exception
      Find the source file for this type
      Parameters:
      type -
      Throws:
      Exception
    • getSourceFileFor

      public String getSourceFileFor(Descriptors.TypeRef type, Collection<File> sourcePath) throws Exception
      Throws:
      Exception
    • setTypeLocation

      public void setTypeLocation(Reporter.SetLocation location, Descriptors.TypeRef type) throws Exception
      Set location information for a type.
      Throws:
      Exception
    • assignable

      public boolean assignable(String annoService, String inferredService)
    • assignable

      public boolean assignable(String annoService, String inferredService, boolean unknownResult)
    • assignable

      public boolean assignable(Clazz annoServiceClazz, Clazz inferredServiceClazz)
    • assignable

      public boolean assignable(Clazz annoServiceClazz, Clazz inferredServiceClazz, boolean unknownResult)
    • getBundleClassPathEntry

      public Optional<String> getBundleClassPathEntry(Clazz clazz)
    • assignable0

      private Boolean assignable0(Clazz annoServiceClazz, Clazz inferredServiceClazz) throws Exception
      Throws:
      Exception
    • addDefinedContracts

      private void addDefinedContracts()