Qwylt

java.lang.module.spi
Class ModuleState

java.lang.Object
  extended by java.lang.module.spi.ModuleState

public abstract class ModuleState
extends java.lang.Object

This class is a state machine that attempts to convert the passive imports of a ModuleArchive instance into a set of active connections to ClassSpace delegates, one per package name, and to create a new Module instance from them. Class space consistency is enforced by default.

Initially unconnected, an instance will be driven through a two-phase commit process when the getModule() method is called. The calling thread is blocked and the two-phase commit process then proceeds on a separate thread to avoid deadlocks.

In the prepare phase, an ImportSpace instance is created and populated, where each import is either:

The ImportSpace ensures that its candidate ModuleArchive(s) also enter the prepare phase if not already connected. Each connection initially must contain one candidate archive, but may hold many candidates. Constraints are applied that may reduce the set of candidates, and fail if the set reduces to zero.

Once connections have been established for all imports, recursively, the commit phase begins. All ModuleState instances that entered the prepare phase apply additional constraints (normally including one that ensures class space consistency).

If both the prepare and commit phases complete normally, a new Module is created and returned to the caller; otherwise, a ConnectionError will be thrown on the calling thread.

PackageConnection instances lazily connect themselves to a ClassSpace from a selected candidate that remains after all constraints are applied. By default, this will return a Module instance as the ClassSpace, but can be extended to return a virtual class space} as would be required for a split package in OSGi.

For existing module systems with their own import resolution mechanisms, the two-phase commit protocol can be short-circuited iff all imports are resolved by modules from the same module system. In that special case, the prepareImports() method can return an empty ImportSpace or the state can be constructed as CONNECTED.

Implementations are free to build the ImportSpace instance via computation or to re-create it via stored data. In the latter case, cache-consistency can be maintained by storing and comparing the repository location and modification time, or a digest of them.

Since:
Dec 21, 2008
Author:
Bryan Atsatt

Nested Class Summary
static class ModuleState.State
          The state of this state machine.
 
Constructor Summary
protected ModuleState(ModuleArchive archive)
          Construct an instance with INITIALIZED state for the specified ModuleArchive.
protected ModuleState(ModuleArchive archive, ImportSpace imports, ModuleState.State state)
          Construct an instance with a specified state for the specified ModuleArchive.
protected ModuleState(ModuleArchive archive, ModuleState.State state)
          Construct an instance with a specified state for the specified ModuleArchive.
 
Method Summary
protected  void commitImports(ImportSpace imports)
          Commit imports.
 void connect()
          Connect this instance, blocking the calling thread until connection completes or fails.
protected abstract  ImportSpace createImports()
          Create and populate a ImportSpace representing the imports of the associated archive: Create an ImportSpace with the relevant constraints, then Convert each package scoped import into a query, find all candidates and add them to the result. Convert each module scoped module import to a query, find a single candidate and add it to the results; this will add the candidate as if there were package imports for each package exported by the candidate. Return the result Called only when state is PREPARING.
protected abstract  Module createInstance()
          Create a new Module instance.
protected abstract  SharedState createSharedState(java.util.List<? extends ModuleArchive> compositeMembers)
          Create shared state.
 void disconnect(boolean deleteStorage)
          Reset all state.
protected  java.util.List<ModuleArchive> findAllImportCandidates(ModuleQuery importQuery, Import theImport)
          Find all import candidates that match the specified query.
protected  ModuleArchive findImportCandidate(ModuleQuery importQuery, Import theImport)
          Find a single import candidate that matches the specified query.
 ModuleArchive getArchive()
          Returns the archive from this ModuleState.
abstract  java.util.List<? extends ModuleArchive> getCompositeMembers()
          Returns the set of ModuleArchives that must share a ClassLoader.
 ConnectionError getError()
          Get the error if this ModuleState is in State.FAILED.
protected  java.util.Set<java.lang.String> getExportedPackages(ImportSpace imports)
          Returns a unmodifiable set of all exported package names, including re-exported imports.
protected  java.util.Set<java.lang.String> getExports()
          Returns the exports.
 java.util.Set<ModuleArchive> getImported()
          Returns the imported ModuleArchives.
