Added: incubator/jdo/trunk/api20/src/java/javax/jdo/spi/I18NHelper.java URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/api20/src/java/javax/jdo/spi/I18NHelper.java?view=auto&rev=159273 ============================================================================== --- incubator/jdo/trunk/api20/src/java/javax/jdo/spi/I18NHelper.java (added) +++ incubator/jdo/trunk/api20/src/java/javax/jdo/spi/I18NHelper.java Mon Mar 28 10:25:05 2005 @@ -0,0 +1,356 @@ +/* + * Copyright 2005 The Apache Software Foundation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * I18NHelper.java + * + */ + +package javax.jdo.spi; + +import java.util.*; +import java.text.MessageFormat; +import java.security.AccessController; +import java.security.PrivilegedAction; + +import javax.jdo.JDOFatalInternalException; + +/** Helper class for constructing messages from bundles. The intended usage + * of this class is to construct a new instance bound to a bundle, as in + * <P> + * <code>I18NHelper msg = I18NHelper.getInstance("javax.jdo.Bundle");</code> + * <P> + * This call uses the class loader that loaded the I18NHelper class to find + * the specified Bundle. The class provides two overloaded getInstance + * methods allowing to specify a different class loader: + * [EMAIL PROTECTED] #getInstance(Class cls)} looks for a bundle + * called "Bundle.properties" located in the package of the specified class + * object and [EMAIL PROTECTED] #getInstance(String bundleName,ClassLoader loader)} + * uses the specified class loader to find the bundle. + * <P> + * Subsequently, instance methods can be used to format message strings + * using the text from the bundle, as in + * <P> + * <code>throw new JDOFatalInternalException (msg.msg("ERR_NoMetadata", cls.getName()));</code> + * @since 1.0.1 + * @version 1.0.2 + */ +public class I18NHelper { + + /** Bundles that have already been loaded + */ + private static Hashtable bundles = new Hashtable(); + + /** Helper instances that have already been created + */ + private static Hashtable helpers = new Hashtable(); + + /** The default locale for this VM. + */ + private static Locale locale = Locale.getDefault(); + + /** The bundle used by this instance of the helper. + */ + private ResourceBundle bundle = null; + + /** Throwable if ResourceBundle couldn't be loaded + */ + private Throwable failure = null; + + /** The unqualified standard name of a bundle. */ + private static final String bundleSuffix = ".Bundle"; // NOI18N + + /** Constructor */ + private I18NHelper() { + } + + /** Constructor for an instance bound to a bundle. + * @param bundleName the name of the resource bundle + * @param loader the class loader from which to load the resource + * bundle + */ + private I18NHelper (String bundleName, ClassLoader loader) { + try { + bundle = loadBundle (bundleName, loader); + } + catch (Throwable e) { + failure = e; + } + } + + /** An instance bound to a bundle. This method uses the current class + * loader to find the bundle. + * @param bundleName the name of the bundle + * @return the helper instance bound to the bundle + */ + public static I18NHelper getInstance (String bundleName) { + return getInstance (bundleName, I18NHelper.class.getClassLoader()); + } + + /** An instance bound to a bundle. This method figures out the bundle name + * for the class object's package and uses the class' class loader to + * find the bundle. Note, the specified class object must not be + * <code>null</code>. + * @param cls the class object from which to load the resource bundle + * @return the helper instance bound to the bundle + */ + public static I18NHelper getInstance (final Class cls) { + ClassLoader classLoader = (ClassLoader) AccessController.doPrivileged ( + new PrivilegedAction () { + public Object run () { + return cls.getClassLoader(); + } + } + ); + String bundle = getPackageName (cls.getName()) + bundleSuffix; + return getInstance (bundle, classLoader); + } + + /** An instance bound to a bundle. This method uses the specified class + * loader to find the bundle. Note, the specified class loader must not + * be <code>null</code>. + * @param bundleName the name of the bundle + * @param loader the class loader from which to load the resource + * bundle + * @return the helper instance bound to the bundle + */ + public static I18NHelper getInstance (String bundleName, + ClassLoader loader) { + I18NHelper helper = (I18NHelper) helpers.get (bundleName); + if (helper != null) { + return helper; + } + helper = new I18NHelper(bundleName, loader); + helpers.put (bundleName, helper); + // if two threads simultaneously create the same helper, return the first + // one to be put into the Hashtable. The other will be garbage collected. + return (I18NHelper) helpers.get (bundleName); + } + + /** Message formatter + * @param messageKey the message key + * @return the resolved message text + */ + public String msg (String messageKey) { + assertBundle (messageKey); + return getMessage (bundle, messageKey); + } + + /** Message formatter + * @param messageKey the message key + * @param arg1 the first argument + * @return the resolved message text + */ + public String msg (String messageKey, Object arg1) { + assertBundle (messageKey); + return getMessage (bundle, messageKey, arg1); + } + + /** Message formatter + * @param messageKey the message key + * @param arg1 the first argument + * @param arg2 the second argument + * @return the resolved message text + */ + public String msg (String messageKey, Object arg1, Object arg2) { + assertBundle (messageKey); + return getMessage (bundle, messageKey, arg1, arg2); + } + + /** Message formatter + * @param messageKey the message key + * @param arg1 the first argument + * @param arg2 the second argument + * @param arg3 the third argument + * @return the resolved message text + */ + public String msg (String messageKey, Object arg1, Object arg2, Object arg3) { + assertBundle (messageKey); + return getMessage (bundle, messageKey, arg1, arg2, arg3); + } + + /** Message formatter + * @param messageKey the message key + * @param args the array of arguments + * @return the resolved message text + */ + public String msg (String messageKey, Object[] args) { + assertBundle (messageKey); + return getMessage (bundle, messageKey, args); + } + + /** Message formatter + * @param messageKey the message key + * @param arg the argument + * @return the resolved message text + */ + public String msg (String messageKey, int arg) { + assertBundle (messageKey); + return getMessage(bundle, messageKey, arg); + } + + /** Message formatter + * @param messageKey the message key + * @param arg the argument + * @return the resolved message text + */ + public String msg (String messageKey, boolean arg) { + assertBundle (messageKey); + return getMessage(bundle, messageKey, arg); + } + + //========= Internal helper methods ========== + + /** + * Load ResourceBundle by bundle name + * @param bundleName the name of the bundle + * @param loader the class loader from which to load the resource bundle + * @return the ResourceBundle + */ + final private static ResourceBundle loadBundle( + String bundleName, ClassLoader loader) { + ResourceBundle messages = (ResourceBundle)bundles.get(bundleName); + + if (messages == null) //not found as loaded - add + { + messages = ResourceBundle.getBundle(bundleName, locale, loader); + bundles.put(bundleName, messages); + } + return messages; + } + + /** Assert resources available + * @param key the message key + * @since 1.0.2 + * @throws JDOFatalInternalException if the resource bundle could not + * be loaded during construction. + */ + private void assertBundle (String key) { + if (failure != null) + throw new JDOFatalInternalException ( + "No resources could be found to annotate error message key:\"" + + key + "\"", failure); + } + + /** + * Returns message as <code>String</code> + * @param messages the resource bundle + * @param messageKey the message key + * @return the resolved message text + */ + final private static String getMessage(ResourceBundle messages, String messageKey) + { + return messages.getString(messageKey); + } + + /** + * Formats message by adding array of arguments + * @param messages the resource bundle + * @param messageKey the message key + * @param msgArgs an array of arguments to substitute into the message + * @return the resolved message text + */ + final private static String getMessage(ResourceBundle messages, String messageKey, Object msgArgs[]) + { + for (int i=0; i<msgArgs.length; i++) { + if (msgArgs[i] == null) msgArgs[i] = ""; // NOI18N + } + MessageFormat formatter = new MessageFormat(messages.getString(messageKey)); + return formatter.format(msgArgs); + } + + /** + * Formats message by adding an <code>Object</code> argument. + * @param messages the resource bundle + * @param messageKey the message key + * @param arg the argument + * @return the resolved message text + */ + final private static String getMessage(ResourceBundle messages, String messageKey, Object arg) + { + Object []args = {arg}; + return getMessage(messages, messageKey, args); + } + + /** + * Formats message by adding two <code>Object</code> arguments. + * @param messages the resource bundle + * @param messageKey the message key + * @param arg1 the first argument + * @param arg2 the second argument + * @return the resolved message text + */ + final private static String getMessage(ResourceBundle messages, String messageKey, Object arg1, + Object arg2) + { + Object []args = {arg1, arg2}; + return getMessage(messages, messageKey, args); + } + + /** + * Formats message by adding three <code>Object</code> arguments. + * @param messages the resource bundle + * @param messageKey the message key + * @param arg1 the first argument + * @param arg2 the second argument + * @param arg3 the third argument + * @return the resolved message text + */ + final private static String getMessage(ResourceBundle messages, String messageKey, Object arg1, + Object arg2, Object arg3) + { + Object []args = {arg1, arg2, arg3}; + return getMessage(messages, messageKey, args); + } + + /** + * Formats message by adding an <code>int</code> as an argument. + * @param messages the resource bundle + * @param messageKey the message key + * @param arg the argument + * @return the resolved message text + */ + final private static String getMessage(ResourceBundle messages, String messageKey, int arg) + { + Object []args = {new Integer(arg)}; + return getMessage(messages, messageKey, args); + } + + /** + * Formats message by adding a <code>boolean</code> as an argument. + * @param messages the resource bundle + * @param messageKey the message key + * @param arg the argument + * @return the resolved message text + */ + final private static String getMessage(ResourceBundle messages, String messageKey, boolean arg) + { + Object []args = {String.valueOf(arg)}; + return getMessage(messages, messageKey, args); + } + + /** + * Returns the package portion of the specified class. + * @param className the name of the class from which to extract the + * package + * @return package portion of the specified class + */ + final private static String getPackageName(final String className) + { + final int index = className.lastIndexOf('.'); + return ((index != -1) ? className.substring(0, index) : ""); // NOI18N + } +}
Added: incubator/jdo/trunk/api20/src/java/javax/jdo/spi/JDOImplHelper.java URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/api20/src/java/javax/jdo/spi/JDOImplHelper.java?view=auto&rev=159273 ============================================================================== --- incubator/jdo/trunk/api20/src/java/javax/jdo/spi/JDOImplHelper.java (added) +++ incubator/jdo/trunk/api20/src/java/javax/jdo/spi/JDOImplHelper.java Mon Mar 28 10:25:05 2005 @@ -0,0 +1,587 @@ +/* + * Copyright 2005 The Apache Software Foundation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * JDOImplHelper.java + * + */ + +package javax.jdo.spi; + +import java.util.HashMap; +import java.util.WeakHashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import java.util.List; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.Collection; +import java.util.Collections; + +import javax.jdo.spi.JDOPermission; +import javax.jdo.JDOFatalUserException; +import javax.jdo.JDOFatalInternalException; + +/** This class is a helper class for JDO implementations. It contains methods + * to register metadata for persistence-capable classes and to perform common + * operations needed by implementations, not by end users. + * <P><code>JDOImplHelper</code> allows construction of instances of persistence-capable + * classes without using reflection. + * <P>Persistence-capable classes register themselves via a static method + * at class load time. + * There is no security restriction on this access. JDO implementations + * get access to the functions provided by this class only if they are + * authorized by the security manager. To avoid having every call go through + * the security manager, only the call to get an instance is checked. Once an + * implementation + * has an instance, any of the methods can be invoked without security checks. + * @version 1.0.2 + * + */ +public class JDOImplHelper extends java.lang.Object { + + /** This synchronized <code>HashMap</code> contains a static mapping of + * <code>PersistenceCapable</code> class to + * metadata for the class used for constructing new instances. New entries + * are added by the static method in each <code>PersistenceCapable</code> class. + * Entries are never removed. + */ + private static Map registeredClasses = Collections.synchronizedMap(new HashMap ()); + + /** This Set contains all classes that have registered for setStateManager + * permissions via authorizeStateManagerClass. + */ + private static Map authorizedStateManagerClasses = new WeakHashMap(); + + /** This list contains the registered listeners for <code>RegisterClassEvent</code>s. + */ + private static List listeners = new ArrayList(); + + /** The singleton <code>JDOImplHelper</code> instance. + */ + private static JDOImplHelper jdoImplHelper = new JDOImplHelper(); + + /** The Internationalization message helper. + */ + private final static I18NHelper msg = I18NHelper.getInstance ("javax.jdo.Bundle"); + + /** Creates new JDOImplHelper */ + private JDOImplHelper() { + } + + /** Get an instance of <code>JDOImplHelper</code>. This method + * checks that the caller is authorized for <code>JDOPermission("getMetadata")</code>, + * and if not, throws <code>SecurityException</code>. + * @return an instance of <code>JDOImplHelper</code>. + * @throws SecurityException if the caller is not authorized for JDOPermission("getMetadata"). + */ + public static JDOImplHelper getInstance() + throws SecurityException { + SecurityManager sec = System.getSecurityManager(); + if (sec != null) { + // throws exception if caller is not authorized + sec.checkPermission (JDOPermission.GET_METADATA); + } + return jdoImplHelper; + } + + /** Get the field names for a <code>PersistenceCapable</code> class. The order + * of fields is the natural ordering of the <code>String</code> class (without + * considering localization). + * @param pcClass the <code>PersistenceCapable</code> class. + * @return the field names for the class. + */ + public String[] getFieldNames (Class pcClass) { + Meta meta = getMeta (pcClass); + return meta.getFieldNames(); + } + + /** Get the field types for a <code>PersistenceCapable</code> class. The order + * of fields is the same as for field names. + * @param pcClass the <code>PersistenceCapable</code> class. + * @return the field types for the class. + */ + public Class[] getFieldTypes (Class pcClass) { + Meta meta = getMeta (pcClass); + return meta.getFieldTypes(); + } + + /** Get the field flags for a <code>PersistenceCapable</code> class. The order + * of fields is the same as for field names. + * @param pcClass the <code>PersistenceCapable</code> class. + * @return the field types for the class. + */ + public byte[] getFieldFlags (Class pcClass) { + Meta meta = getMeta (pcClass); + return meta.getFieldFlags(); + } + + /** Get the persistence-capable superclass for a <code>PersistenceCapable</code> class. + * @param pcClass the <code>PersistenceCapable</code> class. + * @return The <code>PersistenceCapable</code> superclass for this class, + * or <code>null</code> if there isn't one. + */ + public Class getPersistenceCapableSuperclass (Class pcClass) { + Meta meta = getMeta (pcClass); + return meta.getPersistenceCapableSuperclass(); + } + + + /** Create a new instance of the class and assign its <code>jdoStateManager</code>. + * The new instance has its <code>jdoFlags</code> set to <code>LOAD_REQUIRED</code>. + * @see PersistenceCapable#jdoNewInstance(StateManager sm) + * @param pcClass the <code>PersistenceCapable</code> class. + * @param sm the <code>StateManager</code> which will own the new instance. + * @return the new instance, or <code>null</code> if the class is not registered. + */ + public PersistenceCapable newInstance (Class pcClass, StateManager sm) { + Meta meta = getMeta (pcClass); + PersistenceCapable pcInstance = meta.getPC(); + return pcInstance == null?null:pcInstance.jdoNewInstance(sm); + } + + /** Create a new instance of the class and assign its <code>jdoStateManager</code> and + * key values from the ObjectId. If the oid parameter is <code>null</code>, + * no key values are copied. + * The new instance has its <code>jdoFlags</code> set to <code>LOAD_REQUIRED</code>. + * @see PersistenceCapable#jdoNewInstance(StateManager sm, Object oid) + * @param pcClass the <code>PersistenceCapable</code> class. + * @param sm the <code>StateManager</code> which will own the new instance. + * @return the new instance, or <code>null</code> if the class is not registered. + * @param oid the ObjectId instance from which to copy key field values. + */ + public PersistenceCapable newInstance + (Class pcClass, StateManager sm, Object oid) { + Meta meta = getMeta (pcClass); + PersistenceCapable pcInstance = meta.getPC(); + return pcInstance == null?null:pcInstance.jdoNewInstance(sm, oid); + } + + /** Create a new instance of the ObjectId class of this + * <code>PersistenceCapable</code> class. + * @param pcClass the <code>PersistenceCapable</code> class. + * @return the new ObjectId instance, or <code>null</code> if the class is not registered. + */ + public Object newObjectIdInstance (Class pcClass) { + Meta meta = getMeta (pcClass); + PersistenceCapable pcInstance = meta.getPC(); + return pcInstance == null?null:pcInstance.jdoNewObjectIdInstance(); + } + + /** Create a new instance of the ObjectId class of this <code>PersistenceCapable</code> + * class, using the <code>String</code> form of the constructor. + * @return the new ObjectId instance, or <code>null</code> if the class is not registered. + * @param str the <code>String</code> form of the object id + * @param pcClass the <code>PersistenceCapable</code> class. + */ + public Object newObjectIdInstance (Class pcClass, String str) { + Meta meta = getMeta (pcClass); + PersistenceCapable pcInstance = meta.getPC(); + return pcInstance == null?null:pcInstance.jdoNewObjectIdInstance(str); + } + + /** Copy fields from an outside source to the key fields in the ObjectId. + * This method is generated in the <code>PersistenceCapable</code> class to + * generate a call to the field manager for each key field in the ObjectId. + * <P>For example, an ObjectId class that has three key fields (<code>int id</code>, + * <code>String name</code>, and <code>Float salary</code>) would have the method generated: + * <P><code> + * void jdoCopyKeyFieldsToObjectId (Object oid, ObjectIdFieldSupplier fm) { + * <BR> oid.id = fm.fetchIntField (0); + * <BR> oid.name = fm.fetchStringField (1); + * <BR> oid.salary = fm.fetchObjectField (2); + * <BR>}</code> + * <P>The implementation is responsible for implementing the + * <code>ObjectIdFieldSupplier</code> to provide the values for the key fields. + * @param pcClass the <code>PersistenceCapable Class</code>. + * @param oid the ObjectId target of the copy. + * @param fm the field manager that supplies the field values. + */ + public void copyKeyFieldsToObjectId + (Class pcClass, PersistenceCapable.ObjectIdFieldSupplier fm, Object oid) { + Meta meta = getMeta (pcClass); + PersistenceCapable pcInstance = meta.getPC(); + if (pcInstance == null) { + throw new JDOFatalInternalException ( + msg.msg("ERR_AbstractClassNoIdentity", pcClass.getName())); //NOI18N + } + pcInstance.jdoCopyKeyFieldsToObjectId(fm, oid); + } + + /** Copy fields to an outside source from the key fields in the ObjectId. + * This method is generated in the <code>PersistenceCapable</code> class to generate + * a call to the field manager for each key field in the ObjectId. For + * example, an ObjectId class that has three key fields (<code>int id</code>, + * <code>String name</code>, and <code>Float salary</code>) would have the method generated: + * <P><code>void jdoCopyKeyFieldsFromObjectId + * <BR> (PersistenceCapable oid, ObjectIdFieldConsumer fm) { + * <BR> fm.storeIntField (0, oid.id); + * <BR> fm.storeStringField (1, oid.name); + * <BR> fm.storeObjectField (2, oid.salary); + * <BR>}</code> + * <P>The implementation is responsible for implementing the + * <code>ObjectIdFieldConsumer</code> to store the values for the key fields. + * @param pcClass the <code>PersistenceCapable</code> class + * @param oid the ObjectId source of the copy. + * @param fm the field manager that receives the field values. + */ + public void copyKeyFieldsFromObjectId + (Class pcClass, PersistenceCapable.ObjectIdFieldConsumer fm, Object oid) { + Meta meta = getMeta (pcClass); + PersistenceCapable pcInstance = meta.getPC(); + if (pcInstance == null) { + throw new JDOFatalInternalException ( + msg.msg("ERR_AbstractClassNoIdentity", pcClass.getName())); //NOI18N + } + pcInstance.jdoCopyKeyFieldsFromObjectId(fm, oid); + } + + /** Register metadata by class. The registration will be done in the + * class named <code>JDOImplHelper</code> loaded by the same or an + * ancestor class loader as the <code>PersistenceCapable</code> class + * performing the registration. + * + * @param pcClass the <code>PersistenceCapable</code> class + * used as the key for lookup. + * @param fieldNames an array of <code>String</code> field names for persistent and transactional fields + * @param fieldTypes an array of <code>Class</code> field types + * @param fieldFlags the Field Flags for persistent and transactional fields + * @param pc an instance of the <code>PersistenceCapable</code> class + * @param persistenceCapableSuperclass the most immediate superclass that is <code>PersistenceCapable</code> + */ + public static void registerClass (Class pcClass, + String[] fieldNames, Class[] fieldTypes, + byte[] fieldFlags, Class persistenceCapableSuperclass, + PersistenceCapable pc) { + if (pcClass == null) + throw new NullPointerException(msg.msg("ERR_NullClass")); + Meta meta = new Meta (fieldNames, fieldTypes, + fieldFlags, persistenceCapableSuperclass, pc); + registeredClasses.put (pcClass, meta); + + // handle class registration listeners + synchronized (listeners) { + if (!listeners.isEmpty()) { + RegisterClassEvent event = new RegisterClassEvent( + jdoImplHelper, pcClass, fieldNames, fieldTypes, + fieldFlags, persistenceCapableSuperclass); + for (Iterator i = listeners.iterator(); i.hasNext();) { + RegisterClassListener crl = + (RegisterClassListener)i.next(); + if (crl != null) { + crl.registerClass(event); + } + } + } + } + } + + /** + * Unregister metadata by class loader. This method unregisters all + * registered <code>PersistenceCapable</code> classes loaded by the + * specified class loader. Any attempt to get metadata for unregistered + * classes will result in a <code>JDOFatalUserException</code>. + * @param cl the class loader. + * @since 1.0.2 + */ + public void unregisterClasses (ClassLoader cl) + { + SecurityManager sec = System.getSecurityManager(); + if (sec != null) { + // throws exception if caller is not authorized + sec.checkPermission (JDOPermission.MANAGE_METADATA); + } + synchronized(registeredClasses) { + for (Iterator i = registeredClasses.keySet().iterator(); i.hasNext();) { + Class pcClass = (Class)i.next(); + // Note, the pc class was registered by calling the static + // method JDOImplHelper.registerClass. This means the + // JDOImplHelper class loader is the same as or an ancestor + // of the class loader of the pc class. In this case method + // getClassLoader does not perform a security check for + // RuntimePermission("getClassLoader") and thus we do not + // need a privileged block for the getClassLoader call. + if ((pcClass != null) && (pcClass.getClassLoader() == cl)) { + // unregister pc class, if its class loader is the + // specified one. + i.remove(); + } + } + } + } + + /** + * Unregister metadata by class. This method unregisters the specified + * class. Any further attempt to get metadata for the specified class will + * result in a <code>JDOFatalUserException</code>. + * @param pcClass the <code>PersistenceCapable</code> class to be unregistered. + * @since 1.0.2 + */ + public void unregisterClass (Class pcClass) + { + if (pcClass == null) + throw new NullPointerException(msg.msg("ERR_NullClass")); + SecurityManager sec = System.getSecurityManager(); + if (sec != null) { + // throws exception if caller is not authorized + sec.checkPermission (JDOPermission.MANAGE_METADATA); + } + registeredClasses.remove(pcClass); + } + + /** + * Add the specified <code>RegisterClassListener</code> to the listener list. + * @param crl the listener to be added + */ + public void addRegisterClassListener (RegisterClassListener crl) { + HashSet alreadyRegisteredClasses = null; + synchronized (listeners) { + listeners.add(crl); + // Make a copy of the existing set of registered classes. + // Between these two lines of code, any number of new class registrations + // might occur, and will then all wait until this synchronized block completes. + // Some of the class registrations might be delivered twice to + // the newly registered listener. + alreadyRegisteredClasses = new HashSet (registeredClasses.keySet()); + } + // new registrations will call the new listener while the following occurs + // notify the new listener about already-registered classes + for (Iterator it = alreadyRegisteredClasses.iterator(); it.hasNext();) { + Class pcClass = (Class)it.next(); + Meta meta = getMeta (pcClass); + RegisterClassEvent event = new RegisterClassEvent( + this, pcClass, meta.getFieldNames(), meta.getFieldTypes(), + meta.getFieldFlags(), meta.getPersistenceCapableSuperclass()); + crl.registerClass (event); + } + } + + /** + * Remove the specified <code>RegisterClassListener</code> from the listener list. + * @param crl the listener to be removed + */ + public void removeRegisterClassListener (RegisterClassListener crl) { + synchronized (listeners) { + listeners.remove(crl); + } + } + + /** + * Returns a collection of class objects of the registered + * persistence-capable classes. + * @return registered persistence-capable classes + */ + public Collection getRegisteredClasses() { + return Collections.unmodifiableCollection(registeredClasses.keySet()); + } + + /** Look up the metadata for a <code>PersistenceCapable</code> class. + * @param pcClass the <code>Class</code>. + * @return the <code>Meta</code> for the <code>Class</code>. + */ + private static Meta getMeta (Class pcClass) { + Meta ret = (Meta) registeredClasses.get (pcClass); + if (ret == null) { + throw new JDOFatalUserException( + msg.msg ("ERR_NoMetadata", pcClass.getName())); //NOI18N + } + return ret; + } + + /** Register a class authorized to replaceStateManager. The caller of + * this method must be authorized for JDOPermission("setStateManager"). + * During replaceStateManager, a persistence-capable class will call + * the corresponding checkAuthorizedStateManager and the class of the + * instance of the parameter must have been registered. + * @param smClass a Class that is authorized for JDOPermission("setStateManager"). + * @throws SecurityException if the caller is not authorized for JDOPermission("setStateManager"). + * @since 1.0.1 + */ + public static void registerAuthorizedStateManagerClass (Class smClass) + throws SecurityException { + if (smClass == null) + throw new NullPointerException(msg.msg("ERR_NullClass")); + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + sm.checkPermission(JDOPermission.SET_STATE_MANAGER); + } + synchronized (authorizedStateManagerClasses) { + authorizedStateManagerClasses.put(smClass, null); + } + } + + /** Register classes authorized to replaceStateManager. The caller of + * this method must be authorized for JDOPermission("setStateManager"). + * During replaceStateManager, a persistence-capable class will call + * the corresponding checkAuthorizedStateManager and the class of the + * instance of the parameter must have been registered. + * @param smClasses a Collection of Classes that are authorized for JDOPermission("setStateManager"). + * @throws SecurityException if the caller is not authorized for JDOPermission("setStateManager"). + * @since 1.0.1 + */ + public static void registerAuthorizedStateManagerClasses (Collection smClasses) + throws SecurityException { + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + sm.checkPermission(JDOPermission.SET_STATE_MANAGER); + synchronized (authorizedStateManagerClasses) { + for (Iterator it = smClasses.iterator(); it.hasNext();) { + Object smClass = it.next(); + if (!(smClass instanceof Class)) { + throw new ClassCastException( + msg.msg("ERR_StateManagerClassCast", + smClass.getClass().getName())); + } + registerAuthorizedStateManagerClass((Class)it.next()); + } + } + } + } + + /** Check that the parameter instance is of a class that is authorized for + * JDOPermission("setStateManager"). This method is called by the + * replaceStateManager method in persistence-capable classes. + * A class that is passed as the parameter to replaceStateManager must be + * authorized for JDOPermission("setStateManager"). To improve performance, + * first the set of authorized classes is checked, and if not present, a + * regular permission check is made. The regular permission check requires + * that all callers on the stack, including the persistence-capable class + * itself, must be authorized for JDOPermission("setStateManager"). + * @param sm an instance of StateManager whose class is to be checked. + * @since 1.0.1 + */ + public static void checkAuthorizedStateManager (StateManager sm) { + checkAuthorizedStateManagerClass(sm.getClass()); + } + + /** Check that the parameter instance is a class that is authorized for + * JDOPermission("setStateManager"). This method is called by the + * constructors of JDO Reference Implementation classes. + * @param smClass a Class to be checked for JDOPermission("setStateManager") + * @since 1.0.1 + */ + public static void checkAuthorizedStateManagerClass (Class smClass) { + final SecurityManager scm = System.getSecurityManager(); + if (scm == null) { + // if no security manager, no checking. + return; + } + synchronized(authorizedStateManagerClasses) { + if (authorizedStateManagerClasses.containsKey(smClass)) { + return; + } + } + + // if not already authorized, perform "long" security checking. + scm.checkPermission(JDOPermission.SET_STATE_MANAGER); + } + + /** This is a helper class to manage metadata per persistence-capable + * class. The information is used at runtime to provide field names and + * field types to the JDO Model. + * + * This is the value of the <code>HashMap</code> which + * relates the <code>PersistenceCapable Class</code> + * as a key to the metadata. + */ + static class Meta { + + /** Construct an instance of <code>Meta</code>. + * @param fieldNames An array of <code>String</code> + * @param fieldTypes An array of <code>Class</code> + * @param fieldFlags an array of <code>int</code> + * @param persistenceCapableSuperclass the most immediate <code>PersistenceCapable</code> superclass + * @param pc An instance of the <code>PersistenceCapable</code> class + */ + Meta (String[] fieldNames, Class[] fieldTypes, byte[] fieldFlags, + Class persistenceCapableSuperclass, PersistenceCapable pc) { + this.fieldNames = fieldNames; + this.fieldTypes = fieldTypes; + this.fieldFlags = fieldFlags; + this.persistenceCapableSuperclass = persistenceCapableSuperclass; + this.pc = pc; + } + + /** This is an array of field names used + * for the Model at runtime. The field + * is passed by the static class initialization. + */ + String fieldNames[]; + + /** Get the field names from the metadata. + * @return the array of field names. + */ + String[] getFieldNames() { + return fieldNames; + } + + /** This is an array of field types used + * for the Model at runtime. The field + * is passed by the static class initialization. + */ + Class fieldTypes[]; + + /** Get the field types from the metadata. + * @return the array of field types. + */ + Class[] getFieldTypes() { + return fieldTypes; + } + + /** This is an array of field flags used + * for the Model at runtime. The field + * is passed by the static class initialization. + */ + byte fieldFlags[]; + + /** Get the field types from the metadata. + * @return the array of field types. + */ + byte[] getFieldFlags() { + return fieldFlags; + } + + /** This is the <code>Class</code> instance of the <code>PersistenceCapable</code> superclass. + */ + Class persistenceCapableSuperclass; + + /** Return the <code>PersistenceCapable</code> superclass. + * @return the <code>PersistenceCapable</code> superclass + */ + Class getPersistenceCapableSuperclass() { + return persistenceCapableSuperclass; + } + /** This is an instance of <code>PersistenceCapable</code>, + * used at runtime to create new instances. + */ + PersistenceCapable pc; + + /** Get an instance of the <code>PersistenceCapable</code> class. + * @return an instance of the <code>PersistenceCapable Class</code>. + */ + PersistenceCapable getPC() { + return pc; + } + + /** Return the string form of the metadata. + * @return the string form + */ + public String toString() { + return "Meta-" + pc.getClass().getName(); //NOI18N + } + } +} Added: incubator/jdo/trunk/api20/src/java/javax/jdo/spi/JDOPermission.java URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/api20/src/java/javax/jdo/spi/JDOPermission.java?view=auto&rev=159273 ============================================================================== --- incubator/jdo/trunk/api20/src/java/javax/jdo/spi/JDOPermission.java (added) +++ incubator/jdo/trunk/api20/src/java/javax/jdo/spi/JDOPermission.java Mon Mar 28 10:25:05 2005 @@ -0,0 +1,133 @@ +/* + * Copyright 2005 The Apache Software Foundation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package javax.jdo.spi; + +/** + * The <code>JDOPermission</code> class is for operations that are reserved for JDO + * implementations and should not be called by other code. A + * <code>JDOPermission</code> is a <em>named permission</em> and has no + * actions. There are two names currently defined. Each named permission + * has a corresponding public static final field which contains an instance + * of the named permission. + * <P> + * The following table + * provides a summary description of what each named permission allows, + * and discusses the risks of granting code the permission. + * <P> + * + * <table border=1 cellpadding=5> + * <tr> + * <th>Permission Target Name</th> + * <th>What the Permission Allows</th> + * <th>Risks of Allowing this Permission</th> + * </tr> + * + * <tr> + * <td><code>setStateManager</code></td> + * <td>This allows setting the <code>StateManager</code> for an instance of <code>PersistenceCapable</code>. + * The <code>StateManager</code> + * has unlimited access to get and set persistent and transactional fields of + * the <code>PersistenceCapable</code> instance.</td> + * <td>This is dangerous in that information (possibly confidential) + * normally unavailable would be accessible to malicious code.</td> + * </tr> + * + * <tr> + * <td><code>getMetadata</code></td> + * <td>This allows getting metadata for any <code>PersistenceCapable</code> class that has + * registered with <code>JDOImplHelper</code>.</td> + * <td>This is dangerous in that metadata information (possibly confidential) + * normally unavailable would be accessible to malicious code.</td> + * </tr> + * + * <tr> + * <td><code>manageMetadata</code></td> + * <td>This allows managing metadata for any <code>PersistenceCapable</code> class that has + * registered with <code>JDOImplHelper</code>.</td> + * <td>This is dangerous in that metadata information (possibly confidential) + * normally unavailable would be manageable (modifiable) by malicious code.</td> + * </tr> + * + * <tr> + * <td><code>closePersistenceManagerFactory</code></td> + * <td>This allows closing a <code>PersistenceManagerFactory</code>, + * thereby releasing resources.</td> + * <td>This is dangerous in that resources bound to the + * <code>PersistenceManagerFactory</code> would be releaseable by + * malicious code.</td> + * </tr> + * + * </table> + * + * @see java.security.Permission + * @see java.security.BasicPermission + * @see javax.jdo.spi.JDOImplHelper + * @see javax.jdo.spi.PersistenceCapable + * @version 1.0.2 + */ +public final +class JDOPermission extends java.security.BasicPermission { + + /** + * Constructs a <code>JDOPermission</code> with the specified name. + * + * @param name the name of the <code>JDOPermission</code> + */ + public JDOPermission(String name) { + super(name); + } + + /** + * Constructs a <code>JDOPermission</code> with the specified name and actions. + * The actions should be <code>null</code>; they are ignored. This + * constructor exists for use by the <code>Policy</code> object + * to instantiate new <code>Permission</code> objects. + * + * @param name the name of the <code>JDOPermission</code> + * @param actions should be <code>null</code>. + */ + public JDOPermission(String name, String actions) { + super(name, actions); + } + + /** An instance of <code>JDOPermission</code> to be used for + * <code>getMetadata</code> permission checking. + */ + public final static JDOPermission GET_METADATA = + new JDOPermission("getMetadata"); // NOI18N + + /** An instance of <code>JDOPermission</code> to be used for + * <code>manageMetadata</code> permission checking. + * @since 1.0.2 + */ + public final static JDOPermission MANAGE_METADATA = + new JDOPermission("manageMetadata"); // NOI18N + + /** An instance of <code>JDOPermission</code> to be used for + * <code>setStateManager</code> permission checking. + */ + public final static JDOPermission SET_STATE_MANAGER = + new JDOPermission("setStateManager"); // NOI18N + + /** An instance of <code>JDOPermission</code> to be used for + * <code>closePersistenceManagerFactory</code> permission checking. + * @since 1.0.1 + */ + public final static JDOPermission CLOSE_PERSISTENCE_MANAGER_FACTORY = + new JDOPermission("closePersistenceManagerFactory"); // NOI18N + +} Added: incubator/jdo/trunk/api20/src/java/javax/jdo/spi/PersistenceCapable.java URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/api20/src/java/javax/jdo/spi/PersistenceCapable.java?view=auto&rev=159273 ============================================================================== --- incubator/jdo/trunk/api20/src/java/javax/jdo/spi/PersistenceCapable.java (added) +++ incubator/jdo/trunk/api20/src/java/javax/jdo/spi/PersistenceCapable.java Mon Mar 28 10:25:05 2005 @@ -0,0 +1,564 @@ +/* + * Copyright 2005 The Apache Software Foundation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package javax.jdo.spi; + +import javax.jdo.PersistenceManager; +import javax.jdo.JDOHelper; // for javadoc + +/** + * + * @version 2.0 + */ + +/** + * A class that can be managed by a JDO implementation must implement this interface. + * + * <P>Every class whose instances can be managed by a JDO PersistenceManager must + * implement the PersistenceCapable interface. + * + * <P>This interface defines methods that allow the implementation to manage + * the instances. It also defines methods that allow a JDO aware + * application to examine the runtime state of instances. For example, + * an application can discover whether the instance is persistent, transactional, + * dirty, new, or deleted; and to get its associated + * PersistenceManager if it has one. + * + * <P>In the Reference Implementation, the JDO Enhancer modifies the class + * to implement PersistenceCapable prior to loading the class into the runtime + * environment. The Reference Enhancer also adds code to implement the + * methods defined by PersistenceCapable. + * + *<P>The extra methods in the PersistenceCapable interface might be generated + * by pre-processing a .java file, or might be generated from a tool directly. + * The exact technique for generating the extra methods is not specified by + * JDO. + * + * <P>The PersistenceCapable interface is designed to avoid name conflicts + * in the scope of user-defined classes. All of its declared method + * names are prefixed with 'jdo'. + */ +public interface PersistenceCapable { + /** If jdoFlags is set to READ_WRITE_OK, then the fields in the default fetch group + * can be accessed for read or write without notifying the StateManager. + */ + static final byte READ_WRITE_OK = 0; + + /** If jdoFlags is set to LOAD_REQUIRED, then the fields in the default fetch group + * cannot be accessed for read or write without notifying the StateManager. + */ + static final byte LOAD_REQUIRED = 1; + + /** If jdoFlags is set to READ_OK, then the fields in the default fetch group + * can be accessed for read without notifying the StateManager. + */ + static final byte READ_OK = -1; + + /** If jdoFieldFlags for a field includes CHECK_READ, then + * the field has been enhanced to call the jdoStateManager on read + * if the jdoFlags setting is not READ_OK or READ_WRITE_OK. + */ + static final byte CHECK_READ = 1; + + /** If jdoFieldFlags for a field includes MEDIATE_READ, then + * the field has been enhanced to always call the jdoStateManager + * on all reads. + */ + static final byte MEDIATE_READ = 2; + + /** If jdoFieldFlags for a field includes CHECK_WRITE, + * then the field has been enhanced to call the + * jdoStateManager on write if the jdoFlags setting is not + * READ_WRITE_OK;. + */ + static final byte CHECK_WRITE = 4; + + /** If jdoFieldFlags for a field includes MEDIATE_WRITE, then + * the field has been enhanced to always call the jdoStateManager + * on all writes. + */ + static final byte MEDIATE_WRITE = 8; + + /** If jdoFieldFlags for a field includes SERIALIZABLE, + * then the field is not declared as TRANSIENT. + */ + static final byte SERIALIZABLE = 16; + + /** Return the associated PersistenceManager if there is one. + * Transactional and persistent instances return the associated + * PersistenceManager. + * + * <P>Transient non-transactional instances return null. + * <P>This method always delegates to the StateManager if it is non-null. + * @return the PersistenceManager associated with this instance. + */ + PersistenceManager jdoGetPersistenceManager(); + + /** This method sets the StateManager instance that manages the state + * of this instance. This method is normally used by the StateManager + * during the process of making an instance persistent, transient, + * or transactional. + * + * The caller of this method must have JDOPermission for the instance, + * if the instance is not already owned by a StateManager. + * If the parameter is null, and the StateManager approves the change, + * then the jdoFlags field will be reset to READ_WRITE_OK. + * If the parameter is not null, and the security manager approves + * the change, then the jdoFlags field will be reset to LOAD_REQUIRED. + * @param sm The StateManager which will own this instance, or null + * to reset the instance to transient state + * @throws SecurityException if the caller does not have JDOPermission + * @see JDOPermission + */ + void jdoReplaceStateManager(StateManager sm) + throws SecurityException; + + /** The owning StateManager uses this method to ask the instance to + * provide the value of the single field identified by fieldNumber. + * @param fieldNumber the field whose value is to be provided by + * a callback to the StateManager's + * providedXXXField method + */ + void jdoProvideField(int fieldNumber); + + /** The owning StateManager uses this method to ask the instance to + * provide the values of the multiple fields identified by fieldNumbers. + * @param fieldNumbers the fields whose values are to be provided by + * multiple callbacks to the StateManager's + * providedXXXField method + */ + void jdoProvideFields(int[] fieldNumbers); + + /** The owning StateManager uses this method to ask the instance to + * replace the value of the single field identified by number. + * @param fieldNumber the field whose value is to be replaced by + * a callback to the StateManager's + * replacingXXXField method + */ + void jdoReplaceField(int fieldNumber); + + /** The owning StateManager uses this method to ask the instance to + * replace the values of the multiple fields identified by number. + * @param fieldNumbers the fields whose values are to be replaced by + * multiple callbacks to the StateManager's + * replacingXXXField method + */ + void jdoReplaceFields(int[] fieldNumbers); + + /** The owning StateManager uses this method to ask the instance to + * replace the value of the flags by calling back the StateManager + * replacingFlags method. + */ + void jdoReplaceFlags(); + + /** Copy field values from another instance of the same class + * to this instance. + *<P>This method will throw an exception if the other instance is + * not managed by the same StateManager as this instance. + * @param other the PC instance from which field values are to be copied + * @param fieldNumbers the field numbers to be copied into this instance + */ + void jdoCopyFields(Object other, int[] fieldNumbers); + + /** Explicitly mark this instance and this field dirty. + * Normally, PersistenceCapable classes are able to detect changes made + * to their fields. However, if a reference to an array is given to a + * method outside the class, and the array is modified, then the + * persistent instance is not aware of the change. This API allows the + * application to notify the instance that a change was made to a field. + * + *<P>The field name should be the fully qualified name, including package + * name and class name of the class declaring the field. This allows + * unambiguous identification of the field to be marked dirty. + * If multiple classes declare the same field, and + * if the package and class name are not provided by the parameter in + * this API, then the field marked + * dirty is the field declared by the most derived class. + * <P>Transient instances ignore this method. + *<P> + * @param fieldName the name of the field to be marked dirty. + */ + void jdoMakeDirty(String fieldName); + + /** Return a copy of the JDO identity associated with this instance. + * + * <P>Persistent instances of PersistenceCapable classes have a JDO identity + * managed by the PersistenceManager. This method returns a copy of the + * ObjectId that represents the JDO identity. + * + * <P>Transient instances return null. + * + * <P>The ObjectId may be serialized + * and later restored, and used with a PersistenceManager from the same JDO + * implementation to locate a persistent instance with the same data store + * identity. + * + * <P>If the JDO identity is managed by the application, then the ObjectId may + * be used with a PersistenceManager from any JDO implementation that supports + * the PersistenceCapable class. + * + * <P>If the JDO identity is not managed by the application or the data store, + * then the ObjectId returned is only valid within the current transaction. + * <P>If the JDO identity is being changed in the transaction, this method + * returns the object id as of the beginning of the current transaction. + * + * @see PersistenceManager#getObjectId(Object pc) + * @see PersistenceManager#getObjectById(Object oid, boolean validate) + * @return a copy of the ObjectId of this instance as of the beginning of the transaction. + */ + Object jdoGetObjectId(); + + /** Return a copy of the JDO identity associated with this instance. + * This method is the same as jdoGetObjectId if the identity of the + * instance has not changed in the current transaction. + * <P>If the JDO identity is being changed in the transaction, this method + * returns the current object id as modified in the current transaction. + * + * @see #jdoGetObjectId() + * @see PersistenceManager#getObjectId(Object pc) + * @see PersistenceManager#getObjectById(Object oid, boolean validate) + * @return a copy of the ObjectId of this instance as modified in the transaction. + */ + Object jdoGetTransactionalObjectId(); + + /** Return the version of this instance. + * @return the version + * @since 2.0 + */ + Object jdoGetVersion(); + + /** Tests whether this object is dirty. + * + * Instances that have been modified, deleted, or newly + * made persistent in the current transaction return true. + * + *<P>Transient instances return false. + *<P> + * @see JDOHelper#isDirty(Object pc) + * @see JDOHelper#makeDirty(Object pc, String fieldName) + * @see #jdoMakeDirty(String fieldName) + * @return true if this instance has been modified in the current transaction. + */ + boolean jdoIsDirty(); + + /** Tests whether this object is transactional. + * + * Instances whose state is associated with the current transaction + * return true. + * + *<P>Transient instances return false. + *<P> + * @see JDOHelper#isTransactional(Object pc) + * @see PersistenceManager#makeTransactional(Object pc) + * @return true if this instance is transactional. + */ + boolean jdoIsTransactional(); + + /** Tests whether this object is persistent. + * Instances that represent persistent objects in the data store + * return true. + * @see JDOHelper#isPersistent(Object pc) + * @see PersistenceManager#makePersistent(Object pc) + * @return true if this instance is persistent. + */ + boolean jdoIsPersistent(); + + /** Tests whether this object has been newly made persistent. + * + * Instances that have been made persistent in the current transaction + * return true. + * + *<P>Transient instances return false. + *<P> + * @see JDOHelper#isNew(Object pc) + * @see PersistenceManager#makePersistent(Object pc) + * @return true if this instance was made persistent + * in the current transaction. + */ + boolean jdoIsNew(); + + /** Tests whether this object has been deleted. + * + * Instances that have been deleted in the current transaction return true. + * + *<P>Transient instances return false. + *<P> + * @see JDOHelper#isDeleted(Object pc) + * @see PersistenceManager#deletePersistent(Object pc) + * @return true if this instance was deleted + * in the current transaction. + */ + boolean jdoIsDeleted(); + + /** Tests whether this object has been detached. + * + * Instances that have been detached return true. + * + *<P>Transient instances return false. + *<P> + * @see JDOHelper#isDetached(Object pc) + * @return true if this instance is detached. + * @since 2.0 + */ + boolean jdoIsDetached(); + + /** Return a new instance of this class, with the jdoStateManager set to the + * parameter, and jdoFlags set to LOAD_REQUIRED. + * <P>This method is used as a performance optimization as an alternative to + * using reflection to construct a new instance. It is used by the + * JDOImplHelper class method newInstance. + * @return a new instance of this class. + * @see JDOImplHelper#newInstance(Class pcClass, StateManager sm) + * @param sm the StateManager that will own the new instance. + */ + PersistenceCapable jdoNewInstance(StateManager sm); + + /** Return a new instance of this class, with the jdoStateManager set to the + * parameter, key fields initialized to the values in the oid, and jdoFlags + * set to LOAD_REQUIRED. + * <P>This method is used as a performance optimization as an alternative to + * using reflection to construct a new instance of a class that uses + * application identity. It is used by the + * JDOImplHelper class method newInstance. + * @return a new instance of this class. + * @see JDOImplHelper#newInstance(Class pcClass, StateManager sm) + * @param sm the StateManager that will own the new instance. + * @param oid an instance of the object id class (application identity). + */ + PersistenceCapable jdoNewInstance(StateManager sm, Object oid); + + /** Create a new instance of the ObjectId class for this PersistenceCapable class. + * The fields will have their Java default values. + * @return the new instance created. + */ + Object jdoNewObjectIdInstance(); + + /** Create a new instance of the class used for JDO identity, using the + * key constructor of the object id class. It is intended only for single + * field identity. The identity + * instance returned has no relationship with the values of the primary key + * fields of the persistence-capable instance on which the method is called. + * If the key is the wrong class for the object id class, null is returned. + * @return the new instance created. + * @param o the String form of the object identity + * @since 2.0 + */ + Object jdoNewObjectIdInstance(Object o); + + /** Copy fields from this PersistenceCapable instance to the Object Id instance. + * @param oid the ObjectId target of the key fields + */ + void jdoCopyKeyFieldsToObjectId(Object oid); + + /** Copy fields from an outside source to the key fields in the ObjectId. + * This method is generated in the PersistenceCapable class to generate + * a call to the field manager for each key field in the ObjectId. For + * example, an ObjectId class that has three key fields (int id, + * String name, and Float salary) would have the method generated: + * <P>void jdoCopyKeyFieldsToObjectId + * <P> (ObjectIdFieldSupplier fm, Object objectId) { + * <P> EmployeeKey oid = (EmployeeKey)objectId; + * <P> oid.id = fm.fetchIntField (0); + * <P> oid.name = fm.fetchStringField (1); + * <P> oid.salary = fm.fetchObjectField (2); + * <P>} + * <P>The implementation is responsible for implementing the + * ObjectIdFieldSupplier to produce the values for the key fields. + * @param oid the ObjectId target of the copy. + * @param fm the field supplier that supplies the field values. + */ + void jdoCopyKeyFieldsToObjectId(ObjectIdFieldSupplier fm, Object oid); + + /** Copy fields to an outside source from the key fields in the ObjectId. + * This method is generated in the PersistenceCapable class to generate + * a call to the field manager for each key field in the ObjectId. For + * example, an ObjectId class that has three key fields (int id, + * String name, and Float salary) would have the method generated: + * <P>void copyKeyFieldsFromObjectId + * <P> (ObjectIdFieldConsumer fm, Object objectId) { + * <P> EmployeeKey oid = (EmployeeKey)objectId; + * <P> fm.storeIntField (0, oid.id); + * <P> fm.storeStringField (1, oid.name); + * <P> fm.storeObjectField (2, oid.salary); + * <P>} + * <P>The implementation is responsible for implementing the + * ObjectIdFieldManager to store the values for the key fields. + * @param oid the ObjectId source of the copy. + * @param fm the field manager that receives the field values. + */ + void jdoCopyKeyFieldsFromObjectId(ObjectIdFieldConsumer fm, Object oid); + + /** This interface is a convenience interface that allows an instance to + * implement both ObjectIdFieldSupplier and ObjectIdFieldConsumer. + */ + static interface ObjectIdFieldManager extends ObjectIdFieldConsumer, ObjectIdFieldSupplier {} + + /** This interface is used to provide fields to the Object id instance. It is used + * by the method copyKeyFieldsToObjectId. When the method is called, the + * generated code calls the instance of ObjectIdFieldManager for each field in + * the object id. + */ + static interface ObjectIdFieldSupplier { + + /** Fetch one field from the field manager. This field will be stored in the + * proper field of the ObjectId. + * @param fieldNumber the field number of the key field. + * @return the value of the field to be stored into the ObjectId. + */ + boolean fetchBooleanField(int fieldNumber); + + /** Fetch one field from the field manager. This field will be stored in the + * proper field of the ObjectId. + * @param fieldNumber the field number of the key field. + * @return the value of the field to be stored into the ObjectId. + */ + char fetchCharField(int fieldNumber); + + /** Fetch one field from the field manager. This field will be stored in the + * proper field of the ObjectId. + * @param fieldNumber the field number of the key field. + * @return the value of the field to be stored into the ObjectId. + */ + byte fetchByteField(int fieldNumber); + + /** Fetch one field from the field manager. This field will be stored in the + * proper field of the ObjectId. + * @param fieldNumber the field number of the key field. + * @return the value of the field to be stored into the ObjectId. + */ + short fetchShortField(int fieldNumber); + + /** Fetch one field from the field manager. This field will be stored in the + * proper field of the ObjectId. + * @param fieldNumber the field number of the key field. + * @return the value of the field to be stored into the ObjectId. + */ + int fetchIntField(int fieldNumber); + + /** Fetch one field from the field manager. This field will be stored in the + * proper field of the ObjectId. + * @param fieldNumber the field number of the key field. + * @return the value of the field to be stored into the ObjectId. + */ + long fetchLongField(int fieldNumber); + + /** Fetch one field from the field manager. This field will be stored in the + * proper field of the ObjectId. + * @param fieldNumber the field number of the key field. + * @return the value of the field to be stored into the ObjectId. + */ + float fetchFloatField(int fieldNumber); + + /** Fetch one field from the field manager. This field will be stored in the + * proper field of the ObjectId. + * @param fieldNumber the field number of the key field. + * @return the value of the field to be stored into the ObjectId. + */ + double fetchDoubleField(int fieldNumber); + + /** Fetch one field from the field manager. This field will be stored in the + * proper field of the ObjectId. + * @param fieldNumber the field number of the key field. + * @return the value of the field to be stored into the ObjectId. + */ + String fetchStringField(int fieldNumber); + + /** Fetch one field from the field manager. This field will be stored in the + * proper field of the ObjectId. + * @param fieldNumber the field number of the key field. + * @return the value of the field to be stored into the ObjectId. + */ + Object fetchObjectField(int fieldNumber); + } + + /** This interface is used to store fields from the Object id instance. It is used + * by the method copyKeyFieldsFromObjectId. When the method is called, the + * generated code calls the instance of ObjectIdFieldManager for each field in + * the object id. + */ + static interface ObjectIdFieldConsumer { + + /** Store one field into the field manager. This field was retrieved from + * the field of the ObjectId. + * @param fieldNumber the field number of the key field. + * @param value the value of the field from the ObjectId. + */ + void storeBooleanField(int fieldNumber, boolean value); + + /** Store one field into the field manager. This field was retrieved from + * the field of the ObjectId. + * @param fieldNumber the field number of the key field. + * @param value the value of the field from the ObjectId. + */ + void storeCharField(int fieldNumber, char value); + + /** Store one field into the field manager. This field was retrieved from + * the field of the ObjectId. + * @param fieldNumber the field number of the key field. + * @param value the value of the field from the ObjectId. + */ + void storeByteField(int fieldNumber, byte value); + + /** Store one field into the field manager. This field was retrieved from + * the field of the ObjectId. + * @param fieldNumber the field number of the key field. + * @param value the value of the field from the ObjectId. + */ + void storeShortField(int fieldNumber, short value); + + /** Store one field into the field manager. This field was retrieved from + * the field of the ObjectId. + * @param fieldNumber the field number of the key field. + * @param value the value of the field from the ObjectId. + */ + void storeIntField(int fieldNumber, int value); + + /** Store one field into the field manager. This field was retrieved from + * the field of the ObjectId. + * @param fieldNumber the field number of the key field. + * @param value the value of the field from the ObjectId. + */ + void storeLongField(int fieldNumber, long value); + + /** Store one field into the field manager. This field was retrieved from + * the field of the ObjectId. + * @param fieldNumber the field number of the key field. + * @param value the value of the field from the ObjectId. + */ + void storeFloatField(int fieldNumber, float value); + + /** Store one field into the field manager. This field was retrieved from + * the field of the ObjectId. + * @param fieldNumber the field number of the key field. + * @param value the value of the field from the ObjectId. + */ + void storeDoubleField(int fieldNumber, double value); + + /** Store one field into the field manager. This field was retrieved from + * the field of the ObjectId. + * @param fieldNumber the field number of the key field. + * @param value the value of the field from the ObjectId. + */ + void storeStringField(int fieldNumber, String value); + + /** Store one field into the field manager. This field was retrieved from + * the field of the ObjectId. + * @param fieldNumber the field number of the key field. + * @param value the value of the field from the ObjectId. + */ + void storeObjectField(int fieldNumber, Object value); + } +} Added: incubator/jdo/trunk/api20/src/java/javax/jdo/spi/RegisterClassEvent.java URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/api20/src/java/javax/jdo/spi/RegisterClassEvent.java?view=auto&rev=159273 ============================================================================== --- incubator/jdo/trunk/api20/src/java/javax/jdo/spi/RegisterClassEvent.java (added) +++ incubator/jdo/trunk/api20/src/java/javax/jdo/spi/RegisterClassEvent.java Mon Mar 28 10:25:05 2005 @@ -0,0 +1,122 @@ +/* + * Copyright 2005 The Apache Software Foundation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * RegisterClassEvent.java + * + */ + +package javax.jdo.spi; + +import java.util.EventObject; + +/** + * A <code>RegisterClassEvent</code> event gets delivered whenever a persistence-capable + * class registers itself with the <code>JDOImplHelper</code>. + * + * @version 1.0 + */ +public class RegisterClassEvent + extends EventObject +{ + /** The class object of the registered persistence-capable class */ + protected Class pcClass; + + /** The names of managed fields of the persistence-capable class */ + protected String[] fieldNames; + + /** The types of managed fields of the persistence-capable class */ + protected Class[] fieldTypes; + + /** The flags of managed fields of the persistence-capable class */ + protected byte[] fieldFlags; + + /** */ + protected Class persistenceCapableSuperclass; + + /** + * Constructs a new <code>RegisterClassEvent</code>. + * @param helper the <code>JDOImplHelper</code> instance + * @param registeredClass the persistence-capable class + * @param fieldNames the names of the managed fields + * @param fieldTypes the types of the managed fields + * @param fieldFlags the flags of the managed fields + * @param persistenceCapableSuperclass the persistence-capable superclass + **/ + public RegisterClassEvent(JDOImplHelper helper, + Class registeredClass, + String[] fieldNames, + Class[] fieldTypes, + byte[] fieldFlags, + Class persistenceCapableSuperclass) + { + super(helper); + this.pcClass = registeredClass; + this.fieldNames = fieldNames; + this.fieldTypes = fieldTypes; + this.fieldFlags = fieldFlags; + this.persistenceCapableSuperclass = persistenceCapableSuperclass; + } + + /** + * Returns the class object of the registered persistence-capable class. + * @return the persistence-capable class. + */ + public Class getRegisteredClass() + { + return pcClass; + } + + /** + * Returns the names of the managed field of the persistence-capable class. + * @return the names of the managed fields + */ + public String[] getFieldNames() + { + return fieldNames; + } + + /** + * Returns the types of the managed field of the persistence-capable class. + * @return the types of the managed fields + */ + public Class[] getFieldTypes() + { + return fieldTypes; + } + + /** + * Returns the flags of the managed field of the persistence-capable class. + * @return the flags of the managed fields + */ + public byte[] getFieldFlags() + { + return fieldFlags; + } + + /** + * Returns the class object of the persistence-capable superclass. + * @return the persistence-capable superclass. + */ + public Class getPersistenceCapableSuperclass() + { + return persistenceCapableSuperclass; + } + +} + + + Added: incubator/jdo/trunk/api20/src/java/javax/jdo/spi/RegisterClassListener.java URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/api20/src/java/javax/jdo/spi/RegisterClassListener.java?view=auto&rev=159273 ============================================================================== --- incubator/jdo/trunk/api20/src/java/javax/jdo/spi/RegisterClassListener.java (added) +++ incubator/jdo/trunk/api20/src/java/javax/jdo/spi/RegisterClassListener.java Mon Mar 28 10:25:05 2005 @@ -0,0 +1,43 @@ +/* + * Copyright 2005 The Apache Software Foundation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * RegisterClassListener.java + * + */ + +package javax.jdo.spi; + +import java.util.EventListener; + +/** + * A "RegisterClassEvent" event gets fired whenever a persistence-capable class + * is loaded and gets registered with the <code>JDOImplHelper</code>. You can register a + * <code>RegisterClassListener</code> so as to be notified of any registration of a + * persistence-capable class. + * + * @version 1.0 + */ +public interface RegisterClassListener + extends EventListener +{ + /** + * This method gets called when a persistence-capable class is registered. + * @param event a <code>RegisterClassEvent</code> instance describing the registered + * class plus metadata. + */ + public void registerClass(RegisterClassEvent event); +} Added: incubator/jdo/trunk/api20/src/java/javax/jdo/spi/StateInterrogation.java URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/api20/src/java/javax/jdo/spi/StateInterrogation.java?view=auto&rev=159273 ============================================================================== --- incubator/jdo/trunk/api20/src/java/javax/jdo/spi/StateInterrogation.java (added) +++ incubator/jdo/trunk/api20/src/java/javax/jdo/spi/StateInterrogation.java Mon Mar 28 10:25:05 2005 @@ -0,0 +1,177 @@ +/* + * Copyright 2005 The Apache Software Foundation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * StateInterrogation.java + * + */ + +package javax.jdo.spi; + +import javax.jdo.PersistenceManager; + +/** + * This interface is implemented by a non-binary-compatible JDO implementation + * to provide state interrogation for non-enhanced persistent classes. + * + * An instance that implements this interface is registered with the + * [EMAIL PROTECTED] JDOImplHelper}. + * @version 2.0 + * @since 2.0 + */ +public interface StateInterrogation { + + + /** Tests whether the parameter instance is persistent. + * + * Instances that represent persistent objects in the data store + * return <code>true</code>. + * + *<P>Transient instances and instances of classes + * that do not implement <code>PersistenceCapable</code> return <code>false</code>. + *<P> + * @see PersistenceManager#makePersistent(Object pc) + * @see PersistenceCapable#jdoIsPersistent() + * @param pc the <code>PersistenceCapable</code> instance. + * @return <code>true</code> if the parameter instance is persistent. + */ + Boolean isPersistent (Object pc); + + /** Tests whether the parameter instance is transactional. + * + * Instances whose state is associated with the current transaction + * return true. + * + *<P>Transient instances and instances of classes + * that do not implement <code>PersistenceCapable</code> return <code>false</code>. + * @see PersistenceCapable#jdoIsTransactional() + * @param pc the <code>PersistenceCapable</code> instance. + * @return <code>true</code> if the parameter instance is transactional. + */ + Boolean isTransactional (Object pc); + + /** Tests whether the parameter instance is dirty. + * + * Instances that have been modified, deleted, or newly + * made persistent in the current transaction return <code>true</code>. + * + *<P>Transient instances and instances of classes + * that do not implement <code>PersistenceCapable</code> return <code>false</code>. + *<P> + * @see StateManager#makeDirty(PersistenceCapable pc, String fieldName) + * @see PersistenceCapable#jdoIsDirty() + * @param pc the <code>PersistenceCapable</code> instance. + * @return <code>true</code> if the parameter instance has been modified in the current transaction. + */ + Boolean isDirty (Object pc); + + /** Tests whether the parameter instance has been newly made persistent. + * + * Instances that have been made persistent in the current transaction + * return <code>true</code>. + * + *<P>Transient instances and instances of classes + * that do not implement <code>PersistenceCapable</code> return <code>false</code>. + *<P> + * @see PersistenceManager#makePersistent(Object pc) + * @see PersistenceCapable#jdoIsNew() + * @param pc the <code>PersistenceCapable</code> instance. + * @return <code>true</code> if the parameter instance was made persistent + * in the current transaction. + */ + Boolean isNew (Object pc); + + /** Tests whether the parameter instance has been deleted. + * + * Instances that have been deleted in the current transaction return <code>true</code>. + * + *<P>Transient instances and instances of classes + * that do not implement <code>PersistenceCapable</code> return <code>false</code>. + *<P> + * @see PersistenceManager#deletePersistent(Object pc) + * @see PersistenceCapable#jdoIsDeleted() + * @param pc the <code>PersistenceCapable</code> instance. + * @return <code>true</code> if the parameter instance was deleted + * in the current transaction. + */ + Boolean isDeleted (Object pc); + + /** Return the associated <code>PersistenceManager</code> if there is one. + * Transactional and persistent instances return the associated + * <code>PersistenceManager</code>. + * + * <P>Transient non-transactional instances and instances of classes + * that do not implement <code>PersistenceCapable</code> return <code>null</code>. + * @see PersistenceCapable#jdoGetPersistenceManager() + * @param pc the <code>PersistenceCapable</code> instance. + * @return the <code>PersistenceManager</code> associated with the parameter instance. + */ + PersistenceManager getPersistenceManager (Object pc); + + /** Return a copy of the JDO identity associated with the parameter instance. + * + * <P>Persistent instances of <code>PersistenceCapable</code> classes have a JDO identity + * managed by the <code>PersistenceManager</code>. This method returns a copy of the + * ObjectId that represents the JDO identity. + * + * <P>Transient instances and instances of classes + * that do not implement <code>PersistenceCapable</code> return <code>null</code>. + * + * <P>The ObjectId may be serialized + * and later restored, and used with a <code>PersistenceManager</code> from the same JDO + * implementation to locate a persistent instance with the same data store + * identity. + * + * <P>If the JDO identity is managed by the application, then the ObjectId may + * be used with a <code>PersistenceManager</code> from any JDO implementation that supports + * the <code>PersistenceCapable</code> class. + * + * <P>If the JDO identity is not managed by the application or the data store, + * then the ObjectId returned is only valid within the current transaction. + *<P> + * @see PersistenceManager#getObjectId(Object pc) + * @see PersistenceCapable#jdoGetObjectId() + * @see PersistenceManager#getObjectById(Object oid, boolean validate) + * @param pc the PersistenceCapable instance. + * @return a copy of the ObjectId of the parameter instance as of the beginning of the transaction. + */ + Object getObjectId (Object pc); + + /** Return a copy of the JDO identity associated with the parameter instance. + * + * @see PersistenceCapable#jdoGetTransactionalObjectId() + * @see PersistenceManager#getObjectById(Object oid, boolean validate) + * @param pc the <code>PersistenceCapable</code> instance. + * @return a copy of the ObjectId of the parameter instance as modified in this transaction. + */ + Object getTransactionalObjectId (Object pc); + + /** Explicitly mark the parameter instance and field dirty. + * Normally, <code>PersistenceCapable</code> classes are able to detect changes made + * to their fields. However, if a reference to an array is given to a + * method outside the class, and the array is modified, then the + * persistent instance is not aware of the change. This API allows the + * application to notify the instance that a change was made to a field. + * + * <P>Transient instances and instances of classes + * that do not implement <code>PersistenceCapable</code> ignore this method. + * @see PersistenceCapable#jdoMakeDirty(String fieldName) + * @param pc the <code>PersistenceCapable</code> instance. + * @param fieldName the name of the field to be marked dirty. + */ + boolean makeDirty (Object pc, String fieldName); + +} \ No newline at end of file