<!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 name="Author" content="Build"> | |
<meta name="GENERATOR" content="Mozilla/4.5 [en] (Win98; I) [Netscape]"> | |
<title>JDT - Extension Directories</title> | |
</head> | |
<body> | |
<h2> | |
Extension Directories</h2> | |
Last revised 17:10 Thursday October 25, 2001 | |
<p>Work item: Add support to Java model for JDK 1.2-style extension directories | |
(aka optional packages) | |
<p>An extension directory is a folder containing any number of JAR files | |
(including 0). Extension directories were originally added in JDK 1.2, | |
and are described in <a href="http://java.sun.com/j2se/1.3/docs/guide/extensions/index.html">http://java.sun.com/j2se/1.3/docs/guide/extensions/index.html</a>. | |
<p>The proposal is to allow a library classpath entry to refer to an extension | |
directory. A library classpath entry (<tt>CPE_LIBRARY</tt>) with a path | |
whose last segment is "*" indicates an extension directory; for example, | |
a library entry with the path "D:/jdk1.4/jre/lib/ext/*" means the extension | |
directory "D:/jdk1.4/jre/lib/ext". Like all library entries, extension | |
directories can be in folders inside the workspace or in directories in | |
the local file system outside the workspace. A variable classpath entry | |
may also resolve to an extension directory following the same rule about | |
ending in "*". Thus a variable classpath entry like "JRE_LIB/ext/*" would | |
resolve to an extension directory; and a simple one like "FOO" could resolve | |
to either a JAR library, a library folder, an extension directory, or a | |
project. | |
<p>Each of the JARs in an extension directory on a project's class path | |
would give rise to a separate <tt>IPackageFragmentRoot</tt> (kind <tt>K_BINARY</tt>); | |
these package fragment roots are all child elements of the <tt>IJavaProject</tt>. | |
The Java model would not have a Java element corresponding to the extension | |
directory itself. A classpath entry that identifies a extension folder | |
internal to the workspace gives rise to 0, 1, or more binary package fragment | |
roots for JAR file resources internal to the workspace; similarly, a classpath | |
entry that identifies a extension folder external to the workspace gives | |
rise to binary package fragment roots for JAR files outside the workspace. | |
<p>Every package fragment root that is a child of a project element stems | |
from some entry on that project's original classpath. Given a package fragment | |
root, how does one trace it back to the classpath entry that gave rise | |
to it? In the presence of variable classpath entries and extension directories, | |
the answer is not obvious. Having a simple answer is important to some | |
clients. For instance, the Java UI includes the names of classpath variables | |
in items in its Packages view. | |
<p><tt>IPackageFragmentRoot</tt> | |
<br><tt>/**</tt> | |
<br><tt> * Returns the classpath entry that gives rise to this package | |
fragment root.</tt> | |
<br><tt> * This package fragment root must exist. The returned classpath | |
entry is</tt> | |
<br><tt> * equivalent to one of the classpath entries of this package | |
fragment</tt> | |
<br><tt> * root's project.</tt> | |
<br><tt> *</tt> | |
<br><tt> * @return the originating classpath entry</tt> | |
<br><tt> * @exception JavaModelException if this element does not | |
exist</tt> | |
<br><tt> */</tt> | |
<br><tt>IClasspathEntry getOriginatingClasspathEntry() throws JavaModelException;</tt> | |
<p>This method would replace <tt>IJavaProject.getPackageFragmentRoots(IClasspathEntry | |
entry)</tt>, which has problems and would be removed from the API (via | |
deprecation). | |
<h3> | |
Packages View Clutter</h3> | |
The packages view would show all the JARs from an extension directory as | |
children of a project. Packages view clutter exists for anyone with a large | |
number of JAR libraries on their build classpath. Extension directories | |
exacerbate the problem by making it easy to include a whole set of JAR | |
libraries with a single classpath entry (WSAD reputedly has 70+ JARs in | |
its extension directory). | |
<p>The packages view supports filtering out JAR libraries, meaning they | |
could be hidden. However, the filter is off by default and not all users | |
are aware that the filter even exists. | |
<p>Note that extension folders typically contain a bunch of unrelated JARs, | |
making it likely that a user will be interested in a particular subset | |
and uninterested in the rest. The IBM 1.3.0 JRE jre\lib\ext contains indicim.jar | |
and JawBridge.jar. The Sun JDK 1.4.0-beta jre\lib\ext contains dnsns.jar, | |
ldapsec.jar, and sunjre_provider.jar. All these JARs are likely pure noise | |
and do not contain API that a client would write to. In a J2EE JRE, | |
there would be a diverse collection of JARs in the jre\lib\ext extension | |
directory (e.g., Java Telephony, JavaMail, Java 2D, Java 3D, Java Media | |
Frameworks), only a handful of which would be used within any given project. | |
<p>One idea is to allow a new JavaElement "ExtensionFolder". This would | |
allow to group the extension JARs and would avoid some clutter. Although | |
an extension folder element could avoid clutter, it may not provide enough | |
of an improvement over the existing filtering mechanism to warrant complicating | |
the Java model API. | |
<p>[This problem is still open. I recommend living with the currently supported | |
filtering for now. We could come back later and look at ways to reduce | |
clutter as a separate work item.] | |
<h3> | |
Default Build Classpath</h3> | |
The standard JRE implicitly has the jre/lib/ext extension directory on | |
its runtime classpath. By default, the build classpath for a typical project | |
should include entries for both the standard class library (jre/lib/rt.jar) | |
and the standard extension directory (jre/lib/ext/*). | |
<p>These defaults should be a function of the VM launcher for the project. | |
It should always be possible for the user to override the defaults and | |
set up their build classpath as they see fit. | |
<h3> | |
Build Classpath Ordering</h3> | |
The UI currently allows users to freely reorder package fragment roots | |
for the project. This does not really make sense for package fragments | |
roots that arise from extension directories. | |
<p>Indeed, the addition of extension directories means that there is no | |
longer a 1-1 correspondence between package fragment roots and classpath | |
entries. The UI should allow the user to determine the order of classpath | |
entries. Here are the guidelines and restrictions on the build classpath | |
for a project (N.B., these apply to the raw classpath, not necessarily | |
to a partially or fully "resolved" classpath): | |
<ul> | |
<li> | |
There may be 0, 1, or more source folders on the classpath. The relative | |
ordering of multiple source folders is significant to the user. Source | |
code in an earlier source folder hides a source file of the same name in | |
a later folder. This flexibility is rarely used: multiple source folders | |
is rare enough, and duplicated source files, even rarer.</li> | |
<li> | |
Source folders must precede all other types of classpath entries. Nothing | |
should hide source (except another source). This property is implicitly | |
relied on whenever a source code patch is being applied to a binary library.</li> | |
<li> | |
The relative ordering of non-source classpath entries (library folders, | |
library JARs, extension folders, required projects, and ones involving | |
variables) is significant to the user. The main reason it is significant | |
is to deal with conflicting library versions, where the user needs to control | |
which version wins. The ones earlier in the list should take precedence | |
over ones later in the list.</li> | |
<li> | |
For a standard Java runtime, all libraries on the boot classpath (usually | |
just the standard JRE class library) are consulted, in the order specified, | |
and before other libraries). Placing the standard JRE class library as | |
the first non-source entry on the build classpath mirrors the most common | |
configuration.</li> | |
<li> | |
For a standard Java runtime, all extension directories (usually just the | |
standard JRE extension directory) are consulted, in the order specified, | |
after libraries on the boot classpath but before other libraries. Within | |
an extension directory, the various library JARs are consulted in unspecified | |
order. Placing the standard JRE extension directory as the second non-source | |
entry on the build classpath mirrors the most common configuration.</li> | |
</ul> | |
<h3> | |
Build Classpath Duplicates</h3> | |
How are duplicates libraries on the build classpath handled? For instance, | |
if there are two classpath entries on a project's build classpath for exactly | |
the same JAR, should there be one or two package fragment roots? What if | |
a JAR classpath entry explicitly mentions a JAR that is included in an | |
extension folder also on the build classpath? | |
<p>At the Java model API, package fragment roots are handle objects with | |
well-known identity criteria. It turns out that this dictates the answer | |
to how dupicates are handled. | |
<p>For library package fragment roots based on a resource in the workspace, | |
the identity criteria includes the resource handle (handle constructor | |
isJavaProject.getPackageFragmentRoot(IResource)) For library package fragment | |
roots based on files outside the workspace, the identity criteria includes | |
the path (handle constructor isJavaProject.getPackageFragmentRoot(String)). | |
<p>This means the answer is forced: any duplication in the build classpath | |
necessarily washes out in the mapping to package fragment roots. Two classpath | |
entries for exactly the same JAR must map to a single package fragment | |
root. JARs from an extension directory gives rise to the same package fragment | |
roots one would get if each JAR was mentioned explicitly. | |
<p>In the case of duplicates, we do have a choice for which classpath entry | |
is considered the originating one. <tt>IPackageFragmentRoot.getOriginatingClasspathEntry()</tt>, | |
described above, will be used to locate an entry in the build classpath | |
carring important source attachment information. A specific classpath entry | |
should always be preferred to a generic classpath entry (extension folders | |
entries carry no source attahment info), and an earlier entry should be | |
preferred over a later one. | |
<p>For example, given the following (unusual) build classpath: | |
<br><classpath> | |
<br> <classpathentry kind="lib" path="/jre/lib/ext/*"> | |
<br> <classpathentry kind="lib" | |
<br> path="/jre/lib/ext/servlet.jar" | |
<br> sourcepath="/src/servletsrc.zip"> | |
<br> <classpathentry kind="lib" | |
<br> path="/jre/lib/ext/servlet.jar" | |
<br> sourcepath="/backup/servletsrc.zip"> | |
<br></classpath> | |
<br>the package fragment root for "/jre/lib/ext/servlet.jar" is considered | |
to originate from the second classpath entry: the second is more specific | |
that the first, and is equally specific to, but ordered earlier than, the | |
third. | |
<h3> | |
Extension Directories and the Runtime Classpath</h3> | |
By default, jre/lib/ext is the extension directory at runtime. Overriding | |
this default entails specifying a command line argument to set the value | |
of the <tt>java.ext.dirs</tt> system property. This system property specifies | |
one or more directories to search for installed extensions, each separated | |
by <tt>File.pathSeparatorChar</tt>. | |
<p>We need to determine whether the JAR needs to be added to the runtime | |
class path or not. Since the launcher is JVM-install-type-specific, it | |
feels like the right place to hardcode the knowledge of how to map a build | |
classpath to a runtime classpath. The JAR for the standard class library | |
does not need to be included in the runtime classpath because it is implicitly | |
on the boot classpath. Similarly, any JAR that is included in an extension | |
directory does not need to be mentioned explicitly. | |
<h3> | |
Attaching Source to Library JARs in an Extension Folder</h3> | |
JARs from extension directories are not really any different from other | |
class libraries. It would make debugging difficult if there were no way | |
to attached source code to a JAR in a extension directory. | |
<p>How does one attach source to JARs in an extension directory? As you | |
recall from R0.9, we consciously opted to put the source attachment information | |
in a place where it would be sharable, rather than leave this information | |
local to the workspace. The API for attaching source is on the classpath | |
entry; this allows this information to be shared between developers. Clearly, | |
this would not work for extension directories, where the names of the JARs | |
in the directory might not even be known in advance. There is no general | |
naming scheme for locating the source code for a given JAR (we do not proposing | |
to invent one). | |
<p>As discussed in the section on package view clutter, it will be common | |
for an extension directory to contain a diverse set of JARs, only a handful | |
of which would be used within any given project. The proposal is to provide | |
no direct support for attaching source via an extension folder classpath | |
entry. If the user needs to see source code for a JAR in an extension folder, | |
they would need to create an additional explicit classpath entry for that | |
JAR. As discussed above, this would not result in a new package fragment | |
root; however, it would effectively change the originating classpath entry | |
to the explicit one where the source attachment information would be found. | |
This would allow the user to attach source code to JARs on an as-needed | |
basis. The bet is that this will suffice (and finesses the issue of where | |
one might find the source for a JAR in an extension folder). | |
<br> | |
</body> | |
</html> |