Here is a somewhat readable version of the changes in the specification for 2.3 for datastore timeout, exact class getObjectById, and the enhancer. Please review and comment.

11.1:
Datastore Timeout
Some datastore operations can exceed the expected or desired time to execute, due to conditions that might not be influenced by the application directly. In order to allow the application to gracefully recover from these conditions, the application can specify timeouts to be applied separately to read and write datastore operations. DatastoreReadTimeoutMillis: the number of milliseconds allowed for read operations to complete. Read operations include retrieving instances from the datastore, loading fields, and executing queries that do not change the datastore. DatastoreWriteTimeoutMillis: the number of milliseconds allowed for write operations to complete. Write operations include flushing changes and deleting instances by query. Timeouts can be specified at three locations: the PersistenceManagerFactory, the PersistenceManager, and the Query. Timeouts specified at the PersistenceManagerFactory are the defaults for timeouts of the PersistenceManager. Timeous specified at the PersistenceManager are the defaults for Query. Timeouts specified at the Query apply only to that specific query. If a timeout is specified, the implementation will use the supplied value as a timeout for operations where the underlying datastore supports it. The timeouts are in milliseconds. If it is not specified then there is no timeout.

11.1.1:
"javax.jdo.option.DatastoreReadTimeoutMillis"
"javax.jdo.option.DatastoreWriteTimeoutMillis"

11.1.4:
<!DOCTYPE jdoconfig
PUBLIC “-//Sun Microsystems, Inc.//DTD Java Data Objects Configuration 2.3//EN”
http://java.sun.com/dtd/jdoconfig_2_3.dtd”>
-->
<!ELEMENT jdoconfig (persistence-manager-factory+)>

<!ELEMENT persistence-manager-factory (property*, instance-lifecycle- listener*)>
<!ATTLIST persistence-manager-factory class CDATA #IMPLIED>
<!ATTLIST persistence-manager-factory name CDATA #IMPLIED>
<!ATTLIST persistence-manager-factory persistence-unit-name CDATA #IMPLIED> <!ATTLIST persistence-manager-factory optimistic (true|false) CDATA #IMPLIED> <!ATTLIST persistence-manager-factory readonly (true|false) CDATA ‘false’> <!ATTLIST persistence-manager-factory retain-values (true|false) CDATA #IMPLIED> <!ATTLIST persistence-manager-factory restore-values (true|false) CDATA #IMPLIED> <!ATTLIST persistence-manager-factory ignore-cache (true|false) CDATA #IMPLIED> <!ATTLIST persistence-manager-factory nontransactional-read (true| false) CDATA #IMPLIED> <!ATTLIST persistence-manager-factory nontransactional-write (true| false) CDATA #IMPLIED> <!ATTLIST persistence-manager-factory multithreaded (true|false) CDATA #IMPLIED> <!ATTLIST persistence-manager-factory transaction-isolation-level CDATA #IMPLIED> <!ATTLIST persistence-manager-factory connection-driver-name CDATA #IMPLIED> <!ATTLIST persistence-manager-factory connection-user-name CDATA #IMPLIED> <!ATTLIST persistence-manager-factory connection-password CDATA #IMPLIED>
<!ATTLIST persistence-manager-factory connection-url CDATA #IMPLIED>
<!ATTLIST persistence-manager-factory connection-factory-name CDATA #IMPLIED> <!ATTLIST persistence-manager-factory connection-factory2-name CDATA #IMPLIED>
<!ATTLIST persistence-manager-factory mapping CDATA #IMPLIED>
<!ATTLIST persistence-manager-factory detach-all-on-commit (true| false) CDATA #IMPLIED> <!ATTLIST persistence-manager-factory server-time-zone-id CDATA #IMPLIED> <!ATTLIST persistence-manager-factory datastore-read-timeout-millis CDATA #IMPLIED> <!ATTLIST persistence-manager-factory datastore-write-timeout-millis CDATA #IMPLIED>

<!ELEMENT property EMPTY>
<!ATTLIST property name CDATA #REQUIRED>
<!ATTLIST property value CDATA #IMPLIED>

<!ELEMENT instance-lifecycle-listener EMPTY>
<!ATTLIST instance-lifecycle-listener listener CDATA #REQUIRED>
<!ATTLIST instance-lifecycle-listener classes CDATA #IMPLIED>


11.6:
javax.jdo.option.QueryCancel
The JDO implementation supports canceling a running query. The underlying datastore must also support canceling a running query. The cancel support in the datastore must at least free the client thread executing the query. The server cancel behavior is not specified.
javax.jdo.option.DatastoreTimeout
The JDO implementation supports datastore timeouts. The underlying datastore must also support datastore timeouts. The server timeout behavior is not specified.

