| <html> | |
| <head> | |
| <meta http-equiv="Content-Type" content="text/html; charset=windows-1252"> | |
| <meta name="GENERATOR" content="Microsoft FrontPage 4.0"> | |
| <meta name="ProgId" content="FrontPage.Editor.Document"> | |
| <title>Design of a Tool for Checking API Usage in Eclipse-based Components</title> | |
| </head> | |
| <body> | |
| <h1>Design of a Tool for Checking API Usage in Eclipse-based Components</h1> | |
| <p>Jim des Rivieres<br> | |
| Last updated Jan 14, 2005</p> | |
| <p>This document contains the design for a tool for checking API usage in | |
| Eclipse-based components and products.</p> | |
| <h2>Components</h2> | |
| <p>For the purposes of this tool, a component is a set of plug-ins and plug-in | |
| fragments. Components must be disjoint, in that the plug-ins and fragments | |
| within one component must be distinct from those in other components. In other | |
| words, components partition the set of plug-ins and plug-in fragments into | |
| disjoint subsets. We also allow a form of library component containing no | |
| plug-ins or fragments; library components are used to describe class libraries | |
| such as J2SE that are not located inside any plug-in.</p> | |
| <p>The code for a component is the sum total of the code in the component's | |
| plug-ins and fragments (as described by the plug-in manifest). The code is in | |
| the form of Java types (predominantly classes and interfaces; J2SE 5.0 adds | |
| enumerations and annotation types). The types that are intended to be used by | |
| other components are called the component's API, and referred to as API types. A | |
| component can provide any number of API types, including none. Typically, only a | |
| subset of a component's types are part of its API. The rest are referred to as | |
| internal types. Non-public types are always considered internal.</p> | |
| <p>It's common to use Java packages to separate one component from another, and | |
| to separate API from internal within a component. Each component generally | |
| declares its code in packages different from those used by any other component. | |
| An API package is one that contains at least one API type. An internal package | |
| is one that contains no API types. The default assumption is that all public | |
| top-level types in an API package are API types.</p> | |
| <p>An API type declared in one component can be used by other components is | |
| various ways:</p> | |
| <ul> | |
| <li>Declare a field, variable, parameter, or return type where the type is an | |
| API type.</li> | |
| <li>Cast the value on an expression to an API type.</li> | |
| <li>Declare a class that implements an API interface.</li> | |
| <li>Declare an interface that extends an API interface.</li> | |
| <li>Declare a class that extends (subclasses) an API class.</li> | |
| <li>Creates an instance of an API class.</li> | |
| </ul> | |
| <p>It is common for an API type to be intended to be used only in certain ways. | |
| In some cases, Java modifiers can be used to rule out unintended uses (e.g., | |
| prevent subclassing by declaring the class "final"). But in many | |
| cases, the intended uses are spelled out in the type's specification (doc | |
| comment). The most common restrictions are:</p> | |
| <ul> | |
| <li>Clients may not instantiate this API class.</li> | |
| <li>Clients may not subclass this API class.</li> | |
| <li>Clients may not implement this API interface. It follows that the client | |
| may not extend the interface either.</li> | |
| </ul> | |
| <p>Types have members (fields, methods, types). For the present, we make the | |
| simplifying assumption that all public and protected members of an API type are | |
| intended to be used by other components.</p> | |
| <h2>Component description files</h2> | |
| <p>Each component will be described via a component description file. The file | |
| format is XML-based; the DTD follows (complete <a href="http://dev.eclipse.org/viewcvs/index.cgi/working/apitools/component.xsd?cvsroot=WebTools_Project">XML | |
| scheme</a>):</p> | |
| <pre><!ELEMENT component (plugin* package* component-depends)> | |
| <!ATTLIST component | |
| name CDATA #REQUIRED | |
| ></pre> | |
| The <component> element provides information about a component. | |
| Attributes: | |
| <ul> | |
| <li><b>name</b> - the component name; "Eclipse Platform Generic | |
| Workbench"; note that this name is used to refer to the component and | |
| distinguish it from other components (but otherwise has no official status | |
| in Eclipse ontology)</li> | |
| </ul> | |
| <p>Child elements or the <component> element describe the set of plug-ins | |
| and fragments making up the component, provide information about the Java | |
| packages and types in the component's code, and include a list of other | |
| components on which this component may depend.</p> | |
| <p>Each <plugin> element must identify a distinct plug-in or fragment. The | |
| list of plug-ins must be complete; that is, a component contains a plug-in (or | |
| fragment) if and only if a <plugin> element occurs as a child of the | |
| <component> element.</p> | |
| <pre><!ELEMENT plugin EMPTY> | |
| <!ATTLIST plugin | |
| id CDATA #REQUIRED | |
| fragment ("true" | "false") "false" | |
| ></pre> | |
| The <plugin> element identifies a plug-in or plug-in fragment that is part | |
| of the component. Attributes: | |
| <ul> | |
| <li><b>id</b> - the plug-in id or plug-in fragment id; e.g., "org.eclipse.core.resources"; | |
| note that in the case of a fragment, this is the id of fragment itself</li> | |
| <li><b>fragment</b> - whether this is a plug-in fragment as opposed to a | |
| plug-in (default: plug-in)</li> | |
| </ul> | |
| <p>Each <plugin> element must identify a distinct plug-in or fragment. The | |
| list of plug-ins must be complete; that is, a component contains a plug-in (or | |
| fragment) if and only if a <plugin> element occurs as a child of the | |
| <component> element.</p> | |
| <pre><!ELEMENT package (type*)> | |
| <!ATTLIST package | |
| name CDATA #REQUIRED | |
| exclusive ("true" | "false") "true" | |
| api ("true" | "false") "true" | |
| ></pre> | |
| The <package> element provides information about a package as used by the | |
| component. Attributes: | |
| <ul> | |
| <li><b>name</b> - Java package name; e.g., "javax.swing", "org.eclipse.ui"</li> | |
| <li><b>api</b> - whether top-level types in this package are API types by | |
| default (default: true). It's good practice for all public classes API | |
| top-level types in a package to be considered API. Specify "false" | |
| in order to explicitly list API types found in the package.</li> | |
| <li><b>exclusive</b> - whether this package is reserved for exclusive use by | |
| this component (default: true); specify "false" in (rare) cases | |
| where a multiple components declared types in the same package. Package | |
| sharing is only by mutual consent; all components involved must explicitly | |
| declare the package as exclusive="false" (even if it has no API | |
| types).</li> | |
| </ul> | |
| <p>Each <package> element must identify a distinct package relative to | |
| that component. If the unusual case where a package is shared with other | |
| components, the <package> element is understood to apply only to the types | |
| the component actually declares, and has no bearing on the types declared in the | |
| same package in any other component. The list of packages may be incomplete; if | |
| the component contains code in a package not mentioned in the list, the package | |
| is considered to be internal (equivalent to being explicitly described as | |
| <package name="..." api="false" />). The children of | |
| the <package> element provide information about specific types in the | |
| package.</p> | |
| <pre><!ELEMENT type EMPTY> | |
| <!ATTLIST type | |
| name CDATA #REQUIRED | |
| reference ("true" | "false") "true" | |
| implement ("true" | "false") "true" | |
| subclass ("true" | "false") "true" | |
| instantiate ("true" | "false") "true" | |
| ></pre> | |
| The <type> element provides information about a top-level type in a | |
| package. Attributes: | |
| <ul> | |
| <li><b>name</b> - simple name of a top-level Java class, interface, | |
| enumeration, or annotation type; e.g., "String", "IResource"</li> | |
| <li><b>reference</b> - whether other components are expected to reference this | |
| type by name (default: true); specify "false" to indicate that the | |
| type is internal</li> | |
| <li><b>implement</b> - whether other components are expected to declare a | |
| class that implements this interface (default: true); specify | |
| "false" for an interface that other components are not supposed to | |
| implement directly; this attribute is ignored for classes, enumerations, and | |
| annotation types, none of which can be meaningfully implemented</li> | |
| <li><b>subclass</b> - whether other components are expected to declare a class | |
| that directly subclasses this class (default: true); specify | |
| "false" for a class that other components are not supposed to | |
| subclass directly; this attribute is ignored for interfaces, enumerations, | |
| and annotation types, none of which can be meaningfully subclassed</li> | |
| <li><b>instantiate</b> - whether other components are expected to create | |
| instances of this class or annotation type (default: true); specify | |
| "false" for a type that other components are not supposed to | |
| instantiate directly; this attribute is ignored for interfaces and | |
| enumerations, neither of which can be meaningfully instantiated; this | |
| attribute is moot for classes that are declared final (or ones with no | |
| generally accessible constructors), since the Java compiler and JRE will | |
| block outside attempts to instantiate</li> | |
| </ul> | |
| <p>(Note: We could extend the schema in the future to allow <type> | |
| elements to provide analogous information about their members. We could also | |
| extend the <component> element to allow aspects other than code API to be | |
| described.)</p> | |
| <pre><!ELEMENT component-depends (component-ref*)> | |
| <!ATTLIST component-depends | |
| unrestricted ("true" | "false") "false" | |
| > | |
| <!ELEMENT component-ref EMPTY> | |
| <!ATTLIST component-ref | |
| name CDATA #REQUIRED | |
| ></pre> | |
| The <component-depends> element identifies other components on which this | |
| component is allowed to depend. Attributes: | |
| <ul> | |
| <li><b>unrestricted</b> - whether this component is allowed to depend on | |
| arbitrary other components, or just the ones explicitly named by the | |
| <component-ref> children</li> | |
| </ul> | |
| If a component specifies <component-depends | |
| unrestricted="true">, then it is allowed to depend on any component | |
| (and the children, if any, are ignored). Otherwise, the <component-ref> | |
| elements give the names of the component on which this component may depend. The | |
| <component-ref> element identifies a component by name. Attributes: | |
| <ul> | |
| <li><b>name</b> - the name of the referenced component; e.g., "Eclipse | |
| Platform Generic Workbench"</li> | |
| </ul> | |
| <h3>Example</h3> | |
| <p>A component description of one of the Eclipse Platform components:</p> | |
| <pre><component name="Eclipse Platform Core Resources"> | |
| <plugin id="org.eclipse.core.resources" /> | |
| <plugin id="org.eclipse.core.resources.win32" fragment="true" /> | |
| <plugin id="org.eclipse.core.resources.linux" fragment="true" /> | |
| <plugin id="org.eclipse.core.resources.hpux" fragment="true" /> | |
| <plugin id="org.eclipse.core.resources.macosx" fragment="true" /> | |
| <plugin id="org.eclipse.core.resources.qnx" fragment="true" /> | |
| <package name="org.eclipse.core.resources"> | |
| <type name="ICommand" implement="false" /> | |
| <type name="IContainer" implement="false" /> | |
| <type name="IFile" implement="false" /> | |
| <type name="IFileState" implement="false" /> | |
| <type name="IFolder" implement="false" /> | |
| <type name="IMarker" implement="false" /> | |
| <type name="IMarkerDelta" implement="false" /> | |
| <type name="IPathVariableChangeEvent" implement="false" /> | |
| <type name="IPathVariableManager" implement="false" /> | |
| <type name="IProject" implement="false" /> | |
| <type name="IProjectDescription" implement="false" /> | |
| <type name="IProjectNatureDescriptor" implement="false" /> | |
| <type name="IResource" implement="false" /> | |
| <type name="IResourceChangeEvent" implement="false" /> | |
| <type name="IResourceDelta" implement="false" /> | |
| <type name="IResourceProxy" implement="false" /> | |
| <type name="IResourceRuleFactory" implement="false" /> | |
| <type name="IResourceStatus" implement="false" /> | |
| <type name="ISaveContext" implement="false" /> | |
| <type name="ISavedState" implement="false" /> | |
| <type name="ISynchronizer" implement="false" /> | |
| <type name="IWorkspace" implement="false" /> | |
| <type name="IWorkspaceDescription" implement="false" /> | |
| <type name="IWorkspaceRoot" implement="false" /> | |
| <type name="ResourcesPlugin" subclass="false" instantiate="false" /> | |
| </package> | |
| <package name="org.eclipse.core.resources.mapping"> | |
| </package> | |
| <package name="org.eclipse.core.resources.refresh"> | |
| <type name="IRefreshResult" implement="false" /> | |
| </package> | |
| <package name="org.eclipse.core.resources.team"> | |
| <type name="IResourceTree" implement="false" /> | |
| </package> | |
| <component-depends> | |
| <component-ref name="Eclipse Platform Core Resources" /> | |
| <component-ref name="J2SE" /> | |
| </component-depends> | |
| </component></pre> | |
| <h2>How component descriptions are used</h2> | |
| <ul> | |
| <li><b>Component package/type map</b> - Given the code for a component and its | |
| component description, you can generate a fleshed-out list of the API types | |
| declared by the component. (It's considerably harder to properly describe | |
| the set of API members, since this involves building the supertype chain and | |
| performing inheritance. Since the supertype chain need not be confined to a | |
| single component, you also need the code for required plug-ins, etc.)</li> | |
| <li><b>Inter-component reference map</b> - Given the code for a component, its | |
| component description, and the component descriptions for all other | |
| components to which the given component may contain references, you can | |
| generate the list of external references from the component to types in some | |
| other component (possibly unknown, possibly ambiguous). In particular, you | |
| can do this without needing to consult the code for the other components (or | |
| even needing the code to be available).</li> | |
| <li><b>Fragile usage map</b> - You can go further and classify inter-component | |
| usage as fragile. This requires the code for a component, its component | |
| description, and the component descriptions for all other components to | |
| which the given component may contain references. In the limited case of | |
| shared packages between components, the code for these components may be | |
| needed to disambiguate external references to types in the shared package. A | |
| fragile external reference is any of: | |
| <ul> | |
| <li>A reference to an internal type in another (possibly unknown) | |
| component.</li> | |
| <li>A declaration of a subclass of a class C in another component where C | |
| is described as subclass="false".</li> | |
| <li>A declaration of a class implementing an interface I in another | |
| component where I is described as implement="false".</li> | |
| <li>An invocation of a constructor of a class C in another component where | |
| C is described as instantiate="false".</li> | |
| <li>A declaration of a type in a package P that another component | |
| describes as exclusive="true".</li> | |
| </ul> | |
| </li> | |
| </ul> | |
| <h2>Change history</h2> | |
| <ul> | |
| <li>Dec. 23, 2004 - Initial version</li> | |
| <li>Jan. 14, 2005 | |
| <ul> | |
| <li>Added <component-depends> element to allow each component to | |
| explicitly specify which other component it may depend on.</li> | |
| <li>Added clarification to "api" attribute of <package> | |
| element re: this is in line with good practice of making all top-types | |
| public types in an API package being considered API.</li> | |
| </ul> | |
| </li> | |
| </ul> | |
| </body> | |
| </html> |