Similar to the way we develop and ship plug-ins (bundles), we want to be able to develop and ship API information. This information can then be used by the integrated API tooling or by the build process to report API defects. The developers of a plug-in will be responsible for maintaining associated API information. An API description will be shipped with each bundle as metadata in a binary build allowing the tooling to understand the API rules of each bundle and report problems for improper use of API and for binary compatibility issues between releases.
Components and Profiles
API tooling models APIs using the following abstractions.
- API Component - Describes the API of a software component. In our case a software component is a plug-in or bundle but the concept could be extended to other constructs such as a Java project. An API component has the following attributes:
- Symbolic Name - For example, plug-in identifier.
- Descriptive Name - A human readable name such as "Platform UI".
- Version - Identifies the version of the component. For example, "3.3.0".
- Class Files - Original class files (jars, folders, etc), or class file stubs (compressed version with same information). One of the interesting features of API tooling is its ability to produce and process class file stubs (i.e. minimal class files with just member signatures and reference information). The comparison and reference analysis tools can process standard class files or class file stubs. The stubs allow “API components” to be produced that are smaller than the original code intended for distribution. The class file stubs can be used as libraries to compile against, but not run.
- Required Execution Environment - Defines the execution environment required by the component for building and running. Execution environments are defined by standard OSGi profiles such as J2SE-1.4, CDC-1.1/Foundation-1.1, etc.
- Required API Components - Defines all components required by a component in terms of symbolic names and compatible version ranges.
- API Description - Defines visibility of elements within the component as API, SPI, private, or private permissable. Defines restrictions of elements within the component as not to be subclassed, instantiated, implemented or referenced.
- API Profile - A collection of related API components that can be compared with another profile. For example, all of the API components of the plug-ins in an Eclipse SDK. An API profile has the following attributes:
- API Components - The components contained in the profile.
- Execution Environment - The execution environment required by the profile for building and running.
- Symbolic Name - For example, "eclipse.sdk"
- Descriptive Name - For example, "Eurpoa"
- Version - For example, "3.3.0"
API tooling provides the following engines, analyzers that operate on the API components.
- Reference Scanner - Scans a class file compiling all references a class file makes to other class files.
- Delta Engine - Compares two versions of the same class file building a hierarchical delta of the differences between to the two files. The delta can then be analyzed for binary compatibility and to determine what changes (if any) affect bundle version numbers and @since tags.
- Search Engine - Searches a scoped set of class files for specific kinds of references that match API usage and visiblity restrictions. For example, among other things the builder provided by API tooling uses the search engine to locate instantiations of classes that are not intended to be instantiated. However, the search engine allows for more general searches such as all references to methods that match a regular expression or are contained in a certain package.
- Javadoc Scanner - Scans Java source for special API restriction tags to annotate a component's API decription.
- Manifest Reader - Analyzes a bunlde's MANIFEST.MF to annotate a component's package level API description. For example, annotates exported packages as API or private with exceptions for specific components (friends).
API Javadoc Tags
Special Javadoc tags are used to annotate code with API information. The Javadoc tags are intended to replace existing 'component.xml' files (which have to be maintained manually). The tooling defines a fixed set of restrictions that can be assocaited with an extensible set of javadoc tags. The restrictions currently supported are:
- @noreference - Indicates that other bundles must not reference this member by name. I.e., the member is internal. This tag is intended to be used very rarely when a public class wants to restrict access to one of its members, but is not intended for general usage. When this tag is applied to a type (class, interface, enum or annotation) it acts as though it has been applied to all of the members of that type. If the tag is applied to a type it does not apply to final fields.
- @noimplement - Indicates that other bundles must not implement this interface. This tag is ignored for all types except for interfaces.
- @noextend - Indicates that other bundles must not extend the class or interface it appears on. This tag is ignored for all members that are not interfaces or classes.
- @noinstantiate - Indicates that other bundles must not create instances of this class. This tag is ignored for all other types that are not classes.
- @nooverride - Indicates that other bundles must not extend (re-implement with a call to the overridden parent) or re-implement (with no call to the overridden parent) this method. This tag is ignored for all other members except method declarations.