11.10:
Metadata Access
Metadata can be specified via annotations, xml, or API. These methods provide access to metadata managed by the PersistenceManagerFactory.
void registerMetadata(JDOMetadata metadata);
Register metadata with this PersistenceManagerFactory. Metadata can be created using the newMetadata method.
JDOMetadata newMetadata();
Return a new JDO metadata object that can be subsequently modified and registered with this PersistenceManagerFactory.
ComponentMetadata getMetadata(String className);
Return the class or interface metadata object for the specified class or interface, if there is metadata defined for that class or interface.

12.6.3:
void setDatastoreReadTimeoutMillis(Integer milliseconds);
Integer getDatastoreReadTimeoutMillis();
These methods set and get the datastore read timeout value in milliseconds. The value might have been set in the PersistenceManagerFactory via API or properties. Setting the value to null will use the value specified in PersistenceManagerFactory. Setting the timeout to a non-null value will override the value specified in PersistenceManagerFactory.
void setDatastoreWriteTimeoutMillis(Integer milliseconds);
Integer getDatastoreWriteTimeoutMillis();
These methods set and get the datastore write timeout value in milliseconds. The value might have been set in the PersistenceManagerFactory via API or properties. Setting the value to null will use the value specified in PersistenceManagerFactory. Setting the timeout to a non-null value will override the value specified in PersistenceManagerFactory.