protected  ImportSpace getImports()
          Returns the imports.
protected  SharedState getSharedState()
          Returns the shared state for this instance, if any.
 ModuleState.State getState()
          Returns the state of this ModuleState.
protected abstract  boolean isComposite()
          Returns whether or not Module instances created from this archive share a ClassLoader.
 boolean isConnected()
          Test if this instance is connected.
protected  ImportSpace load()
          Load stored state if available.
protected  SharedState loadShared()
          Load stored shared state if available.
 Module newInstance()
          TODO: change to 'module' access.
protected  ModuleState.State nextState()
           
protected  ImportSpace prepareImports()
          Creates and prepares an ImportSpace representing the imports of the associated archive.
protected  void reset(boolean deleteStorage)
          Reset state, called on disconnect.
protected  void setFailed(ConnectionError failure)
          Set state to FAILED with the specified failure.
protected  void setFailed(java.lang.Throwable failure)
          Set state to FAILED with the specified failure.
protected  void store(ImportSpace imports, SharedState shared)
          Store state.
 java.lang.String toString()
          Returns a string representation of this instance.
 void uninstall()
          Mark this instance as UNINSTALLED.
protected  void updateState(ModuleState.State newState)
          Update the state of this ModuleState instance.
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
 

Constructor Detail

ModuleState

protected ModuleState(ModuleArchive archive)
Construct an instance with INITIALIZED state for the specified ModuleArchive.

Parameters:
archive - The ModuleArchive.

ModuleState

protected ModuleState(ModuleArchive archive,
                      ModuleState.State state)
Construct an instance with a specified state for the specified ModuleArchive.

Parameters:
archive - The ModuleArchive.
state - The state.

ModuleState

protected ModuleState(ModuleArchive archive,
                      ImportSpace imports,
                      ModuleState.State state)
Construct an instance with a specified state for the specified ModuleArchive. Schedules this instance with the coordinator to complete the connection if required.

Parameters:
archive - The ModuleArchive.
imports - The comitted imports.
state - The state.
Throws:
ConnectionError - if imports are not connected.
Method Detail

disconnect

public void disconnect(boolean deleteStorage)
Reset all state.

Parameters:
deleteStorage - true iff stored state should be deleted.

getState

public ModuleState.State getState()
Returns the state of this ModuleState.

Returns:
The state.

getError

public ConnectionError getError()
Get the error if this ModuleState is in State.FAILED.

Returns:
ConnectionError if the state is State.FAILED; otherwise, returns null.

getArchive

public ModuleArchive getArchive()
Returns the archive from this ModuleState.

Returns:
The archive.

isConnected

public boolean isConnected()
Test if this instance is connected.

Returns:
true if state == State.CONNECTED; otherwise, returns false.

getSharedState

protected SharedState getSharedState()
Returns the shared state for this instance, if any. Can only be called in connected state.

Returns:
The shared state, or null if archive does not share a class loader.
Throws:
java.lang.IllegalStateException - if state is not CONNECTED.

uninstall

public void uninstall()
Mark this instance as UNINSTALLED.


newInstance

public Module newInstance()
TODO: change to 'module' access. Create a new, fully connected Module instance. If not connected, the calling thread is, blocked until connection completes or fails. Should ONLY be called by ModuleArchive.getModule().

Returns:
A new, fully connected Module instance.
Throws:
ConnectionError - if connection fails.

toString

public java.lang.String toString()
Returns a string representation of this instance.

Overrides:
toString in class java.lang.Object
Returns:
The string.

connect

public void connect()
Connect this instance, blocking the calling thread until connection completes or fails.

Throws:
ConnectionError - if connection fails.

isComposite

protected abstract boolean isComposite()
Returns whether or not Module instances created from this archive share a ClassLoader.

Returns:
true if Module instances created from this archive share a ClassLoader or false if not.

getCompositeMembers

public abstract java.util.List<? extends ModuleArchive> getCompositeMembers()
Returns the set of ModuleArchives that must share a ClassLoader.

