6722586: Updates APIs and cleans up javadoc.
authorstanleyh
Tue Jul 08 12:14:10 2008 -0700 (16 months ago)
changeset 397fd7a1cbf88a3
parent 396fe6ca591bf85
child 398715252233bd3
6722586: Updates APIs and cleans up javadoc.
Summary: Updates JSR 277 APIs to reflect latest changes.
Reviewed-by: mchung
src/share/classes/java/lang/ModuleInfo.java
src/share/classes/java/module/ImportDependency.java
src/share/classes/java/module/ImportOverridePolicy.java
src/share/classes/java/module/ImportPolicy.java
src/share/classes/java/module/Module.java
src/share/classes/java/module/ModuleArchiveInfo.java
src/share/classes/java/module/ModuleContent.java
src/share/classes/java/module/ModuleDefinition.java
src/share/classes/java/module/ModuleDependency.java
src/share/classes/java/module/ModuleFormatException.java
src/share/classes/java/module/ModuleInitializer.java
src/share/classes/java/module/ModuleSystem.java
src/share/classes/java/module/ModuleSystemEvent.java
src/share/classes/java/module/ModuleSystemListener.java
src/share/classes/java/module/ModuleSystemPermission.java
src/share/classes/java/module/Modules.java
src/share/classes/java/module/PackageDefinition.java
src/share/classes/java/module/PackageDependency.java
src/share/classes/java/module/Query.java
src/share/classes/java/module/Repository.java
src/share/classes/java/module/RepositoryEvent.java
src/share/classes/java/module/RepositoryListener.java
src/share/classes/java/module/UnsatisfiedDependencyException.java
src/share/classes/java/module/Version.java
src/share/classes/java/module/VersionConstraint.java
src/share/classes/java/module/VersionRange.java
src/share/classes/java/module/VisibilityPolicy.java
src/share/classes/java/module/annotation/ClassesDirectoryPath.java
src/share/classes/java/module/annotation/ExportLegacyClasses.java
src/share/classes/java/module/annotation/ExportResources.java
src/share/classes/java/module/annotation/ImportModule.java
src/share/classes/java/module/annotation/JarLibraryPath.java
src/share/classes/java/module/annotation/MainClass.java
src/share/classes/java/module/annotation/NativeLibraryPath.java
src/share/classes/java/module/annotation/NativeLibraryPaths.java
src/share/classes/java/module/annotation/PlatformBinding.java
src/share/classes/java/module/annotation/ResourceModuleConstraint.java
src/share/classes/java/module/annotation/ResourceTargetConstraint.java
src/share/classes/java/module/annotation/Version.java
src/share/classes/java/module/annotation/package-info.java
src/share/classes/java/module/package-info.java
src/share/classes/sun/module/JamUtils.java
src/share/classes/sun/module/ModuleLauncher.java
src/share/classes/sun/module/annotation/ModuleName.java
src/share/classes/sun/module/bootstrap/BootstrapModuleSystem.java
src/share/classes/sun/module/bootstrap/BootstrapRepository.java
src/share/classes/sun/module/bootstrap/VirtualModuleDefinitions.java
src/share/classes/sun/module/config/DefaultImportOverridePolicy.java
src/share/classes/sun/module/config/ImportOverridePolicyFile.java
src/share/classes/sun/module/core/JamModuleDefinition.java
src/share/classes/sun/module/core/JamModuleDependency.java
src/share/classes/sun/module/core/JamPackageDefinition.java
src/share/classes/sun/module/core/ModuleImpl.java
src/share/classes/sun/module/core/ModuleLoader.java
src/share/classes/sun/module/core/ModuleSystemImpl.java
src/share/classes/sun/module/repository/AbstractRepository.java
src/share/classes/sun/module/repository/GlobalRepositoryFactory.java
src/share/classes/sun/module/repository/JamModuleArchiveInfo.java
src/share/classes/sun/module/repository/LocalRepository.java
src/share/classes/sun/module/repository/MetadataXMLWriter.java
src/share/classes/sun/module/repository/RepositoryConfig.java
src/share/classes/sun/module/repository/URLRepository.java
src/share/classes/sun/module/repository/UserRepositoryFactory.java
src/share/classes/sun/module/repository/cache/Cache.java
src/share/classes/sun/module/repository/cache/CacheModuleContent.java
src/share/classes/sun/module/repository/cache/LocalModuleContent.java
src/share/classes/sun/module/repository/cache/LocalModuleDefInfo.java
src/share/classes/sun/module/repository/cache/URLModuleContent.java
src/share/classes/sun/module/tools/JRepo.java
test/java/module/config/DefaultImportOverridePolicy/DefaultImportOverridePolicyTest.java
test/java/module/config/DefaultVisibilityPolicy/DefaultVisibilityPolicyTest.java
test/java/module/config/ImportOverridePolicyFile/ImportOverridePolicyFileTest.java
test/java/module/config/VisibilityPolicyFile/VisibilityPolicyFileTest.java
test/java/module/modinit/RunMTest.java
test/java/module/modinit/mtest/disablemodule/disablemodule.mtest
test/java/module/modinit/mtest/extclassloader/extclassloader.mtest
test/java/module/modinit/mtest/importpolicy/import4.mtest
test/java/module/modinit/mtest/importpolicy/import5.mtest
test/java/module/modinit/mtest/importpolicy/optional4.mtest
test/java/module/modinit/mtest/initializer/basic1.mtest
test/java/module/modinit/mtest/initializer/basic2.mtest
test/java/module/modinit/mtest/initializer/basic3.mtest
test/java/module/modinit/mtest/initializer/error1.mtest
test/java/module/modinit/mtest/initializer/error2.mtest
test/java/module/modinit/mtest/moduleevent/exceptionOccurred.mtest
test/java/module/modinit/mtest/moduleevent/moduleDefinitionDisabled.mtest
test/java/module/modinit/mtest/moduleevent/moduleInitialized.mtest
test/java/module/modinit/mtest/moduleevent/moduleReleased.mtest
test/java/module/modinit/mtest/override/invalid1.mtest
test/java/module/modinit/mtest/releasemodule/releasemodule1.mtest
test/java/module/modinit/mtest/releasemodule/releasemodule2.mtest
test/java/module/modinit/mtest/releasemodule/releasemodule3.mtest
test/java/module/modinit/mtest/releasemodule/releasemodule4.mtest
test/java/module/modinit/mtest/releasemodule/releasemodule5.mtest
test/java/module/query/QueryTest.java
test/java/module/repository/EventChecker.java
test/java/module/repository/LegacyJarTest.java
test/java/module/repository/LocalRepositoryTest.java
test/java/module/repository/MetadataCompareTest.java
test/java/module/repository/NativeLibraryTest.java
test/java/module/repository/RepositoryTest.java
test/java/module/repository/ShutdownOnExitTest.java
test/java/module/repository/Test6574851.java
test/java/module/repository/Test6574852.java
test/java/module/repository/URLRepoInstallTest.java
test/java/module/repository/URLRepositoryReloadTest.java
test/java/module/repository/URLRepositoryTest.java
test/java/module/repository/VisibilityPolicyTest.java
test/java/module/service/src/modserv/client/Main.java
test/java/module/version/VersionConstraintTest.java
--- a/src/share/classes/java/lang/ModuleInfo.java Mon Jul 07 10:13:08 2008 -0700
+++ b/src/share/classes/java/lang/ModuleInfo.java Tue Jul 08 12:14:10 2008 -0700
@@ -208,6 +208,22 @@ public final class ModuleInfo implements
return exported.toArray(S0);
}
+ /**
+ * Returns an array of String objects reflecting the binary names of all
+ * exported classes and interfaces that are a member of this module.
+ *
+ * <p>The elements in the array returned are not sorted and are not in
+ * any particular order. This method returns an array of length 0 if
+ * the module has no exported types.
+ *
+ * @return an array of the names of all exported types.
+ * @throws UnsupporterOperationException if the exported types cannot be
+ * determined.
+ */
+ public String[] getExportedClasses() {
+ return exported.toArray(S0);
+ }
+
private static Set<String> getPackages(Collection<String> classes) {
Set<String> packages = new HashSet<String>();
for (String clazz : classes ) {
@@ -263,7 +279,7 @@ public final class ModuleInfo implements
* module information corresponding to the named module.
*
* @param name a module name, for example, {@code java.se.core}.
- * @return the module information of the requested name. It may be null if
+ * @return the module information of the requested name. It returns null if
* no module information is available.
*/
public static ModuleInfo getModuleInfo(String name) {
--- a/src/share/classes/java/module/ImportDependency.java Mon Jul 07 10:13:08 2008 -0700
+++ b/src/share/classes/java/module/ImportDependency.java Tue Jul 08 12:14:10 2008 -0700
@@ -32,7 +32,7 @@ import java.util.Set;
/**
- * This class represents an import dependency in a module definition.
+ * This interface represents an import dependency in a module definition.
* <p>
* @see java.module.VersionConstraint
* @see java.io.Serializable
@@ -40,129 +40,35 @@ import java.util.Set;
* @since 1.7
* @serial include
*/
-public class ImportDependency implements java.io.Serializable {
-
- private static final long serialVersionUID = -4888614342905988975L;
-
- private final String type;
- private final String name;
- private final VersionConstraint constraint;
- private final boolean reexport;
- private final boolean optional;
- private final Map<String, String> attributes;
-
- /**
- * Constructs a {@code ImportDependency} object based on module-level dependency.
- *
- * @param name the name of the import.
- * @param constraint the version constraint of the import.
- * @param reexport true if the import is re-exported; otherwise, false.
- * @param optional true if the import is optional; otherwise, false.
- * @param attributes map of attributes of the import; null if there is no
- * attributes.
- * @throws NullPointerException if name is null or constraint is null.
- */
- public static ImportDependency newImportModuleDependency(String name, VersionConstraint constraint, boolean reexport, boolean optional, Map<String, String> attributes) {
- return new ImportDependency("module", name, constraint, reexport, optional, attributes);
- }
-
- /**
- * Constructs a {@code ImportDependency} object based on package-level dependency.
- *
- * @param name the name of the import.
- * @param constraint the version constraint of the import.
- * @param optional true if the import is optional; otherwise, false.
- * @param attributes map of attributes of the import; null if there is no
- * attributes.
- * @throws NullPointerException if name is null or constraint is null.
- */
- public static ImportDependency newImportPackageDependency(String name, VersionConstraint constraint, boolean optional, Map<String, String> attributes) {
- return new ImportDependency("package", name, constraint, false, optional, attributes);
- }
-
- /**
- * Constructs a {@code ImportDependency} object.
- *
- * @param type the type of the import.
- * @param name the name of the import.
- * @param constraint the version constraint of the import.
- * @param reexport true if the import is re-exported; otherwise, false.
- * @param optional true if the import is optional; otherwise, false.
- * @param attributes map of attributes of the import; null if there is no
- * attributes.
- * @throws NullPointerException if type is null, name is null or
- * constraint is null.
- */
- public ImportDependency(String type, String name,
- VersionConstraint constraint,
- boolean reexport, boolean optional,
- Map<String, String> attributes) {
-
- if (type == null)
- throw new NullPointerException("type must not be null.");
-
- if (name == null)
- throw new NullPointerException("name must not be null.");
-
- if (constraint == null)
- throw new NullPointerException("constraint must not be null.");
-
- this.type = type;
- this.name = name;
- this.constraint = constraint;
- this.reexport = reexport;
- this.optional = optional;
- if (attributes == null) {
- this.attributes = Collections.emptyMap();;
- } else {
- this.attributes = new HashMap<String, String>(attributes);
- }
- }
+public interface ImportDependency extends java.io.Serializable {
/**
* Returns the name of the import.
*
* @return the name of the import.
*/
- public String getName() {
- return name;
- }
+ public String getName();
/**
* Returns the version constraint of the import.
*
* @return the version constraint of the import.
*/
- public VersionConstraint getVersionConstraint() {
- return constraint;
- }
+ public VersionConstraint getVersionConstraint();
/**
* Returns true if the import is re-exported; otherwise, returns false.
*
* @return true if the import is re-exported; otherwise, returns false.
*/
- public boolean isReexported() {
- return reexport;
- }
+ public boolean isReexported();
/**
* Returns true if the import is optional; otherwise, returns false.
*
* @return true if the import is optional; otherwise, returns false.
*/
- public boolean isOptional() {
- return optional;
- }
-
- /**
- * Returns the type of the import dependency.
- *
- * @return the type of the import dependency.
- */
- public String getType() {
- return type;
- }
+ public boolean isOptional();
/**
* Returns an unmodifiable set of the names of the attributes associated
@@ -170,9 +76,7 @@ public class ImportDependency implements
*
* @return an unmodifiable set of the names of the attributes.
*/
- public Set<String> getAttributeNames() {
- return attributes.keySet();
- }
+ public Set<String> getAttributeNames();
/**
* Returns the value corresponding to the specified attribute name that is
@@ -182,83 +86,5 @@ public class ImportDependency implements
* @return the value of the attribute. Returns null if the specified
* attribute name is not found.
*/
- public String getAttribute(String name) {
- return attributes.get(name);
- }
-
- /**
- * Compare two {@code ImportDependency} objects for equality. The result is
- * {@code true} if and only if the argument is not {@code null} and is a
- * {@code ImportDependency} object that imported type, name, version
- * constraint, reexport, optional, and attributes are the same as those of
- * this {@code ImportDependency}.
- *
- * @param obj the object to compare with.
- * @return whether or not the two objects are equal
- */
- @Override
- public boolean equals(Object obj) {
- if (this == obj)
- return true;
-
- if (!(obj instanceof ImportDependency))
- return false;
-
- ImportDependency dep = (ImportDependency) obj;
-
- return (type.equals(dep.getType())
- && name.equals(dep.getName())
- && constraint.equals(dep.getVersionConstraint())
- && reexport == dep.isReexported()
- && optional == dep.isOptional()
- && attributes.equals(dep.attributes));
- }
-
- /**
- * Returns a hash code for this {@code ImportDependency}.
- *
- * @return a hash code value for this {@code ImportDependency}.
- */
- @Override
- public int hashCode() {
- int result = 17;
- result = 37 * result + type.hashCode();
- result = 37 * result + name.hashCode();
- result = 37 * result + constraint.hashCode();
- result = 37 * result + (reexport ? 0 : 1);
- result = 37 * result + (optional ? 0 : 1);
- result = 37 * result + attributes.hashCode();
- return result;
- }
-
- /**
- * Returns a {@code String} object representing this
- * {@code ImportDependency}.
- *
- * @return a string representation of the {@code ImportDependency} object.
- */
- @Override
- public String toString() {
- StringBuilder builder = new StringBuilder();
-
- builder.append("ImportDependency[type=");
- builder.append(type);
- builder.append(",name=");
- builder.append(name);
- builder.append(",version=");
- builder.append(constraint.toString());
- if (reexport) {
- builder.append(",re-export");
- }
- if (optional) {
- builder.append(",optional");
- }
- if (attributes != null) {
- builder.append(",attributes=");
- builder.append(attributes);
- }
- builder.append("]");
-
- return builder.toString();
- }
+ public String getAttribute(String name);
}
--- a/src/share/classes/java/module/ImportOverridePolicy.java Mon Jul 07 10:13:08 2008 -0700
+++ b/src/share/classes/java/module/ImportOverridePolicy.java Tue Jul 08 12:14:10 2008 -0700
@@ -29,12 +29,16 @@ import java.util.Map;
import java.util.Map;
/**
- * This interface represents the import override policy which is a mechanism
- * that allows deployers to narrow the version constraints in the import
- * dependencies of a specific module definition to control the resolution.
+ * This interface represents the import override policy in the JAM
+ * module system. The import override policy allows deployers to narrow
+ * the version constraints in the import dependencies of a specific
+ * module definition to control the resolution in the module system.
* <p>
- * The import override policy is invoked before the default or custom
- * import policy of the module instance is executed during initialization.
+ * During the module initialization in the JAM module system, the
+ * {@link #narrow(ModuleDefinition, Map) <tt>narrow</tt>} method of the
+ * {@code ImportOverridePolicy} object returned from
+ * {@link Modules#getImportOverridePolicy()} is
+ * invoked before the import policy of the module instance is executed.
* <p>
* @see java.module.ImportDependency;
* @see java.module.ImportPolicy
@@ -47,8 +51,8 @@ public interface ImportOverridePolicy {
/**
* Returns a map of import dependencies and overridden version constraints
- * for the module definition. The returned map contains the same set of
- * import dependencies as in the given map.
+ * for the module definition. The returned map must contain the same set of
+ * import dependencies as in the given {@code map}.
* <p>
* For each import dependency, the overridden version constraint must be
* within the boundary of the original version constraint that was
@@ -56,12 +60,12 @@ public interface ImportOverridePolicy {
* initialization will fail.
*
* @param importer the importing module definition.
- * @param constraints an unmodifiable map of import dependencies and
+ * @param map an unmodifiable map of import dependencies and
* overridden version constraints.
* @return the map of import dependencies and overridden version
* constraints. It contains the same set of import dependencies as
- * in the given map.
+ * in the given {@code map}.
*/
public abstract Map<ImportDependency, VersionConstraint> narrow(ModuleDefinition importer,
- Map<ImportDependency, VersionConstraint> constraints);
+ Map<ImportDependency, VersionConstraint> map);
}
--- a/src/share/classes/java/module/ImportPolicy.java Mon Jul 07 10:13:08 2008 -0700
+++ b/src/share/classes/java/module/ImportPolicy.java Tue Jul 08 12:14:10 2008 -0700
@@ -29,9 +29,10 @@ import java.util.Map;
import java.util.Map;
/**
- * This interface represents the import policy of a module definition. The
- * import policy is used to determine the version constraints that should be
- * used to resolve the import dependencies in a module during initialization.
+ * This interface represents the import policy of a module definition
+ * in the JAM module system. The import policy is used to
+ * determine the version constraints that should be used to resolve
+ * the import dependencies in a module during initialization.
* <p>
* @see java.module.ImportDependency
* @see java.module.ImportOverridePolicy
--- a/src/share/classes/java/module/Module.java Mon Jul 07 10:13:08 2008 -0700
+++ b/src/share/classes/java/module/Module.java Tue Jul 08 12:14:10 2008 -0700
@@ -29,6 +29,11 @@ import java.util.List;
/**
* This class represents a reified module instance in a module system.
+ *
+ * Each {@code Module} instance has its own copies of the classes defined
+ * by the module definition, each with their own independent static
+ * state. Each {@code Module} instance is also interconnected with
+ * instances of the modules it imports.
* <p>
* @see java.lang.ClassLoader
* @see java.module.ModuleDefinition
--- a/src/share/classes/java/module/ModuleArchiveInfo.java Mon Jul 07 10:13:08 2008 -0700
+++ b/src/share/classes/java/module/ModuleArchiveInfo.java Tue Jul 08 12:14:10 2008 -0700
@@ -26,7 +26,7 @@ package java.module;
package java.module;
/**
- * This class represents the information of an installed module archive
+ * This interface represents the information of an installed module archive
* in a repository.
*
* @see java.module.Repository
@@ -34,132 +34,47 @@ package java.module;
*
* @since 1.7
*/
-public class ModuleArchiveInfo {
- private Repository repository;
-
- // These fields are a reflection of the information in the module archive.
- private String name;
- private Version version;
- private String platform;
- private String arch;
- private String fileName;
- private long lastModified;
-
- /**
- * Constructs a new {@code ModuleArchiveInfo} instance.
- * <p>
- * If the module definition in the module archive is platform and
- * architecture neutral, both {@code platform} and {@code arch} must be
- * null.
- *
- * @param repository the repository
- * @param name the name of the module definition in the module archive.
- * @param version the version of the module definition in the module
- * archive.
- * @param platform the platform which the module definition in the module
- * archive targets.
- * @param arch the architecture which the module definition in the module
- * archive targets.
- * @param fileName the filename of the module archive.
- * @param lastModified the last modified time of the module archive.
- * @throws NullPointerException if repository is null, name is null,
- * version is null, or the last modified time is less than 0. It
- * is also thrown if platform is null but arch is not null, or
- * platform is not null but arch is null.
- */
- public ModuleArchiveInfo(Repository repository, String name,
- Version version, String platform, String arch,
- String fileName, long lastModified) {
- if (repository == null) {
- throw new IllegalArgumentException("repository must not be null.");
- }
- if (name == null) {
- throw new IllegalArgumentException("name must not be null.");
- }
- if (version == null) {
- throw new IllegalArgumentException(
- "version must not be null.");
- }
- if ((platform == null ^ arch == null)) {
- throw new IllegalArgumentException(
- "platform and arch must be either both provided, or neither provided.");
- }
-
- if (lastModified <0) {
- throw new IllegalArgumentException(
- "lastModified must be greater than or equal to 0.");
- }
-
- this.repository = repository;
- this.name = name;
- this.version = version;
- this.platform = platform;
- this.arch = arch;
- this.fileName = fileName;
- this.lastModified = lastModified;
- }
+public interface ModuleArchiveInfo {
/**
* Returns the repository where the module archive is stored.
*
* @return the repository.
*/
- public Repository getRepository() {
- return repository;
- }
+ public Repository getRepository();
/**
* Returns the name of the module definition in the module archive.
*
- * @return the name of the module definition.
+ * @return the name of the module definition in the module archive.
*/
- public String getName() {
- return name;
- }
+ public String getName();
/**
* Returns the version of the module definition in the module archive.
*
- * @return the version of the module definition.
+ * @return the version of the module definition in the module archive.
*/
- public Version getVersion() {
- return version;
- }
+ public Version getVersion();
/**
- * Returns the name of the platform of the module definition in the
- * module archive. The value should be one of the possible values
+ * Returns the name of the platform which the module archive targets.
+ * The value should be one of the possible values
* of the system property {@code "os.platform"}.
*
- * @return the name of the platform. If the module definition has no
+ * @return the name of the platform. If the module archive has no
* platform binding, returns null.
*/
- public String getPlatform() {
- return platform;
- }
+ public String getPlatform();
/**
- * Returns the name of the architecture of the module definition in the
- * module archive. The value should be one of the possible values of
- * the system property {@code "os.arch"}.
+ * Returns the name of the architecture of the module archive targets.
+ * The value should be one of the possible values of the system property {@code "os.arch"}.
*
- * @return the name of the architecture. If the module definition has no
+ * @return the name of the architecture. If the module archive has no
* platform binding, returns null.
*/
- public String getArch() {
- return arch;
- }
-
- /**
- * Determines if the module definition in the module archive is
- * platform and architecture neutral.
- *
- * @return true if the module definition in the module archive is platform
- * and architecture neutral; otherwise return false.
- */
- public boolean isPlatformArchNeutral() {
- return (platform == null && arch == null);
- }
+ public String getArch();
/**
* Returns the filename of the module archive.
@@ -167,9 +82,7 @@ public class ModuleArchiveInfo {
* @return the filename of the module archive. If the module archive does not
* have a filename, return null.
*/
- public String getFileName() {
- return fileName;
- }
+ public String getFileName();
/**
* Returns the last modified time of the module archive in the repository. The
@@ -177,42 +90,5 @@ public class ModuleArchiveInfo {
*
* @return the time the module archive was last modified, or 0 if not known.
*/
- public long getLastModified() {
- return lastModified;
- }
-
- /**
- * Returns a {@code String} object representing this
- * {@code ModuleArchiveInfo}.
- *
- * @return a string representation of the {@code ModuleArchiveInfo} object.
- */
- @Override
- public String toString() {
- StringBuilder builder = new StringBuilder();
-
- builder.append("ModuleArchiveInfo[repository=");
- builder.append(repository.getName());
- builder.append(",module=");
- builder.append(name);
- builder.append(" v");
- builder.append(version);
- if (!isPlatformArchNeutral()) {
- builder.append(",platform-arch=");
- builder.append(platform);
- builder.append("-");
- builder.append(arch);
- }
- if (fileName != null) {
- builder.append(",fileName=");
- builder.append(fileName);
- }
- if (lastModified >= 0) {
- builder.append(",lastModified=");
- builder.append(new java.util.Date(lastModified));
- }
- builder.append("]");
-
- return builder.toString();
- }
+ public long getLastModified();
}
--- a/src/share/classes/java/module/ModuleContent.java Mon Jul 07 10:13:08 2008 -0700
+++ b/src/share/classes/java/module/ModuleContent.java Tue Jul 08 12:14:10 2008 -0700
@@ -30,117 +30,98 @@ import java.io.ByteArrayOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.nio.channels.ReadableByteChannel;
import java.util.Set;
import java.security.CodeSigner;
/**
- * This class represents the content of a module definition.
+ * This interface represents the content of a module definition. The content
+ * can be obtained from a {@code ModuleDefinition} instance using the
+ * {@link ModuleDefinition#getModuleContent() <tt>getModuleContent()</tt>}
+ * method.
*
- * <p> Unless otherwise specified, passing a <tt>null</tt> argument to any
- * method in this class will cause a {@link NullPointerException} to be thrown.
- * <p>
* @see java.module.ModuleDefinition
* @see java.security.CodeSigner
*
* @since 1.7
*/
-public abstract class ModuleContent {
+public interface ModuleContent {
/**
- * Constructor used by subclasses.
+ * Returns true if the specified entry is found.
+ * <p>
+ * The entry's name is specified using {@code '/'} as path separator; it
+ * has no leading {@code '/'}.
+ *
+ * @param name the name of the entry.
+ * @return true if the specified entry is found; otherwise, return false.
+ * @throws IOException if an I/O error occurs.
*/
- protected ModuleContent() {
- // empty
- }
+ public boolean hasEntry(String name) throws IOException;
/**
- * Determines if an entry exists in the module definition.
+ * Returns the readable byte channel for the specified entry or
+ * {@code null} if not found.
* <p>
- * The entry's name is specified as {@code '/'} separated paths, with no
- * leading {@code '/'}.
+ * The entry's name is specified using {@code '/'} as path separator; it
+ * has no leading {@code '/'}.
*
- * @param name entry's name.
- * @return true if entry exists in the module definition; otherwise,
- * returns false.
+ * @param name the name of the entry.
+ * @return the readable byte channel for the specified entry or
+ * {@code null} if not found.
* @throws IOException if an I/O error occurs.
*/
- public abstract boolean hasEntry(String name) throws IOException;
+ public ReadableByteChannel getEntryAsChannel(String name) throws IOException;
/**
- * Returns an entry in the module definition as an input stream.
+ * Returns the read-only byte buffer for the specified entry or
+ * {@code null} if not found.
* <p>
- * The entry's name is specified as {@code '/'} separated paths, with no
- * leading {@code '/'}.
+ * The entry's name is specified using {@code '/'} as path separator; it
+ * has no leading {@code '/'}.
*
- * @param name entry's name.
- * @return if entry exists, return input stream; otherwise, return null.
+ * @param name the name of the entry.
+ * @return the readable byte channel for the specified entry or
+ * {@code null} if not found.
* @throws IOException if an I/O error occurs.
*/
- public abstract InputStream getEntryAsStream(String name) throws IOException;
+ public ByteBuffer getEntryAsByteBuffer(String name) throws IOException;
/**
- * Returns an entry in the module definition as byte array.
+ * Returns an unmodifiable set of the names of the entries.
* <p>
- * The entry's name is specified as {@code '/'} separated paths, with no
- * leading {@code '/'}.
+ * The entry's name is specified using {@code '/'} as path separator; it
+ * has no leading {@code '/'}.
*
- * @param name entry's name.
- * @return if an entry exists, return byte array; otherwise, returns null.
+ * @return an unmodifiable set of the names of the entries.
* @throws IOException if an I/O error occurs.
*/
- public byte[] getEntryAsByteArray(String name) throws IOException {
- BufferedInputStream bis = new BufferedInputStream(getEntryAsStream(name));
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
- byte[] buffer = new byte[8192];
-
- int byteRead = 0;
-
- // Read the stream until it is EOF
- while ((byteRead = bis.read(buffer, 0, 8192)) != -1)
- baos.write(buffer, 0, byteRead);
-
- // Close input stream
- bis.close();
-
- // Convert to byte array
- return baos.toByteArray();
- }
+ public Set<String> getEntryNames() throws IOException;
/**
- * Returns the set of the names of the entries in the module definition.
- * <p>
- * Each entry's name is in the form of {@code '/'} separated paths, with no
- * leading {@code '/'}.
+ * Returns the path of the native library for the specified library name
+ * or {@code null} if not found.
*
- * @return the set of the names of the entries in the module definition.
+ * @param libraryName the library name.
+ * @return the path of the native library or {@code null} if not found.
* @throws IOException if an I/O error occurs.
*/
- public abstract Set<String> getEntryNames() throws IOException;
+ public File getNativeLibrary(String libraryName) throws IOException;
/**
- * Returns the path of the native library associated with the module
- * definition.
+ * Returns an unmodifiable set of code signers. If there is no code
+ * signer, an empty set is returned.
*
- * @param libraryName the library name.
- * @return native library if it is found; otherwise, returns null.
+ * @return an unmodifiable set of code signers.
* @throws IOException if an I/O error occurs.
*/
- public abstract File getNativeLibrary(String libraryName) throws IOException;
+ public Set<CodeSigner> getCodeSigners() throws IOException;
/**
- * Returns the code signers associated with the module definition.
+ * Returns true if the entire content is available locally.
*
- * @return code signers of the module definition.
- * @throws IOException if an I/O error occurs.
+ * @return true if the entire content is available locally; false otherwise.
*/
- public abstract CodeSigner[] getCodeSigners() throws IOException;
-
-
- /**
- * Determines if the entire content of the module definition is stored locally.
- *
- * @return true if the entire content of the module definition is stored
- * locally. Otherwise, returns false.
- */
- public abstract boolean isDownloaded();
+ public boolean isDownloaded();
}
--- a/src/share/classes/java/module/ModuleDefinition.java Mon Jul 07 10:13:08 2008 -0700
+++ b/src/share/classes/java/module/ModuleDefinition.java Tue Jul 08 12:14:10 2008 -0700
@@ -32,16 +32,87 @@ import java.util.Set;
import java.util.Set;
/**
-* This class represents a reified module definition in a module system.
-* <p>
-* @see java.lang.ClassLoader
-* @see java.module.Module
-* @see java.module.ModuleSystem
-* @see java.module.Repository
-* @see java.module.Version
-*
-* @since 1.7
-*/
+ * This class represents a reified module definition in a module system.
+ * <p>
+ * A {@code ModuleDefinition} identifies a logical module in a module system.
+ * It specifies which classes and resources are provided by the module, and
+ * what the module imports and exports. The classes in the
+ * {@code ModuleDefinition} could be from one or more Java packages.
+ * {@code ModuleDefinition}s from one or more module systems can coexist in
+ * the same Java virtual machine (JVM) instance. A {@code ModuleDefinition}
+ * is inherently stateless, and its identity is represented by its
+ * {@link #getName() <tt>name</tt>} and
+ * {@link #getVersion() <tt>version</tt>}.
+ * <p>
+ * A module definition can be instantiated by its module system creating a
+ * {@code Module} instance at runtime, using the
+ * {@link #getModuleInstance() <tt>getModuleInstance</tt>} method or the
+ * module system's
+ * {@link ModuleSystem#getModule(ModuleDefinition)
+ * <tt>getModule(ModuleDefinition)</tt>} method.
+ * <p>
+ * The name of a {@code ModuleDefinition} is a case-sensitive string.
+ * The Java Module System does not enforce any naming convention on module
+ * definitions; each module system can have its own naming convention for its
+ * module definitions.
+ * <p>
+ * Each {@code ModuleDefinition} contains zero or more module
+ * attributes. Each module attribute is a name-value pair of case-sensitive
+ * strings. Module attributes are generally defined and used by components
+ * at a higher layer on top of the Java Module System.
+ * <p>
+ * Each {@code ModuleDefinition} defines which classes that are part of
+ * the module, and the information can be obtained using the
+ * {@link getMemberClasses()} method.
+ * <p>
+ * Each {@code ModuleDefinition} defines which classes and resources are visible
+ * externally to other modules though the export mechanism. The export
+ * mechanisms for classes and resources serve different purposes:
+ * <ul>
+ * <li><p>The class export defines which classes are visible to other
+ * modules at build-time and after the module is interconnected
+ * at runtime. When Java code is compiled against other imported
+ * modules at build-time, the compiler would leverage the class
+ * export of the imported modules to ensure only exported classes
+ * can be compiled against. At runtime, a module system could also
+ * leverage the class export to determine how to search classes
+ * efficiently across imported modules in a module.
+ * The class export information can be obtained using the
+ * {@link #getExportedClasses()} method and the
+ * {@link #isClassExported(String)} method.</p></li>
+ *
+ * <li><p>The resource export defines which resources are visible to
+ * other modules at runtime after the module is interconnected.
+ * A module system could leverage the resource export to search
+ * resources efficiently across imported modules; however, at
+ * build-time, the compiler compiles classes but not resources,
+ * thus the resource export is not used at all.
+ * Similarly, the resource export information can be obtained
+ * using the {@link #getExportedResources()} method and the
+ * {@link #isResourceExported(String)} method.</p></li>
+ * </ul>
+ * <p>
+ * Each {@code ModuleDefinition} also defines its dependencies upon other
+ * module definitions using the import mechanism. These imports are expressed
+ * as a list of {@link ImportDependency} instances which are returned by the
+ * {@link #getImportDependencies()} method. At runtime, the module system of
+ * the {@code ModuleDefinition} is the one responsible to recognize and
+ * resolve these imports accordingly when it creates a module instance from
+ * the module definition.
+ * <p>
+ * Some implememtations of {@code ModuleDefinition} may not support the
+ * {@link #getExportedClasses()}, {@link #getMemberClasses()}, and
+ * {@link #getModuleContent()} methods; invoking these methods may throw
+ * {@code UnsupportedOperationException}.
+ *
+ * <p>
+ * @see java.module.Module
+ * @see java.module.ModuleSystem
+ * @see java.module.Repository
+ * @see java.module.Version
+ *
+ * @since 1.7
+ */
public abstract class ModuleDefinition {
/**
@@ -104,14 +175,18 @@ public abstract class ModuleDefinition {
/**
* Returns the module system that is associated with this
- * {@code ModuleDefinition}. Equivalent to:
- * <pre>
- * getRepository().getModuleSystem();
- * </pre>
+ * {@code ModuleDefinition}.
+ *
* @return the {@code ModuleSystem} object.
*/
public abstract ModuleSystem getModuleSystem();
+ /**
+ * Returns the name of the main class in this {@code ModuleDefinition}.
+ *
+ * @return the name of the main class if it exists; otherwise returns null.
+ */
+ public abstract String getMainClass();
/**
* Returns an unmodifiable set of the names of the classes that are members
@@ -153,8 +228,14 @@ public abstract class ModuleDefinition {
public abstract Set<PackageDefinition> getExportedPackageDefinitions();
/**
- * Check if the specified class is exported by this
- * {@code ModuleDefinition}.
+ * Returns true if the specified class is exported by this
+ * {@code ModuleDefinition}; returns false otherwise.
+ * <p>
+ * If this method returns {@code true} for a specified class, it implies
+ * neither that the class is actually found in the module definition, nor
+ * the class is guaranteed to be loaded successfully through the
+ * {@link ClassLoader#loadClass(String) loadClass} methods of
+ * the {@code ClassLoader} object in the module instance at runtime.
*
* @param name the name of the class.
* @return true if the class is exported; otherwise, returns false.
@@ -173,7 +254,8 @@ public abstract class ModuleDefinition {
* Returns an unmodifiable set of the path of the resources exported by
* this {@code ModuleDefinition}.
* <p>
- * Resources are specified as '/' separated paths, with no leading '/'.
+ * Each resource's path is specified using {@code '/'} as path
+ * separator, with no leading {@code '/'}.
*
* @return The unmodifiable set of the path of the exported resources.
* @throws UnsupportedOperationException if the set of exported resources
@@ -182,10 +264,19 @@ public abstract class ModuleDefinition {
public abstract Set<String> getExportedResources();
/**
- * Check if the specified resource is exported by this
- * {@code ModuleDefinition}.
- *
- * @param path A '/' delimited path (e.g. x/y/Z.class")
+ * Returns true if the specified resource is exported by this
+ * {@code ModuleDefinition}; returns false otherwise.
+ * <p>
+ * If this method returns {@code true} for a specified resource, it implies
+ * neither that the resource is actually found in the module definition, nor
+ * the resource is guaranteed to be loaded successfully through the
+ * {@link ClassLoader#getResource(String) getResource},
+ * {@link ClassLoader#getResourceAsStream(String) getResourceAsStream},
+ * or {@link ClassLoader#getResources(String) getResources}
+ * methods of the {@code ClassLoader} object in the module
+ * instance at runtime.
+
+ * @param path A {@code '/'} delimited path (e.g. {@code x/y/Z.class})
* @return true if the resource in the path is exported.
*/
public boolean isResourceExported(String path) {
@@ -202,8 +293,7 @@ public abstract class ModuleDefinition {
* {@code ModuleDefinition} in the {@code ModuleSystem}. The {@code Module}
* is initialized and ready to use. Equivalent to:
* <pre>
- * getModuleSystem().getModule(this);
- * </pre>
+ * getModuleSystem().getModule(this);</pre>
*
* @return a {@code Module} instance of the {@code ModuleDefinition}.
* @throws ModuleInitializationException if the module instance cannot be initialized.
@@ -222,7 +312,6 @@ public abstract class ModuleDefinition {
* annotation type
* @return this {@code ModuleDefinition}'s annotation for the specified
* annotation type if present, else null
- * @throws NullPointerException if the given annotation class is null
*/
public abstract <T extends Annotation> T getAnnotation(Class<T> annotationClass);
@@ -277,6 +366,8 @@ public abstract class ModuleDefinition {
* @throws SecurityException if a security manager exists and
* its {@code checkPermission} method denies access
* to the content of this {@code ModuleDefinition}.
+ * @throws UnsupportedOperationException if the {@code ModuleContent}
+ * in this {@code ModuleDefinition} cannot be determined.
*/
public abstract ModuleContent getModuleContent();
@@ -288,7 +379,7 @@ public abstract class ModuleDefinition {
*
* @param obj the object to be compared for equality with this
* {@code ModuleDefinition}.
- * @return {@code true} if the specified object is equal to this
+ * @return {@code true} if the specified object is the same object as this
* {@code ModuleDefinition}; otherwise, returns false.
*/
@Override
--- a/src/share/classes/java/module/ModuleFormatException.java Mon Jul 07 10:13:08 2008 -0700
+++ b/src/share/classes/java/module/ModuleFormatException.java Tue Jul 08 12:14:10 2008 -0700
@@ -28,8 +28,8 @@ import java.io.IOException;
import java.io.IOException;
/**
- * Thrown to indicate that the format of the module archive is neither
- * recognized nor supported.
+ * Thrown to indicate that the module format is neither recognized nor
+ * supported.
*
* @since 1.7
*/
--- a/src/share/classes/java/module/ModuleInitializer.java Mon Jul 07 10:13:08 2008 -0700
+++ b/src/share/classes/java/module/ModuleInitializer.java Tue Jul 08 12:14:10 2008 -0700
@@ -26,13 +26,17 @@ package java.module;
package java.module;
/**
- * This interface represents a module initializer of a module instance. The
- * initializer is invoked when the module system initializes a module instance,
- * and when that module instance is released from the module system.
+ * This interface represents a module initializer of a module instance
+ * specifically in the JAM module system. The
+ * {@link #initialize(Module) initialize} method is invoked when
+ * the module system initializes a module instance; the
+ * {@link #release(Module) release} method is invoked when that module
+ * instance is released from the module system.
* <p>
* @see java.module.Module
* @see java.module.ModuleDefinition
* @see java.module.ModuleInitializationException
+ * @see java.module.annotation.ModuleInitializerClass
*
* @since 1.7
*/
@@ -50,9 +54,10 @@ public interface ModuleInitializer {
* imported modules are still in the middle of the initialization, and
* there are two potential issues:
* <p>
- * 1. The exported classes from these imported modules might not yet be
- * accessible from this method.<p>
- * 2. The initializer of these imported modules might not yet been invoked.
+ * 1. The exported classes from an imported module are not guaranteed
+ * to be accessible from this method.<p>
+ * 2. If an imported module have a module initializer, its
+ * {@link #initialize(Module) initialize} method may not yet been invoked.
* <p>
* Implementations of this method should avoid accessing classes from the
* imported modules, and should make no assumption that the imported
@@ -62,8 +67,11 @@ public interface ModuleInitializer {
* Note that the module instance passed as the argument of this method has
* not been fully initialized. The only methods in {@code Module} that the
* implementation of this method could invoke reliably are
- * {@code Module}'s {@code getModuleDefinition()}, {@code hashCode()}, and
- * {@code toString()}. Otherwise, the result is undeterministric.
+ * {@code Module}'s
+ * {@link Module#getModuleDefinition() <tt>getModuleDefinition</tt>},
+ * {@link Module#hashCode() <tt>hashCode</tt>}, and
+ * {@link Module#toString() <tt>toString</tt>} methods.
+ * Otherwise, the result is undeterministric.
*
* @param module the {@code Module} instance to be initialized.
* @throws ModuleInitializationException if this {@code ModuleInitializer}
@@ -75,18 +83,21 @@ public interface ModuleInitializer {
* This method is invoked when a module instance is released from the
* module system. It is invoked in the following situations:
* <p>
- * 1. The {@link #initialize(Module) initialize(Module)} method has been
+ * 1. The {@link #initialize(Module) initialize} method has been
* invoked successfully, but this module instance still gets into error
* state because one or more of its imported modules get into error
* state, or<p>
- * 2. After the {@code releaseModule} method of the {@code ModuleSystem}
- * is invoked.
+ * 2. After the {@link ModuleSystem#releaseModule(ModuleDefinition) releaseModule}
+ * method of the {@code ModuleSystem} is invoked.
* <p>
* In the first situation, the module instance passed as the argument of
* this method is in error state. The only methods in {@code Module} that
* the implementation of this method could invoke reliably are
- * {@code Module}'s {@code getModuleDefinition()}, {@code hashCode()}, and
- * {@code toString()}. Otherwise, the result is undeterministric.
+ * {@code Module}'s
+ * {@link Module#getModuleDefinition() <tt>getModuleDefinition</tt>},
+ * {@link Module#hashCode() <tt>hashCode</tt>}, and
+ * {@link Module#toString() <tt>toString</tt>} methods.
+ * Otherwise, the result is undeterministric.
* <p>
* Note that after this method is invoked, the module classloader of this
* module instance might still be accessible from other modules. If the
@@ -97,7 +108,7 @@ public interface ModuleInitializer {
* <p>
* Also, when the virtual machine exits, there is no guarantee that this
* method is ever invoked even if the
- * {@link #initialize(Module) initialize(Module)} method has been invoked
+ * {@link #initialize(Module) initialize} method has been invoked
* successfully.
*
* @param module the {@code Module} instance to be released.
--- a/src/share/classes/java/module/ModuleSystem.java Mon Jul 07 10:13:08 2008 -0700
+++ b/src/share/classes/java/module/ModuleSystem.java Tue Jul 08 12:14:10 2008 -0700
@@ -31,9 +31,27 @@ import java.util.concurrent.ThreadFactor
import java.util.concurrent.ThreadFactory;
/**
- * This class represents a module system. A module system is responsible for
- * instantiating module instances from module definitions, and managing their
- * lifetimes.
+ * This class represents a module system.
+ * <p>
+ * A {@code ModuleSystem} is responsible for creating and initializing
+ * module instances from module definitions, and managing their lifetimes.
+ * <p>
+ * A {@code ModuleSystem} object is used to instantiate and
+ * initialize a {@link Module}
+ * instance from a {@link ModuleDefinition} using the
+ * {@link getModule(ModuleDefinition) <tt>getModule</tt>} method or the
+ * {@link getModules(ModuleDefinition, List) <tt>getModules</tt>} method.
+ * The {@code ModuleSystem} object manages the lifetime of each
+ * {@code Module} instance it creates, until the
+ * {@code Module} instance is released using the
+ * {@link releaseModule(ModuleDefinition) <tt>releaseModule</tt>} method.
+ * <p>
+ * A {@code ModuleDefinition} can be disabled in its {@code ModuleSystem}
+ * using the
+ * {@link disableModuleDefinition(ModuleDefinition)
+ * <tt>disableModuleDefinition</tt>} method;
+ * the module system must not instantiate any new {@code Module} instance
+ * from a disabled {@code ModuleDefinition}.
* <p>
* @see java.module.Module
* @see java.module.ModuleDefinition
@@ -45,14 +63,25 @@ import java.util.concurrent.ThreadFactor
@java.util.Service
public abstract class ModuleSystem {
- private static ModuleSystem defaultImpl = null;
-
- /**
- * Constructor used by subclasses.
+ /**
+ * Creates a {@code ModuleSystem} instance.
+ * <p>
+ * If a security manager is present, this method calls the security
+ * manager's {@code checkPermission} method with
+ * {@code ModuleSystemPermission("createModuleSystem")} permission to
+ * ensure it's ok to create a module system.
+ *
+ * @throws SecurityException if a security manager exists and its
+ * {@code checkPermission} method denies access to create a new
+ * module system instance.
*/
protected ModuleSystem() {
- // empty
- }
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null) {
+ sm.checkPermission(new ModuleSystemPermission("createModuleSystem"));
+ }
+ }
+
/**
* Returns a {@code Module} instance for the specified
@@ -158,18 +187,6 @@ public abstract class ModuleSystem {
*/
public abstract void disableModuleDefinition(ModuleDefinition moduleDef);
- /**
- * Returns the system's default module system.
- *
- * @return the system's default module system.
- */
- public static synchronized ModuleSystem getDefault() {
- if (defaultImpl == null) {
- defaultImpl = sun.module.core.ModuleSystemImpl.INSTANCE;
- }
- return defaultImpl;
- }
-
// Module system listener(s)
private static ModuleSystemListener moduleSystemListener = null;
private static Object listenerSyncObject = new Object();
@@ -218,7 +235,6 @@ public abstract class ModuleSystem {
* @throws SecurityException if a security manager exists and its
* checkPermission method denies access to remove a module system
* listener from the module systems.
- * @throws NullPointerException if listener is null.
*/
public static final void removeModuleSystemListener(ModuleSystemListener listener) {
if (listener == null) {
--- a/src/share/classes/java/module/ModuleSystemEvent.java Mon Jul 07 10:13:08 2008 -0700
+++ b/src/share/classes/java/module/ModuleSystemEvent.java Tue Jul 08 12:14:10 2008 -0700
@@ -26,7 +26,7 @@ package java.module;
package java.module;
/**
- * This class represents a module system event that occurs in a module
+ * This class represents an event that occurs in a module
* system.
*
* @see java.module.Module
@@ -43,22 +43,22 @@ public class ModuleSystemEvent {
*/
public enum Type {
/**
- * A module instance has been initialized successfully.
+ * A module instance has been initialized successfully in a module system.
*/
MODULE_INITIALIZED,
/**
- * A module instance has been released successfully.
+ * A module instance has been released successfully in a module system.
*/
MODULE_RELEASED,
/**
- * The initialization of a module instance has failed.
+ * The initialization of a module instance has failed in a module system.
*/
MODULE_INITIALIZATION_EXCEPTION,
/**
- * A module definition has been disabled successfully.
+ * A module definition has been disabled successfully in a module system.
*/
MODULE_DEFINITION_DISABLED
};
@@ -70,89 +70,57 @@ public class ModuleSystemEvent {
private ModuleInitializationException exception;
/**
- * Constructs a {@code ModuleSystemEvent} object with event type
- * {@code MODULE_INITIALIZED} or {@code MODULE_RELEASED}, using the
+ * Constructs a {@code ModuleSystemEvent} instance using the
* specified module system, event type, and module instance.
*
* @param source the module system where the event occurs
* @param type the event type
* @param module the module instance that the event applies to
- * @throws IllegalArgumentException if type is
- * {@code MODULE_INITIALIZATION_EXCEPTION} or
- * {@code MODULE_DEFINITION_DISABLED}
- * @throws NullPointerException if source is null, type is null,
- * or module is null.
- *
+ * @param moduleDef the module definition that the event applies to
+ * @param exception module initialization exception
+ * @throws NullPointerException if source is {@code null} or type is
+ * {@code null}.
+ * @throws IllegalArgumentException
+ * <ul>
+ * <li><p>if type is {@link Type#MODULE_INITIALIZED
+ * <tt>MODULE_INITIALIZED</tt>} or
+ * {@link Type#MODULE_RELEASED
+ * <tt>MODULE_RELEASED</tt>} but
+ * module is {@code null}, or</p></li>
+ * <li><p>if type is {@link Type#MODULE_DEFINITION_DISABLED
+ * <tt>MODULE_DEFINITION_DISABLED</tt>} but
+ * moduleDef is {@code null}, or</p></li>
+ * <li><p>if type is {@link Type#MODULE_INITIALIZATION_EXCEPTION
+ * <tt>MODULE_INITIALIZATION_EXCEPTION</tt>} but
+ * exception is {@code null}.</p></li>
+ * </ul></p>
*/
- public ModuleSystemEvent(ModuleSystem source, Type type, Module module) {
+ public ModuleSystemEvent(ModuleSystem source, Type type, Module module,
+ ModuleDefinition moduleDef, ModuleInitializationException exception) {
if (source == null)
throw new NullPointerException("source must not be null");
if (type == null)
throw new NullPointerException("type must not be null");
- if (module == null)
- throw new NullPointerException("module must not be null");
+ if ((type.equals(Type.MODULE_INITIALIZED) || type.equals(Type.MODULE_RELEASED))
+ && module == null)
+ throw new IllegalArgumentException("module must not be null with event type " + type);
- if (!(type.equals(Type.MODULE_INITIALIZED) || type.equals(Type.MODULE_RELEASED)))
- throw new IllegalArgumentException("type must not be " + type);
+ if (type.equals(Type.MODULE_DEFINITION_DISABLED) && moduleDef == null)
+ throw new IllegalArgumentException("moduleDef must not be null with event type " + type);
+
+ if (type.equals(Type.MODULE_INITIALIZATION_EXCEPTION) && exception == null)
+ throw new NullPointerException("exception must not be null with event type " + type);
this.type = type;
this.source = source;
this.module = module;
- this.moduleDef = module.getModuleDefinition();
- this.exception = null;
- }
-
- /**
- * Constructs a {@code ModuleSystemEvent} object with event type
- * {@code MODULE_DEFINITION_DISABLED}, using the specified module system
- * and module definition.
- *
- * @param source the module system where the event occurs
- * @param moduleDef the module definition that the event applies to
- * @throws NullPointerException if source is null, or moduleDef is null.
- *
- */
- public ModuleSystemEvent(ModuleSystem source, ModuleDefinition moduleDef) {
- if (source == null)
- throw new NullPointerException("source must not be null");
-
- if (moduleDef == null)
- throw new NullPointerException("moduleDef must not be null");
-
- this.type = ModuleSystemEvent.Type.MODULE_DEFINITION_DISABLED;
- this.source = source;
- this.module = null;
- this.moduleDef = moduleDef;
- this.exception = null;
- }
-
- /**
- * Constructs a {@code ModuleSystemEvent} object with event type
- * {@code MODULE_INITIALIZATION_EXCEPTION}, using the specified module
- * system, module definition, and module initialization exception.
- *
- * @param source the module system where the event occurs
- * @param moduleDef the module definition that the event applies to
- * @param exception module initialization exception
- * @throws NullPointerException if source is null, moduleDef is null, or
- * exception is null.
- */
- public ModuleSystemEvent(ModuleSystem source, ModuleDefinition moduleDef, ModuleInitializationException exception) {
- if (source == null)
- throw new NullPointerException("source must not be null");
-
- if (moduleDef == null)
- throw new NullPointerException("moduleDef must not be null");
-
- if (exception == null)
- throw new NullPointerException("exception must not be null");
-
- this.type = ModuleSystemEvent.Type.MODULE_INITIALIZATION_EXCEPTION;
- this.source = source;
- this.module = null;
- this.moduleDef = moduleDef;
+ if (module != null)
+ this.moduleDef = module.getModuleDefinition();
+ else {
+ this.moduleDef = moduleDef;
+ }
this.exception = exception;
}
@@ -164,7 +132,7 @@ public class ModuleSystemEvent {
}
/**
- * Returns the module system associated with the event.
+ * Returns the module system where the event occurs.
*/
public ModuleSystem getSource() {
return source;
--- a/src/share/classes/java/module/ModuleSystemListener.java Mon Jul 07 10:13:08 2008 -0700
+++ b/src/share/classes/java/module/ModuleSystemListener.java Tue Jul 08 12:14:10 2008 -0700
@@ -31,12 +31,16 @@ import java.util.EventListener;
* The listener interface for receiving module system events.
* <p>
* The class that is interested in processing module system events implements
- * this interface. Instances of that class register with a module system,
- * using the module system's {@code addModuleSystemListener} static method.
+ * this interface, and the object created with that class is registered, using
+ * the
+ * {@link ModuleSystem#addModuleSystemListener(ModuleSystemListener)
+ * <tt>addModuleSystemListener</tt>} method of the {@code ModuleSystem} class.
* <p>
* Listeners that are no longer interested in processing any module system
- * events can be unregistered with the module system, using the module system's
- * {@code removedModuleSystemListener} static method.
+ * events can be unregistered, using the
+ * {@link ModuleSystem#removeModuleSystemListener(ModuleSystemListener)
+ * <tt>removeModuleSystemListener</tt>} method of the {@code ModuleSystem}
+ * class.
*
* @see java.module.ModuleSystem
* @see java.module.ModuleSystemEvent
@@ -46,10 +50,7 @@ public interface ModuleSystemListener ex
public interface ModuleSystemListener extends EventListener {
/**
- * Invoked after a module instance has been initialized successfully, after
- * a module instance has been released successfully, after a module
- * initialization exception occurs, or after a module definition has been
- * disabled successfully.
+ * Invoked when a change has occurred in a module system.
*
* @param e module system event
*/
--- a/src/share/classes/java/module/ModuleSystemPermission.java Mon Jul 07 10:13:08 2008 -0700
+++ b/src/share/classes/java/module/ModuleSystemPermission.java Tue Jul 08 12:14:10 2008 -0700
@@ -30,7 +30,7 @@ import java.security.BasicPermission;
/**
* The permission which the {@code SecurityManager} will check when code that
* is running with a {@code SecurityManager} calls methods defined in the
- * module system for the Java platform.
+ * Java Module System.
* <P>
* The following table provides a summary description of what the permission
* allows, and discusses the risks of granting code the permission.
@@ -45,9 +45,18 @@ at the permission allows, and associated
* </tr>
*
* <tr>
+ * <td>createModuleSystem</td>
+ * <td>Creation of a module system.</td>
+ * <td>This is an extremely dangerous permission to grant. Malicious
+ * applications that can instantiate their own module systems could then
+ * load their rogue modules and classes into the system.</td>
+ * </tr>
+ * <tr>
* <td>releaseModule</td>
* <td>Releases an existing module instance from a module system via calls to
- * the {@code ModuleSystem}'s {@code releaseModule} method.</td>
+ * the {@code ModuleSystem}'s
+ * {@link ModuleSystem#releaseModule(ModuleDefinition)
+ * <tt>releaseModule</tt>} method.</td>
* <td>This is a dangerous permission to grant. Malicious applications could
* allow an attacker to release an existing module instance, so the
* runtime characteristics of the Java virtual machine is changed
@@ -56,7 +65,9 @@ at the permission allows, and associated
* <tr>
* <td>disableModuleDefinition</td>
* <td>Disables a module definition in a module system via calls to
- * the {@code ModuleSystem}'s {@code disableModuleDefinition} method.</td>
+ * the {@code ModuleSystem}'s
+ * {@link ModuleSystem#disableModuleDefinition(ModuleDefinition)
+ * <tt>disableModuleDefinition</tt>} method.</td>
* <td>This is an extremely dangerous permission to grant. Malicious
* applications could allow an attacker to perform denial-of-service
* attack by disabling a module definition, and the module system will be
@@ -66,20 +77,23 @@ at the permission allows, and associated
* <tr>
* <td>installModuleArchive</td>
* <td>Installs a module archive in a repository via calls to the
- * {@code Repository}'s {@code install} method.</td>
+ * {@code Repository}'s {@link Repository#install(URI)
+ * <tt>install</tt>} method.</td>
* <td>This allows an attacker to install malicious code into a repository.</td>
* </tr>
* <tr>
* <td>uninstallModuleArchive</td>
* <td>Uninstalls a module archive in a repository via calls to the
- * {@code Repository}'s {@code uninstall} method.</td>
+ * {@code Repository}'s {@link Repository#uninstall(ModuleArchiveInfo)
+ * <tt>uninstall</tt>} method.</td>
* <td>This allows an attacker to remove critical module definitions from a
* repository.</td>
* </tr>
* <tr>
* <td>listModuleArchive</td>
* <td>Discovers the installed module archives in a repository via calls
- * to the {@code Repository}'s {@code list} method.</td>
+ * to the {@code Repository}'s {@link Repository#list()
+ * <tt>list</tt>} method.</td>
* <td>This allows an attacker to discover the installed module archives in a
* repository.</td>
* </tr>
@@ -92,50 +106,72 @@ at the permission allows, and associated
* </tr>
* <tr>
* <td>shutdownRepository</td>
- * <td>Shutdown a repository.</td>
+ * <td>Shutdown a repository via calls
+ * to the {@code Repository}'s {@link Repository#shutdown()
+ * <tt>shutdown</tt>} method.</td>
* <td>This allows an attacker to shutdown a repository so the repository
* can no longer serve any module definition.</td>
* </tr>
* <tr>
* <td>reloadRepository</td>
- * <td>Reloads module definitions in a repository.</td>
+ * <td>Reloads module definitions in a repository via calls
+ * to the {@code Repository}'s {@link Repository#reload()
+ * <tt>reload</tt>} method.</td>
* <td>This allows an attacker to invalidate the lifetime of the outstanding
* module instances instantiated from the module definitions in the
* repository.</td>
* </tr>
* <tr>
* <td>accessModuleContent</td>
- * <td>Accesses the content of the module definition.</td>
+ * <td>Accesses the content of the module definition via calls
+ * to the {@code ModuleDefinition}'s {@link ModuleDefinition#getModuleContent()
+ * <tt>getModuleContent</tt>} method.</td>
* <td>This allows an attacker to have access to the actual content of the
* module definition, which may contain sensitive information internally.</td>
* </tr>
* <tr>
* <td>setImportOverridePolicy</td>
- * <td>Changes the default import override policy in the module system.</td>
+ * <td>Changes the default import override policy in the JAM module system via calls
+ * to the {@code Modules}'s
+ * {@link Modules#setImportOverridePolicy(ImportOverridePolicy)
+ * <tt>setImportOverridePolicy</tt>} method.</td>
+ * .</td>
* <td>This allows an attacker to choose specific versions of imported
* modules when a module instance is initialized.</td>
* </tr>
* <tr>
* <td>addModuleSystemListener</td>
- * <td>Adds a module system listener that listens to all module systems.</td>
+ * <td>Adds a module system listener that listens to all module systems via
+ * calls to the {@code ModuleSystem}'s
+ * {@link ModuleSystem#addModuleSystemListener(ModuleSystemListener)
+ * <tt>addModuleSystemListener</tt>} method.</td>
* <td>This allows an attacker to monitor the module system events in the
* module systems.</td>
* </tr>
* <tr>
* <td>removeModuleSystemListener</td>
- * <td>Removes a module system listener from listening to any module systems.</td>
+ * <td>Removes a module system listener from listening to any module system
+ * via calls to the {@code ModuleSystem}'s
+ * {@link ModuleSystem#removeModuleSystemListener(ModuleSystemListener)
+ * <tt>removeModuleSystemListener</tt>} method.</td>
* <td>This allows an attacker to remove a system-provided module system
* listener from the module systems.</td>
* </tr>
* <tr>
* <td>addRepositoryListener</td>
- * <td>Adds a repository listener that listens to all repositories.</td>
+ * <td>Adds a repository listener that listens to all repositories
+ * via calls to the {@code Repository}'s
+ * {@link Repository#addRepositoryListener(RepositoryListener)
+ * <tt>addRepositoryListener</tt>} method.</td>
* <td>This allows an attacker to monitor the repository events in the
* repositories.</td>
* </tr>
* <tr>
* <td>removeRepositoryListener</td>
- * <td>Removes a repository listener from listening to any repositories.</td>
+ * <td>Removes a repository listener from listening to any repository
+ * via calls to the {@code Repository}'s
+ * {@link Repository#removeRepositoryListener(RepositoryListener)
+ * <tt>removeRepositoryListener</tt>} method.</td>
* <td>This allows an attacker to remove a system-provided repository
* listener from the repositories.</td>
* </tr>
@@ -150,6 +186,10 @@ at the permission allows, and associated
* @see java.security.Permissions
* @see java.security.PermissionCollection
* @see java.lang.SecurityManager
+ * @see java.module.Modules
+ * @see java.module.ModuleDefinition
+ * @see java.module.ModuleSystem
+ * @see java.module.Repository
*
* @since 1.7
*/
--- a/src/share/classes/java/module/Modules.java Mon Jul 07 10:13:08 2008 -0700
+++ b/src/share/classes/java/module/Modules.java Tue Jul 08 12:14:10 2008 -0700
@@ -31,6 +31,7 @@ import java.util.List;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable;
+import sun.module.core.JamModuleDefinition;
import sun.module.config.DefaultImportOverridePolicy;
import sun.module.config.DefaultVisibilityPolicy;
import sun.module.config.ModuleSystemConfig;
@@ -39,22 +40,225 @@ import sun.module.repository.URLReposito
/**
* This class consists exclusively of static methods that are specifically for
- * the default module system. It contains methods which construct module
- * definitions that are defined by the default module system. It also contains
- * methods that construct the local repository and URL repository. In
- * addition, it contains methods for setting or getting the system's visibility
- * policy and import override policy.
- *
- * <p> Unless otherwise specified, passing a <tt>null</tt> argument to any
- * method in this class will cause a {@link NullPointerException} to be thrown.
+ * the JAM (JAva Module) modules in the JAM module system.
+ * <p>
+ * <h3> ModuleSystem implementation</h3>
+ * The JAM module system provides a concrete {@link ModuleSystem}
+ * implementation for JAM modules. Applications can obtain the
+ * {@code ModuleSystem} objects by calling the
+ * {@link getModuleSystem() <tt>getModuleSystem</tt>} method.
+ * <p>
+ * <h3> ModuleDefinition implementation</h3>
+ * The JAM module system provides a concrete {@link ModuleDefinition}
+ * implementation for JAM modules. Applications can obtain the
+ * {@code ModuleDefinition} objects by calling one of the
+ * {@link #newModuleDefinition(byte[], ModuleContent,Repository,boolean)
+ * <tt>newModuleDefinition</tt>} factory methods.
+ * <p>
+ * <h3> Repository implementations</h3>
+ * The JAM module system provides two concrete repository implementations:
+ * <i>Local repository</i> and <i>URL repository</i>.
+ * <p>
+ * <h4>Local Repository</h4>
+ * A <i>local repository</i> loads module definitions whose module archives
+ * are stored in a directory in the file system. This allows deployers to
+ * easily deploy module definitions into the repository by copying, ftp-ing,
+ * or dragging-and-dropping the module archives into a directory. This also
+ * facilitates sharing between different repositories if they process the
+ * module archives from the same directory. Hence, this directory is also
+ * called a <i>repository interchange directory</i>.
+ * <p>
+ * The policy for processing the module archives in the repository
+ * interchange directory is as follows:
+ * <ul>
+ * <li><p>Files whose names end in {@code .jam} that follow the naming
+ * convention scheme defined in Section 4.1 of the JAM Module
+ * System specification will be processed. Files whose names end
+ * in {@code .jam} but do not follow the naming convention scheme
+ * will be ignored. Files whose names end in
+ * {@code .jam.pack.gz}, {@code .jar}, {@code .zip} or other
+ * filename extensions would also be ignored.</p></li>
+ *
+ * <li><p>Files would be considered regardless of whether or not they
+ * are "hidden" in the UNIX sense, i.e., the files are stored
+ * under a directory and the name of the directory begins with
+ * {@code '.'}.</p></li>
+ *
+ * <li><p>Subdirectories would not be searched recursively, i.e.,
+ * if the directory is foo, the repository implementation should
+ * only looks for JAM files in {@code foo}, not in {@code foo/bar},
+ * {@code foo/baz}, etc.</p></li>
+ *
+ * <li><p>The order in which the JAM files are enumerated is not specified
+ * and may vary from platform to platform and even from invocation
+ * to invocation on the same machine. If there is more than one JAM
+ * file containing the same version of the module definition, the
+ * repository implementation should only load the first enumerated
+ * one, and ignore the others.</p></li>
+ * </ul>
+ * <p>
+ * Instances of this {@code Repository} can be constructed using one of the
+ * {@link #newLocalRepository(String, File, Map, Repository)
+ * <tt>newLocalRepository</tt>} factory methods, and the factory methods
+ * also invokes the {@code Repository}'s
+ * {@link Repository#initialize() <tt>initialize</tt>} method automatically.
+ * <p>
+ * Instance of this {@code Repository} is read-only if its <i>repository
+ * interchange directory</i> is read-only during repository
+ * initialization. Instance of this {@code Repository} also supports the
+ * {@link Repository#install(URI) <tt>install</tt>} and
+ * {@link Repository#uninstall(ModuleArchiveInfo) <tt>uninstall</tt>} operations
+ * if the {@code Repository} is not read-only.
+ * <p>
+ * Instance of this {@code Repository} supports reload. When the
+ * {@code Repository} instance is reloaded, the set of module archives
+ * in the <i>repository interchange directory</i> are checked against
+ * the set of module archives that were recognized during repository
+ * initialization to determine if the set of module archives and the
+ * set of module definitions should be changed. See
+ * {@link Repository#reload()} for more details.
+ * <p>
+ * Below is an example showing how to construct a <i>local repository</i> to
+ * search for a specific module definition:
+ * <pre>
+ * // Create a local repository instance. The source location is
+ * // interpreted by the repository implementation as a local directory
+ * // where the module definitions are stored. The local repository
+ * // instance is automatically initialized during construction.
+ * File file = new File("/home/wombat/repository");
+ * Repository repo = Modules.newLocalRepository("wombat", file, null);
+ *
+ * // Search org.foo.xml version 1.0.0 from the repository instance.
+ * ModuleDefinition moduleDef = repo.find("org.foo.xml", VersionConstraint.valueOf("1.0.0"));</pre>
+ *
+ * <h4>URL Repository</h4>
+ * A <i>URL repository</i> loads module definitions whose module archives
+ * are stored in a codebase URL, and it is designed to optimize loading
+ * through specific files and directories layout. <i>URL repository</i>
+ * is typically used to download module definitions from server, but it
+ * could also be used with a file-based URL.
+ * <p>
+ * Instance of this {@code Repository} can be constructed using one of the
+ * {@link #newURLRepository(String, URL, Map, Repository)
+ * <tt>newURLRepository</tt>} factory methods, and the factory methods also
+ * invokes the newly constructed {@code Repository}'s
+ * {@link Repository#initialize() <tt>initialize</tt>} method automatically.
+ * <p>
+ * Information about the module definitions available from the
+ * codebase URL must be published in a <i>repository metadata file</i>
+ * (i.e. {@code repository-metadata.xml}. The contents of the file must
+ * follow the schema of the URL Repository metadata described in the
+ * JAM Module System specification.
+ * <p>
+ * When this {@code Repository}is initialized, the repository metadata file
+ * (i.e. repository-metadata.xml) is downloaded from the codebase URL.
+ * <pre>
+ * {codebase}/repository-metadata.xml</pre>
+ * In the repository metadata file, each module definition is described
+ * with a name, a version, a platform binding, and a path (relative to
+ * the codebase URL where the JAM module metadata file, the module
+ * archive, and/or the packed module archive are located). If no path
+ * and no platform binding is specified, the default path is
+ * {@code "{name}/{version}"}. If the path is not specified and the
+ * module definition has platform binding, the default path is
+ * {@code "{name}/{version}/{platform}-{arch}"}.
+ * <p>
+ * After the {@code Repository} successfully downloads the repository
+ * metadata file, the JAM module metadata file of each module definition
+ * (i.e. {@code MODULE.METADATA file}) in the repository is downloaded
+ * based on the information in the <i>repository metadata file</i>:
+ * <pre>
+ * {codebase}/{path}/MODULE.METADATA</pre>
+ * If a module definition is platform-specific, its JAM module metadata file
+ * is downloaded if and only if the platform binding described in the
+ * <i>repository metadata file</i> matches the platform and the architecture
+ * of the system.
+ * <p>
+ * Module definitions are available for searches using one of the
+ * {@link Repository#find(Query) <tt>find</tt>} methods after the
+ * {@code Repository} instance is initialized. If a module instance is
+ * instantiated from a module definition that has no platform binding, the
+ * module archive is downloaded by probing in the following order:
+ * <pre>
+ * {codebase}/{path}/{name}-{version}.jam.pack.gz
+ * {codebase}/{path}/{name}-{version}.jam</pre>
+ * On the other hand, if a module instance is instantiated from a
+ * platform-specific module definition, the module archive is
+ * downloaded by probing in the following order:
+ * <pre>
+ * {codebase}/{path}/{name}-{version}-{platform}-{arch}.jam.pack.gz
+ * {codebase}/{path}/{name}-{version}-{platform}-{arch}.jam</pre>
+ * To ensure the integrity of the separately-hosted JAM module metadata
+ * file is in sync with that in the module archive of the same module
+ * definition, they are compared bit-wise against each other after the
+ * module archive is downloaded when the module instance is
+ * instantiated from the module definition. If these JAM module metadata
+ * files are not in sync, the instantiation of the module definition
+ * will fail.
+ * <p>
+ * Instance of this {@code Repository} is read-only unless the codebase
+ * URL is a file-based URL which represents a writable directory on the
+ * file system. Instance of this {@code Repository}
+ * supports the {@link Repository#install(java.net.URI) <tt>install</tt>} and
+ * {@link Repository#uninstall(ModuleArchiveInfo) <tt>uninstall</tt>} operations
+ * when the {@code Repository} is not read-only.
+ * <p>
+ * Instance of this {@code Repository} supports reload. When the
+ * {@code Repository} instance is reloaded, the timestamp of the
+ * <i>repository metadata file</i> is checked against the timestamp of
+ * the same file that was downloaded during repository initialization.
+ * If the timestamps are identical, there is no change in the set of
+ * module archives and the set of module definitions in the repository.
+ * Otherwise, all existing module archives and module definitions in
+ * the repository are removed, the repository metadata file is downloaded,
+ * and the module definitions described in the <i>repository metadata file</i>
+ * are downloaded and are available for subsequent searches.
+ * See {@link Repository#reload()} for more details.
+ * <p>
+ * Below is an example showing how to construct a <i>URL repository</i> to
+ * search for a specific module definition:
+ * <pre>
+ * // Create a URL repository instance. The source location is
+ * // interpreted by the repository implementation as the codebase
+ * // where the module definitions are downloaded on demand based on
+ * // requests. The URL repository instance is automatically initialized
+ * // during construction.
+ * //
+ * URL url = new URL("http://x.y.z/");
+ * Repository repo = Modules.newURLRepository("x.y.z", url, null);
+ *
+ * // Search org.foo.xml version 1.3.0 from the repository instance.
+ * ModuleDefinition moduleDef = repo.find("org.foo.xml", VersionConstraint.valueOf("1.3.0"));</pre>
+ *
+ * <h3> Module dependency and package dependency implementations</h3>
+ * The JAM module system provides a concrete implementation for
+ * {@link ModuleDependency} and another concrete implementation for
+ * {@link PackageDependency}. Instances of the {@code ModuleDependency}
+ * can be created using the
+ * {@link #newModuleDependency(String, VersionConstraint, boolean, boolean, Map)
+ * <tt>newModuleDependency</tt>} method, and
+ * instances of the {@code PackageDependency} can be created using the
+ * {@link #newPackageDependency(String, VersionConstraint, boolean, boolean, Map)
+ * <tt>newPackageDependency</tt>} method.
+ * <p>
+ * <h3> Import override policy</h3>
+ * The JAM module system allows deployers to narrow the version constraints
+ * in the import dependencies of a specific module definition using
+ * {@link ImportOverridePolicy} to control the resolution during module
+ * initialization.
+ * <p>
+ * The system's import override policy can be obtained using the
+ * {@link getImportOverridePolicy()
+ * <tt>getImportOverridePolicy</tt>} method. The system's import override policy
+ * can be changed using the {@link setImportOverridePolicy(ImportOverridePolicy)
+ * <tt>setImportOverridePolicy</tt>} method.
* <p>
* @see java.module.ImportOverridePolicy
* @see java.module.Module
* @see java.module.ModuleDefinition
- * @see java.module.ModuleSystemEvent;
+ * @see java.module.ModuleSystemEvent
* @see java.module.ModuleSystemPermission
* @see java.module.Repository
- * @see java.module.VisibilityPolicy
*
* @since 1.7
*/
@@ -70,6 +274,9 @@ public class Modules {
getVisibilityPolicy();
}
+ // ModuleSystem implementation for JAM module system.
+ private static ModuleSystem defaultImpl = null;
+
// Default import override policy
private static ImportOverridePolicy importOverridePolicy;
@@ -82,67 +289,109 @@ public class Modules {
}
/**
- * Constructs and initializes a new {@code Repository} instance that loads
- * module definitions from a directory on the file system.
+ * Returns the JAM module system.
+ *
+ * @return the JAM module system.
+ */
+ public static synchronized ModuleSystem getModuleSystem() {
+ if (defaultImpl == null) {
+ defaultImpl = sun.module.core.ModuleSystemImpl.INSTANCE;
+ }
+ return defaultImpl;
+ }
+
+ /**
+ * Constructs a new {@code ModuleDependency} instance.
+ *
+ * @param name the name of the imported module.
+ * @param constraint the version constraint.
+ * @param reexport true if the imported module is re-exported; otherwise, false.
+ * @param optional true if the module dependency is optional; otherwise, false.
+ * @param attributes map of attributes in the module dependency; null if no
+ * attributes.
+ * @throws NullPointerException if name is null or constraint is null.
+ */
+ public static ModuleDependency newModuleDependency(String name, VersionConstraint constraint,
+ boolean reexport, boolean optional,
+ Map<String, String> attributes) {
+ return new sun.module.core.JamModuleDependency(name, constraint, reexport, optional, attributes);
+ }
+
+ /**
+ * Constructs a new {@code PackageDependency} instance.
+ *
+ * @param name the name of the package.
+ * @param constraint the version constraint.
+ * @param reexport true if the imported package is re-exported; otherwise, false.
+ * @param optional true if the package dependency is optional; otherwise, false.
+ * @param attributes map of attributes in the package depdenency; null if no
+ * attributes.
+ * @throws NullPointerException if name is null or constraint is null.
+ */
+ public static PackageDependency newPackageDependency(String name, VersionConstraint constraint,
+ boolean reexport, boolean optional,
+ Map<String, String> attributes) {
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ /**
+ * Constructs a new {@code Repository} instance that loads module
+ * archives from a directory on the file system, and initializes
+ * using information from the given {@code config}.
+ * <p>
+ * If {@code config} is null, the configuration is ignored.
* <p>
* If a security manager is present, this method calls the security
* manager's {@code checkPermission} method with
* {@code ModuleSystemPermission("createRepository")} permission to
* ensure it's ok to create a repository.
*
- * @param parent the parent repository for delegation.
* @param name the repository name.
* @param source the directory on the file system.
- * @return a new {@coder Repository} instance.
- * @throws SecurityException if a security manager exists and
- * its {@code checkPermission} method denies access
- * to create a new {@code Repository} instance.
- * @throws IOException if the repository cannot be constructed and
- * initialized.
- * @throws IllegalArgumentException if a circularity is detected.
- */
- public static Repository newLocalRepository(Repository parent, String name, File source)
- throws IOException {
- return new LocalRepository(parent, name, source.toURI().toURL());
- }
-
- /**
- * Constructs and initializes a new {@code Repository} instance that loads
- * module definitions from a directory on the file system. Equivalent to:
- * <pre>
- * newLocalRepository(Repository.getSystemRepository(), name, source);
- * </pre>
- * If a security manager is present, this method calls the security
- * manager's {@code checkPermission} method with
- * {@code ModuleSystemPermission("createRepository")} permission to
- * ensure it's ok to create a repository.
- *
- * @param name the repository name.
- * @param source the directory on the file system.
+ * @param config Map of configuration names to their values
+ * @param parent the parent repository for delegation.
* @return a new {@code Repository} instance.
* @throws SecurityException if a security manager exists and
* its {@code checkPermission} method denies access
* to create a new repository instance.
+ * @throws NullPointerException if name is null, source is null, or
+ * parent is null.
* @throws IOException if the repository cannot be constructed and
* initialized.
- */
- public static Repository newLocalRepository(String name, File source)
+ * @throws IllegalArgumentException if a circularity is detected.
+ */
+ public static Repository newLocalRepository(String name,
+ File source,
+ Map<String, String> config,
+ Repository parent)
throws IOException {
- return new LocalRepository(Repository.getSystemRepository(), name,
- source.toURI().toURL());
+ if (name == null) {
+ throw new NullPointerException("name must not be null.");
+ }
+ if (source == null) {
+ throw new NullPointerException("source must not be null.");
+ }
+ if (parent == null) {
+ throw new NullPointerException("parent must not be null.");
+ }
+
+ return new LocalRepository(name, source.toURI(), config, parent);
}
/**
* Constructs a new {@code Repository} instance that loads module
* definitions from a directory on the file system, and initializes
- * using information from the given {@code config}.
+ * the repository using information from the given {@code config}.
+ * Equivalent to:
+ * <pre>
+ * newLocalRepository(name, codebase, config, Repository.getSystemRepository());</pre>
+ * If {@code config} is null, the configuration is ignored.
* <p>
* If a security manager is present, this method calls the security
* manager's {@code checkPermission} method with
* {@code ModuleSystemPermission("createRepository")} permission to
* ensure it's ok to create a repository.
*
- * @param parent the parent repository for delegation.
* @param name the repository name.
* @param source the directory on the file system.
* @param config Map of configuration names to their values
@@ -150,157 +399,79 @@ public class Modules {
* @throws SecurityException if a security manager exists and
* its {@code checkPermission} method denies access
* to create a new repository instance.
- * @throws IOException if the repository cannot be constructed and
- * initialized.
- * @throws IllegalArgumentException if a circularity is detected.
- */
- public static Repository newLocalRepository(Repository parent, String name,
- File source, Map<String, String> config)
- throws IOException {
- return new LocalRepository(parent, name, source.toURI().toURL(), config);
- }
-
- /**
- * Constructs a new {@code Repository} instance that loads module
- * definitions from a directory on the file system, and initializes
- * using information from the given {@code config}. Equivalent to:
- * <pre>
- * newLocalRepository(Repository.getSystemRepository(), name, source, config);
- * </pre>
- * If a security manager is present, this method calls the security
- * manager's {@code checkPermission} method with
- * {@code ModuleSystemPermission("createRepository")} permission to
- * ensure it's ok to create a repository.
- *
- * @param name the repository name.
- * @param source the directory on the file system.
- * @param config Map of configuration names to their values
- * @return a new {@code Repository} instance.
- * @throws SecurityException if a security manager exists and
- * its {@code checkPermission} method denies access
- * to create a new repository instance.
+ * @throws NullPointerException if name is null or source is null.
* @throws IOException if the repository cannot be constructed and
* initialized.
*/
public static Repository newLocalRepository(String name, File source,
Map<String, String> config)
throws IOException {
- return new LocalRepository(Repository.getSystemRepository(), name,
- source.toURI().toURL(), config);
- }
-
- /**
- * Constructs and initializes a new repository instance that loads
+ if (name == null) {
+ throw new NullPointerException("name must not be null.");
+ }
+ if (source == null) {
+ throw new NullPointerException("source must not be null.");
+ }
+
+ return new LocalRepository(name, source.toURI(), config,
+ Repository.getSystemRepository());
+ }
+
+ /**
+ * Constructs and initializes a new {@code Repository} instance that loads
* module definitions from a codebase URL.
- * <p>
- * Information about the module definitions available from the
- * codebase URL must be published in a repository metadata file. The
- * contents of the file must follow the schema of the URL Repository
- * metadata described in the Java Module System specification.
- * <p><i>
- * {codebase}/repository-metadata.xml
- * <p></i>
- * When the repository is initialized, the repository metadata file
- * (i.e. repository-metadata.xml) would be downloaded from the
- * codebase URL.
- * <p>
- * In the repository metadata file, each module definition is described
- * with a name, a version, a platform binding, and a path (relative to
- * the codebase URL where the module file, the module archive, and/or
- * the packed module archive are located). If no path and no platform
- * binding is specified, the default path is "{name}/{version}". If the
- * path is not specified and the module definition has platform
- * binding, the default path is "{name}/{version}/{platform}-{arch}".
- * <p>
- * After the repository instance successfully downloads the repository
- * metadata file, the module file of each module definition
- * (i.e. MODULE.METADATA file) in the repository is downloaded based on
- * the information in the repository metadata file:
- * <p><i>
- * {codebase}/{path}/MODULE.METADATA
- * <p></i>
- * If a module definition is platform-specific, its module file is
- * downloaded if and only if the platform binding described in the
- * repository metadata file matches the platform and the architecture
- * of the system.
- * <p>
- * Module definitions are available for searches after the repository
- * instance is initialized. If a module instance is instantiated from a
- * module definition that has no platform binding, the module archive is
- * downloaded by probing in the following order:
- * <p><i>
- * {codebase}/{path}/{name}-{version}.jam.pack.gz<p>
- * {codebase}/{path}/{name}-{version}.jam
- * <p></i>
- * On the other hand, if a module instance is instantiated from a
- * platform-specific module definition, the module archive is
- * downloaded by probing in the following order:
- * <p><i>
- * {codebase}/{path}/{name}-{version}-{platform}-{arch}.jam.pack.gz<p>
- * {codebase}/{path}/{name}-{version}-{platform}-{arch}.jam
- * <p></i>
- * To ensure the integrity of the separately-hosted module file is in
- * sync with that in the module archive of the same module definition,
- * they are compared bit-wise against each other after the module
- * archive is downloaded.
* <p>
* If a security manager is present, this method calls the security
* manager's {@code checkPermission} method with a
* {@code ModuleSystemPermission("createRepository")} permission to ensure
* it's ok to create a repository.
*
- * @param parent the parent repository for delegation.
* @param name the repository name.
* @param codebase the source location.
+ * @param config Map of configuration names to their values
+ * @param parent the parent repository for delegation.
* @return a new {@code Repository} instance.
* @throws SecurityException if a security manager exists and
* its {@code checkPermission} method denies access
* to create a new repository instance.
+ * @throws NullPointerException if name is null, codebase is null,
+ * or parent is null.
* @throws IOException if the repository cannot be constructed and
* initialized.
* @throws IllegalArgumentException if a circularity is detected.
*/
- public static Repository newURLRepository(Repository parent, String name, URL codebase)
+ public static Repository newURLRepository(String name, URL codebase,
+ Map<String, String> config,
+ Repository parent)
throws IOException {
- return new URLRepository(parent, name, codebase);
- }
-
- /**
- * Constructs and initializes a new {@code Repository} instance that loads
- * module definitions from a codebase URL. Equivalent to:
+ if (name == null) {
+ throw new NullPointerException("name must not be null.");
+ }
+ if (codebase == null) {
+ throw new NullPointerException("source must not be null.");
+ }
+ if (parent == null) {
+ throw new NullPointerException("parent must not be null.");
+ }
+
+ try {
+ return new URLRepository(name, codebase.toURI(), config, parent);
+ } catch (java.net.URISyntaxException ex) {
+ throw new IOException(ex);
+ }
+ }
+
+ /**
+ * Constructs a new {@code Repository} instance that loads module
+ * definitions from a codebase URL, and initializes using information
+ * from the given {@code config}. Equivalent to:
* <pre>
- * newURLRepository(Repository.getSystemRepository(), name, codebase);
- * </pre>
- * If a security manager is present, this method calls the security
- * manager's {@code checkPermission} method with
- * {@code ModuleSystemPermission("createRepository")} permission to
- * ensure it's ok to create a repository.
- *
- * @param name the repository name.
- * @param codebase the source location.
- * @return a new {@code Repository} instance.
- * @throws SecurityException if a security manager exists and its
- * {@code checkPermission} method denies access to create a new
- * repository instance.
- * @throws IOException if the repository cannot be constructed and
- * initialized.
- */
- public static Repository newURLRepository(String name, URL codebase)
- throws IOException {
- return new URLRepository(Repository.getSystemRepository(), name, codebase);
- }
-
- /**
- * Constructs a new repository instance that loads module definitions
- * from a codebase URL, and initializes using information from the
- * given {@code config}.
- * <p>
+ * newURLRepository(name, codebase, config, Repository.getSystemRepository());</pre>
* If a security manager is present, this method calls the
* security manager's {@code checkPermission} method with
* a {@code ModuleSystemPermission("createRepository")}
* permission to ensure it's ok to create a repository.
*
- * @param parent the parent repository for delegation.
* @param name the repository name.
* @param codebase the source location.
* @param config Map of configuration names to their values
@@ -308,42 +479,14 @@ public class Modules {
* @throws SecurityException if a security manager exists and
* its {@code checkPermission} method denies access
* to create a new instance of repository.
- * @throws IOException if the repository cannot be constructed and
- * initialized.
- * @throws IllegalArgumentException if a circularity is detected.
- */
- public static Repository newURLRepository(Repository parent, String name,
- URL codebase, Map<String, String> config)
- throws IOException {
- return new URLRepository(parent, name, codebase, config);
- }
-
- /**
- * Constructs a new repository instance that loads module definitions
- * from a codebase URL, and initializes using information from the
- * given {@code config}. Equivalent to:
- * <pre>
- * newURLRepository(Repository.getSystemRepository(), name, codebase, config);
- * </pre>
- * If a security manager is present, this method calls the
- * security manager's {@code checkPermission} method with
- * a {@code ModuleSystemPermission("createRepository")}
- * permission to ensure it's ok to create a repository.
- *
- * @param name the repository name.
- * @param codebase the source location.
- * @param config Map of configuration names to their values
- * @return a new repository instance.
- * @throws SecurityException if a security manager exists and
- * its {@code checkPermission} method denies access
- * to create a new instance of repository.
+ * @throws NullPointerException if name is null or codebase is null.
* @throws IOException if the repository cannot be constructed and
* initialized.
*/
public static Repository newURLRepository(String name, URL codebase,
Map<String, String> config)
throws IOException {
- return new URLRepository(Repository.getSystemRepository(), name, codebase, config);
+ return newURLRepository(name, codebase, config, Repository.getSystemRepository());
}
/**
@@ -432,7 +575,7 @@ public class Modules {
*
* @return the system's default visibility policy for module definitions.
*/
- public synchronized static VisibilityPolicy getVisibilityPolicy() {
+ synchronized static VisibilityPolicy getVisibilityPolicy() {
if (visibilityPolicy == null) {
try {
@@ -477,27 +620,25 @@ public class Modules {
}
/**
- * Returns a new {@code ModuleDefinition} for modules based on the Java
- * Module System's module metadata file format described in the Java
- * Module System specification.
+ * Constructs a new {@code ModuleDefinition} instance for a JAM module.
*
* <p>This method will typically be called by repository implementations
* and not by applications.
*
* @param metadata an array of bytes which is the content of the
- * {@code MODULE-INF/METADATA.MODULE} file
+ * module metadata file
* @param content the {@code ModuleContent} to be used to access the
- * contents of the module archive
- * @param repository the {@code Repository} in which the module archive is
- * stored
+ * contents of the module definition
+ * @param repository the {@code Repository} in which the module definition
+ * is associated with
* @param moduleReleasable true if the module instance instantiated from
* this {@code ModuleDefinition} is releasable from its module
* system
- * @throws ModuleFormatException if the contents of {@code metadata}
- * are not recognized or are not well formed.
+ * @throws ModuleFormatException if the content of module metadata file
+ * is not recognized or is not well formed.
* @return a new {@code ModuleDefinition}.
*/
- public static ModuleDefinition newJamModuleDefinition(byte[] metadata,
+ public static ModuleDefinition newModuleDefinition(byte[] metadata,
ModuleContent content, Repository repository, boolean moduleReleasable)
throws ModuleFormatException {
if (metadata == null) {
@@ -510,13 +651,12 @@ public class Modules {
throw new NullPointerException("repository must not be null.");
}
return new JamModuleDefinition
- (null, null, metadata, null, content, repository, moduleReleasable);
- }
-
- /**
- * Returns a new {@code ModuleDefinition} for modules based on the Java
- * Module System's module metadata file format described in the Java
- * Module System specification.
+ (getModuleSystem(),
+ null, null, metadata, null, content, repository, moduleReleasable);
+ }
+
+ /**
+ * Constructs a new {@code ModuleDefinition} instance for a JAM module.
*
* <p>This method will typically be called by repository implementations
* and not by applications. It is useful in case the metadata has not
@@ -528,15 +668,15 @@ public class Modules {
* {@code MODULE-INF/METADATA.MODULE} file can be retrieved
* as an array of bytes
* @param content the {@code ModuleContent} to be used to access the
- * contents of the module archive
- * @param repository the {@code Repository} in which the module archive is
- * stored
+ * contents of the module definition
+ * @param repository the {@code Repository} in which the module definition
+ * is associated with
* @param moduleReleasable true if the module instance instantiated from
* this {@code ModuleDefinition} is releasable from the module
* system
* @return a new {@code ModuleDefinition}.
*/
- public static ModuleDefinition newJamModuleDefinition(String name, Version version,
+ public static ModuleDefinition newModuleDefinition(String name, Version version,
Callable<byte[]> metadataHandle, ModuleContent content,
Repository repository, boolean moduleReleasable) {
if (name == null) {
@@ -555,6 +695,7 @@ public class Modules {
throw new NullPointerException("repository must not be null.");
}
return new JamModuleDefinition
- (name, version, null, metadataHandle, content, repository, moduleReleasable);
+ (getModuleSystem(), name, version, null,
+ metadataHandle, content, repository, moduleReleasable);
}
}
--- a/src/share/classes/java/module/PackageDefinition.java Mon Jul 07 10:13:08 2008 -0700
+++ b/src/share/classes/java/module/PackageDefinition.java Tue Jul 08 12:14:10 2008 -0700
@@ -77,7 +77,6 @@ public abstract class PackageDefinition
* annotation type
* @return this {@code PackageDefinition}'s annotation for the specified
* annotation type if present, else null
- * @throws NullPointerException if the given annotation class is null
*/
public abstract <T extends Annotation> T getAnnotation(Class<T> annotationClass);
--- a/src/share/classes/java/module/Query.java Mon Jul 07 10:13:08 2008 -0700
+++ b/src/share/classes/java/module/Query.java Tue Jul 08 12:14:10 2008 -0700
@@ -41,13 +41,10 @@ import java.util.Set;
* Composition of calls can construct arbitrary nestings of constraints, as
* the following example illustrates:</p>
* <pre>
- * Query query = Query.and(Query.module("com.wombat.webservice", "2.0.0+"),
+ * Query query = Query.and(Query.module("com.wombat.webservice"),
* Query.annotation(ServiceProviders.class));
* </pre>
*
- * <p> Unless otherwise specified, passing a <tt>null</tt> argument to any
- * method in this class will cause a {@link NullPointerException} to be thrown.
- * <p>
* @see java.module.ModuleDefinition
* @see java.module.VersionConstraint
* @since 1.7
@@ -67,9 +64,20 @@ public abstract class Query implements S
private static final Query MATCH_NONE = new NoneQuery();
/**
- * A {@code Query} object that matches everything.
+ * A {@code Query} object that matches any module definition.
*/
public static final Query ANY = MATCH_ALL;
+
+
+ /**
+ * Index hints based on the name of the module definition.
+ */
+ public static final String MODULE_NAME_INDEX_HINTS = "MODULE_NAME_INDEX_HINTS";
+
+ /**
+ * Index hints based on the name of the exported package in a module definition.
+ */
+ public static final String EXPORTED_PACKAGE_NAME_INDEX_HINTS = "EXPORTED_PACKAGE_NAME_INDEX_HINTS";
/**
* @serial include
@@ -77,13 +85,16 @@ public abstract class Query implements S
private static class AllQuery extends Query {
private static final long serialVersionUID = 4847340912937723526L;
public boolean match(ModuleDefinition moduleDef) {
+ if (moduleDef == null) {
+ throw new NullPointerException();
+ }
return true;
}
- public Set<String> getIndexableModuleNames() {
- return null;
- }
- public Set<String> getIndexablePackageNames() {
- return null;
+ public Set<String> getIndexHints(String indexType) {
+ if (indexType == null) {
+ throw new NullPointerException();
+ }
+ throw new UnsupportedOperationException();
}
public boolean equals(Object obj) {
return (obj instanceof AllQuery);
@@ -102,12 +113,15 @@ public abstract class Query implements S
private static class NoneQuery extends Query {
private static final long serialVersionUID = 469940504421183286L;
public boolean match(ModuleDefinition moduleDef) {
+ if (moduleDef == null) {
+ throw new NullPointerException();
+ }
return false;
}
- public Set<String> getIndexableModuleNames() {
- return Collections.emptySet();
- }
- public Set<String> getIndexablePackageNames() {
+ public Set<String> getIndexHints(String indexType) {
+ if (indexType == null) {
+ throw new NullPointerException();
+ }
return Collections.emptySet();
}
public boolean equals(Object obj) {
@@ -142,13 +156,13 @@ public abstract class Query implements S
name = s.readUTF();
constraint = VersionConstraint.valueOf(s.readUTF());
}
- public Set<String> getIndexableModuleNames() {
+ public Set<String> getIndexHints(String indexType) {
+ if (indexType.equals(MODULE_NAME_INDEX_HINTS) == false) {
+ throw new UnsupportedOperationException();
+ }
Set<String> indexableNames = new HashSet<String>();
indexableNames.add(name);
return Collections.unmodifiableSet(indexableNames);
- }
- public Set<String> getIndexablePackageNames() {
- return null;
}
public boolean match(ModuleDefinition moduleDef) {
return moduleDef.getName().equals(name)
@@ -200,10 +214,10 @@ public abstract class Query implements S
name = s.readUTF();
constraint = VersionConstraint.valueOf(s.readUTF());
}
- public Set<String> getIndexableModuleNames() {
- return null;
- }
- public Set<String> getIndexablePackageNames() {
+ public Set<String> getIndexHints(String indexType) {
+ if (indexType.equals(IndexType.EXPORTED_PACKAGE_NAME) == false) {
+ throw new UnsupportedOperationException();
+ }
Set<String> indexableNames = new HashSet<String>();
indexableNames.add(name);
return Collections.unmodifiableSet(indexableNames);
@@ -268,11 +282,11 @@ public abstract class Query implements S
else
return (v.equals(value));
}
- public Set<String> getIndexableModuleNames() {
- return null;
- }
- public Set<String> getIndexablePackageNames() {
- return null;
+ public Set<String> getIndexHints(String indexType) {
+ if (indexType == null) {
+ throw new NullPointerException();
+ }
+ throw new UnsupportedOperationException();
}
public boolean equals(Object obj) {
if (!(obj instanceof AttributeQuery))
@@ -314,11 +328,11 @@ public abstract class Query implements S
// No match if annotation is not present.
return (annotation != null);
}
- public Set<String> getIndexableModuleNames() {
- return null;
- }
- public Set<String> getIndexablePackageNames() {
- return null;
+ public Set<String> getIndexHints(String indexType) {
+ if (indexType == null) {
+ throw new NullPointerException();
+ }
+ throw new UnsupportedOperationException();
}
public boolean equals(Object obj) {
if (!(obj instanceof AnnotationQuery))
@@ -348,11 +362,11 @@ public abstract class Query implements S
public boolean match(ModuleDefinition moduleDef) {
return !query.match(moduleDef);
}
- public Set<String> getIndexableModuleNames() {
- return null;
- }
- public Set<String> getIndexablePackageNames() {
- return null;
+ public Set<String> getIndexHints(String indexType) {
+ if (indexType == null) {
+ throw new NullPointerException();
+ }
+ throw new UnsupportedOperationException();
}
public boolean equals(Object obj) {
if (!(obj instanceof NotQuery))
@@ -385,31 +399,26 @@ public abstract class Query implements S
public boolean match(ModuleDefinition moduleDef) {
return query1.match(moduleDef) && query2.match(moduleDef);
}
- public Set<String> getIndexableModuleNames() {
- Set<String> indexableNames1 = query1.getIndexableModuleNames();
- Set<String> indexableNames2 = query2.getIndexableModuleNames();
- if (indexableNames1 == null) {
- return indexableNames2;
- } else if (indexableNames2 == null) {
- return indexableNames1;
- } else {
- Set<String> result = new HashSet<String>(indexableNames1);
- result.retainAll(indexableNames2);
- return Collections.unmodifiableSet(result);
- }
- }
- public Set<String> getIndexablePackageNames() {
- Set<String> indexableNames1 = query1.getIndexablePackageNames();
- Set<String> indexableNames2 = query2.getIndexablePackageNames();
- if (indexableNames1 == null) {
- return indexableNames2;
- } else if (indexableNames2 == null) {
- return indexableNames1;
- } else {
- Set<String> result = new HashSet<String>(indexableNames1);
- result.retainAll(indexableNames2);
- return Collections.unmodifiableSet(result);
- }
+ public Set<String> getIndexHints(String indexType) {
+ if (indexType == null) {
+ throw new NullPointerException();
+ }
+
+ Set<String> indexHints1, indexHints2;
+ try {
+ indexHints1 = query1.getIndexHints(indexType);
+ } catch (UnsupportedOperationException e) {
+ return query2.getIndexHints(indexType);
+ }
+ try {
+ indexHints2 = query2.getIndexHints(indexType);
+ } catch (UnsupportedOperationException e) {
+ return indexHints1;
+ }
+
+ Set<String> result = new HashSet<String>(indexHints1);
+ result.retainAll(indexHints2);
+ return Collections.unmodifiableSet(result);
}
public boolean equals(Object obj) {
if (!(obj instanceof AndQuery))
@@ -447,31 +456,14 @@ public abstract class Query implements S
public boolean match(ModuleDefinition moduleDef) {
return query1.match(moduleDef) || query2.match(moduleDef);
}
- public Set<String> getIndexableModuleNames() {
- Set<String> indexableNames1 = query1.getIndexableModuleNames();
- Set<String> indexableNames2 = query2.getIndexableModuleNames();
- if (indexableNames1 == null) {
- return indexableNames2;
- } else if (indexableNames2 == null) {
- return indexableNames1;
- } else {
- Set<String> result = new HashSet<String>(indexableNames1);
- result.addAll(indexableNames2);
- return Collections.unmodifiableSet(result);
- }
- }
- public Set<String> getIndexablePackageNames() {
- Set<String> indexableNames1 = query1.getIndexablePackageNames();
- Set<String> indexableNames2 = query2.getIndexablePackageNames();
- if (indexableNames1 == null) {
- return indexableNames2;
- } else if (indexableNames2 == null) {
- return indexableNames1;
- } else {
- Set<String> result = new HashSet<String>(indexableNames1);
- result.addAll(indexableNames2);
- return Collections.unmodifiableSet(result);
- }
+ public Set<String> getIndexHints(String indexType) {
+
+ Set<String> indexHints1 = query1.getIndexHints(indexType);
+ Set<String> indexHints2 = query2.getIndexHints(indexType);
+
+ Set<String> result = new HashSet<String>(indexHints1);
+ result.addAll(indexHints2);
+ return Collections.unmodifiableSet(result);
}
public boolean equals(Object obj) {
if (!(obj instanceof OrQuery))
@@ -512,13 +504,14 @@ public abstract class Query implements S
}
/**
- * Returns a {@code Query} that is the conjunction of two other queries.
+ * Returns a {@code Query} that is the conjunction of two or more queries.
*
* @param query1 A query.
* @param query2 Another query.
- * @return the {@code Query} object.
- */
- public static Query and(Query query1, Query query2) {
+ * @param queries Additional queries.
+ * @return the {@code Query} object.
+ */
+ public static Query and(Query query1, Query query2, Query... queries) {
if (query1 == null)
throw new NullPointerException("query1 must not be null.");
if (query2 == null)
@@ -534,19 +527,24 @@ public abstract class Query implements S
if (query1 == MATCH_NONE || query2 == MATCH_NONE)
return MATCH_NONE;
+
// ----
-
- return new AndQuery(query1, query2);
- }
-
- /**
- * Returns a {@code Query} that is the disjunction of two other queries.
+ Query result = new AndQuery(query1, query2);
+ for (Query q : queries) {
+ result = new AndQuery(result, q);
+ }
+ return result;
+ }
+
+ /**
+ * Returns a {@code Query} that is the disjunction of two or more queries.
*
* @param query1 A query.
* @param query2 Another query.
- * @return the {@code Query} object.
- */
- public static Query or(Query query1, Query query2) {
+ * @param queries Additional queries.
+ * @return the {@code Query} object.
+ */
+ public static Query or(Query query1, Query query2, Query... queries) {
if (query1 == null)
throw new NullPointerException("query1 must not be null.");
if (query2 == null)
@@ -562,9 +560,13 @@ public abstract class Query implements S
if (query2 == MATCH_NONE)
return query1;
+
// ----
-
- return new OrQuery(query1, query2);
+ Query result = new OrQuery(query1, query2);
+ for (Query q : queries) {
+ result = new OrQuery(result, q);
+ }
+ return result;
}
/**
@@ -601,26 +603,6 @@ public abstract class Query implements S
}
/**
- * Returns a {@code Query} that requires the name of a module definition
- * equals to the specified name and that the version of a module definition
- * to be contained within any of the ranges known to the specified version
- * constraint.
- *
- * @param name the name of the module definition.
- * @param constraint the string to be parsed as version constraint.
- * @return the {@code Query} object.
- * @throws IllegalArgumentException if the string cannot be parsed.
- */
- public static Query module(String name, String constraint) {
- if (name == null)
- throw new NullPointerException("name must not be null.");
- if (constraint == null)
- throw new NullPointerException("version constraint must not be null.");
-
- return module(name, VersionConstraint.valueOf(constraint));
- }
-
- /**
* Returns a {@code Query} that requires the specified name of a module attribute
* exists.
*
@@ -635,14 +617,14 @@ public abstract class Query implements S
}
/**
- * Returns a {@code Query} that requires an attribute of a module definition
- * matches the specified name and value.
- *
- * @param name the name of the module attribute.
+ * Returns a {@code Query} that requires a module attribute of a module
+ * definition matches the specified name and value.
+ *
+ * @param name the name of the module attribute.
* @param value the value of the module attribute.
* @return the {@code Query} object.
*/
- public static Query attribute(String name, String value) {
+ public static Query attribute(String name, String value) {
if (name == null)
throw new NullPointerException("attribute's name must not be null.");
if (value == null)
@@ -703,28 +685,6 @@ public abstract class Query implements S
*/
/**
- * Returns a {@code Query} that requires a module definition to have an
- * exported package definition of the specified name and that the version
- * of the package definition to be contained within any of the ranges known
- * to the specified version constraint.
- *
- * @param name the name of the package definition
- * @param constraint the string to be parsed as version constraint.
- * @return the {@code Query} object.
- * @throws IllegalArgumentException if the string cannot be parsed.
- */
-/*
- public static Query exportedPackage(String name, String constraint) {
- if (name == null)
- throw new NullPointerException("name must not be null.");
- if (constraint == null)
- throw new NullPointerException("version constraint must not be null.");
-
- return exportedPackage(name, VersionConstraint.valueOf(constraint));
- }
-*/
-
- /**
* Determine if the specified module definition matches this query.
*
* @param target the {@code ModuleDefinition} to be matched.
@@ -734,33 +694,19 @@ public abstract class Query implements S
public abstract boolean match(ModuleDefinition target);
/**
- * Returns an unmodifiable set of the indexable names of the module
- * definitions that is represented by this query.
- *
- * This method is intended to be used by the repository implementation as
- * an optimization to determine a set of module definitions that matches
- * this query, solely based on the requirement on the module names.
- *
- * @return an unmodifiable set of indexable module names if it exists;
- * returns null otherwise. If the set is empty, no module
- * definition would match this query.
- */
- public abstract Set<String> getIndexableModuleNames();
-
- /**
- * Returns an unmodifiable set of the indexable names of the package
- * definitions that is represented by this query.
- *
- * This method is intended to be used by the repository implementation as
- * an optimization to determine a set of module definitions that have
- * exported package definitions which match this query, solely based on
- * the requirement on the package names.
- *
- * @return an unmodifiable set of indexable package names if it exists;
- * returns null otherwise. If the set is empty, no module
- * definition would match this query.
- */
- private Set<String> getIndexablePackageNames() {
- return null;
- }
+ * Returns an unmodifiable set of strings that represent the index hints
+ * in the query based on the specified index type.
+ *
+ * This method is intended to be used by the repository implementations
+ * as an optimization technique to determine a set of module definitions
+ * that matches this query based on index.
+ *
+ * @param indexType index type
+ * @return an unmodifiable set of strings that represent the index
+ * hints if they exist in the query. If the query matches no
+ * module definition, an empty set is returned.
+ * @throws UnsupportedOperationException if no index hints is
+ * available for the specified index type.
+ */
+ public abstract Set<String> getIndexHints(String indexType);
}
--- a/src/share/classes/java/module/Repository.java Mon Jul 07 10:13:08 2008 -0700
+++ b/src/share/classes/java/module/Repository.java Tue Jul 08 12:14:10 2008 -0700
@@ -22,35 +22,67 @@
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
-
package java.module;
import java.io.IOException;
-import java.net.URL;
+import java.net.URI;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
import java.util.List;
+import java.util.Set;
import java.util.concurrent.Executors;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.ThreadFactory;
import sun.module.bootstrap.BootstrapRepository;
+import sun.module.config.DefaultVisibilityPolicy;
import sun.module.repository.RepositoryConfig;
/**
- * This class represents a repository. A repository is a mechanism for storing,
- * discovering, and retrieving module definitions that can be used by a module
- * system.
+ * This class represents a repository. A repository is responsible for
+ * storing, discovering, and retrieving {@linkplain ModuleDefinition module
+ * definitions}.
+ * <p>
+ * A {@code Repository} is {@linkplain #isActive active} when it has been
+ * {@linkplain #initialize() initialized} but not {@linkplain #shutdown()
+ * shutdown}. When a repository is no longer needed, a program should
+ * shutdown the repository to release the resources.
+ * <p>
+ * The {@code Repository} class uses a delegation model to search for
+ * module definitions. Each instance of {@code Repository} has an associated
+ * parent repository. When requested to find a module definition, a
+ * {@code Reposiory} instance will delegate the search for the
+ * module definition to its parent repository before attempting to find
+ * the module definition itself. The virtual machine's built-in repository,
+ * called the <i>bootstrap repository</i>, does not itself have a parent
+ * but may serve as the parent of a {@code Repository} instance.
+ * <p>
+ * The system's {@linkplain #getVisibilityPolicy visibility policy} controls
+ * which module definitions be visible in a repository.
+ * <p>
+ * Applications implement subclasses of {@code Repository} in order to
+ * extend the manner in which the Java virtual machine dynamically
+ * finds module definitions. Typically, repository implementors
+ * should override the
+ * {@link #doInitialize()} and {@link #doShutdown()} methods.
+ * <p>
+ * There are two default repositories provided by the Java platform: the
+ * <i>bootstrap repository</i> and the <i>system repository</i>. The
+ * <i>bootstrap repository</i> exposes the standard module definitions
+ * for the Java platform and is the only repository that does not have
+ * a parent. All module definitions whose name begins with "java." must
+ * be exposed by the <i>bootstrap repository</i>. The <i>system
+ * repository</i> is the default parent for new {@code Repository} instances.
*
- * <p> Unless otherwise specified, passing a <tt>null</tt> argument to any
- * method in this class will cause a {@link NullPointerException} to be thrown.
- * <p>
* @see java.module.ModuleDefinition
* @see java.module.ModuleSystemPermission
* @see java.module.Query
* @see java.module.RepositoryEvent
* @see java.module.RepositoryListener
* @see java.module.VersionConstraint
+ * @see java.module.VisibilityPolicy
*
* @since 1.7
*/
@@ -58,9 +90,21 @@ public abstract class Repository {
private final Repository parent;
private final String name;
- private final URL source;
-
- private final ModuleSystem system;
+ private final URI source;
+
+ /**
+ * Internal data structures for the repository.
+ */
+ private volatile List<ModuleDefinition> moduleDefs =
+ new ArrayList<ModuleDefinition>();
+ private volatile List<ModuleArchiveInfo> moduleArchiveInfos =
+ new ArrayList<ModuleArchiveInfo>();
+
+ /** True if this repository has been initialized but not yet shutdown. */
+ private boolean active;
+
+ /** True if this repository has been shutdown. */
+ private boolean shutdown;
/** Listeners of RepositoryEvents. */
private static RepositoryListener repositoryListener = null;
@@ -87,36 +131,28 @@ public abstract class Repository {
* {@code ModuleSystemPermission("createRepository")} permission to ensure
* it's ok to create a repository.
*
- * @param parent the parent repository for delegation.
* @param name the repository name.
* @param source the source location.
- * @param system the module system with which the module definitions in the
- * repository are associated.
+ * @param parent the parent repository for delegation.
* @throws SecurityException if a security manager exists and its
* {@code checkPermission} method denies access to create a new
* repository instance.
- * @throws IllegalArgumentException if a circularity is detected.
- */
- protected Repository(Repository parent, String name, URL source, ModuleSystem system) {
+ * @throws IllegalArgumentException if a circularity among the same
+ * repsoitory is detected.
+ */
+ protected Repository(String name, URI source, Repository parent) {
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
sm.checkPermission(new ModuleSystemPermission("createRepository"));
}
-
+ if (source == null && !(this instanceof BootstrapRepository)) {
+ throw new NullPointerException("source must not be null.");
+ }
+ if (name == null) {
+ throw new NullPointerException("name must not be null.");
+ }
if (parent == null && !(this instanceof BootstrapRepository)) {
throw new NullPointerException("parent must not be null.");
- }
-
- if (source == null && !(this instanceof BootstrapRepository)) {
- throw new NullPointerException("source must not be null.");
- }
-
- if (name == null) {
- throw new NullPointerException("name must not be null.");
- }
-
- if (system == null) {
- throw new NullPointerException("system must not be null.");
}
Repository theParent = parent;
@@ -130,11 +166,12 @@ public abstract class Repository {
this.parent = parent;
this.name = name;
this.source = source;
- this.system = system;
- }
-
- /**
- * Creates a {@code Repository} instance.
+ }
+
+ /**
+ * Creates a {@code Repository} instance with the
+ * {@linkplain #getSystemRepository system repository} as the
+ * parent for delegation.
* <p>
* If a security manager is present, this method calls the security
* manager's {@code checkPermission} method with
@@ -143,15 +180,12 @@ public abstract class Repository {
*
* @param name the repository name.
* @param source the source location.
- * @param system the module system with which the module definitions in the
- * repository are associated.
* @throws SecurityException if a security manager exists and its
* {@code checkPermission} method denies access to create a new
* instance of repository.
- * @throws IllegalArgumentException if a circularity is detected.
- */
- protected Repository(String name, URL source, ModuleSystem system) {
- this(getSystemRepository(), name, source, system);
+ */
+ protected Repository(String name, URI source) {
+ this(name, source, getSystemRepository());
}
/**
@@ -168,13 +202,13 @@ public abstract class Repository {
*
* @return the source location.
*/
- public final URL getSourceLocation() {
+ public final URI getSourceLocation() {
return source;
}
/**
- * Returns the parent repository for delegation. If this is the bootstrap
- * repository, its parent is null.
+ * Returns the parent repository for delegation. This method will return
+ * {@code null} if this repository is the bootstrap repository.
*
* @return the parent {@code Repository}.
*/
@@ -183,19 +217,10 @@ public abstract class Repository {
}
/**
- * Returns the {@code ModuleSystem} associated with the module definitions
- * in this {@code Repository}.
- *
- * @return the {@code ModuleSystem} associated with the module definitions
- * in this {@code Repository}.
- */
- public final ModuleSystem getModuleSystem() {
- return system;
- }
-
- /**
- * Returns the bootstrap repository. This is the repository provided by
- * the Java Runtime.
+ * Returns the bootstrap repository.
+ * <p>
+ * The bootstrap repository is an implementation-dependent instance of
+ * this class , and it is provided by the Java Runtime.
*
* @return the bootstrap repository.
*/
@@ -204,8 +229,12 @@ public abstract class Repository {
}
/**
- * Returns the system repository. This is the default delegation parent
- * for new {@code Repository} instances.
+ * Returns the system repository for delegation. This is the default
+ * delegation parent for new {@code Repository} instances, and is
+ * typically the repository used to start the application.
+ * <p>
+ * The system repository is an implementation-dependent instance of
+ * this class, and it is provided by the Java Runtime.
*
* @return the system repository.
*/
@@ -214,35 +243,217 @@ public abstract class Repository {
}
/**
- * Initializes this {@code Repository}.
- *
+ * Returns the system's default visibility policy for module definitions
+ * in the repositories.
+ * <p>
+ * The default class of the visibility policy can be overridden using the
+ * {@code java.module.visibility.policy.classname} system property.
+ *
+ * @return the system's default visibility policy for module definitions.
+ */
+ public static VisibilityPolicy getVisibilityPolicy() {
+ return Modules.getVisibilityPolicy();
+ }
+
+ /**
+ * Initializes this {@code Repository}. This method should be overridden
+ * by repository implementations as follows:
+ * <p><ol>
+ * <li><p> If this {@code Repository} is {@linkplain #isActive() active},
+ * return.</p></li>
+ *
+ * <li><p> If this {@code Repository} has been
+ * {@linkplain #shutdown() shutdown},
+ * throws an {@code IllegalStateException}.</p></li>
+ *
+ * <li><p> Perform the actual initialization and this is repository
+ * implementation specific. Fire a single
+ * {@link RepositoryEvent.Type#MODULE_DEFINITION_ADDED
+ * <tt>MODULE_DEFINITION_ADDED</tt>} event if there is one or
+ * more module definitions constructed during initialization.
+ * </p></li>
+ *
+ * <li><p> Fire a {@link RepositoryEvent.Type#REPOSITORY_INITIALIZED
+ * <tt>REPOSITORY_INITIALIZED</tt>} event.</p></li>
+ * </ol>
+ *
+ * The default implementation of this method initializes the repository as
+ * follows:
+ * <p><ol>
+ * <li><p> If this {@code Repository} is {@linkplain #isActive() active},
+ * return.</p></li>
+ *
+ * <li><p> If this {@code Repository} has been
+ * {@linkplain #shutdown() shutdown},
+ * throws an {@code IllegalStateException}.</p></li>
+ *
+ * <li><p> Invoke the {@link #doInitialize()} method.</p></li>
+ *
+ * <li><p> Fire a {@link RepositoryEvent.Type#REPOSITORY_INITIALIZED
+ * <tt>REPOSITORY_INITIALIZED</tt>} event.</p></li>
+ * </ol>
+ *
+ * <p> Subclasses of <tt>Repository</tt> are encouraged to override {@link
+ * #doInitialize()} method, rather than this method.</p>
+ *
+ * @throws IllegalStateException if this {@code Repository} has been
+ * shutdown.
* @throws IOException if an I/O error occurs.
- * @throws IllegalStateException if this {@code Repository} has been
- * initialized or has been shutdown.
- */
- public abstract void initialize() throws IOException;
-
- /**
- * Shutdown this {@code Repository}.
+ */
+ public synchronized void initialize() throws IOException {
+ if (active) {
+ return; // initialize only once
+ }
+ if (shutdown) {
+ throw new IllegalStateException("Repository is already shutdown");
+ }
+
+ moduleArchiveInfos = Collections.unmodifiableList(doInitialize());
+
+ active = true;
+
+ // Send REPOSITORY_INITIALIZED event
+ RepositoryEvent evt2 = new RepositoryEvent(this,
+ RepositoryEvent.Type.REPOSITORY_INITIALIZED, null, null);
+ processEvent(evt2);
+ }
+
+
+ /**
+ * Initializes this {@code Repository}. This method should be overridden
+ * by repository implementations to initialize the repository by load
+ * module archives and construct module definitions, and will be invoked
+ * by the {@link #initialize()} method.
* <p>
- * If a security manager is present, this method calls the security
- * manager's {@code checkPermission} method with a
- * {@code ModuleSystemPermission("shutdownRepository")} permission to
- * ensure it's ok to shutdown this {@code Repository}.
+ * If the module archives are loaded successfully by this method,
+ * the implementation should return the information of the module archives
+ * as a list of {@code ModuleArchiveInfo}s. The implementation should NOT
+ * invoke the {@link #addModuleArchiveInfo(ModuleArchiveInfo)} method with
+ * the information of the module archives.
+ * <p>
+ * If new module definition(s) are constructed successfully by this method,
+ * the implementation should add the module definitions to this
+ * {@code Repository} by invoking the
+ * {@link #addModuleDefinitions(Set)} method or the
+ * {@link #addModuleDefinition(ModuleDefinition)} method.
+ * <p>
+ * The default implementation of this method throws an {@code IOException}.
+ *
+ * @return a list of {@code ModuleArchiveInfo}s that represents the module
+ * archives loaded during initialization.
+ * @throws IOException if an I/O error occurs.
+ * @see #initialize()
+ */
+ protected List<ModuleArchiveInfo> doInitialize() throws IOException {
+ throw new IOException("Repository's initialization is not yet implemented.");
+ }
+
+
+ /**
+ * Shutdown this {@code Repository}. This method should be overridden by
+ * repository implementations as follows:
+ * <p><ol>
+ * <li><p> If a security manager is present, calls the security
+ * manager's {@code checkPermission} method with a
+ * {@code ModuleSystemPermission("shutdownRepository")}
+ * permission to ensure it's ok to shutdown this
+ * {@code Repository}.</p></li>
+ *
+ * <li><p> If this {@code Repository} is not
+ * {@linkplain #isActive() active},
+ * throws an {@code IllegalStateException}.</p></li>
+ *
+ * <li><p> Perform the actual shutdown and this is repository
+ * implementation specific.</p></li>
+ *
+ * <li><p> For each module definition in this {@code Repository}, invoke
+ * its module system's
+ * {@link ModuleSystem#disableModuleDefinition(ModuleDefinition)
+ * <tt>disableModuleDefinition(ModuleDefinition)</tt>}
+ * method and {@link ModuleSystem#releaseModule(ModuleDefinition)
+ * <tt>releaseModule(ModuleDefinition)</tt>} method.</p></li>
+ *
+ * <li><p> Fire a single {@link RepositoryEvent.Type#MODULE_DEFINITION_REMOVED
+ * <tt>MODULE_DEFINITION_REMOVED</tt>} event if there is one or
+ * more module definitions in this {@code Repository}.</p></li>
+ *
+ * <li><p> Fire a {@link RepositoryEvent.Type#REPOSITORY_SHUTDOWN
+ * <tt>REPOSITORY_SHUTDOWN</tt>} event.</p></li>
+ * </ol>
+ *
+ * The default implementation of this method shutdown the repository as follows:
+ * <p><ol>
+ * <li><p> If a security manager is present, calls the security
+ * manager's {@code checkPermission} method with a
+ * {@code ModuleSystemPermission("shutdownRepository")}
+ * permission to ensure it's ok to shutdown this
+ * {@code Repository}.</p></li>
+ *
+ * <li><p> If this {@code Repository} is not
+ * {@linkplain #isActive() active},
+ * throws an {@code IllegalStateException}.</p></li>
+ *
+ * <li><p> Invoke the {@link #doShutdown()} method.</p></li>
+ *
+ * <li><p> Invoke the {@link #removeModuleDefinitions(Set)}
+ * method with the set of module definitions in this
+ * {@code Repository}.</p></li>
+ *
+ * <li><p> Fire a {@link RepositoryEvent.Type#REPOSITORY_SHUTDOWN
+ * <tt>REPOSITORY_SHUTDOWN</tt>} event.</p></li>
+ * </ol>
+ *
+ * <p> Subclasses of <tt>Repository</tt> are encouraged to override {@link
+ * #doShutdown()}, rather than this method.</p>
*
* @throws SecurityException if a security manager exists and its
* {@code checkPermission} method denies access to shutdown this
* {@code Repository}.
+ * @throws IllegalStateException if this {@code Repository} is not active.
* @throws IOException if an I/O error occurs.
- * @throws IllegalStateException if this {@code Repository} has not been
- * initialized or has been shutdown.
- */
- public abstract void shutdown() throws IOException;
+ */
+ public synchronized void shutdown() throws IOException {
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null) {
+ sm.checkPermission(new ModuleSystemPermission("shutdownRepository"));
+ }
+ if (shutdown) {
+ return; // shutdown only once
+ }
+ assertActive();
+
+ doShutdown();
+
+ removeModuleDefinitions(new HashSet<ModuleDefinition>(moduleDefs));
+
+ moduleDefs = null;
+ moduleArchiveInfos = null;
+
+ active = false;
+ shutdown = true;
+
+ // Send REPOSITORY_SHUTDOWN event
+ RepositoryEvent evt2 = new RepositoryEvent(this,
+ RepositoryEvent.Type.REPOSITORY_SHUTDOWN, null, null);
+ processEvent(evt2);
+ }
+
+ /**
+ * Shutdown this {@code Repository}. This method should be overridden
+ * by repository implementations, and will be invoked by the
+ * {@link #shutdown()} method. The default implementation is a no-op.
+ *
+ * @throws IOException if an I/O error occurs.
+ * @see #shutdown()
+ */
+ protected void doShutdown() throws IOException {
+ // no-op
+ }
/**
* Enable or disable that this {@code Repository} is shutdown when the
- * module system terminates. Shutdown will be attempted only during the
- * normal termination of the virtual machine, as defined by the Java
+ * Java Module System terminates. Shutdown will be attempted only during
+ * the normal termination of the virtual machine, as defined by the Java
* Language Specification. By default, shutdown on exit is disabled.
* <p>
* If a security manager is present, this method calls the security
@@ -254,6 +465,7 @@ public abstract class Repository {
* @throws SecurityException if a security manager exists and its
* {@code checkPermission} method denies access to shutdown this
* {@code Repository}.
+ * @see #shutdown()
*/
public final synchronized void shutdownOnExit(final boolean value) {
SecurityManager sm = System.getSecurityManager();
@@ -294,59 +506,77 @@ public abstract class Repository {
}
/**
- * Returns whether or not this {@code Repository} is active. A repository
- * instance is active if it has been initialized but has not been shutdown.
- *
- * @return true if this repository instance is active; otherwise, returns
+ * Returns whether or not this {@code Repository} is active. A
+ * {@code Repository} is active when it has been
+ * {@linkplain #initialize() initialized} but not
+ * {@linkplain #shutdown() shutdown}. This method should be overridden
+ * by subclasses of {@code Repository} if the {@link initialize()} and
+ * {@link shutdown()} methods are also overridden.
+ *
+ * @return true if this {@code Repository} is active; otherwise, returns
* false.
- */
- public abstract boolean isActive();
-
- /**
- * Returns whether or not this {@code Repository} is read-only.
+ * @see #initialize()
+ * @see #shutdown()
+ */
+ public synchronized boolean isActive() {
+ return active;
+ }
+
+ /**
+ * Returns whether or not this {@code Repository} is read-only. This method
+ * should be overridden by repository implementations. The default
+ * implementation returns {@code true}.
*
* @return true if this {@code Repository} is read-only; otherwise, returns
* false.
*/
- public abstract boolean isReadOnly();
-
- /**
- * Returns whether or not this {@code Repository} supports reload
- * of module definitions.
+ public boolean isReadOnly() {
+ return true;
+ }
+
+ /**
+ * Returns whether or not this {@code Repository} supports reload of
+ * module archives. This method should be overridden by repository
+ * implementations. The default implementation returns {@code false}.
*
* @return true if this {@code Repository} supports reload; otherwise,
* returns false.
* @see #reload()
*/
- public abstract boolean supportsReload();
-
- /**
- * Find a module definition. Equivalent to:
+ public boolean supportsReload() {
+ return false;
+ }
+
+ /**
+ * Find a module definition across multiple repositories through
+ * the delegation model. Equivalent to:
* <pre>
- * find(moduleName, VersionConstraint.DEFAULT);
- * </pre>
+ * find(name, VersionConstraint.DEFAULT);</pre>
+ *
* @param name the module definition's name.
- * @return the module definition or null if not found. If more than one
- * module definition matches the specified name, the highest
- * version is returned.
- * @throws IllegalStateException if this {@code Repository} has not been
- * initialized or if it has been shutdown.
+ * @return the module definition that matches the specified name and
+ * version constraint, or null if there is no match.
+ * @throws IllegalStateException if this {@code Repository} is not active.
+ * @see #find(String, VersionConstraint)
*/
public final ModuleDefinition find(String name) {
- assertActive();
return find(name, VersionConstraint.DEFAULT);
}
/**
- * Find a module definition.
+ * Find a module definition across multiple repositories through the
+ * delegation model. Equivalent to:
+ * <pre>
+ * find(Query.module(name, versionConstraint))</pre>
+ * and returns only the highest version if more than one module definition
+ * matches the specified name and version constraint.
*
* @param name the module definition's name.
* @param versionConstraint the version constraint.
- * @return the module definition or null if not found. If more than one
- * module definition matches the specified name and version
- * constraint, the highest version is returned.
- * @throws IllegalStateException if this {@code Repository} has not been
- * initialized or if it has been shutdown.
+ * @return the module definition that matches the specified name and
+ * version constraint, or null if there is no match.
+ * @throws IllegalStateException if this {@code Repository} is not active.
+ * @see #find(Query)
*/
public final ModuleDefinition find(String name, VersionConstraint versionConstraint) {
assertActive();
@@ -371,13 +601,14 @@ public abstract class Repository {
}
/**
- * Find all module definitions. Equivalent to:
+ * Find all module definitions across multiple repositories through the
+ * delegation model. Equivalent to:
* <pre>
- * find(Query.ANY);
- * </pre>
- * @return the list of matching module definitions.
- * @throws IllegalStateException if this {@code Repository} has not been
- * initialized or if it has been shutdown.
+ * find(Query.ANY);</pre>
+ *
+ * @return a list of module definitions.
+ * @throws IllegalStateException if this {@code Repository} is not active.
+ * @see #find(Query)
*/
public final List<ModuleDefinition> findAll() {
assertActive();
@@ -385,12 +616,49 @@ public abstract class Repository {
}
/**
- * Find all matching module definitions that match the specified constraint.
+ * Find all matching module definitions across multiple repositories
+ * through the delegation model. This method performs the following:
+ * <p><ol>
+ * <li><p> Invoke the {@link #getParent()} method to determine the
+ * parent repository.</p></li>
+ *
+ * <li><p> If the parent repository is {@code null}, invoke
+ * the {@link #findModuleDefinitions(Query)} method to obtain
+ * the set of module definitions and return.</p></li>
+ *
+ * <li><p> Invoke the {@link #find(Query)} method of the parent
+ * repository to obtain the set of module definitions
+ * <i>P</i>.</p></li>
+ *
+ * <li><p> Invoke the {@link #findModuleDefinitions(Query)} method
+ * to obtain the set of module definitions <i>C</i>.</p></li>
+ *
+ * <li><p> If the name of any module definition in <i>C</i> begins with
+ * "java.", throw a {@code SecurityException}.</p></li>
+ *
+ * <li><p> For each module definition in <i>C</i>, invoke the
+ * {@link VisibilityPolicy#isVisible(ModuleDefinition)
+ * <tt>isVisible()</tt>} method of the {@link VisibilityPolicy}
+ * object returned from {@link #getVisibilityPolicy()} to
+ * determine if the module definition is visible. If not,
+ * remove the module definition from <i>C</i>.</p></li>
+ *
+ * <li><p> Determine the set of module definitions <i>R</i> as
+ * follows:</p></li>
+ * <ul>
+ * <li><p> All module definitions in <i>P</i> are in <i>R</i>.</p></li>
+ * <li><p> For each module definition in <i>C</i>, it is in
+ * <i>R</i> if and only if the module definition with the
+ * same name and version is not present in <i>P</i>.</p></li>
+ * </ul>
+ *
+ * <li><p> Return <i>R</i> as the result.</p></li>
+ * </ol></p>
*
* @param constraint the constraint.
* @return the list of matching module definitions.
- * @throws IllegalStateException if this {@code Repository} has not been
- * initialized or if it has been shutdown.
+ * @throws IllegalStateException if this {@code Repository} is not active.
+ * @see #findModuleDefinitions(Query)
*/
public final List<ModuleDefinition> find(Query constraint) {
assertActive();
@@ -409,7 +677,7 @@ public abstract class Repository {
result.addAll(parentModuleDefs);
// Obtains system's visibility policy
- VisibilityPolicy vp = Modules.getVisibilityPolicy();
+ VisibilityPolicy vp = getVisibilityPolicy();
// Iterates each module definition in this repository
for (ModuleDefinition moduleDef : thisModuleDefs) {
@@ -443,116 +711,519 @@ public abstract class Repository {
/**
* Find all matching module definitions in this {@code Repository}. This
- * method must be implemented by repository implementations for finding
- * matching module definitions, and will be invoked by the
- * {@link #find} method after checking the parent repository for the
- * requested module definitions.
+ * method should be overridden by repository implementations only for
+ * optimization, and will be invoked by the {@link #find(Query)} method.
+ * The default implementation determines the result by matching each
+ * module definition in this {@code Repository} with the specified
+ * constraint.
*
* @param constraint the constraint.
* @return the list of matching module definitions.
- * @throws IllegalStateException if this {@code Repository} has not been
- * initialized or has been shutdown.
- */
- protected abstract List<ModuleDefinition> findModuleDefinitions(Query constraint);
+ * @throws IllegalStateException if this {@code Repository} is not active.
+ * @see find(Query)
+ */
+ protected synchronized List<ModuleDefinition> findModuleDefinitions(Query constraint) {
+ assertActive();
+
+ if (constraint == Query.ANY) {
+ return moduleDefs;
+ } else {
+ List<ModuleDefinition> result = new ArrayList<ModuleDefinition>();
+ for (ModuleDefinition md : moduleDefs) {
+ if (md != null && constraint.match(md)) {
+ result.add(md);
+ }
+ }
+ return result;
+ }
+ }
/**
* Returns an unmodifiable list of the installed module archives'
- * information in this {@code Repository}. The list will contain a snapshot
- * of the installed module archives in this {@code Repository} at the time
- * of the given invocation of this method.
- * <p>
- * If a security manager is present, this method calls the security
- * manager's {@code checkPermission} method with a
- * {@code ModuleSystemPermission("listModuleArchive")} permission to
- * ensure it's ok to return the information of the installed module
- * archives in this {@code Repository}.
- *
- * @return an unmodifiable list of the installed module archives'
- * information.
+ * information in this {@code Repository}. This method should be overridden
+ * and implemented by repository implementations as follows:
+ * <p><ul>
+ * <li><p> If a security manager is present, calls the security
+ * manager's {@code checkPermission} method with a
+ * {@code ModuleSystemPermission("listModuleArchive")} permission
+ * to ensure it's ok to return the information of the installed
+ * module archives in this {@code Repository}.</p></li>
+ *
+ * <li><p> If this {@code Repository} is not
+ * {@linkplain #isActive() active},
+ * throws an {@code IllegalStateException}.</p></li>
+ *
+ * <li><p> Invoke the {@link #getModuleArchiveInfos()} method to
+ * determine the list of {@code ModuleArchiveInfo}s, and return
+ * the result.</p></li>
+ * </ul>
+ * The default implementation of this method throws an
+ * {@code UnsupportedOperationException}.
+ *
+ * @return an unmodifiable list of {@code ModuleArchiveInfo}.
* @throws SecurityException if a security manager exists and its
* <tt>checkPermission</tt> method denies access to return the
* information of the installed module archives.
- * @throws IllegalStateException if this {@code Repository} has not been
- * initialized or it has been shutdown.
- */
- public abstract List<ModuleArchiveInfo> list();
-
- /**
- * Install a module archive with the module definition into this
- * {@code Repository}.
- * <p>
- * If a security manager is present, this method calls the security
- * manager's {@code checkPermission} method with a
- * {@code ModuleSystemPermission("installModuleArchive")} permission
- * to ensure it's ok to install a module archive into this
- * {@code Repository}.
- *
- * @param url the URL to the module archive.
+ * @throws UnsupportedOperationException if {@code Repository} does not
+ * support this operation.
+ * @throws IllegalStateException if this {@code Repository} is not active.
+ */
+ public List<ModuleArchiveInfo> list() {
+ throw new UnsupportedOperationException("Repository does not support the list operation.");
+ }
+
+ /**
+ * Install a module archive into this {@code Repository}. This method
+ * should be overridden by repository implementations as follows:
+ * <p><ol>
+ * <li><p> If a security manager is present, calls the security
+ * manager's {@code checkPermission} method with a
+ * {@code ModuleSystemPermission("installModuleArchive")} permission
+ * to ensure it's ok to return the information of the installed
+ * module archives in this {@code Repository}.</p></li>
+ *
+ * <li><p> If {@code uri} is {@code null}, throws a
+ * {@code NullPointerException}.</p></li>
+ *
+ * <li><p> If this {@code Repository} is not
+ * {@linkplain #isActive() active},
+ * throws an {@code IllegalStateException}.</p></li>
+ *
+ * <li><p> Invoke the {@link #isReadOnly()} method to check if this
+ * {@code Repository} is read-only. If it returns {@code false},
+ * throws an {@code UnsupportedOperationException}.</p></li>
+ *
+ * <li><p> Perform the actual installation of the module archive and this
+ * is repository implementation specific.</p></li>
+ *
+ * <li><p> If the module archive is installed successfully, invoke the
+ * {@link #addModuleArchiveInfo(ModuleArchiveInfo)} method.
+ * </p></li>
+ * </ol>
+ *
+ * <p> If the repository implementations change the set of module
+ * definitions after the installation of the module archive, they should
+ * perform the following:
+ * <p><ul>
+ * <li><p> If a new module definition is added, invoke the
+ * {@link #addModuleDefinition(ModuleDefinition)} method with
+ * that module definition.
+ * </p></li>
+ *
+ * <li><p> If an existing module definition is replaced, invoke the
+ * {@link #removeModuleDefinition(ModuleDefinition)}
+ * method with the old module definition, and invoke the
+ * {@link #addModuleDefinition(ModuleDefinition)}
+ * method with the new module definition.</p></li>
+ * </ul>
+ * The default implementation of this method throws an
+ * {@code UnsupportedOperationException}.
+ *
+ * @param uri the URI to the module archive.
* @return the {@code ModuleArchiveInfo} object that represents the
* installed module archive.
* @throws SecurityException if a security manager exists and its
* {@code checkPermission} method denies access to install a
* module archive in this {@code Repository}.
- * @throws UnsupportedOperationException if {@code Repository} is
- * read-only.
- * @throws IOException if an error occurs while installing the module
- * archive.
+ * @throws UnsupportedOperationException if {@code Repository} does
+ * not support this operation.
* @throws ModuleFormatException if the module archive format is not
* supported by this implementation.
- * @throws IllegalStateException if a module definition with the same name,
- * version and platform binding is already installed, or if this
- * {@code Repository} has not been initialized or it has been
- * shutdown.
- */
- public abstract ModuleArchiveInfo install(URL url) throws IOException;
-
- /**
- * Uninstall a module archive from this {@code Repository}.
- * <p>
- * If a security manager is present, this method calls the security
- * manager's {@code checkPermission} method with a
- * {@code ModuleSystemPermission("uninstallModuleArchive")}
- * permission to ensure it's ok to uninstall a module archive from this
- * {@code Repository}.
- *
- * @param m the module archive to be uninstalled.
+ * @throws IllegalStateException if the same module archive is
+ * already installed, or if this
+ * {@code Repository} is not active.
+ * @throws IOException if an I/O error occurs while installing the module
+ * archive.
+ */
+ public ModuleArchiveInfo install(URI uri) throws IOException {
+ throw new UnsupportedOperationException("Repository does not support the install operation.");
+ }
+
+ /**
+ * Uninstall a module archive from this {@code Repository}. This method
+ * should be overridden by repository implementations as follows:
+ * <p><ol>
+ * <li><p> If a security manager is present, calls the security
+ * manager's {@code checkPermission} method with a
+ * {@code ModuleSystemPermission("uninstallModuleArchive")}
+ * permission to ensure it's ok to return the information of the
+ * installed module archives in this {@code Repository}.</p></li>
+ *
+ * <li><p> If {@code mai} is {@code null}, throws a
+ * {@code NullPointerException}.</p></li>
+ *
+ * <li><p> If this {@code Repository} is not
+ * {@linkplain #isActive active},
+ * throws an {@code IllegalStateException}.</p></li>
+ *
+ * <li><p> Invoke the {@link #isReadOnly()} method to check if this
+ * {@code Repository} is read-only. If it returns {@code false},
+ * throws an {@code UnsupportedOperationException}.</p></li>
+ *
+ * <li><p> Perform the actual uninstallation of the module archive and
+ * this is repository implementation specific.</p></li>
+ *
+ * <li><p> If the module archive is uninstalled successfully, invoke the
+ * {@link #removeModuleArchiveInfo(ModuleArchiveInfo)} method.
+ * </p></li>
+ * </ol>
+ *
+ * <p> If the repository implementations change the set of module
+ * definitions after the uninstallation of the module archive, they
+ * should perform the following:
+ * <p><ul>
+ * <li><p> If an existing module definition is removed, invoke the
+ * {@link #removeModuleDefinition(ModuleDefinition)} method
+ * with that module definition.
+ * </p></li>
+ *
+ * <li><p> If an existing module definition is replaced, invoke the
+ * {@link #removeModuleDefinition(ModuleDefinition)}
+ * method with the old module definition, and invoke the
+ * {@link #addModuleDefinition(ModuleDefinition)}
+ * method with the new module definition.</p></li>
+ * </ul>
+ * The default implementation of this method throws an
+ * {@code UnsupportedOperationException}.
+ *
+ * @param mai the module archive to be uninstalled.
* @return true if the module archive is found and uninstalled, returns
* false otherwise.
* @throws SecurityException if a security manager exists and its
* {@code checkPermission} method denies access to uninstall the
* module archive in this {@code Repository}.
- * @throws UnsupportedOperationException if this {@code Repository} is
- * read-only.
- * @throws IllegalStateException if the module definition in the specified
- * specified module archive is in use, or if this
- * {@code Repository} has not been initialized or it has been
- * shutdown.
- * @throws IOException If an error occurs while uninstalling the module
+ * @throws UnsupportedOperationException if this {@code Repository} does
+ * not support this operation.
+ * @throws IllegalStateException if this {@code Repository} is not active.
+ * @throws IOException If an I/O error occurs while uninstalling the module
* archive.
*/
- public abstract boolean uninstall(ModuleArchiveInfo m) throws IOException;
-
- /**
- * Reload this {@code Repository}. The behavior of this method depends on
- * the implementation.
- * <p>
- * If a security manager is present, this method calls the security
- * manager's {@code checkPermission} method with a
- * {@code ModuleSystemPermission("reloadRepository")} permission
- * to ensure it's ok to reload module definitions in this
- * {@code Repository}.
+ public boolean uninstall(ModuleArchiveInfo mai) throws IOException {
+ throw new UnsupportedOperationException("Repository does not support the uninstall operation.");
+ }
+
+ /**
+ * Reload the module archives in this {@code Repository}. This method
+ * should be overridden and implemented by repository implementations
+ * as follows:
+ * <p><ol>
+ * <li><p> If a security manager is present, calls the security
+ * manager's {@code checkPermission} method with a
+ * {@code ModuleSystemPermission("reloadRepository")}
+ * permission to ensure it's ok to reload the module
+ * definitions in this {@code Repository}.</p></li>
+ *
+ * <li><p> If this {@code Repository} is not
+ * {@linkplain #isActive active},
+ * throws an {@code IllegalStateException}.</p></li>
+ *
+ * <li><p> Invoke the {@link #supportsReload()} method to check if this
+ * {@code Repository} supports reload. If it returns {@code false},
+ * throws an {@code UnsupportedOperationException}.</p></li>
+ *
+ * <li><p> Perform the actual reload of module definitions and this is
+ * repository implementation specific.</p></li>
+ * </ol>
+ * <p> If the repository implementations change the set of module archives
+ * after reload, they should perform the following:
+ * <p><ul>
+ * <li><p> If a new module archive is added, invoke the
+ * {@link #addModuleArchiveInfo(ModuleArchiveInfo)}
+ * method with that module archive's information.
+ * </p></li>
+ *
+ * <li><p> If an existing module archive is removed, invoke the
+ * {@link #removeModuleArchiveInfo(ModuleArchiveInfo)} method
+ * with that module archive's information.
+ * </p></li>
+ *
+ * <li><p> If an existing module archive is replaced, invoke the
+ * {@link #removeModuleArchiveInfo(ModuleArchiveInfo)}
+ * method with the old module archive's information, and invoke the
+ * {@link #addModuleArchiveInfo(ModuleArchiveInfo)}
+ * method with the new module archive's information.</p></li>
+ * </ul>
+ * <p> If the repository implementations change the set of module
+ * definitions after reload, they should perform the following:
+ * <p><ul>
+ * <li><p> If a new module definition is added, invoke the
+ * {@link #addModuleDefinition(ModuleDefinition)}
+ * method with that module definition.
+ * </p></li>
+ *
+ * <li><p> If an existing module definition is removed, invoke the
+ * {@link #removeModuleDefinition(ModuleDefinition)} method
+ * with that module definition.
+ * </p></li>
+ *
+ * <li><p> If an existing module definition is replaced, invoke the
+ * {@link #removeModuleDefinition(ModuleDefinition)}
+ * method with the old module definition, and invoke the
+ * {@link #addModuleDefinition(ModuleDefinition)}
+ * method with the new module definition.</p></li>
+ * </ul>
+ * The default implementation of this method throws an
+ * {@code UnsupportedOperationException}.
*
* @throws SecurityException if a security manager exists and its
* {@code checkPermission} method denies access to reload module
* definitions in this {@code Repository}.
* @throws UnsupportedOperationException if this {@code Repository}
- * does not support reload.
- * @throws IllegalStateException if a module definition is in use thus
- * cannot be reloaded.
- * @throws IOException If an error occurs while reloading the module
- * definitions.
- */
- public abstract void reload() throws IOException;
+ * does not support this operation.
+ * @throws IllegalStateException if a module archive is in use thus
+ * cannot be reloaded, or if this {@code Repository} is not
+ * active.
+ * @throws IOException If an I/O error occurs while reloading the module
+ * archives.
+ */
+ public void reload() throws IOException {
+ throw new UnsupportedOperationException("Repository does not support the reload operation.");
+ }
+
+ /**
+ * Adds a module definition into this {@code Repository}. Returns
+ * {@code true} if the module definitions in this
+ * {@code Repository} changed as a result of the call, and fires
+ * a {@link RepositoryEvent.Type#MODULE_DEFINITION_ADDED
+ * <tt>MODULE_DEFINITION_ADDED</tt>} event. Returns {@code false}
+ * if this {@code Repository} already contains
+ * the specified module definition.
+ *
+ * @param moduleDef module definition to be added
+ * @return true if the module definitions in this {@code Repository}
+ * changed as a result of the call.
+ * @throws IllegalStateException if this {@code Repository} has been
+ * shutdown.
+ */
+ protected final boolean addModuleDefinition(ModuleDefinition moduleDef) {
+ Set<ModuleDefinition> mds = new HashSet<ModuleDefinition>();
+ mds.add(moduleDef);
+ return addModuleDefinitions(mds);
+ }
+
+ /**
+ * Adds a set of module definitions into this {@code Repository}.
+ * Returns {@code true} if the module definitions in this
+ * {@code Repository} changed as a result of the call, and fires
+ * a single {@link RepositoryEvent.Type#MODULE_DEFINITION_ADDED
+ * <tt>MODULE_DEFINITION_ADDED</tt>} event. Returns {@code false}
+ * if this {@code Repository} already contains
+ * one of more of the specified module definitions.
+ *
+ * @param moduleDef a set of module definitions to be added
+ * @return true if the module definitions in this {@code Repository}
+ * changed as a result of the call.
+ * @throws IllegalStateException if this {@code Repository} has been
+ * shutdown.
+ */
+ protected final boolean addModuleDefinitions(Set<ModuleDefinition> mds) {
+ assertNotShutdown();
+
+ if (mds.size() == 0) {
+ return false;
+ }
+
+ for (ModuleDefinition moduleDef : mds) {
+ if (moduleDefs.contains(moduleDef)) {
+ return false;
+ }
+ }
+
+ // Add module definition into internal data structure
+ List<ModuleDefinition> newModuleDefs = new ArrayList<ModuleDefinition>(moduleDefs);
+ newModuleDefs.addAll(mds);
+ moduleDefs = Collections.unmodifiableList(newModuleDefs);
+
+ // Send a MODULE_DEFINITION_ADDED event
+ RepositoryEvent evt = new RepositoryEvent(this,
+ RepositoryEvent.Type.MODULE_DEFINITION_ADDED,
+ null, mds);
+ processEvent(evt);
+
+ return true;
+ }
+
+ /**
+ * Removes a module definition from this {@code Repository}. Returns
+ * {@code true} if the module definitions in this
+ * {@code Repository} changed as a result of the call, and fires a
+ * {@link RepositoryEvent.Type#MODULE_DEFINITION_REMOVED
+ * <tt>MODULE_DEFINITION_REMOVED</tt>} event. Returns {@code false}
+ * if the specified module definition is not present in this
+ * {@code Repository}.
+ * <p>
+ * If the module definition is removed successfully, this method invokes
+ * its module system's
+ * {@link ModuleSystem#disableModuleDefinition(ModuleDefinition)
+ * <tt>disableModuleDefinition(ModuleDefinition)</tt>} method and the
+ * {@link ModuleSystem#releaseModule(ModuleDefinition)
+ * <tt>releaseModule(ModuleDefinition)</tt>} method.</p></li>
+ *
+ * @param moduleDef module definition to be removed
+ * @return true if the module definitions in this {@code Repository}
+ * changed as a result of the call.
+ * @throws IllegalStateException if this {@code Repository} has been
+ * shutdown.
+ */
+ protected final boolean removeModuleDefinition(final ModuleDefinition moduleDef) {
+ Set<ModuleDefinition> mds = new HashSet<ModuleDefinition>();
+ mds.add(moduleDef);
+ return removeModuleDefinitions(mds);
+ }
+
+ /**
+ * Removes a set of module definitions from this {@code Repository}.
+ * Returns {@code true} if the module definitions in this
+ * {@code Repository} changed as a result of the call, and fires a single
+ * {@link RepositoryEvent.Type#MODULE_DEFINITION_REMOVED
+ * <tt>MODULE_DEFINITION_REMOVED</tt>} event. Returns {@code false} if
+ * any of the specified module definitions is not present in this
+ * {@code Repository}.
+ * <p>
+ * For each module definition that is removed successfully, this method
+ * invokes its module system's
+ * {@link ModuleSystem#disableModuleDefinition(ModuleDefinition)
+ * <tt>disableModuleDefinition(ModuleDefinition)</tt>}
+ * method and
+ * {@link ModuleSystem#releaseModule(ModuleDefinition)
+ * <tt>releaseModule(MOduleDefinition)</tt>} method.
+ *
+ * @param mds the set of module definitions to be removed
+ * @return true if the module definitions in this {@code Repository}
+ * changed as a result of the call.
+ * @throws IllegalStateException if this {@code Repository} has been
+ * shutdown.
+ */
+ protected final boolean removeModuleDefinitions(final Set<ModuleDefinition> mds) {
+ assertNotShutdown();
+
+ if (mds.size() == 0 || moduleDefs.containsAll(mds) == false) {
+ return false;
+ }
+
+ // Remove module definition from internal data structure
+ List<ModuleDefinition> newModuleDefs = new ArrayList<ModuleDefinition>(moduleDefs);
+ newModuleDefs.removeAll(mds);
+ moduleDefs = Collections.unmodifiableList(newModuleDefs);
+
+ // Send MODULE_DEFINITION_REMOVED event
+ RepositoryEvent evt = new RepositoryEvent(this,
+ RepositoryEvent.Type.MODULE_DEFINITION_REMOVED,
+ null, mds);
+ processEvent(evt);
+
+ // disable and release module definitions under doPrivileged()
+ AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
+ public Boolean run() {
+ for (ModuleDefinition moduleDef : mds) {
+ try {
+ // Disables the module definition in the module system.
+ moduleDef.getModuleSystem().disableModuleDefinition(moduleDef);
+ } catch (UnsupportedOperationException uoe) {
+ // no-op
+ } catch (IllegalStateException ise) {
+ // no-op
+ }
+ try {
+ // Releases any module instance corresponding to the module definition
+ // in the module system
+ moduleDef.getModuleSystem().releaseModule(moduleDef);
+ } catch (UnsupportedOperationException uoe) {
+ // no-op
+ }
+ }
+
+ return Boolean.TRUE;
+ }
+ });
+
+ return true;
+ }
+
+ /**
+ * Adds a {@code ModuleArchiveInfo} into this {@code Repository}. Returns
+ * {@code true} if the {@code ModuleArchiveInfo}s in this
+ * {@code Repository} changed as a result of the call, and fires
+ * a {@link RepositoryEvent.Type#MODULE_ARCHIVE_INSTALLED
+ * <tt>MODULE_ARCHIVE_INSTALLED</tt>} event. Returns {@code false}
+ * if this {@code Repository} already contains the specified
+ * {@code ModuleArchiveInfo}.
+ *
+ * @param mai {@code ModuleArchiveInfo} to be added
+ * @return true if the {@code ModuleArchiveInfo}s in this
+ * {@code Repository} changed as a result of the call.
+ * @throws IllegalStateException if this {@code Repository} has been
+ * shutdown.
+ */
+ protected final boolean addModuleArchiveInfo(ModuleArchiveInfo mai) {
+ assertNotShutdown();
+
+ if (moduleArchiveInfos.contains(mai)) {
+ return false;
+ }
+
+ // Add module archive info into internal data structure
+ List<ModuleArchiveInfo> newModuleArchiveInfos = new ArrayList<ModuleArchiveInfo>(moduleArchiveInfos);
+ newModuleArchiveInfos.add(mai);
+ moduleArchiveInfos = Collections.unmodifiableList(newModuleArchiveInfos);
+
+ // Send MODULE_ARCHIVE_INSTALLED event
+ RepositoryEvent evt = new RepositoryEvent(this,
+ RepositoryEvent.Type.MODULE_ARCHIVE_INSTALLED,
+ mai, null);
+ processEvent(evt);
+
+ return true;
+ }
+
+ /**
+ * Removes a {@code ModuleArchiveInfo} from this {@code Repository}.
+ * Returns {@code true} if the {@code ModuleArchiveInfo}s in this
+ * {@code Repository} changed as a result of the call, and fires
+ * a {@link RepositoryEvent.Type#MODULE_ARCHIVE_UNINSTALLED
+ * <tt>MODULE_ARCHIVE_UNINSTALLED</tt>} event. Returns {@code false}
+ * if the specified {@code ModuleArchiveInfo} is not present in this
+ * {@code Repository}.
+ *
+ * @param mai {@code ModuleArchiveInfo} to be removed
+ * @return true if the {@code ModuleArchiveInfo}s in this {@code Repository}
+ * changed as a result of the call.
+ * @throws IllegalStateException if this {@code Repository} has been
+ * shutdown.
+ */
+ protected final boolean removeModuleArchiveInfo(ModuleArchiveInfo mai) {
+ assertNotShutdown();
+
+ if (moduleArchiveInfos.contains(mai) == false) {
+ return false;
+ }
+
+ // Remove module archive info from internal data structure
+ List<ModuleArchiveInfo> newModuleArchiveInfos = new ArrayList<ModuleArchiveInfo>(moduleArchiveInfos);
+ newModuleArchiveInfos.remove(mai);
+ moduleArchiveInfos = Collections.unmodifiableList(newModuleArchiveInfos);
+
+ // Send MODULE_ARCHIVE_UNINSTALLED event
+ RepositoryEvent evt = new RepositoryEvent(this,
+ RepositoryEvent.Type.MODULE_ARCHIVE_UNINSTALLED,
+ mai, null);
+ processEvent(evt);
+
+ return true;
+ }
+
+ /**
+ * Returns an unmodifiable list of {@code ModuleArchiveInfo}s in this
+ * {@code Repository}.
+ *
+ * @return an unmodifiable list of {@code ModuleArchiveInfo}s.
+ * @throws IllegalStateException if this {@code Repository} has been
+ * shutdown.
+ */
+ protected final List<ModuleArchiveInfo> getModuleArchiveInfos() {
+ assertNotShutdown();
+ return moduleArchiveInfos;
+ }
/**
* Adds the specified repository listener to receive repository events from
@@ -628,8 +1299,10 @@ public abstract class Repository {
switch (event.getType()) {
case REPOSITORY_INITIALIZED:
case REPOSITORY_SHUTDOWN:
- case MODULE_INSTALLED:
- case MODULE_UNINSTALLED:
+ case MODULE_DEFINITION_ADDED:
+ case MODULE_DEFINITION_REMOVED:
+ case MODULE_ARCHIVE_INSTALLED:
+ case MODULE_ARCHIVE_UNINSTALLED:
listener.handleEvent(event);
break;
default:
@@ -718,7 +1391,25 @@ public abstract class Repository {
private void assertActive() throws IllegalStateException {
if (!isActive()) {
- throw new IllegalStateException("Repository is not active.");
+ throw new IllegalStateException("Repository is not active.");
+ }
+ }
+
+ private void assertNotActive() throws IllegalStateException {
+ if (isActive()) {
+ throw new IllegalStateException("Repository is active.");
+ }
+ }
+
+ private void assertNotShutdown() throws IllegalStateException {
+ if (shutdown) {
+ throw new IllegalStateException("Repository is already shutdown.");
+ }
+ }
+
+ private void assertNotReadOnly() throws IllegalStateException {
+ if (isReadOnly()) {
+ throw new UnsupportedOperationException("Repository is read-only.");
}
}
}
--- a/src/share/classes/java/module/RepositoryEvent.java Mon Jul 07 10:13:08 2008 -0700
+++ b/src/share/classes/java/module/RepositoryEvent.java Tue Jul 08 12:14:10 2008 -0700
@@ -25,8 +25,12 @@
package java.module;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
/**
- * This class represents a repository event that occurs in a repository.
+ * This class represents an event that occurs in a repository.
*
* @see java.module.ModuleDefinition
* @see java.module.ModuleArchiveInfo
@@ -53,64 +57,82 @@ public class RepositoryEvent {
REPOSITORY_SHUTDOWN,
/**
- * A module definition has been installed successfully in a repository.
+ * One or more module definitions have been added in a repository successfully.
*/
- MODULE_INSTALLED,
+ MODULE_DEFINITION_ADDED,
/**
- * A module definition has been uninstalled successfully in a repository.
+ * One or more module definitions have been removed in a repository successfully.
*/
- MODULE_UNINSTALLED
+ MODULE_DEFINITION_REMOVED,
+
+ /**
+ * A module archive has been installed successfully in a repository.
+ */
+ MODULE_ARCHIVE_INSTALLED,
+
+ /**
+ * A module archive has been uninstalled successfully in a repository.
+ */
+ MODULE_ARCHIVE_UNINSTALLED
};
private Type type;
private Repository source;
private ModuleArchiveInfo info;
+ private Set<ModuleDefinition> moduleDefs;
/**
- * Constructs a {@code RepositoryEvent} object with the specified repository,
- * and event type.
+ * Constructs a {@code RepositoryEvent} instance using the specified
+ * repository, event type, module archive information, and a set
+ * of module definitions
*
* @param source the repository where the event occurs
* @param type the event type
- * @throws NullPointerException if source is null or type is null.
+ * @param info the module archive information
+ * @param moduleDefs a set of module definitions
+ * @throws NullPointerException if source is {@code null} or type is
+ * {@code null}.
+ * @throws IllegalArgumentException
+ * <ul>
+ * <li><p>if type is {@link Type#MODULE_ARCHIVE_INSTALLED
+ * <tt>MODULE_ARCHIVE_INSTALLED</tt>} or
+ * {@link Type#MODULE_ARCHIVE_UNINSTALLED
+ * <tt>MODULE_ARCHIVE_UNINSTALLED</tt>}, and
+ * info is {@code null}, or</p></li>
+ * <li><p>if type is {@link Type#MODULE_DEFINITION_ADDED
+ * <tt>MODULE_DEFINITION_ADDED</tt>} or
+ * {@link Type#MODULE_DEFINITION_REMOVED
+ * <tt>MODULE_DEFINITION_REMOVED</tt>}, and
+ * moduleDefs is {@code null} or is an empty set.</p></li>
+ * </ul>
*/
- public RepositoryEvent(Repository source, Type type) {
+ public RepositoryEvent(Repository source, Type type, ModuleArchiveInfo info,
+ Set<ModuleDefinition> moduleDefs) {
if (source == null)
throw new NullPointerException("source must not be null.");
if (type == null)
throw new NullPointerException("type must not be null.");
- this.type = type;
- this.source = source;
- this.info = null;
- }
+ if ((type.equals(Type.MODULE_ARCHIVE_INSTALLED) || type.equals(Type.MODULE_ARCHIVE_UNINSTALLED))
+ && info == null)
+ throw new IllegalArgumentException("info must not be null with event type " + type);
- /**
- * Constructs a {@code RepositoryEvent} object with the specified repository,
- * event type, and module archive information.
- *
- * @param source the repository where the event occurs
- * @param type the event type
- * @param info the module archive information
- * @throws NullPointerException if source is null, type is null, or
- * info is null.
- */
- public RepositoryEvent(Repository source, Type type, ModuleArchiveInfo info) {
- if (source == null)
- throw new NullPointerException("source must not be null.");
-
- if (type == null)
- throw new NullPointerException("type must not be null.");
-
- if (info == null)
- throw new NullPointerException("info must not be null.");
+ if ((type.equals(Type.MODULE_DEFINITION_ADDED) || type.equals(Type.MODULE_DEFINITION_REMOVED))
+ && (moduleDefs == null || moduleDefs.size() == 0))
+ throw new IllegalArgumentException("moduleDefs must not be null or empty set with event type " + type);
this.type = type;
this.source = source;
this.info = info;
+ if (moduleDefs != null) {
+ this.moduleDefs = Collections.unmodifiableSet(moduleDefs);
+ } else {
+ this.moduleDefs = null;
+ }
}
+
/**
* Returns the event type.
@@ -127,7 +149,14 @@ public class RepositoryEvent {
}
/**
- * Returns the module archive information associated with the event.
+ * Returns an unmodifiable set of module definitions.
+ */
+ public Set<ModuleDefinition> getModuleDefinitions() {
+ return moduleDefs;
+ }
+
+ /**
+ * Returns the module archive information.
*/
public ModuleArchiveInfo getModuleArchiveInfo() {
return info;
@@ -146,6 +175,10 @@ public class RepositoryEvent {
builder.append(type.toString());
builder.append(",repository=");
builder.append(getSource().getName());
+ if (moduleDefs != null) {
+ builder.append(",module-definitions=");
+ builder.append(moduleDefs.toString());
+ }
if (info != null) {
builder.append(",module-archive-info=");
builder.append(info.toString());
--- a/src/share/classes/java/module/RepositoryListener.java Mon Jul 07 10:13:08 2008 -0700
+++ b/src/share/classes/java/module/RepositoryListener.java Tue Jul 08 12:14:10 2008 -0700
@@ -28,14 +28,17 @@ import java.util.EventListener;
import java.util.EventListener;
/**
- * The listener interface for receiving repository events. The class that
- * is interested in processing repository events implements this interface,
- * and the object created with that class is registered, using the
- * repository's {@code addRepositoryListener} static method.
+ * The listener interface for receiving repository events.
+ * <p>
+ * The class that is interested in processing repository events implements
+ * this interface, and the object created with that class is registered, using
+ * the {@link Repository#addRepositoryListener(RepositoryListener)
+ * <tt>addRepositoryListener</tt>} method of the {@code Repository} class.
* <p>
* The object that is no longer interested in processing any repository event
- * is unregistered, using the repository's {@code removedRepositoryListener}
- * static method.
+ * is unregistered, using the
+ * {@link Repository#removeRepositoryListener(RepositoryListener)
+ * <tt>removeRepositoryListener</tt>} method of the {@code Repository} class.
*
* @see java.module.Repository
* @see java.module.RepositoryEvent
@@ -45,10 +48,7 @@ public interface RepositoryListener exte
public interface RepositoryListener extends EventListener {
/**
- * Invoked after a repository has been initialized successfully, after a
- * repository has been shutdown successfully, after a module definition has
- * been installed successfully in a repository, or after a module
- * definition has been uninstalled successfully in a repository.
+ * Invoked when a change has occurred in a repository.
*
* @param e repository event
*/
--- a/src/share/classes/java/module/UnsatisfiedDependencyException.java Mon Jul 07 10:13:08 2008 -0700
+++ b/src/share/classes/java/module/UnsatisfiedDependencyException.java Tue Jul 08 12:14:10 2008 -0700
@@ -26,8 +26,8 @@ package java.module;
package java.module;
/**
- * Thrown to indicate that there is an unsatisifed dependency during module
- * initialization.
+ * Thrown to indicate that an import dependency cannot be satisifed
+ * during initialization of a module instance.
*
* @see java.module.ImportDependency
* @see java.module.ImportPolicy
@@ -84,14 +84,15 @@ public class UnsatisfiedDependencyExcept
}
/**
- * Returns the module definition that has the unsatisfied dependency.
+ * Returns the module definition which the module instance is instantiated
+ * from.
*/
public ModuleDefinition getModuleDefinition() {
return moduleDef;
}
/**
- * Returns the module dependency that is unsatisfied.
+ * Returns the import dependency that is unsatisfied.
*/
public ImportDependency getImportDependency() {
return dependency;
--- a/src/share/classes/java/module/Version.java Mon Jul 07 10:13:08 2008 -0700
+++ b/src/share/classes/java/module/Version.java Tue Jul 08 12:14:10 2008 -0700
@@ -36,11 +36,30 @@ import java.util.regex.Pattern;
import java.util.regex.Pattern;
/**
- * This class represents a version in the module system. The version must
- * be in the following format:<p>
- * <blockquote><pre>
- * <I>major[.minor[.micro[.update]]][-qualifier]</I>
- * </pre></blockquote>
+ * This class represents a version. The format of the version is defined as
+ * follows:
+ * <pre>
+ * major[.minor[.micro[.update]]][-qualifier]</pre>
+ * where
+ * <ul>
+ * <p><li> {@code major}, {@code minor}, {@code micro}, and {@code update}
+ * are non-negative integers, i.e. {@code 0} <= <i>x</i> <=
+ * {@link java.lang.Integer#MAX_VALUE <tt>Integer.MAX_VALUE</tt>}.
+ * </li></p>
+ *
+ * <p><li> {@code qualifier} is a string, and it can contain regular
+ * alphanumeric characters, {@code '-'}, and {@code '_'}.</li></p>
+ *
+ * <p><li> If {@code minor} is not specified, it is treated as {@code 0}.
+ * </li></p>
+ *
+ * <p><li> If {@code micro} is not specified, it is treated as {@code 0}.
+ * </li></p>
+ *
+ * <p><li> If {@code update} is not specified, it is treated as {@code 0}.
+ * </li></p>
+ * </ul></p>
+ *
* For example,
* <blockquote><pre>
* 1
@@ -54,19 +73,41 @@ import java.util.regex.Pattern;
* 1.7.1.3-b56_rc
* </pre></blockquote>
* The version format is described by the following grammar:
- * <blockquote><pre>
+ * <pre>
* version := simple-version ('-' qualifier)?
* simple-version:= major ('.' minor ('.' micro ('.' update)?)?)?
* major := digit+
* minor := digit+
* micro := digit+
* update := digit+
- * qualifier := (alpha | digit | '-' | '_')+
- * </pre></blockquote>
+ * qualifier := (alpha | digit | '-' | '_')+</pre>
* where {@code alpha} is an alphabetic character, {@code a-z, A-Z}.
* {@code digit} is a decimal digit, {@code 0-9}.
- *
- * <p>Instances of this class are immutable and safe for concurrent use by
+ * <p>
+ * When two versions are compared, {@code major}, {@code minor},
+ * {@code micro}, and {@code update} are compared numerically while
+ * {@code qualifier} is compared through string comparison lexicographically.
+ * Two versions are equivalent if and only if the major numbers, the minor
+ * numbers, the micro numbers, the update numbers, and the qualifiers each
+ * are equal respectively. If the major numbers, the minor numbers, the
+ * micro numbers, and the update numbers of two versions are equal
+ * respectively but one version has a qualifier while the other has
+ * none, the latter is considered a higher version. For example,
+ * <pre>
+ * 1 < 1.2 < 1.3.1 < 2
+ *
+ * 1.6.0.5 < 1.7.0 < 1.7.0.1 < 1.7.0.2
+ *
+ * 3.4.5.6 < 3.4.5.7 == 3.4.5.07 < 3.4.6
+ *
+ * 7.8.9-b23 < 7.8.9 < 7.8.9.1-b10-alpha < 7.8.9.1-b18 < 7.8.9.1
+ *
+ * 4.3.2 == 4.3.2.0 < 4.3.2.1</pre>
+ * <p>
+ * Applications can obtain {@code Version} objects by calling one of the
+ * {@link #valueOf(String) valueOf} factory methods.
+ * <p>
+ * Instances of this class are immutable and safe for concurrent use by
* multiple threads.
*
* @see java.module.Query
@@ -149,8 +190,9 @@ public final class Version implements Co
/**
* Returns a {@code Version} object holding the specified version number.
- *
- * <p>Equivalent to {@code valueOf(major, minor, micro, 0, null);}.
+ * Equivalent to:
+ * <pre>
+ * valueOf(major, minor, micro, 0, null)</pre>
*
* @param major the major version number.
* @param minor the minor version number.
@@ -164,8 +206,10 @@ public final class Version implements Co
/**
* Returns a {@code Version} object holding the specified version number.
- *
- * <p>Equivalent to {@code valueOf(major, minor, micro, 0, qualifier);}.
+ * If the version number has no qualifier, {@code qualifier} is
+ * {@code null}. Equivalent to:
+ * <pre>
+ * valueOf(major, minor, micro, 0, qualifier)</pre>
*
* @param major the major version number.
* @param minor the minor version number.
@@ -180,8 +224,9 @@ public final class Version implements Co
/**
* Returns a {@code Version} object holding the specified version number.
- *
- * <p>Equivalent to {@code valueOf(major, minor, micro, update, null);}.
+ * Equivalent to:
+ * <pre>
+ * valueOf(major, minor, micro, update, null)</pre>
*
* @param major the major version number.
* @param minor the minor version number.
@@ -196,6 +241,8 @@ public final class Version implements Co
/**
* Returns a {@code Version} object holding the specified version number.
+ * If the version number has no qualifier, {@code qualifier} is
+ * {@code null}.
*
* @param major the major version number.
* @param minor the minor version number.
@@ -283,7 +330,8 @@ public final class Version implements Co
}
/**
- * Returns the qualifier in the version.
+ * Returns the qualifier. If this {@code Version} has no qualifier, this
+ * method returns {@code null}.
*
* @return the qualifier.
*/
@@ -372,7 +420,6 @@ public final class Version implements Co
* {@code Version} is less than the {@code Version} argument; and a
* value greater than 0 if this {@code Version} is greater than the
* {@code Version} argument.
- * @throws NullPointerException if the {@code Version} argument is null.
*/
@Override
public int compareTo(Version version) {
--- a/src/share/classes/java/module/VersionConstraint.java Mon Jul 07 10:13:08 2008 -0700
+++ b/src/share/classes/java/module/VersionConstraint.java Tue Jul 08 12:14:10 2008 -0700
@@ -36,45 +36,58 @@ import java.util.StringTokenizer;
import java.util.StringTokenizer;
/**
- * This class represents a version constraint in the module system. A version
- * constraint is either a version, a version range, or combination of both.
- * <p>
- * For example,
- * <blockquote><pre>
- * <i>Version:</i>
- * 1
- * 1.7
- * 1.7-b61
- * 1.7.0
- * 1.7.0-b61
- * 1.7.0.0
- * 1.7.0.1
- * 1.7.1.3-b32-beta-1
- * 1.7.1.3-b56_rc
- *
- * <i>General version range:</i>
+ * This class represents a version constraint. A version constraint is
+ * either a version, a version range, or combination of both.
+ * <p>
+ * <h3>Version</h3>
+ * Version is defined in {@link Version}.
+ * <p>
+ * <h3>Version range</h3>
+ * A version range is a range of versions. There are three basic kinds
+ * of version ranges: <i>general</i>, <i>open</i>, and <i>family</i>.
+ * <p>
+ * A general version range matches any version between a lower-bound
+ * version (ignoring qualifier) and an upper-bound version (ignoring
+ * qualifier); each bound is either inclusive or exclusive. It can be
+ * in one of the following formats (The {@code '['} and {@code ']'}
+ * characters mean inclusive; the {@code '('} and {@code ')'}
+ * characters mean exclusive):
+ * <pre>
* [1.2.3.4, 5.6.7.8) ~ 1.2.3.4 <= x < 5.6.7.8
* (1.2.3.4, 5.6.7.8] ~ 1.2.3.4 < x <= 5.6.7.8
* (1.2.3.4, 5.6.7.8) ~ 1.2.3.4 < x < 5.6.7.8
- * [1.2.3.4, 5.6.7.8] ~ 1.2.3.4 <= x <= 5.6.7.8
- *
- * <i>Open version range:</i>
+ * [1.2.3.4, 5.6.7.8] ~ 1.2.3.4 <= x <= 5.6.7.8</pre>
+ * An open version range matches any version (ignoring qualifier) greater
+ * than or equal to a specified version. It can be in one of the following
+ * formats (The {@code '+'} character means this version or later):
+ * <pre>
* 1+ ~ [1, infinity) ~ 1 <= x < infinity
* 1.2+ ~ [1.2, infinity) ~ 1.2 <= x < infinity
* 1.2.3+ ~ [1.2.3, infinity) ~ 1.2.3 <= x < infinity
- * 1.2.3.4+ ~ [1.2.3.4, infinity) ~ 1.2.3.4 <= x < infinity
- *
- * <i>Family version range:</i>
+ * 1.2.3.4+ ~ [1.2.3.4, infinity) ~ 1.2.3.4 <= x < infinity</pre>
+ * A family version range matches any version (ignoring qualifier) that is
+ * in a particular release family, and it can be in one of the following
+ * formats (The {@code '*'} character means wildcard match):
+ * <pre>
* 1.* ~ [1, 2) ~ 1 <= x < 2
* 1.2.* ~ [1.2, 1.3) ~ 1.2 <= x < 1.3
- * 1.2.3.* ~ [1.2.3, 1.2.4) ~ 1.2.3 <= x < 1.2.4
- *
- * <i>Union of ranges:</i>
+ * 1.2.3.* ~ [1.2.3, 1.2.4) ~ 1.2.3 <= x < 1.2.4</pre>
+ * It is possible to group two or more version ranges together as an union of
+ * ranges, using the {@code ';'} character as separator.
+ * <pre>
* [1.2.3.4, 2.0);2.*;3+ ~ 1.2.3.4 <= x < infinity
- * 1.*;[2.0, 2.7.3) ~ 1.0.0 <= x < 2.7.3
- * </pre></blockquote>
- * The version constraint format is described by the following grammar:
- * <blockquote><pre>
+ * 1.*;[2.0, 2.7.3) ~ 1.0.0 <= x < 2.7.3</pre>
+ * <p>
+ * <h3>Version constraint</h3>
+ * A version constraint is a mechanism in expressing versioning requirement
+ * through versions and version ranges. The version and the version range are
+ * really shorthands in establishing compatibility. If more arbitrary range,
+ * version inclusion, or version exclusion is needed, the version and the
+ * version range can be used as building blocks to express the versioning
+ * requirement.
+ * <p>
+ * The grammar for the version constraint is as follows:
+ * <pre>
* version-constraint := simple-version-constraint (';' simple-version-constraint)*
* simple-version-constraint := version | version-range
*
@@ -90,13 +103,12 @@ import java.util.StringTokenizer;
* minor := digit+
* micro := digit+
* update := digit+
- * qualifier := (alpha | digit | '-' | '_')+
- * </pre></blockquote>
+ * qualifier := (alpha | digit | '-' | '_')+</pre>
* where {@code alpha} is an alphabetic character, {@code a-z, A-Z}.
* {@code digit} is a decimal digit, {@code 0-9}.
- *
- * <p>Applications can obtain {@code VersionConstraint} objects by calling the
- * {@link #valueOf(String) valueOf()} factory method.
+ * <p>
+ * Applications can obtain {@code VersionConstraint} objects by calling the
+ * {@link #valueOf(String) valueOf} factory method.
*
* <p>Instances of this class are immutable and safe for concurrent use by
* multiple threads.
@@ -144,6 +156,10 @@ public final class VersionConstraint imp
* known to this version constraint. Otherwise, returns false.
*/
public boolean contains(Version version) {
+ if (version == null) {
+ throw new NullPointerException("version must not be null.");
+ }
+
for (Object cs : normalizedConstraints) {
if (cs instanceof Version) {
Version v = (Version) cs;
@@ -170,6 +186,10 @@ public final class VersionConstraint imp
* false.
*/
private boolean contains(VersionRange versionRange) {
+ if (versionRange == null) {
+ throw new NullPointerException("versionRange must not be null.");
+ }
+
for (Object cs : normalizedConstraints) {
if (cs instanceof VersionRange) {
VersionRange vr = (VersionRange) cs;
@@ -191,6 +211,9 @@ public final class VersionConstraint imp
* returns false.
*/
public boolean contains(VersionConstraint versionConstraint) {
+ if (versionConstraint == null) {
+ throw new NullPointerException("versionConstraint must not be null.");
+ }
for (Object cs : versionConstraint.normalizedConstraints) {
if (cs instanceof Version) {
--- a/src/share/classes/java/module/VersionRange.java Mon Jul 07 10:13:08 2008 -0700
+++ b/src/share/classes/java/module/VersionRange.java Tue Jul 08 12:14:10 2008 -0700
@@ -30,7 +30,7 @@ import java.util.regex.Pattern;
import java.util.regex.Pattern;
/**
- * This class represents a version range in the module system.
+ * This class represents a version range.
*
* @see java.module.Query
* @see java.module.Version
@@ -81,7 +81,6 @@ class VersionRange implements Comparable
* @param lowerBoundInclusive the inclusiveness of the lower bound version.
* @param upperBound the upper bound version in the version range.
* @param upperBoundInclusive the inclusiveness of the upper bound version.
- * @throws NullPointerException if lowerBound is null or upperBound is null.
* @throws IllegalArgumentException if the lowerBound is greater than the
* upperBound.
*/
@@ -182,8 +181,6 @@ class VersionRange implements Comparable
*
* @param lowerBound the lower bound version in the version range.
* @param upperBound the upper bound version in the version range.
- * @throws NullPointerException if lowerBound is null or upperBound is
- * null.
* @throws IllegalArgumentException if the lowerBound is greater than
* the upperBound.
*/
--- a/src/share/classes/java/module/VisibilityPolicy.java Mon Jul 07 10:13:08 2008 -0700
+++ b/src/share/classes/java/module/VisibilityPolicy.java Tue Jul 08 12:14:10 2008 -0700
@@ -26,8 +26,14 @@ package java.module;
package java.module;
/**
- * This interface represents the visibility policy for the module definitions in
- * the repository.
+ * This interface represents the visibility policy for the module definitions.
+ * <p>
+ * The visibility policy is used to determine whether a module definition in a
+ * repository is visible to the application at runtime, when the
+ * {@link Repository#find(Query) <tt>find(Query)</tt>} method of the
+ * {@code Repository} instance is invoked. The system's visibility policy can be
+ * obtained by invoking the {@link Repository#getVisibilityPolicy()
+ * <tt>getVisibilityPolicy()</tt>} method of the {@code Repository} class.
* <p>
* @see java.module.ModuleDefinition
* @see java.module.Repository
@@ -37,7 +43,7 @@ public interface VisibilityPolicy {
public interface VisibilityPolicy {
/**
- * Returns true if the module definition should be visible in the
+ * Returns true if the module definition should be visible from the
* repository; otherwise, returns false.
* <p>
*
--- a/src/share/classes/java/module/annotation/ClassesDirectoryPath.java Mon Jul 07 10:13:08 2008 -0700
+++ b/src/share/classes/java/module/annotation/ClassesDirectoryPath.java Tue Jul 08 12:14:10 2008 -0700
@@ -31,8 +31,8 @@ import java.lang.annotation.RetentionPol
import java.lang.annotation.RetentionPolicy;
/**
- * Indicates the path for searching classes and resources in the module
- * archive. This metadata annotation is applied to a Java module. For example,
+ * Indicates the path for searching classes and resources in the module archive.
+ * This metadata annotation is applied to a Java module. For example,
* <blockquote><pre>
* //
* // com/wombat/webapp/module-info.java
--- a/src/share/classes/java/module/annotation/ExportLegacyClasses.java Mon Jul 07 10:13:08 2008 -0700
+++ b/src/share/classes/java/module/annotation/ExportLegacyClasses.java Tue Jul 08 12:14:10 2008 -0700
@@ -31,10 +31,11 @@ import java.lang.annotation.RetentionPol
import java.lang.annotation.RetentionPolicy;
/**
- * Indicates the legacy classes are exported from a module definition. A legacy
- * class is exportable if it is a public class that does not have any module
- * membership. This metadata annotation is applied to a Java module. For
- * example,
+ * Indicates that the legacy classes are exported from a module definition.
+ * A legacy class is a Java class which does not belong to any Java module;
+ * a legacy class is exportable from a module definition if that class
+ * is public. This metadata annotation is applied to a Java module.
+ * For example,
* <blockquote><pre>
* //
* // com/wombat/xyz/module-info.java
--- a/src/share/classes/java/module/annotation/ExportResources.java Mon Jul 07 10:13:08 2008 -0700
+++ b/src/share/classes/java/module/annotation/ExportResources.java Tue Jul 08 12:14:10 2008 -0700
@@ -67,7 +67,7 @@ import java.lang.annotation.RetentionPol
*
* @since 1.7
*/
-@Target({ElementType.MODULE, ElementType.TYPE})
+@Target({ElementType.MODULE})
@Retention(RetentionPolicy.RUNTIME)
public @interface ExportResources {
--- a/src/share/classes/java/module/annotation/ImportModule.java Mon Jul 07 10:13:08 2008 -0700
+++ b/src/share/classes/java/module/annotation/ImportModule.java Tue Jul 08 12:14:10 2008 -0700
@@ -31,7 +31,7 @@ import java.lang.annotation.RetentionPol
import java.lang.annotation.RetentionPolicy;
/**
- * Indicates the module definition to import. This metadata annotation is used
+ * Indicates a module definition to import. This metadata annotation is used
* as nested annotation inside other enclosing annotations. For example,
* <blockquote><pre>
* //
--- a/src/share/classes/java/module/annotation/JarLibraryPath.java Mon Jul 07 10:13:08 2008 -0700
+++ b/src/share/classes/java/module/annotation/JarLibraryPath.java Tue Jul 08 12:14:10 2008 -0700
@@ -31,8 +31,8 @@ import java.lang.annotation.RetentionPol
import java.lang.annotation.RetentionPolicy;
/**
- * Indicates the path for searching jar files in the module archive. This
- * metadata annotation is applied to a Java module. For example,
+ * Indicates the path for searching JAR (Java ARchive) files in the module
+ * archive. This metadata annotation is applied to a Java module. For example,
* <blockquote><pre>
* //
* // com/wombat/webapp/module-info.java
@@ -49,7 +49,7 @@ public @interface JarLibraryPath {
public @interface JarLibraryPath {
/**
- * The path for searching jar files in the module archive. It must be a
+ * The path for searching JAR files in the module archive. It must be a
* relative path to the root of the module archive, using {@code '/'} as
* path separator and no leading {@code '/'}.
*/
--- a/src/share/classes/java/module/annotation/MainClass.java Mon Jul 07 10:13:08 2008 -0700
+++ b/src/share/classes/java/module/annotation/MainClass.java Tue Jul 08 12:14:10 2008 -0700
@@ -42,8 +42,10 @@ import java.lang.annotation.RetentionPol
* &#064;MainClass("com.wombat.xyz.Main")
* module com.wombat.xyz;
* </pre></blockquote>
- * Being a main class does not imply the class is exported from the module
- * definition; the main class must be declared as exported separately.
+ * The main class must have a {@code main} method which is declared public,
+ * static, and void; the method must accept a single argument that is an array
+ * of strings.
+ *
* @since 1.7
*/
@Target({ElementType.MODULE})
--- a/src/share/classes/java/module/annotation/NativeLibraryPath.java Mon Jul 07 10:13:08 2008 -0700
+++ b/src/share/classes/java/module/annotation/NativeLibraryPath.java Tue Jul 08 12:14:10 2008 -0700
@@ -31,8 +31,8 @@ import java.lang.annotation.RetentionPol
import java.lang.annotation.RetentionPolicy;
/**
- * Indicates the path for searching native libraries in the module archive for
- * a particular platform and architecture. This metadata annotation is used as
+ * Indicates the path for searching native libraries in the module archive for a
+ * particular platform and architecture. This metadata annotation is used as
* nested annotation inside other enclosing annotations. For example,
* <blockquote><pre>
* //
--- a/src/share/classes/java/module/annotation/NativeLibraryPaths.java Mon Jul 07 10:13:08 2008 -0700
+++ b/src/share/classes/java/module/annotation/NativeLibraryPaths.java Tue Jul 08 12:14:10 2008 -0700
@@ -55,7 +55,7 @@ public @interface NativeLibraryPaths {
/**
* An array of paths for searching native libraries in the module archive
- * for different platforms and architectures. .
+ * for different platforms and architectures.
*/
NativeLibraryPath[] value();
}
--- a/src/share/classes/java/module/annotation/PlatformBinding.java Mon Jul 07 10:13:08 2008 -0700
+++ b/src/share/classes/java/module/annotation/PlatformBinding.java Tue Jul 08 12:14:10 2008 -0700
@@ -57,7 +57,7 @@ import java.lang.annotation.RetentionPol
* </pre></blockquote>
* @since 1.7
*/
-@Target({ElementType.MODULE, ElementType.TYPE})
+@Target({ElementType.MODULE})
@Retention(RetentionPolicy.RUNTIME)
public @interface PlatformBinding {
--- a/src/share/classes/java/module/annotation/ResourceModuleConstraint.java Mon Jul 07 10:13:08 2008 -0700
+++ b/src/share/classes/java/module/annotation/ResourceModuleConstraint.java Tue Jul 08 12:14:10 2008 -0700
@@ -31,11 +31,11 @@ import java.lang.annotation.RetentionPol
import java.lang.annotation.RetentionPolicy;
/**
- * Indicates the version constraint that a module definition requires its
- * resource modules to satisfy. The version constraint is either a version,
- * a version range, or a combination of both, following the format described
- * in the {@link java.module.VersionConstraint} class. This metadata annotation
- * is applied to a Java module. For example,
+ * Indicates the version constraint that a <i>target module</i> requires its
+ * <i>resource modules</i> to satisfy. The version constraint is either a
+ * version, a version range, or a combination of both, following the format
+ * described in the {@link java.module.VersionConstraint} class. This metadata
+ * annotation is applied to a Java module. For example,
* <blockquote><pre>
* //
* // org/foo/xml/module-info.java
@@ -45,14 +45,15 @@ import java.lang.annotation.RetentionPol
* module org.foo.xml;
* </pre></blockquote>
* @see java.module.VersionConstraint
+ * @see java.util.ResourceBundle
* @since 1.7
*/
@Target({ElementType.MODULE})
@Retention(RetentionPolicy.RUNTIME)
public @interface ResourceModuleConstraint {
/**
- * The version constraint that this module definition requires its resource
- * modules to satisfy.
+ * The version constraint that this <i>target module</i> requires its
+ * <i>resource modules</i> to satisfy.
*/
String value() default "0.0.0.0+";
}
--- a/src/share/classes/java/module/annotation/ResourceTargetConstraint.java Mon Jul 07 10:13:08 2008 -0700
+++ b/src/share/classes/java/module/annotation/ResourceTargetConstraint.java Tue Jul 08 12:14:10 2008 -0700
@@ -31,8 +31,8 @@ import java.lang.annotation.RetentionPol
import java.lang.annotation.RetentionPolicy;
/**
- * Indicates the version constraint that a resource module definition
- * requires its target module to satisfy. The version constraint is either a
+ * Indicates the version constraint that a <i>resource module</i> requires its
+ * <i>target module</i> to satisfy. The version constraint is either a
* version, a version range, or a combination of both, following the format
* described in the {@link java.module.VersionConstraint} class. This metadata
* annotation is applied to a Java module. For example,
@@ -45,14 +45,15 @@ import java.lang.annotation.RetentionPol
* module org.foo.xml.locale_fr;
* </pre></blockquote>
* @see java.module.VersionConstraint
+ * @see java.util.ResourceBundle
* @since 1.7
*/
-@Target({ElementType.MODULE, ElementType.TYPE})
+@Target({ElementType.MODULE})
@Retention(RetentionPolicy.RUNTIME)
public @interface ResourceTargetConstraint {
/**
- * The version constraint that this resource module definition requires its
- * target module to satisfy.
+ * The version constraint that this <i>resource module</i> requires its
+ * <i>target module</i> to satisfy.
*/
String value() default "0.0.0.0+";
}
--- a/src/share/classes/java/module/annotation/Version.java Mon Jul 07 10:13:08 2008 -0700
+++ b/src/share/classes/java/module/annotation/Version.java Tue Jul 08 12:14:10 2008 -0700
@@ -31,9 +31,9 @@ import java.lang.annotation.RetentionPol
import java.lang.annotation.RetentionPolicy;
/**
- * Indicates the version. The version format must follow the one described in
- * the {@link java.module.Version} class. This metadata annotation can be
- * applied to a Java module. For examples,
+ * Indicates the version of a module definition. The version format must
+ * follow the one described in the {@link java.module.Version} class. This
+ * metadata annotation can be applied to a Java module. For examples,
* <blockquote><pre>
* //
* // com/wombat/xyz/module-info.java
--- a/src/share/classes/java/module/annotation/package-info.java Mon Jul 07 10:13:08 2008 -0700
+++ b/src/share/classes/java/module/annotation/package-info.java Tue Jul 08 12:14:10 2008 -0700
@@ -24,7 +24,7 @@
*/
/**
- * Provides metadata annotations for a Java module.
+ * Provides metadata annotations for modules in the JAM (JAva Module) module system.
*
* @since 1.7
*/
--- a/src/share/classes/java/module/package-info.java Mon Jul 07 10:13:08 2008 -0700
+++ b/src/share/classes/java/module/package-info.java Tue Jul 08 12:14:10 2008 -0700
@@ -24,7 +24,14 @@
*/
/**
- * Provides classes for the module system.
+ * Provides classes and interfaces for the Java Module System and the JAM (JAva
+ * Module) module system.
+ *
+ * <p> Unless otherwise noted, passing a <tt>null</tt> argument to a
+ * constructor or method in any class or interface in this package will cause
+ * a {@link java.lang.NullPointerException NullPointerException} to be thrown.
+ *
+ * <p> The java.module API is thread-safe.
*
* @since 1.7
*/
--- a/src/share/classes/sun/module/JamUtils.java Mon Jul 07 10:13:08 2008 -0700
+++ b/src/share/classes/sun/module/JamUtils.java Tue Jul 08 12:14:10 2008 -0700
@@ -338,14 +338,14 @@ public final class JamUtils {
}
/**
- * Returns the code signers from the JAM file
+ * Returns an unmodifiable set of code signers from the JAM file
*
* @param jamFile jam file
- * @return an array of code signers that sign the JAM file.
+ * @return an unmodifiable set of code signers that sign the JAM file.
* @throws IOException if the JAM file is not consistently signed by same
* set of signers.
*/
- public static CodeSigner[] getCodeSigners(JarFile jamFile) throws IOException {
+ public static Set<CodeSigner> getCodeSigners(JarFile jamFile) throws IOException {
List<CodeSigner> overallCodeSigners = null;
// Iterate each entry in the JAM file
@@ -382,7 +382,9 @@ public final class JamUtils {
+ jamFile.getName());
}
- return overallCodeSigners.toArray(new CodeSigner[0]);
+ Set<CodeSigner> result = new HashSet<CodeSigner>();
+ result.addAll(overallCodeSigners);
+ return Collections.unmodifiableSet(result);
}
/**
--- a/src/share/classes/sun/module/ModuleLauncher.java Mon Jul 07 10:13:08 2008 -0700
+++ b/src/share/classes/sun/module/ModuleLauncher.java Tue Jul 08 12:14:10 2008 -0700
@@ -33,8 +33,6 @@ import java.lang.reflect.*;
import java.lang.reflect.*;
import java.module.*;
-import java.module.annotation.MainClass;
-
import sun.module.*;
import sun.module.repository.RepositoryConfig;
import sun.module.core.ProxyModuleLoader;
@@ -93,8 +91,7 @@ public final class ModuleLauncher {
if (moduleMain != null) {
mainClassName = moduleMain;
} else {
- MainClass mainClass = moddef.getAnnotation(MainClass.class);
- mainClassName = (mainClass != null) ? mainClass.value() : null;
+ mainClassName = moddef.getMainClass();
if (mainClassName == null) {
throw new Exception("No Main-Class attribute in the module definition");
}
@@ -198,9 +195,9 @@ public final class ModuleLauncher {
// The directory which houses the jam becomes the system repository.
File baseDir = new File(jamFileName).getAbsoluteFile().getParentFile();
repository = Modules.newLocalRepository(
- RepositoryConfig.getSystemRepository(),
"application",
- baseDir.getAbsoluteFile()
+ baseDir.getAbsoluteFile(), null,
+ RepositoryConfig.getSystemRepository()
);
ModuleDefinition definition = null;
// Get the basename of the jam file.
@@ -240,9 +237,9 @@ public final class ModuleLauncher {
if (repositoryName == null) {
// Assume the current directory as the system repository.
repository = Modules.newLocalRepository(
- RepositoryConfig.getSystemRepository(),
"application",
- new File(".").getAbsoluteFile());
+ new File(".").getAbsoluteFile(), null,
+ RepositoryConfig.getSystemRepository());
} else {
if (moduleName == null) {
throw new IllegalArgumentException(MODULE_OPT +
@@ -262,12 +259,12 @@ public final class ModuleLauncher {
}
}
repository = Modules.newURLRepository(
- RepositoryConfig.getSystemRepository(),
- "application", u);
+ "application", u, null,
+ RepositoryConfig.getSystemRepository());
} else {
repository = Modules.newLocalRepository(
- RepositoryConfig.getSystemRepository(),
- "application", new File(u.toURI()));
+ "application", new File(u.toURI()), null,
+ RepositoryConfig.getSystemRepository());
}
}
RepositoryConfig.setSystemRepository(repository);
--- a/src/share/classes/sun/module/annotation/ModuleName.java Mon Jul 07 10:13:08 2008 -0700
+++ b/src/share/classes/sun/module/annotation/ModuleName.java Tue Jul 08 12:14:10 2008 -0700
@@ -32,7 +32,7 @@ import java.lang.annotation.RetentionPol
/**
* Indicates the name of a module definition. This metadata annotation is
- * applied to the module.
+ * applied to a Java module.
* <p>
* For example,
* <blockquote><pre>
--- a/src/share/classes/sun/module/bootstrap/BootstrapModuleSystem.java Mon Jul 07 10:13:08 2008 -0700
+++ b/src/share/classes/sun/module/bootstrap/BootstrapModuleSystem.java Tue Jul 08 12:14:10 2008 -0700
@@ -53,7 +53,7 @@ public final class BootstrapModuleSystem
@Override
public Module getModule(ModuleDefinition moduleDef) throws ModuleInitializationException {
- if (moduleDef.getRepository().getModuleSystem() != this) {
+ if (moduleDef.getModuleSystem() != this) {
throw new IllegalArgumentException
("Cannot instantiate new module instance from module definition in a different module system.");
}
@@ -68,7 +68,7 @@ public final class BootstrapModuleSystem
@Override
public List<Module> getModules(Module