12.6.5:
If the validate flag is false, the user asserts that the instance exists and the object id represents the exact class of the persistent instance (specifically not a subclass or an interface): A12.6.5-2 [If the object id represents an interface or abstract class, JDOUserException is thrown.] A12.5.6-2 [If there is already an instance in the cache with the same JDO identity as the oid parameter, then this method returns it.] A12.5.6-3 [There is no change made to the state of the returned instance.] A12.5.6-4 [If there is not an instance already in the cache with the same JDO identity as the oid parameter, then this method creates an instance with the specified JDO identity and returns it. If there is no transaction in progress, the returned instance will be hollow or persistent-nontransactional, at the choice of the implementation.] A12.5.6-5 [If there is a transaction in progress, the returned instance will be hollow, persistent-nontransactional, or persistent- clean, at the choice of the implementation.] A12.6.5-2 [The implementation must not access the datastore to determine the exact class. If the class is not the exact class, then an exception must be thrown subsequently if any field other than the identity field is accessed. ] A12.6.5-1 [If the instance does not exist in the datastore, then this method will not fail. But A12.5.6-6 [a subsequent access of the fields of the instance will throw a JDOObjectNotFoundException if the instance does not exist at that time.] Further, if a relationship is established to this instance, and the instance does not exist when the instance is flushed to the datastore, then the transaction in which the association was made will fail.
If the validate flag is true:
A12.5.6-7 [If there is already a transactional instance in the cache with the same jdo identity as the oid parameter, then this method returns it. There is no change made to the state of the returned instance.] A12.5.6-8 [If there is an instance already in the cache with the same jdo identity as the oid parameter, the instance is not transactional, and the instance does not exist in the datastore, then a JDOObjectNotFoundException is thrown.] A12.5.6-9 [If there is not an instance already in the cache with the same jdo identity as the oid parameter, then this method creates an instance with the specified jdo identity, verifies that it exists in the datastore, and returns it. A12.6.5-2 [The class in the object id might be the exact class or an abstract or concrete superclass of the actual instance.] A12.6.5-2 [If the instance does not exist in the datastore, then a JDOObjectNotFoundException is thrown.] If the fetch plan has been changed from its original value, the fetch plan governs which fields are fetched from the datastore and which related objects are also fetched with them. If there is no transaction in progress, the returned instance will be hollow or persistent-nontransactional, at the choice of the implementation. If there is a datastore transaction in progress, the returned instance will be persistent-clean. If there is an optimistic transaction in progress, the returned instance will be persistent-nontransactional.]

14.6.1:
Query Timeout
Queries may have timeouts associated with them. The timeout values might be set in the PersistenceManagerFactory, in the PersistenceManager, or in the Query instance.
Integer getDatastoreReadTimeoutMillis();
Integer getDatastoreWriteTimeoutMillis();
A value of null indicates that there is no timeout set for this query. A non-null value indicates that the timeout was set by this query, or the value was obtained by the default value set in the PersistenceManager or the PersistenceManagerFactory. A timeout value of 0 indicates that there is no timeout for this query.
void setDatastoreReadTimeoutMillis(Integer timeoutMillis);
void setDatastoreWriteTimeoutMillis(Integer timeoutMillis);
A14.6.1-7 [If a non-null timeout value is specified, a running query will be interrupted if it exceeds the execution time of the timeout value. The thread executing the query will throw JDODatastoreException. Specifying a timeout value of 0 indicates that there is no timeout for this query (a setting of 0 overrides the default specified in the PersistenceManager or the PersistenceManagerFactory).] If the timeout value is specified as null, then the timeout is obtained from the PersistenceManager or the PersistenceManagerFactory. If there is no timeout specified in any of the Query, the PersistenceManager or the PersistenceManagerFactory, there is no timeout for the query.
Query Cancel
Queries might be canceled by a different thread from the thread currently executing the query. There is no requirement that the Multithreaded flag be set in order to invoke the cancel operation from a different thread.
void cancelAll();
void cancel(Thread thread);
A14.6.1-8 [These methods cancel a running query (or queries). The thread that has its query canceled will throw a JDOQueryInterruptedException. If cancel is not supported (most likely due to the underlying implementation not supporting cancel) then JDOUnsupportedOptionException is thrown to the caller. ]

19.2.2

JDO Metadata
JDOMetadata represents the root of the metadata.
/**
 * Represents the top-level JDO metadata.
 * @since 2.3
 */
public interface JDOMetadata extends Metadata {
    /**
     * Method to set the catalog (ORM) to apply to all classes in this
     * JDO Metadata.
     *
     * @param catalog Catalog name
     */
    JDOMetadata setCatalog(String catalog);

    /**
* Accessor for the catalog (ORM) that all classes in this JDO Metadata
     * default to.
     *
     * @return The catalog
     */
    String getCatalog();

    /**
* Method to set the schema (ORM) to apply to all classes in this JDO
     * Metadata.
     *
     * @param schema Schema name
     */
    JDOMetadata setSchema(String schema);

    /**
* Accessor for the schema (ORM) that all classes in this JDO Metadata
     * default to.
     *
     * @return The schema
     */
    String getSchema();

    /**
     * Accessor for all packages defined on the JDO Metadata.
     *
     * @return The packages
     */
    PackageMetadata[] getPackages();

    /**
     * Add a new package to this JDO Metadata.
     *
     * @param pkgName Name of the package
     * @return The PackageMetadata
     */
    PackageMetadata newPackageMetadata(String pkgName);

    /**
     * Add a new package to this JDO Metadata.
     *
     * @param pkg The package
     * @return The PackageMetadata
     */
    PackageMetadata newPackageMetadata(Package pkg);

    /**
* Accessor for the number of packages defined in this JDO Metadata.
     *
     * @return The number of packages.
     */
    int getNumberOfPackages();

    /**
     * Add a new class to this JDO Metadata.
     * Adds its package also if not yet existing.
     *
     * @param cls Class to add
     * @return The ClassMetadata
     */
    ClassMetadata newClassMetadata(Class cls);

    /**
     * Add a new interface to this JDO Metadata.
     * Adds its package also if not yet existing.
     *
     * @param cls Class to add
     * @return The InterfaceMetadata
     */
    InterfaceMetadata newInterfaceMetadata(Class cls);

    /**
     * Accessor for any named queries defined on the JDO Metadata.
     *
     * @return The queries
     */
    QueryMetadata[] getQueries();

    /**
     * Add a new named query to this JDO Metadata.
     *
     * @param name Name of the query
     * @return The QueryMetadata
     */
    QueryMetadata newQueryMetadata(String name);

    /**
* Accessor for the number of named queries defined in this JDO Metadata.
     *
     * @return The number of queries.
     */
    int getNumberOfQueries();

    /**
     * Accessor for any fetch plans defined on the JDO Metadata.
     *
     * @return The fetch plans
     */
    FetchPlanMetadata[] getFetchPlans();

    /**
     * Add a new fetch plan to this JDO Metadata.
     *
     * @param name Name of the query
     * @return The FetchPlanMetadata
     */
    FetchPlanMetadata newFetchPlanMetadata(String name);

    /**
* Accessor for the number of fetch plans defined in this JDO Metadata.
     *
     * @return The number of fetch plans.
     */
    int getNumberOfFetchPlans();
}

Package Metadata
PackageMetadata represents the collection of metadata that share the same package.
/**
 * Represents a package within a JDOMetadata.
 * @since 2.3
 */
public interface PackageMetadata extends Metadata {
    /**
     * Accessor for the name of this package (set on construction).
     *
     * @return The name
     */
    String getName();

    /**
* Method to set the catalog (ORM) to apply to all classes in this package.
     *
     * @param catalog Catalog name
     */
    PackageMetadata setCatalog(String catalog);

    /**
* Accessor for the catalog (ORM) that all classes in this package default
     * to.
     *
     * @return The catalog
     */
    String getCatalog();

    /**
* Method to set the schema (ORM) to apply to all classes in this package.
     *
     * @param schema Schema name
     */
    PackageMetadata setSchema(String schema);

    /**
* Accessor for the schema (ORM) that all classes in this package default to.
     *
     * @return The schema
     */
    String getSchema();

    /**
     * Accessor for all classes defined in this package.
     *
     * @return The classes
     */
    ClassMetadata[] getClasses();

    /**
     * Add a new class to this package.
     *
     * @param name Name of the class
     * @return The ClassMetadata
     */
    ClassMetadata newClassMetadata(String name);

    /**
     * Add a new class to this package.
     *
     * @param cls The class
     * @return The ClassMetadata
     */
    ClassMetadata newClassMetadata(Class cls);

    /**
     * Accessor for the number of classes defined in this package.
     *
     * @return The number of classes.
     */
    int getNumberOfClasses();

    /**
     * Accessor for all interfaces defined in this package.
     *
     * @return The interfaces
     */
    InterfaceMetadata[] getInterfaces();

    /**
     * Add a new interface to this package.
     *
     * @param name The interface name
     * @return The InterfaceMetadata
     */
    InterfaceMetadata newInterfaceMetadata(String name);

    /**
     * Add a new interface to this package.
     *
     * @param cls The class
     * @return The ClassMetadata
     */
    InterfaceMetadata newInterfaceMetadata(Class cls);

    /**
     * Accessor for the number of interfaces defined in this package.
     *
     * @return The number of interfaces.
     */
    int getNumberOfInterfaces();

    /**
     * Accessor for any sequences defined on the package.
     *
     * @return The sequences
     */
    SequenceMetadata[] getSequences();

    /**
     * Add a new sequence to this package.
     *
     * @param name Name of the sequence
     * @param strategy Strategy for the sequence
     * @return The SequenceMetadata
     */
    SequenceMetadata newSequenceMetadata(String name,
            SequenceStrategy strategy);

    /**
     * Accessor for the number of sequences defined for this package.
     *
     * @return The number of sequences.
     */
    int getNumberOfSequences();
}

Component Metadata
ComponentMetadata represents the metadata for classes and interfaces.
/**
* Represents a class or interface. Extended for the specifics of those cases.
 * @since 2.3
 */
public interface ComponentMetadata extends Metadata {
    /**
     * Accessor for the name of this component (set on construction).
     *
     * @return The name
     */
    String getName();

    /**
     * Method to define the identity type to use.
     *
     * @param id identity type
     */
    ComponentMetadata setIdentityType(IdentityType id);

    /**
     * Accessor for the identity type to use.
     *
     * @return identity type
     */
    IdentityType getIdentityType();

    /**
     * Method to set the object-id (PK) class.
     *
     * @param idclass Object-id class
     */
    ComponentMetadata setObjectIdClass(String idclass);

    /**
     * Accessor for the object-id class (if defined).
     *
     * @return The object-id class
     */
    String getObjectIdClass();

    /**
     * Method to set whether the component requires an extent.
     *
     * @param extent Requires extent?
     */
    ComponentMetadata setRequiresExtent(boolean extent);

    /**
     * Accessor for whether the component requires an extent.
     *
     * @return Requires extent?
     */
    boolean getRequiresExtent();

    /**
     * Method to set whether this is detachable
     *
     * @param detachable Detachable?
     */
    ComponentMetadata setDetachable(boolean detachable);

    /**
     * Accessor for whether this is detachable.
     *
     * @return Detachable?
     */
    boolean getDetachable();

    /**
     * Method to set whether this is cacheable
     *
     * @param cacheable Cacheable?
     */
    ComponentMetadata setCacheable(boolean cacheable);

    /**
     * Accessor for whether this is cacheable.
     *
     * @return Cacheable?
     */
    boolean getCacheable();

    /**
     * Method to set whether this is serializeRead
     *
     * @param serializeRead serializeRead?
     */
    ComponentMetadata setSerializeRead(boolean serializeRead);

    /**
     * Accessor for whether this is serializeRead.
     *
     * @return serializeRead?
     */
    boolean getSerializeRead();

    /**
* Method to set whether it is stored only as embedded in other objects.
     *
     * @param embedded Whether it is only stored embedded
     */
    ComponentMetadata setEmbeddedOnly(boolean embedded);

    /**
     * Accessor for whether this is embedded only.
     *
     * @return Only stored as embedded
     */
    Boolean getEmbeddedOnly();

    /**
     * Method to set the catalog (ORM) for this component
     *
     * @param catalog Catalog name
     */
    ComponentMetadata setCatalog(String catalog);

    /**
     * Accessor for the catalog (ORM) for this component
     *
     * @return The catalog
     */
    String getCatalog();

    /**
     * Method to set the schema (ORM) for this component
     *
     * @param schema Schema name
     */
    ComponentMetadata setSchema(String schema);

    /**
     * Accessor for the schema (ORM) for this component
     *
     * @return The schema
     */
    String getSchema();

    /**
     * Method to set the table name.
     *
     * @param table Table name
     */
    ComponentMetadata setTable(String table);

    /**
     * Accessor for the name of the table.
     *
     * @return The name
     */
    String getTable();

    /**
     * Method to define the inheritance metadata.
     *
     * @return The InheritanceMetadata
     */
    InheritanceMetadata newInheritanceMetadata();

    /**
     * Accessor for the inheritance (if any).
     *
     * @return inheritance
     */
    InheritanceMetadata getInheritanceMetadata();

    /**
     * Method to define the version metadata.
     *
     * @return The VersionMetadata
     */
    VersionMetadata newVersionMetadata();

    /**
     * Accessor for the version (if any).
     *
     * @return version
     */
    VersionMetadata getVersionMetadata();

    /**
     * Method to define the datastore identity metadata details.
     *
     * @return The DatastoreIdentityMetadata
     */
    DatastoreIdentityMetadata newDatastoreIdentityMetadata();

    /**
     * Accessor for the datastore identity details.
     *
     * @return datastore identity details
     */
    DatastoreIdentityMetadata getDatastoreIdentityMetadata();

    /**
     * Method to define the primary key details.
     *
     * @return The PrimaryKeyMetadata
     */
    PrimaryKeyMetadata newPrimaryKeyMetadata();

    /**
     * Accessor for the primary key (if any).
     *
     * @return primary key details
     */
    PrimaryKeyMetadata getPrimaryKeyMetadata();

    /**
     * Accessor for all joins(s) defined on the component.
     *
     * @return The join(s)
     */
    JoinMetadata[] getJoins();

    /**
     * Add a join for this component.
     *
     * @return The JoinMetadata
     */
    JoinMetadata newJoinMetadata();

    /**
     * Accessor for the number of join(s) defined for this component.
     *
     * @return The number of join(s)
     */
    int getNumberOfJoins();

    /**
     * Accessor for all fk(s) defined on the component.
     *
     * @return The fk(s)
     */
    ForeignKeyMetadata[] getForeignKeys();

    /**
     * Add a new FK for this component.
     *
     * @return The ForeignKeyMetadata
     */
    ForeignKeyMetadata newForeignKeyMetadata();

    /**
     * Accessor for the number of FKs defined for this component.
     *
     * @return The number of FKs
     */
    int getNumberOfForeignKeys();

    /**
     * Accessor for all index(s) defined on the component.
     *
     * @return The index(s)
     */
    IndexMetadata[] getIndices();

    /**
     * Add a new index for this component.
     *
     * @return The IndexMetadata
     */
    IndexMetadata newIndexMetadata();

    /**
     * Accessor for the number of indices defined for this component.
     *
     * @return The number of indices
     */
    int getNumberOfIndices();

    /**
     * Accessor for all unique constraints defined on the component.
     *
     * @return The unique constraints
     */
    UniqueMetadata[] getUniques();

    /**
     * Add a new unique constraint for this component.
     *
     * @return The UniqueMetadata
     */
    UniqueMetadata newUniqueMetadata();

    /**
* Accessor for the number of unique constraints defined for this component.
     *
     * @return The number of unique constraints
     */
    int getNumberOfUniques();

    /**
     * Accessor for all fields/properties defined on the component.
     *
     * @return The members
     */
    MemberMetadata[] getMembers();

    /**
* Accessor for the number of fields/properties defined for this component.
     *
     * @return The number of members
     */
    int getNumberOfMembers();

    /**
     * Add a new property for this component.
     *
     * @param name Name of the property
     * @return The PropertyMetadata
     */
    PropertyMetadata newPropertyMetadata(String name);

    /**
     * Add a new property for this component.
     *
     * @param method Java bean getter/setter method
     * @return The PropertyMetadata
     */
    PropertyMetadata newPropertyMetadata(Method method);

    /**
     * Accessor for all named queries defined on the component.
     *
     * @return The queries
     */
    QueryMetadata[] getQueries();

    /**
     * Add a new query for this component.
     *
     * @param name
     *            Name of the query to add
     * @return The QueryMetadata
     */
    QueryMetadata newQueryMetadata(String name);

    /**
* Accessor for the number of named queries defined for this component.
     *
     * @return The number of named queries
     */
    int getNumberOfQueries();

    /**
     * Accessor for all FetchGroup defined on the component.
     *
     * @return The FetchGroups
     */
    FetchGroupMetadata[] getFetchGroups();

    /**
     * Add a new FetchGroup for this component.
     *
     * @param name Name of the FetchGroup
     * @return The FetchGroupMetadata
     */
    FetchGroupMetadata newFetchGroupMetadata(String name);

    /**
* Accessor for the number of fetchGroups defined for this component.
     *
     * @return The number of fetch groups
     */
    int getNumberOfFetchGroups();

    /**
     * Accessor for all column(s) defined on the join.
     *
     * @return The column(s)
     */
    ColumnMetadata[] getColumns();

    /**
     * Add a new column for this join.
     *
     * @return The ColumnMetadata
     */
    ColumnMetadata newColumnMetadata();

    /**
     * Accessor for the number of columns defined for this join.
     *
     * @return The number of columns
     */
    int getNumberOfColumns();
}

Class Metadata
ClassMetadata represents metadata for a specific persistence-capable class.
/**
 * Represents a class.
 * @since 2.3
 */
public interface ClassMetadata extends ComponentMetadata {
    /**
     * Method to define the persistence modifier.
     * @param mod persistence modifier
     */
    ClassMetadata setPersistenceModifier(ClassPersistenceModifier mod);

    /**
     * Accessor for the persistence modifier.
     * @return persistence modifier
     */
    ClassPersistenceModifier getPersistenceModifier();

    /**
     * Add a new field to this class.
     * @param name Name of the field
     * @return The FieldMetadata
     */
    FieldMetadata newFieldMetadata(String name);

    /**
     * Add a new field to this class.
     * @param fld The field
     * @return The FieldMetadata
     */
    FieldMetadata newFieldMetadata(Field fld);
}

Interface Metadata
InterfaceMetadata represents metadata for a specific persistence- capable interface.
/**
 * Represents a persistent-interface.
 * @since 2.3
 */
public interface InterfaceMetadata extends ComponentMetadata {

}

Field Metadata
FieldMetadata represents metadata for persistent fields.
/**
 * Represents a field in a class.
 * @since 2.3
 */
public interface FieldMetadata extends MemberMetadata {

}

Property Metadata
PropertyMetadata represents metadata for persistent properties.
/**
 * Represents a property in a class/persistent-interface.
 * @since 2.3
 */
public interface PropertyMetadata extends MemberMetadata {
    /**
     * Method to set the field name (persistent interfaces)
     *
     * @param name field name
     */
    PropertyMetadata setFieldName(String name);

    /**
     * Accessor for the field name
     *
     * @return Field name
     */
    String getFieldName();
}

Query Metadata
QueryMetadata represents metadata for queries.
/**
 * Represents a named query.
 * @since 2.3
 */
public interface QueryMetadata extends Metadata {
    /**
     * Accessor for the name of the query (set on construction).
     *
     * @return The name
     */
    String getName();

    /**
     * Method to set the language of the query.
     *
     * @param lang Query language
     */
    QueryMetadata setLanguage(String lang);

    /**
     * Accessor for the query language.
     *
     * @return The language
     */
    String getLanguage();

    /**
     * Method to set the single-string query.
     *
     * @param query The query
     */
    QueryMetadata setQuery(String query);

    /**
     * Accessor for the single-string query.
     *
     * @return The query
     */
    String getQuery();

    /**
     * Method to set the result class name for the query
     *
     * @param clsName Result class name
     */
    QueryMetadata setResultClass(String clsName);

    /**
     * Accessor for the result class name for the query.
     *
     * @return The result class name
     */
    String getResultClass();

    /**
     * Method to set if the query results are unique
     *
     * @param unique Whether they are unique
     */
    QueryMetadata setUnique(boolean unique);

    /**
     * Accessor for whether results from the query are unique
     *
     * @return Results are unique?
     */
    Boolean getUnique();

    /**
     * Method to set the query as not being modifiable from now.
     */
    QueryMetadata setUnmodifiable();

    /**
     * Accessor for whether the query is unmodifiable.
     *
     * @return Can’t be changed?
     */
    boolean getUnmodifiable();

    /**
     * Method to set the FetchPlan to use for this named query.
     *
     * @param fetchPlanName name of the FetchPlan
     */
    QueryMetadata setFetchPlan(String fetchPlanName);

    /**
     * Accessor for the name of a fetch plan to use (if any).
     *
     * @return The fetch plan name
     */
    String getFetchPlan();
}


23.1
Standard Enhancement
The enhancement process consists of two distinct functions: analyzing user input as to how and what to enhance; and performing the enhancement of the persistent classes. A Java main program is distributed as part of the java specification jar. Plugins for Interactive Development Environments are anticipated by the architecture but not provided by the JDO specification jar itself. Enhancing the persistent classes is the function of a JDO implementation, and in particular, the Reference Implementation. The Enhancer main program calls a standard enhancer by using the services locator architecture. Thus, the Enhancer main program can call any enhancer provided by a JDO implementation and made available on the class path. The name of the class that implements the JDOEnhancer API must be in the class path in the file called META-INF/services/ javax.jdo.JDOEnhancer. The enhancer operates on the byte code representation of persistent classes, and creates new byte code representations of the classes. The input byte code representations can come from four sources:
a byte array such as might be created by a dynamic class generator;
a file that contains the byte codes as generated by the javac compiler;
a jar file containing multiple classes and metadata files;
a resource loaded from a class loader that contains the byte codes as generated by the javac compiler The output byte code representations can be written to one of three destinations:
the same file as was provided as input;
the same jar file as was provided as input, in which case all contents of the jar file that are not enhanced are preserved intact; a directory that contains package names as directory names with identical semantics to the javac compiler's output directive. Restrictions: if a resource is used as input, then the only output possible is a directory. If a class file or jar file is used as input, the file must be read/write. If a byte array is used as input, then the enhanced byte array is available via a separate method call and is not written to output.
Enhancer Main
The Enhancer main class is intended to be run from an interactive shell (command line). It analyzes arguments and delegates to an implementation. The implementation must be identified via an entry in the class loader's resource file META-INF/services/ javax.jdo.JDOEnhancer. If multiple such files exist, the Enhancer main uses the first file containing the name of a class that can be loaded by the Class.forName method, containing a public no-args constructor, that returns an instance that implements javax.jdo.JDOEnhancer.
The enhancer is invoked with the following command line:
java -cp <classpath> javax.jdo.Enhancer <options> <directory, class, jdo, or jar file names> <classpath> must contain the jdo specification jar, the implementation jar and any implementation dependencies, the statically-compiled classes, and the jdo metadata files loadable as resources
<options> include:
-pu <persistence-unit-name> : the name of a persistence unit
-d <target directory> : write the enhanced classes to the specified directory
-checkonly : just check the classes for enhancement status
-v : verbose output
-r : recurse through directories to find all classes and metadata files to enhance -cp <enhancer class loader path> : if not already included in the java class loader, this parameter must contain the statically-compiled classes, and the jdo metadata files loadable as resources
<directory, file, or resource names>

Each entry following the options must be a directory, a file, or a resource name. The enhancer main program processes the command line and passes the parameters to the enhancer found via services lookup. Parameters are processed until the first non-option parameter is found. All subsequent parameters are treated as directory, file, or resource names. Parameters beginning with "-" are considered to be options. If an option is not a standard option, it is added to the non- standard options list. If a non-standard option is not recognized, the enhancer program exits with error code 3 (ENHANCER_USAGE_ERROR).
Parameters are processed as follows:
-cp <enhancer class loader path>: If this option is present, a new class loader is constructed, parented with the context class loader, to which the urls in the <enhancer class loader path> are added. The format of <enhancer class loader path> is the same as the -cp option of the java command. The class loader is passed to the enhancer via the setClassLoader method. -pu <persistence-unit-name>: If this option is present, each persistence-unit-name is passed to the enhancer via the addPersistenceUnit method. -d <target directory>: If this option is present, the target directory is passed to the enhancer via the setOutputDirectory method. -v: If this option is present, the verbose flag is set via the setVerbose method. -r: If this option is present, directories are recursively searched for files. -checkonly: If this option is present, the files are not enhanced, but verified via the validate method. If this option is absent, the files are enhanced via the enhance method. Parameters that follow the last option are passed to the enhancer. The enhancer handles the files as follows: For a .class file, the file must contain the byte codes of a persistent class consistent with the file name. Metadata is found using the algorithm detailed in Chapter 18, using the path specified for the .class file and recursing through parent directories in the file system. All class file names are passed to the enhancer via the addClasses method. For a .jdo file, the file must be a valid metadata file and the classes described in the file are treated as described (persistence- capable, persistence-aware, or not persistent). Metadata is found using the algorithm detailed in Chapter 18. All file names are passed to the enhancer via the addFiles method. For a .jar file, the file may contain .class files and .jdo metadata files. Each jar file name is passed to the enhancer via the addJar method. For a directory, the contents of the directory are analyzed for .class, .jdo, and .jar files which are then treated as if they were passed directly, as directory/*.class directory/*.jdo or directory/*.jar. If the -r option is specified, each subdirectory of the directory is treated as if it were itself the directory parameter, recursively. Thus, every .class file, .jdo file, and .jar file in the directory are included as files for enhancement.
Files that are not recognized as above are silently ignored.

23.22
Enhancer API
/**
 * Interface for a JDO Enhancer.
 * @since 2.3
 */
public interface JDOEnhancer extends ClassFileTransformer
{
    /**
     * Return non-configurable properties of this JDOEnhancer.
* Properties with keys “VendorName” and “VersionNumber” are required.
     * Other keys are optional.
     * @return the non-configurable properties of this JDOEnhancer.
     */
    Properties getProperties();

    /**
     * Whether to provide verbose output
     * @param flag Verbose?
     * @return The enhancer
     */
    JDOEnhancer setVerbose(boolean flag);

    /**
     * Mutator to set the location where enhanced classes are written.
     * Mutator to set the location where enhanced classes are written.
     * If this method is not called, classes will be enhanced in place,
* overwriting the existing classes. If overwriting classes in a jar file, * the existing files in the jar file will be written unchanged except * for the enhanced classes. The directory name can be absolute or relative.
     * @param dirName Name of the directory
     * @return The enhancer
     */
    JDOEnhancer setOutputDirectory(String dirName);

    /**
     * Mutator to set the class loader to use for loading classes.
     * @param loader ClassLoader to use
     * @return The enhancer
     */
    JDOEnhancer setClassLoader(ClassLoader loader);

    /**
     * Add a persistence-unit to the items to be enhanced.
     * @param persistenceUnit Name of the persistence unit
     * @return The enhancer
     */
    JDOEnhancer addPersistenceUnit(String persistenceUnit);

    /**
     * Add an in-memory class to the items to be enhanced.
     * The class name should be of the form “mydomain.MyClass”.
     * @param className Name of the class
     * @param bytes The bytes of the class
     * @return The enhancer
     */
    JDOEnhancer addClass(String className, byte[] bytes);

    /**
     * Add class(es) to the items to be enhanced.
* The class names can be absolute file names, relative file names, or
     * names of CLASSPATH resources.
     * @param classNames Names of the classes
     * @return The enhancer
     */
    JDOEnhancer addClasses(String... classNames);

    /**
     * Add metadata file(s) to the items to be enhanced.
* The metadata file names can be absolute file names, relative file names, or * names of CLASSPATH resources. They should be JDO XML metadata files.
     * @param metadataFiles Names of the files
     * @return The enhancer
     */
    JDOEnhancer addFiles(String... metadataFiles);

    /**
     * Add a jar file to the items to be enhanced.
* The jar file name can be absolute, or relative or a CLASSPATH resource.
     * @param jarFileName Name of the jar file
     * @return The enhancer
     */
    JDOEnhancer addJar(String jarFileName);

    /**
* Method to enhance the items specified using addJar, addFiles, addClasses, addClass,
     * addPersistenceUnit.
     * @return Number of classes enhanced
* @throws JDOEnhanceException if an error occurs during enhancement. If multiple
     * errors occur then the nested exceptions provides this detail.
     */
    int enhance();

    /**
* Method to validate the items specified using addJar, addFiles, addClasses, addClass,
     * addPersistenceUnit.
     * @return Number of classes validated
* @throws JDOEnhanceException if an error occurs during validation. If multiple
     * errors occur then the nested exceptions provides this detail.
     */
    int validate();

    /**
     * Method to retrieve the (enhanced) bytes of the specified class.
* Only applies to the classes enhanced in the most recent enhance() call. * If no enhance has yet been performed will throw a JDOEnhanceException. * If the specified class hasn’t been enhanced then will throw a JDOEnhanceException. * @param className Name of the class (of the form “mydomain.MyClass”)
     * @return Enhanced bytes
     */
    byte[] getEnhancedBytes(String className);

    /**
* Method to register metadata with the enhancement process managed by this
     * <code>JDOEnhancer</code>.
     * Metadata can be created using the method {...@link #newMetadata}.
* If there is already metadata registered for a class contained in this metadata
     * object then a JDOUserException will be thrown.
     * @param metadata The Metadata to register.
     * @since 2.3
     */
    void registerMetadata(JDOMetadata metadata);

    /**
* Method to return a new metadata object that can be subsequently modified * and registered with the enhancement process using the method {...@link #registerMetadata}.
     * @return The metadata
     * @since 2.3
     */
    JDOMetadata newMetadata();
}

Craig L Russell
Architect, Sun Java Enterprise System http://db.apache.org/jdo
408 276-5638 mailto:[email protected]
P.S. A good JDO? O, Gasp!

Reply via email to