Returns:
The composite members, including this instance, or null if this ModuleArchive does not share a ClassLoader.

getImported

public java.util.Set<ModuleArchive> getImported()
Returns the imported ModuleArchives.

Returns:
The archives.

prepareImports

protected ImportSpace prepareImports()
Creates and prepares an ImportSpace representing the imports of the associated archive. Called only when state is PREPARING.

Returns:
The ImportSpace representing the imports.
Throws:
ConnectionError - if connections cannot be created.

createImports

protected abstract ImportSpace createImports()
Create and populate a ImportSpace representing the imports of the associated archive:
  1. Create an ImportSpace with the relevant constraints, then
  2. Convert each package scoped import into a query, find all candidates and add them to the result.
  3. Convert each module scoped module import to a query, find a single candidate and add it to the results; this will add the candidate as if there were package imports for each package exported by the candidate.
  4. Return the result
Called only when state is PREPARING.

Returns:
The ImportSpace representing the imports.
Throws:
ConnectionError - if connections cannot be created.

createSharedState

protected abstract SharedState createSharedState(java.util.List<? extends ModuleArchive> compositeMembers)
Create shared state.

Parameters:
compositeMembers - The composite members.
Returns:
The shared state.

findImportCandidate

protected ModuleArchive findImportCandidate(ModuleQuery importQuery,
                                            Import theImport)
Find a single import candidate that matches the specified query.

Parameters:
importQuery - The query.
theImport - The import.
Returns:
The candidate or null if none and the import is optional.
Throws:
ConnectionError - if import is required and no candidate can be found.

findAllImportCandidates

protected java.util.List<ModuleArchive> findAllImportCandidates(ModuleQuery importQuery,
                                                                Import theImport)
Find all import candidates that match the specified query.

Parameters:
importQuery - The query.
theImport - The import.
Returns:
The candidate or null if none and the import is optional.
Throws:
ConnectionError - if import is required and no candidate can be found.

commitImports

protected void commitImports(ImportSpace imports)
Commit imports. Called after all imports have been prepared.

This implementation validates the imports.

Parameters:
imports - The imports.

getExportedPackages

protected java.util.Set<java.lang.String> getExportedPackages(ImportSpace imports)
Returns a unmodifiable set of all exported package names, including re-exported imports.

Parameters:
imports - The imports of this module.
Returns:
The set of exported package names.

store

protected void store(ImportSpace imports,
                     SharedState shared)
Store state. Called just before entering CONNECTED state. The default implementation does nothing.

Parameters:
imports - The imports.
shared - The shared state, or null if none, in case a reference to it needs to be stored along with the imports.

load

protected ImportSpace load()
Load stored state if available. The default implementation does nothing.

Returns:
The committed imports, or null if none or if an exception occurs.

loadShared

protected SharedState loadShared()
Load stored shared state if available. The default implementation does nothing.

Returns:
The shared state, or null if none or if an exception occurs.

reset

protected void reset(boolean deleteStorage)
Reset state, called on disconnect. The default implementation does nothing.

Parameters:
deleteStorage - true iff stored state should be deleted.

createInstance

protected abstract Module createInstance()
Create a new Module instance. Called only when state is CONNECTED.

Returns:
The new instance.

nextState

protected ModuleState.State nextState()
                               throws java.lang.Exception
Throws:
java.lang.Exception

getImports

protected ImportSpace getImports()
Returns the imports.

Returns:
The imports or null if not yet prepared. Valid only if state is COMMITTED.

getExports

protected java.util.Set<java.lang.String> getExports()
Returns the exports.

Returns:
The exports or null if not yet prepared. Valid only if state is COMMITTED.

setFailed

protected void setFailed(java.lang.Throwable failure)
Set state to FAILED with the specified failure.

Parameters:
failure - The failure.

setFailed

protected void setFailed(ConnectionError failure)
Set state to FAILED with the specified failure.

Parameters:
failure - The failure.

updateState

protected void updateState(ModuleState.State newState)
Update the state of this ModuleState instance. Notifies any waiters if new state is terminal.

Parameters:
newState - The new state.

Qwylt

Send comments or questions to Bryan Atsatt