ClasspathContainerInitializer
through an extension point,
or explicitly assigned using a setter method.
The actual binding from the CPE_Container entry to
the target classpath entries is implemented in term of an extension point
to keep Java Core independent of VM install concerns:
<!ELEMENT classpathContainerInitializer
EMPTY>
<!ATTLIST classpathContainerInitializer
id
CDATA #REQUIRED
class
CDATA #REQUIRED
>
org.eclipse.jdt.core.ClasspathContainerInitializer
with a public 0-argument constructor.The initialize call passes in a project, this enables to resolve a classpath container in the context of a particular project. The initialize method should only be called once to resolve the class path entry (in case of failure, the container will not be considered as having been resolved).
It is possible to register an initializer per container ID. The full container path being passed along to the initializer. Its first segment is the container ID for which an initializer should be registered. The remaining segments can be used to provide additional hints for the container expansion. In case multiple resolvers are registered on the same container ID, the first registered one will be used).
JavaCore provides a method to perform explicit modifications of a container:
JavaCore#setClasspathContainer( IPath containerPath, IJavaProject[] affectedProjects, IClasspathContainer[] respectiveContainers, IProgressMonitor monitor)In particular, this method is to be used in the context of a classpath initializer so as to perform the actual initialization. Note that it allows to modify the value of a container for a set of projects at once. In reaction to invoking this method, the JavaModel will be refreshed and corresponding Java element changes will be notified.
A classpath container implements org.eclipse.jdt.core.IClasspathContainer
and can be queried
through a JavaCore API: JavaCore#getClasspathContainer(IPath containerPath, IJavaProject project)
.
There is no assumption that the returned container must answer the exact same containerPath
when requested IClasspathContainer#getPath
.
Indeed, the containerPath is just an indication for resolving it to an actual container object.
Classpath container values are persisted locally to the workspace, but
are not preserved from a session to another. It is thus highly recommended to register a
ClasspathContainerInitializer
for each referenced container
(through the extension point "org.eclipse.jdt.core.ClasspathContainerInitializer").
public interface IClasspathContainer { /** * Kind for a container mapping to an application library */ int K_APPLICATION = 1; /** * Kind for a container mapping to a system library */ int K_SYSTEM = 2; /** * Kind for a container mapping to a default system library, implicitly contributed by the runtime */ int K_DEFAULT_SYSTEM = 3; /** * Answers the set of classpath entries this container is mapping to. * The set of entries associated with a classpath container may contain any of the following: * - library entries (CPE_LIBRARY
) * - project entries (CPE_PROJECT
) * A classpath container can neither reference further classpath containers or classpath variables. */ IClasspathEntry[] getClasspathEntries(); /** * Answers a readable description of this container */ String getDescription(); /** * Answers the kind of this container. Can be either: * - K_APPLICATION if this container maps to an application library * - K_SYSTEM if this container maps to a system library * Typically, system containers should be placed first on a build path. */ int getKind(); /** * Answers the container path identifying this container. * A container path is formed by a first ID segment followed with extra segments. * which can provide additional hint for resolving. * This container ID is used in conjunction with the hints for resolving to this container. * The container ID is also used to identify a ClasspathContainerInitializer * registered on the extension point "org.eclipse.jdt.core.classpathContainerInitializer", which can * be invoked if needing to resolve the container before it is explicitely set. */ IPath getPath(); }
Issue: The Mac OS X JDK install is an interesting case. There the rt.jar is split into two binary JARs (classes.jar, ui.jar), but there is still a single src.jar. This cases needs to be handled by the source lookup. For example, when src.jar is attached to classes.jar then when looking up java.awt.Frame out of ui.jar, the source attachment of classes.jar needs to searched as well.
<classpath>
<classpathentry kind="src" path="/src"/>
<classpathentry kind="container" path="JDK/1.3"/>
<classpathentry kind="output" path="bin"/>
</classpath>
In the case where the user didn't override the VM install at the project level. Then the Java launching contributed container resolver (registered for container prefixes: "JDK") would resolve "JDK/1.3" using the default VM install, using "1.3" as an hint, and may expand it into the following:
<classpathentry kind="lib" path="d:/jdk/1.3.1/jre/lib/rt.jar" rootpath="d:/jdk1.3.1/lib/src.jar" sourcepath="/src"/>