Some views from a programmer [2/3: architecture]
Daniel Latrémolière
daniel.latremoliere at gmail.com
Wed Sep 16 12:58:15 EDT 2009
Source evolution
The first problem is to have source compatibility. I think it can be
achieved by allowing name of dependency to be omitted from import
declaration (in which case the dependency name, and the dot, will be
omitted from the qualified class name in imports) and send a compilation
error in case of collision between two names. The global resolving will
be made by Java compiler given his visible classes. Refactorings in IDE
will be able of modifying these imports in classes of the module to use
a non-defaulted names (by seeing existing classes in all currently
imported modules).
Example of "module-info.java" suggested:
// module identity (mandatory)
organisation "my organisation name";
module "my module name";
version "my version name";
// classes from "dep1" dependency will be prefixed accurately in classes:
// import dep1.pack1.pack2.ClassName; // new scheme
dependency "dep1";
// classes from "dep2" dependency will be defaulted without module prefix:
// import pack1.pack2.ClassName; // old scheme because defaults keyword.
dependency "dep2" defaults;
// with this defaults, source compatibility with Java6 will be OK, ...
// waiting for an IDE refactoring to infer owner module of each class, given qualified name.
// all non-null String are allowed as names of dependencies except "module"
// reserved as prefix for classes from the current module.
NB: with this configuration, a Java6 source code repository will compile
in Java7 if and only if a module-info.java file is added (but no changes
in each source code file): I think it will be sufficient for
compatibility. Please note that all Java applications will need to
configure an application manager for resolving dependencies. It is not a
new constraint: it is already the case of giving to each application
(java, javac) an application manager in the form of a classpath
repository (or with Ant or IDE wrapping a classpath coming from Ivy
repository, OSGi repository, Jigsaw repository, etc.).
[Small personal comment: If you have some time, please can you remove
from Java source code the package declaration? A source file can obtain
more simply his package name from folder hierarchy (already needed to be
correct) relatively to module-info.java file than from package
declaration. For me, I don't find really useful the package declaration
in source file.]
Binary evolution
A module is very similar to a ClassLoader, then I suggest to retrofit
ClassLoader as a subclass of a new Module class: ClassLoader being
specifically used for pre-Java7 class loading, Module for Java7 and
upwards code.
package java.lang;
/**
* A Module can only load Java7 class format (with qualified classname prefixed by dependency name).
*
* For compatibility with old Java class format, see the ClassLoader subclass.
*/
public class Module {
/* --- free topology between modules --- */
// defineClass(...) method is replaced by a defineModuleClass(...)
// reading qualified names by used the first item as dependency name.
// findClass(String) is replaced by findModuleClass(String) searching
// the class only in the module classes but not in others modules.
// same code than current ClassLoader except topology simplification:
// "parent" field: constructor with parent and getParent().
// system context: getSystemClassLoader() getSystemResource*().
/* --- definition of module identity --- */
// fields and methods added
private final String organisation;
public final String getOrganisation() {return organisation;}
private final String name;
public final String getModuleName() {return name;}
private final String version;
public final String getVersion() {return version;}
// fields and methods added: dependencies names
private final String[] depNames;
public final String[] getDependenciesNames() {return depNames;}
/* --- definition of application manager --- */
// field used for application management:
private final ModuleManager manager;
/* --- others --- */
// only one public constructor, called by application manager
// for creating a module:
public Module(ModuleManager manager, String organisation, String name,
String version, String... dependencies) {
this.manager = manager;
this.organisation = organisation;
this.name = name;
this.version = version;
this.depNames = dependencies;
}
// NB: this Module class has a private subclass reading all these informations
// from module-info.class for static module (JAR library) if the module is given by File/URL.
// But a dynamic code generator can create classes given it had only to declare
// at initialisation the manager, the identity of the module and names of dependencies
// and extends this class.
// dependencies list is frozen except if currently possible
// to implement following methods (not needed for Java7).
// protected void addDependencyName(String name);
// protected void removeDependencyName(String name);
}
// class to be implemented by each application management tool (OSGi, Jigsaw, Classpath, etc.)
public abstract class ModuleManager {
// the core task of application manager
public abstract Module resolveDependency(Module module, String dependency);
/* --- some utilities methods for easing task of creating application management tool --- */
// return all modules managed by this application manager.
public final Module[] listAllManagedModules() {...}
// return all available modules managed by this application manager
// from a specific organisation with this name but any version String.
public final Module[] readAllModuleVersions(String organisation, String name) {...};
/* --- some possibles features --- */
// return all currently loaded application management tools.
public static final ModuleManager[] readAllModuleManagers() {...};
// if possible to replace dynamically a dependency of a not used module by another module
protected final void replaceDependency(Module module, String name, Module dependency)
throws CurrentlyUsedModuleException {...}
}
package java.lang;
/**
* A ClassLoader can only load pre Java7 class format, then is now deprecated.
*/
@Deprecated
public class ClassLoader extends Module {
// keep parent field and getParent();
private final ClassLoader parent;
protected ClassLoader(ClassLoader parent) {
super("java6", hashcode(), "1.0", "parent");
this.parent = parent;
}
// has his old defineClass(...) method reading qualified classname as old behaviour
// but defining all classes not internal to the module a being from the "parent" dependency.
// But for helping current application manager to load old code, this can be configured
// by overriding the following method
protected String resolveDependencyName(String qualifiedClassName) {
return "parent";
// but overrided by OSGi, Jigsaw, etc. using their own configuration rules
// added in their module repository for adapting old Java6 code to Java7 modules, like:
// if (qualifiedClassName.matches("javax\/servlet\/.*")) return "servlet-api";
}
// this need that a new ClassLoader constructor need to be available with dependencies declaration:
protected ClassLoader(ClassLoader parent, String... dependencies) {
super("java6", hashcode(), "1.0", concatenateArrayAndItem(dependencies, "parent"));
this.parent = parent;
}
// to avoid headaches defineModuleClass(...) send always an exception.
// No mixture of Java6 and Java7 classes in one module.
// compatibility for findClass().
protected Class<?> findClass(String name) {
Class<?> clazz = findModuleClass(name);
return (clazz == null) ? parent.findClass(name) : clazz;
}
}
Tools evolution
The changes needed to the tools (java, javac) are the add of a new
switch (like "-manager") for passing the jar module of repository
manager which will declare and import the code of all application
modules. This switch will be incompatible with "-classpath" or direct
declaration of executable. These two cases will use a special repository
manager: a ClasspathManager only for compatibility (almost a current
URLClassLoader, I hope, but I have not exactly studied).
When called with "-manager' switch, the tools will obtain from argument
or JAR manifest of the module the qualified name in the module of the
singleton extending ModuleManager.
For javac, I would like to have a warning if module-info.java contains
defaulted dependency (or package declaration).
Java platform evolution
Please split Java platform in some modules for having smaller parts. I
would be very happy to forget some parts not used by me.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://cs.oswego.edu/pipermail/jsr294-modularity-observer/attachments/20090916/2b55b9ba/attachment-0001.html>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: daniel_latremoliere.vcf
Type: text/x-vcard
Size: 199 bytes
Desc: not available
URL: <http://cs.oswego.edu/pipermail/jsr294-modularity-observer/attachments/20090916/2b55b9ba/attachment-0001.vcf>
More information about the jsr294-modularity-observer
mailing list