| <!doctype html public "-//w3c//dtd html 4.0 transitional//en"> |
| <html> |
| <head> |
| <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> |
| <meta http-equiv="Content-Language" content="en-us"> |
| <meta name="GENERATOR" content="Microsoft FrontPage 4.0"> |
| <meta name="ProgId" content="FrontPage.Editor.Document"> |
| <title>Class Path Container Enhancement</title> |
| </head> |
| <body> |
| |
| <h1>Class Path Container Enhancement</h1> |
| <span style="FONT-SIZE: 10pt">Last Modified April 23, 2002</span> |
| |
| |
| <h2> |
| Background</h2> |
| JDT supports to switch the JDK that is used for building. It is currently |
| implemented as follows: |
| <ul> |
| <li> |
| org.eclipse.jdt.launching maintains the following JDK/VM information in |
| its plugin metadata:</li> |
| |
| <ul> |
| <li> |
| a set of <i>VM install types</i>: a description of a VM install. It knows |
| how to find the location of the binary JAR and the source JARs.</li> |
| |
| <li> |
| <i>VM installs: </i>the location/home of a VM install on the file system. |
| A VM install has an internal ID that is not visible to the user.</li> |
| |
| <li> |
| one of the VM installs is marked as the <i>default VM install</i>.</li> |
| </ul> |
| |
| <li> |
| org.eclipse.jdt.launching defines a JRE_LIB, JRE_SRC, JRE_SRCROOT variables |
| that binds to the default VM install:</li> |
| |
| <ul> |
| <li> |
| JRE_LIB: the binary JAR (e.g. rt.jar)</li> |
| |
| <li> |
| JRE_SRC: the source JAR/zip (e.g. src.jar)</li> |
| |
| <li> |
| JRE_SRCROOT: the prefix in the source JAR (e.g. "src")</li> |
| </ul> |
| |
| <li> |
| The Java project creation wizard adds a JRE_LIB classpath variable on a |
| project's build class path.</li> |
| |
| <li> |
| org.eclipse.jdt.debug.ui contributes a preference page to define new VM |
| installs and to set the default VM install. When the default VM install |
| changes, then the bindings of the JRE_* variables are changed accordingly.</li> |
| |
| <li> |
| org.eclipse.jdt.ui contributes a class path variable preference page. It |
| "knows" that the JRE_* variables are reserved and doesn't allow the user |
| to edit them.</li> |
| |
| <li> |
| The packages view shows the resolved JRE_LIB contents as a referenced library.</li> |
| </ul> |
| Characteristics of the current implementation: |
| <ul> |
| <li> |
| Class path stability: changing the default JRE/VM install doesn't affect |
| the build class path since the JRE_LIB variable is not affected by this |
| change. In other words, when a user changes the JRE for building then the |
| .classpath file is not affected.</li> |
| |
| <li> |
| JDK switching at the workspace level for all projects is straightforward |
| by the user, only the default VM install needs to be changed and all projects |
| in the workspace switch to use this VM install.</li> |
| |
| <li> |
| Since class path variables can only bind to a single JAR, the JRE_LIB variable |
| can only bind to a single JAR (for the standard SUN JRE this is rt.jar).</li> |
| |
| <li> |
| There is some magic involved with regard to the handling of JRE_* variables |
| that is not obvious to the user:</li> |
| |
| <ul> |
| <li> |
| on the build class path the user sees JRE_LIB but when defining a launch |
| configuration then the user sees VM Installs. The user has to know that |
| JRE_LIB is indirectly bound to the VM install via the JRE installed preference |
| settings.</li> |
| |
| <li> |
| The user also has to understand that the reserved variables cannot be edited |
| like the other class path variables, etc.</li> |
| </ul> |
| |
| <li> |
| Build class path ordering - users can control the order of the build class |
| path in a simple way. For example, to do JCL development, to do so users |
| can put their source folders in front of the JRE_LIB class path entry.</li> |
| |
| <li> |
| Java Core is not affected by the JDK switching support and is independent |
| of launching concerns.</li> |
| </ul> |
| |
| <h2> |
| Motivation for enhancing the current implementation</h2> |
| |
| <h3> |
| New Requirements</h3> |
| There are new requirements with regard to the handling of the JRE/JDK on |
| the build class path that need to be addressed by 2.0: |
| <ul> |
| <li> |
| Multiple JARs per JDK</li> |
| |
| <br>The JRE_LIB class path variable can only bind to a single JAR file |
| typically the rt.jar. However, there are JDK installs that have split the |
| rt.jar into multiple JARs. For example, the JDK on the MacOS X has split |
| the rt.jar into: classes.jar and ui.jar (contains AWT and Swing). |
| <br> |
| <li> |
| Workspaces with a different JDK per project</li> |
| |
| <br>WSDD needs support for having a workspace where different projects |
| build against different JDKs. The JRE_LIB variable is global and there |
| is no infrastructure and UI support to have different JDKs for different |
| projects. WSDD defined their own build description mechanism that bypasses |
| the JRE_LIB support. This results in a problematic user experience when |
| switching from WSAD or vanilla Eclipse Java development to WSDD.</ul> |
| |
| <h3> |
| Existing characteristics to be preserved in the new implementation</h3> |
| |
| <ul> |
| <li> |
| Class path stability, it has to be possible to switch a JDK locally in |
| a workspace without affecting the .classpath file.</li> |
| |
| <li> |
| Easy JDK switching at the workspace level, i.e., a single setting can be |
| changed to change the build class path of all projects.</li> |
| |
| <li> |
| Java Core is independent of the VM install infrastructure</li> |
| </ul> |
| |
| <h2> |
| Proposal</h2> |
| The proposal affects core, launching, java debug UI, and the Java UI components. |
| <h3> |
| JavaCore</h3> |
| JavaCore provides a new type of classpath entry "CPE_CONTAINER", |
| which is just a named reference to a set of other classpath entries. |
| A container entry refers to a container path, which can be resolved by |
| a <code>ClasspathContainerInitializer</code> 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: |
| <p><tt> <!ELEMENT classpathContainerInitializer |
| EMPTY></tt> |
| <br><tt> <!ATTLIST classpathContainerInitializer</tt> |
| <br><tt> id |
| CDATA #REQUIRED</tt> |
| <br><tt> class |
| CDATA #REQUIRED</tt> |
| <br><tt> ></tt></p> |
| <ul> |
| <li><b>id</b> - the container unique name for which this resolver will be activated.</li> |
| <li><b>class</b> - the class that implements this container initializer. |
| The class must implement a public subclass of <code>org.eclipse.jdt.core.ClasspathContainerInitializer</code> |
| with a public 0-argument constructor.</li> |
| </ul> |
| <tt> abstract class ClasspathContainerResolver |
| {</tt> |
| <br><tt> |
| void initialize(IPath containerPath, IJavaProject project) throws CoreException;</tt> |
| <br> } |
| <p>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). |
| </p> |
| <p>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). |
| </p> |
| <p>JavaCore provides a method to perform explicit modifications of a container: |
| <pre> |
| JavaCore#setClasspathContainer( |
| IPath containerPath, |
| IJavaProject[] affectedProjects, |
| IClasspathContainer[] respectiveContainers, |
| IProgressMonitor monitor) |
| </pre> |
| 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. |
| </p> |
| <p> A classpath container implements <code>org.eclipse.jdt.core.IClasspathContainer</code> and can be queried |
| through a JavaCore API: <code>JavaCore#getClasspathContainer(IPath containerPath, IJavaProject project) </code>. |
| |
| There is no assumption that the returned container must answer the exact same containerPath |
| when requested <code>IClasspathContainer#getPath</code>. |
| Indeed, the containerPath is just an indication for resolving it to an actual container object.</p> |
| <p> |
| 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 |
| <code>ClasspathContainerInitializer</code> for each referenced container |
| (through the extension point "org.eclipse.jdt.core.ClasspathContainerInitializer"). |
| |
| <pre> |
| 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 (<code>CPE_LIBRARY</code>) |
| * - project entries (<code>CPE_PROJECT</code>) |
| * 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(); |
| } |
| </pre> |
| </p> |
| <p><font color="#FF0000"><b>Issue</b>: 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 </font><font color="#FF0000">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.</font></p> |
| |
| <h2> |
| Example</h2> |
| The class path of a project will look as follows: |
| <p> |
| <classpath> |
| <br> |
| <classpathentry kind="src" path="/src"/> |
| <br> |
| <classpathentry kind="container" path="JDK/1.3"/> |
| <br> |
| <classpathentry kind="output" path="bin"/> |
| <br> |
| </classpath></p> |
| <p>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:</p> |
| <p> |
| <classpathentry kind="lib" path="d:/jdk/1.3.1/jre/lib/rt.jar" |
| rootpath="d:/jdk1.3.1/lib/src.jar" sourcepath="/src"/> |
| </p> |
| </body> |
| </html> |