I've committed some work that does the majority of this work,
but it is still incomplete and almost certainly requires a bit more refactoring
internally.
This introduces the notion of a ClassLoadingSpace
which is really just a Set of related ClassLoading modules.
The ClassLoadingSpace has a two phase api:
join() - for when a module joins a classloading space
split() - for when a module leaves a classloading space
resolve() - work out when classloading spaces need to join
unresolve() - nothing currently ;-)
The basic strategy is that as each module is added to the ClassLoading
a ClassLoaderSpace of just that module is constructed.
Then during the resolution, it figures out that it and an imported Module
need to be in the same ClassLoadingSpace so it does a join on the
their respective ClassLoadingSpaces.
Consistency checks are done during the join()
The work still to do at this point is:
* Tests (and handling) for circularity/self-depdendency in imports
* Handling of split packages (i.e. two modules have the same
package at the same version - but probably different classes, e.g. language packs)
* Validation of optional imports (e.g. uses constraints) currently, I'm ignoring these
* Better error reporting, i.e. more info on why a conflict occurs (why the
modules are related) rather than just that a conflict has occurred
Also, currently the initial resolve() is done at ClassLoading.addModule().
But since that is an inCallback throwing an error from there
doesn't lead to a failed deployment, just a warning. So this needs
to be revisited (it should just be done lazily when the MC calls back on
the RequirementDependencyItem).
As part of this work I also add a Requirement/VersionRange.isConsistent()
such that people can write their own consistenty checks between requirements.