You are viewing a plain text version of this content. The canonical link for it is here.
Posted to jdo-commits@db.apache.org by mb...@apache.org on 2005/05/22 20:40:21 UTC
svn commit: r171355 [6/31] - in /incubator/jdo/trunk/fostore20: ./ src/
src/conf/ src/java/ src/java/org/ src/java/org/apache/
src/java/org/apache/jdo/ src/java/org/apache/jdo/impl/
src/java/org/apache/jdo/impl/fostore/ test/ test/conf/ test/fsuid2/
test/fsuid2/org/ test/fsuid2/org/apache/ test/fsuid2/org/apache/jdo/
test/fsuid2/org/apache/jdo/pc/ test/java/ test/java/org/
test/java/org/apache/ test/java/org/apache/jdo/
test/java/org/apache/jdo/impl/ test/java/org/apache/jdo/impl/fostore/
test/java/org/apache/jdo/pc/ test/java/org/apache/jdo/pc/appid/
test/java/org/apache/jdo/pc/empdept/
test/java/org/apache/jdo/pc/serializable/
test/java/org/apache/jdo/pc/xempdept/ test/java/org/apache/jdo/test/
test/java/org/apache/jdo/test/query/ test/java/org/apache/jdo/test/util/
test/jdo/ test/jdo/org/ test/jdo/org/apache/ test/jdo/org/apache/jdo/
test/jdo/org/apache/jdo/pc/ test/jdo/org/apache/jdo/pc/appid/
test/jdo/org/apache/jdo/pc/empdept/ test/jdo/org/apache/jdo/pc/serializable/
test/jdo/org/apache/jdo/pc/xempdept/
Added: incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/FOStorePMF.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/FOStorePMF.java?rev=171355&view=auto
==============================================================================
--- incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/FOStorePMF.java (added)
+++ incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/FOStorePMF.java Sun May 22 11:40:13 2005
@@ -0,0 +1,836 @@
+/*
+ * 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 org.apache.jdo.impl.fostore;
+
+import java.io.Externalizable;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Properties;
+import java.util.WeakHashMap;
+
+import javax.jdo.JDOException;
+import javax.jdo.JDOFatalException;
+import javax.jdo.PersistenceManager;
+import javax.jdo.spi.PersistenceCapable;
+import javax.naming.NamingException;
+import javax.naming.Reference;
+import javax.naming.Referenceable;
+import javax.naming.StringRefAddr;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.jdo.impl.model.java.runtime.RuntimeJavaModelFactory;
+import org.apache.jdo.impl.pm.PersistenceManagerFactoryImpl;
+import org.apache.jdo.jdoql.JDOQLQueryFactory;
+import org.apache.jdo.jdoql.tree.QueryTree;
+import org.apache.jdo.model.jdo.JDOClass;
+import org.apache.jdo.store.StoreManager;
+import org.apache.jdo.store.TranscriberFactory;
+import org.apache.jdo.util.I18NHelper;
+
+//
+// Note the exception handling herein; it is intentional: if we catch a
+// subclass of JDOException, rethrow it as it is "expected" by calling code,
+// but if it is not, then create a subclass of JDOException (as are all
+// FOStore exceptions) and throw that. In other words, the intent is that
+// only JDOException subclasses be thrown by this class.
+//
+
+/**
+* The File/Object Store's implementation of a PersistenceManagerFactory.
+* <p>
+* This class is <code>public</code> so that clients can create instances of it
+* with <code>new</code>.
+*
+* @author Dave Bristor
+*/
+public class FOStorePMF
+ extends PersistenceManagerFactoryImpl
+ implements Externalizable, Referenceable
+{
+ /**
+ * StoreManagers provided by this PMF, one per-PM.
+ */
+ private transient final HashMap storeManagers = new HashMap();
+
+ /**
+ * Map provisional id's that were created on behalf of this PMF to the
+ * real id's that have been returned by various StoreManager instances
+ * that are bound to this PMF.
+ */
+ private transient final WeakHashMap provisionalOIDs = new WeakHashMap();
+
+ // ConnectionFactory associated with this PMF.
+ private transient FOStoreConnectionFactory cf;
+
+ /** Model associated with this PMF. */
+ private transient final FOStoreModel model = new FOStoreModel();
+
+ /** Flag to tell whether to create. This is not a JDO property.
+ */
+ private boolean create;
+
+ /** The Properties instance from which this PersistenceManagerFactory
+ * was configured. This is the key into the Properties/PersistenceManagerFactory
+ * map.
+ */
+ private Properties configuredFrom = null;
+
+ /** The name of the JDOQLQueryFactory class */
+ private String jdoqlQueryFactoryClassName =
+ "org.apache.jdo.impl.jdoql.JDOQLQueryFactoryImpl";
+
+ /** The query factory for JDOQL. */
+ private JDOQLQueryFactory jdoqlQueryFactory;
+
+ /** RuntimeJavaModelFactory. */
+ private static final RuntimeJavaModelFactory javaModelFactory =
+ (RuntimeJavaModelFactory) AccessController.doPrivileged(
+ new PrivilegedAction () {
+ public Object run () {
+ return RuntimeJavaModelFactory.getInstance();
+ }
+ }
+ );
+
+ /** I18N support. */
+ private static final I18NHelper msg = I18NHelper.getInstance(
+ I18N.NAME, FOStorePMF.class.getClassLoader());
+
+ /** Logger */
+ static final Log logger = LogFactory.getFactory().getInstance(
+ "org.apache.jdo.impl.fostore"); // NOI18N
+
+ /** JNDI property type
+ */
+ static final String addrType =
+ "Serialized-org.apache.jdo.impl.fostore.FOStorePMF"; // NOI18N
+
+ /** Supported list of options for this implementation.
+ */
+ private final String[] optionArray = new String[] {
+ "javax.jdo.option.TransientTransactional", // NOI18N
+ "javax.jdo.option.NontransactionalRead", // NOI18N
+ "javax.jdo.option.NontransactionalWrite", // NOI18N
+ "javax.jdo.option.RetainValues", // NOI18N
+ "javax.jdo.option.Optimistic", // NOI18N
+ "javax.jdo.option.ApplicationIdentity", // NOI18N
+ "javax.jdo.option.DatastoreIdentity", // NOI18N
+// "javax.jdo.option.NonDatastoreIdentity", // NOI18N
+ "javax.jdo.option.ArrayList", // NOI18N
+ "javax.jdo.option.HashMap", // NOI18N
+ "javax.jdo.option.Hashtable", // NOI18N
+ "javax.jdo.option.LinkedList", // NOI18N
+ "javax.jdo.option.TreeMap", // NOI18N
+ "javax.jdo.option.TreeSet", // NOI18N
+ "javax.jdo.option.Vector", // NOI18N
+// "javax.jdo.option.Map", // NOI18N
+// "javax.jdo.option.List", // NOI18N
+ "javax.jdo.option.Array", // NOI18N
+ "javax.jdo.option.NullCollection", // NOI18N
+ "javax.jdo.query.JDOQL" // NOI18N
+ };
+
+ /** Properties accessors hash map for fostore-specific properties.
+ */
+ protected static HashMap fostorePropsAccessors = new HashMap(3);
+
+ /**
+ * Mapping of supported java.util classes to the tracked
+ * SCO classes in org.apache.jdo.impl.sco package
+ */
+ private static HashMap trackedClasses = new HashMap();
+
+ /** Initialize fostorePropsAccessors.
+ */
+ // XXX Jikes bug
+ // If this is protected, FOStorePMF.initPropsAccessors cannot invoke it,
+ // due to a bug in jikes (http://www-124.ibm.com/developerworks/bugs/?func=detailbug&bug_id=213&group_id=10)
+ //protected static void initPropsAccessors() {
+ //
+ public static void initPropsAccessors() {
+ PersistenceManagerFactoryImpl.initPropsAccessors();
+ if (fostorePropsAccessors.size() != 0)
+ return;
+ synchronized (fostorePropsAccessors) {
+ if (fostorePropsAccessors.size() != 0) {
+ return;
+ }
+ fostorePropsAccessors.put(
+ "org.apache.jdo.ConnectionCreate", // NOI18N
+ new PMFAccessor() {
+ public String get(PersistenceManagerFactoryImpl pmf) { return new Boolean(((FOStorePMF)pmf).getConnectionCreate()).toString(); }
+ public String getNonDefault(PersistenceManagerFactoryImpl pmf) { return (!((FOStorePMF)pmf).getConnectionCreate())?null:"true"; } // NOI18N
+ public String getDefault() { return "false"; } // NOI18N
+ public void set(PersistenceManagerFactoryImpl pmf, String s) { ((FOStorePMF)pmf).setConnectionCreate(Boolean.valueOf(s).booleanValue()); }
+ });
+ fostorePropsAccessors.put(
+ "org.apache.jdo.option.QueryTimeout", // NOI18N
+ new PMFAccessor() {
+ public String get(PersistenceManagerFactoryImpl pmf) { return Integer.toString(pmf.getQueryTimeout()); }
+ public String getNonDefault(PersistenceManagerFactoryImpl pmf) { return (pmf.getQueryTimeout()==0)?null:Integer.toString(pmf.getQueryTimeout()); }
+ public String getDefault() { return "0"; } // NOI18N
+ public void set(PersistenceManagerFactoryImpl pmf, String s) { pmf.setQueryTimeout(toInt(s)); }
+ });
+ fostorePropsAccessors.put(
+ "org.apache.jdo.option.UpdateTimeout", // NOI18N
+ new PMFAccessor() {
+ public String get(PersistenceManagerFactoryImpl pmf) { return Integer.toString(pmf.getUpdateTimeout()); }
+ public String getNonDefault(PersistenceManagerFactoryImpl pmf) { return (pmf.getUpdateTimeout()==0)?null:Integer.toString(pmf.getUpdateTimeout()); }
+ public String getDefault() { return "0"; } // NOI18N
+ public void set(PersistenceManagerFactoryImpl pmf, String s) { pmf.setUpdateTimeout(toInt(s)); }
+ });
+ }
+ }
+
+ /** Sets the JDOQLQueryFactory class name used by getJDOQLQueryFactory.
+ * @param jdoqlQueryFactoryClassName the name of the JDOQLQueryFactory
+ * class.
+ */
+ public void setJDOQLQueryFactoryClassName(String jdoqlQueryFactoryClassName)
+ {
+ this.jdoqlQueryFactoryClassName = jdoqlQueryFactoryClassName;
+ }
+
+ /**
+ * Returns the JDOQLQueryFactory bound to this FOStorePMF.
+ * @return JDOQLQueryFactory
+ */
+ public synchronized JDOQLQueryFactory getJDOQLQueryFactory() {
+ if (this.jdoqlQueryFactory == null) {
+ try {
+ Class clazz = Class.forName(jdoqlQueryFactoryClassName);
+ this.jdoqlQueryFactory = (JDOQLQueryFactory) clazz.newInstance();
+ } catch (Exception ex) {
+ throw new JDOFatalException(
+ msg.msg("EXC_CannotCreateJDOQLQueryFactory", //NOI18N
+ jdoqlQueryFactoryClassName), ex);
+ }
+ }
+ return this.jdoqlQueryFactory;
+ }
+
+ /** Returns a new QueryTree instance. This instance allows to specify a
+ * query with an API (see {@link org.apache.jdo.jdoql.tree.QueryTree} and
+ * {@link org.apache.jdo.jdoql.tree.ExpressionFactory}) rather than as JDOQL
+ * strings. To run you create a query object from the QueryTree (see
+ * {@link javax.jdo.PersistenceManager#newQuery(Object compiled)})
+ * and call the execute method on the Query object.
+ * @return new QueryTree instance.
+ */
+ public QueryTree newQueryTree() {
+ return getJDOQLQueryFactory().newTree();
+ }
+
+ /** Return the FOStore-specific accessors (the
+ * properties that are not in the JDO specification).
+ * @return the hash map of FOStore accessors
+ */
+ protected HashMap getLocalAccessors() {
+ initPropsAccessors();
+ return fostorePropsAccessors;
+ }
+
+ /** Initialize trackedClasses.
+ */
+ private void initTrackedClasses() {
+ if (trackedClasses.size() != 0) {
+ return;
+ }
+ synchronized (trackedClasses) {
+ if (trackedClasses.size() != 0) {
+ return;
+ }
+
+ // We will need to compare equals to ensure that we do not override
+ // user's defined classes:
+
+ // java.util.Date and java.sql classes:
+ trackedClasses.put(java.util.Date.class,
+ org.apache.jdo.impl.sco.Date.class);
+ trackedClasses.put(org.apache.jdo.impl.sco.Date.class,
+ org.apache.jdo.impl.sco.Date.class);
+ trackedClasses.put(java.sql.Date.class,
+ org.apache.jdo.impl.sco.SqlDate.class);
+ trackedClasses.put(org.apache.jdo.impl.sco.SqlDate.class,
+ org.apache.jdo.impl.sco.SqlDate.class);
+ trackedClasses.put(java.sql.Time.class,
+ org.apache.jdo.impl.sco.SqlTime.class);
+ trackedClasses.put(org.apache.jdo.impl.sco.SqlTime.class,
+ org.apache.jdo.impl.sco.SqlTime.class);
+ trackedClasses.put(java.sql.Timestamp.class,
+ org.apache.jdo.impl.sco.SqlTimestamp.class);
+ trackedClasses.put(org.apache.jdo.impl.sco.SqlTimestamp.class,
+ org.apache.jdo.impl.sco.SqlTimestamp.class);
+
+ // java.util.Set
+ trackedClasses.put(java.util.HashSet.class,
+ org.apache.jdo.impl.sco.HashSet.class);
+ trackedClasses.put(java.util.AbstractSet.class,
+ org.apache.jdo.impl.sco.HashSet.class);
+ trackedClasses.put(java.util.Set.class,
+ org.apache.jdo.impl.sco.HashSet.class);
+ trackedClasses.put(org.apache.jdo.impl.sco.HashSet.class,
+ org.apache.jdo.impl.sco.HashSet.class);
+
+ // java.util.List
+ trackedClasses.put(java.util.ArrayList.class,
+ org.apache.jdo.impl.sco.ArrayList.class);
+ trackedClasses.put(java.util.AbstractList.class,
+ org.apache.jdo.impl.sco.ArrayList.class);
+ trackedClasses.put(java.util.List.class,
+ org.apache.jdo.impl.sco.ArrayList.class);
+ trackedClasses.put(java.util.AbstractCollection.class,
+ org.apache.jdo.impl.sco.ArrayList.class);
+ trackedClasses.put(java.util.Collection.class,
+ org.apache.jdo.impl.sco.ArrayList.class);
+ trackedClasses.put(org.apache.jdo.impl.sco.ArrayList.class,
+ org.apache.jdo.impl.sco.ArrayList.class);
+
+ // java.util.Vector
+ trackedClasses.put(java.util.Vector.class,
+ org.apache.jdo.impl.sco.Vector.class);
+ trackedClasses.put(org.apache.jdo.impl.sco.Vector.class,
+ org.apache.jdo.impl.sco.Vector.class);
+
+ // java.util.SortedSet
+ trackedClasses.put(java.util.TreeSet.class,
+ org.apache.jdo.impl.sco.TreeSet.class);
+ trackedClasses.put(java.util.SortedSet.class,
+ org.apache.jdo.impl.sco.TreeSet.class);
+ trackedClasses.put(org.apache.jdo.impl.sco.TreeSet.class,
+ org.apache.jdo.impl.sco.TreeSet.class);
+
+ // java.util.LinkedList
+ trackedClasses.put(java.util.LinkedList.class,
+ org.apache.jdo.impl.sco.LinkedList.class);
+ trackedClasses.put(java.util.AbstractSequentialList.class,
+ org.apache.jdo.impl.sco.LinkedList.class);
+ trackedClasses.put(org.apache.jdo.impl.sco.LinkedList.class,
+ org.apache.jdo.impl.sco.LinkedList.class);
+
+ // java.util.Map
+ trackedClasses.put(java.util.Map.class,
+ org.apache.jdo.impl.sco.HashMap.class);
+ trackedClasses.put(java.util.AbstractMap.class,
+ org.apache.jdo.impl.sco.HashMap.class);
+ trackedClasses.put(java.util.HashMap.class,
+ org.apache.jdo.impl.sco.HashMap.class);
+ trackedClasses.put(org.apache.jdo.impl.sco.HashMap.class,
+ org.apache.jdo.impl.sco.HashMap.class);
+
+ // java.util.Hashtable
+ trackedClasses.put(java.util.Hashtable.class,
+ org.apache.jdo.impl.sco.Hashtable.class);
+ trackedClasses.put(org.apache.jdo.impl.sco.Hashtable.class,
+ org.apache.jdo.impl.sco.Hashtable.class);
+
+ // java.util.SortedMap
+ trackedClasses.put(java.util.SortedMap.class,
+ org.apache.jdo.impl.sco.TreeMap.class);
+ trackedClasses.put(java.util.TreeMap.class,
+ org.apache.jdo.impl.sco.TreeMap.class);
+ trackedClasses.put(org.apache.jdo.impl.sco.TreeMap.class,
+ org.apache.jdo.impl.sco.TreeMap.class);
+ }
+ }
+
+ //
+ // Methods from PersistenceManagerFactory that are not already
+ // implemented in org.apache.jdo.impl.pm.PersistenceManagerFactoryImpl.
+ //
+
+ /** Create a new instance of PersistenceManager with
+ * the specific user name and password.
+ * @see org.apache.jdo.impl.pm.PersistenceManagerFactoryImpl#createPersistenceManager(String userid, String password)
+ * @param userid the user name
+ * @param password the password
+ * @return the Persistencemanager
+ */
+ protected PersistenceManager createPersistenceManager(
+ String userid, String password) {
+
+ PersistenceManager rc = null;
+ try {
+ rc = new FOStorePM(this, userid, password);
+ setConfigured();
+ } catch (JDOException ex) {
+ throw ex;
+ } catch (Exception ex) {
+ throw new FOStoreFatalInternalException(
+ getClass(), "createPersistenceManager(userid, password)", ex); // NOI18N
+ }
+ return rc;
+ }
+
+ /** Close this PersistenceManagerFactory. Check for
+ * JDOPermission("closePersistenceManagerFactory") and if not authorized,
+ * throw SecurityException.
+ * <P>If the authorization check succeeds, check to see that all
+ * PersistenceManager instances obtained from this PersistenceManagerFactory
+ * have no active transactions. If any PersistenceManager instances have
+ * an active transaction, throw a JDOUserException, with one nested
+ * JDOUserException for each PersistenceManager with an active Transaction.
+ * <P>If there are no active transactions, then close all PersistenceManager
+ * instances obtained from this PersistenceManagerFactory, mark this
+ * PersistenceManagerFactory as closed, disallow getPersistenceManager
+ * methods, and allow all other get methods. If a set method or
+ * getPersistenceManager method is called after close, then
+ * JDOUserException is thrown.
+ */
+ public void close() {
+ super.close();
+ /* remove this PMF from the map so another PMF with the same
+ * properties can be constructed.
+ */
+ if (configuredFrom != null) {
+ synchronized (hashMapByFilteredProperties) {
+ hashMapByFilteredProperties.remove(configuredFrom);
+ }
+ }
+ close(true);
+ }
+
+ /**
+ * Closes the database unless there are any active store managers.
+ * @param force If true, forces the database to close anyway, regardless of
+ * whether or not any store managers are still active.
+ * @return true if the database was closed, false if not (i.e., force is
+ * false and there are active store managers).
+ * @see javax.jdo.PersistenceManagerFactory#getPersistenceManager
+ */
+ public boolean close(boolean force) {
+ boolean rc = false;
+
+ try {
+ if (storeManagers.isEmpty() || force) {
+ if (logger.isDebugEnabled()) {
+ logger.debug("FOPMF closing database"); // NOI18N
+ }
+ if (null != cf) {
+ cf.closeDatabase();
+ cf = null;
+ }
+ rc = true;
+ }
+ } catch (JDOException ex) {
+ throw ex;
+ } catch (Exception ex) {
+ throw new FOStoreFatalInternalException(
+ getClass(), "close", ex); // NOI18N
+ }
+ return rc;
+ }
+
+ //
+ // Methods from PersistenceManagerFactoryInternal
+ //
+
+ /** Override PersistenceManagerFactoryImpl's method so we can use our
+ * own cf variable.
+ * @param cf the connection factory
+ */
+ public void setConnectionFactory(Object cf) {
+ this.cf = (FOStoreConnectionFactory) cf;
+ }
+
+ /**
+ * Override PersistenceManagerFactoryImpl's method so that we can get a
+ * handle on the connection factory to close the database at close() time.
+ * @see org.apache.jdo.impl.pm.PersistenceManagerFactoryImpl#getConnectionFactory
+ * @return the connection factory
+ */
+ public synchronized Object getConnectionFactory () {
+ FOStoreConnectionFactory rc = cf;
+
+ // If we already have a connection factory, use that. Otherwise, if
+ // our superclass has one, use that. Otherwise, make one, and use
+ // that. In the latter 2 cases, set our connection factory to be the
+ // one acquired/made.
+ if (null == rc) {
+ try {
+ cf = (FOStoreConnectionFactory)super.getConnectionFactory();
+ if (logger.isDebugEnabled()) {
+ logger.debug("FOPMF.getCF: super.cf = " + cf); // NOI18N
+ }
+ if (null == cf) {
+ String cfName = getConnectionFactoryName();
+ if (null != cfName) {
+ // cf = JNDI lookup of name
+ // XXX In what context?
+ }
+ }
+ if (null == cf) {
+ cf = new FOStoreConnectionFactory();
+ cf.setPMF(this);
+ cf.setUserName(getConnectionUserName());
+ cf.setPassword(password);
+ cf.setURL(getConnectionURL());
+ cf.setCreate(create);
+ }
+ rc = cf;
+ } catch (JDOException ex) {
+ throw ex;
+ } catch (Exception ex) {
+ throw new FOStoreFatalInternalException(
+ getClass(), "getConnectionFactory", ex); // NOI18N
+ }
+ }
+ return rc;
+ }
+
+ /** Verifies that the associated connection factory
+ * is configured (at least the URL is specified).
+ * @return if the connection factory is properly configured
+ */
+ protected boolean isConnectionFactoryConfigured() {
+ return (cf==null?false:cf.isConfigured());
+ }
+
+ /**
+ * @see org.apache.jdo.pm.PersistenceManagerFactoryInternal#getTranscriberFactory()
+ * @return The PersistenceManagerFactory's transcriber factory.
+ */
+ public TranscriberFactory getTranscriberFactory() {
+ return FOStoreTranscriberFactory.getInstance();
+ }
+
+ /**
+ * If parameter is non-null and implements PersistenceCapable, returns
+ * OID.class.
+ * @see org.apache.jdo.pm.PersistenceManagerFactoryInternal#getObjectIdClass(
+ * Class cls)
+ */
+ public Class getObjectIdClass(Class cls) {
+ Class rc = null;
+ if (null != cls && PersistenceCapable.class.isAssignableFrom(cls)) {
+ JDOClass jdoClass = model.getJDOClass(cls);
+ rc = javaModelFactory.getJavaClass(jdoClass.getObjectIdClass());
+ if (rc == null)
+ rc = OID.class;
+ }
+ return rc;
+ }
+
+ /**
+ * @see org.apache.jdo.pm.PersistenceManagerFactoryInternal#getStoreManager(
+ * PersistenceManager pm)
+ */
+ public StoreManager getStoreManager(PersistenceManager pm) {
+ FOStoreStoreManager rc = null;
+ try {
+ rc = (FOStoreStoreManager)storeManagers.get(pm);
+ if (null == rc) {
+ rc = new FOStoreStoreManager(this);
+ storeManagers.put(pm, rc);
+ }
+ } catch (JDOException ex) {
+ throw ex;
+ } catch (Exception ex) {
+ throw new FOStoreFatalInternalException(
+ getClass(), "getStoreManager", ex); // NOI18N
+ }
+ return rc;
+ }
+
+ /**
+ * @see org.apache.jdo.pm.PersistenceManagerFactoryInternal#releaseStoreManager(
+ * PersistenceManager pm)
+ */
+ public void releaseStoreManager(PersistenceManager pm) {
+ try {
+ storeManagers.remove(pm);
+ } catch (JDOException ex) {
+ throw ex;
+ } catch (Exception ex) {
+ throw new FOStoreFatalInternalException(
+ getClass(), "releaseStoreManager", ex); // NOI18N
+ }
+ }
+
+ /**
+ * @see org.apache.jdo.pm.PersistenceManagerFactoryInternal#getTrackedClass(
+ * Class type)
+ */
+ public Class getTrackedClass(Class type) {
+ initTrackedClasses();
+ return (Class)trackedClasses.get(type);
+ }
+
+ /**
+ * Returns metadata associated with this PersistenceManagerFactory.
+ */
+ public FOStoreModel getModel() {
+ return model;
+ }
+
+ //
+ // Package-private methods
+ //
+
+ /**
+ * Provides the request factory.
+ * <em>Currently, this is statically bound to return an instance of a
+ * {@link BufferedRequestFactory}. In the future, this could be
+ * configurable.</em>
+ * @return A RequestFactory.
+ */
+ RequestFactory getRequestFactory() {
+ return BufferedRequestFactory.getInstance();
+ }
+
+ /**
+ * Sets up a mapping from the given provisional OID to real OID.
+ * @exception JDOFatalException Thrown if the given OID is not provisional, or if
+ * the given provisional OID is already mapped to a real OID.
+ */
+ // If you change this code, see method of same name in FOStoreDatabase.
+ void mapProvisionalOIDToReal(OID pOID, OID rOID) {
+ if (null == pOID || null == rOID || (! pOID.isProvisional())) {
+ throw new JDOFatalException(msg.msg("ERR_OIDNotProv", pOID)); // NOI18N
+ }
+ if (null != provisionalOIDs.get(pOID)) {
+ throw new JDOFatalException(msg.msg("ERR_DuplicateProvOID", pOID)); // NOI18N
+ }
+ provisionalOIDs.put(pOID, rOID);
+ }
+
+ /**
+ * Provides the real OID for the given provisional OID. Returns null if
+ * there is no mapping.
+ * @exception JDOFatalException Thrown if the given OID is not provisional.
+ */
+ // If you change this code, see method of same name in FOStoreDatabase.
+ OID getRealOIDFromProvisional(OID pOID) {
+ if (null == pOID || (! pOID.isProvisional())) {
+ throw new JDOFatalException(msg.msg("ERR_OIDNotProv", pOID)); // NOI18N
+ }
+ return (OID)provisionalOIDs.get(pOID);
+ }
+
+ //
+ // Implement Externalizable
+ // Support for serialization. We don't have any state to save, but want
+ // all the superclass's state saved
+ //
+
+ /**
+ * Writes this PMF's state to the given object output.
+ * @param out ObjectOutput to which this PMF's state is written.
+ */
+ public void writeExternal(java.io.ObjectOutput out)
+ throws java.io.IOException {
+
+ java.io.ObjectOutputStream oos = (java.io.ObjectOutputStream)out;
+ super.doWriteObject(oos);
+ oos.writeBoolean(create);
+ }
+
+ /**
+ * Reads this PMF's state from the given object input.
+ * @param in ObjectInput from which this PMF's state is read.
+ */
+ public void readExternal(java.io.ObjectInput in)
+ throws java.io.IOException, ClassNotFoundException {
+
+ java.io.ObjectInputStream ois = (java.io.ObjectInputStream)in;
+ super.doReadObject(ois);
+ create = ois.readBoolean();
+ }
+
+ /**
+ * Uses rot13 algorithm.
+ * @see org.apache.jdo.impl.pm.PersistenceManagerFactoryImpl#encrypt
+ */
+ protected String encrypt(String s) {
+ return doEncrypt(s);
+ }
+
+ /**
+ * Uses rot13 algorithm.
+ * @see org.apache.jdo.impl.pm.PersistenceManagerFactoryImpl#decrypt
+ */
+ protected String decrypt(String s) {
+ return doEncrypt(s);
+ }
+
+ /**
+ * Use same encryption for others in this package (e.g. FOStoreConnectionFactory).
+ */
+ static String doEncrypt(String s) {
+ return doDecrypt(s);
+ }
+
+ /**
+ * Use same encryption for others in this package (e.g. FOStoreConnectionFactory).
+ */
+ static String doDecrypt(String s) {
+ String rc = null;
+ if (null != s) {
+ rc = rot13(s);
+ }
+ return rc;
+ }
+
+ // Standard Rot13 stuff. Translated to Java from a C implementation found
+ // on the net.
+ private static String rot13(String s) {
+ String rc = null;
+ int length = s.length();
+ StringBuffer sb = new StringBuffer(length);
+ for (int i = 0; i < length; i++) {
+ int c = s.charAt(i);
+ int cap = c & 32;
+ c &= ~cap;
+ c = ((c >= 'A') && (c <= 'Z') ? ((c - 'A' + 13) % 26 + 'A') : c) | cap;
+ sb.append((char)c);
+ }
+ rc = sb.toString();
+ if (logger.isDebugEnabled()) {
+ logger.debug("encrypted " + s + " to be " + rc); // NOI18N
+ }
+ return rc;
+ }
+
+ /**
+ * @param create specifies whether to create the database */
+ public void setConnectionCreate (boolean create) {
+ this.create = create;
+ }
+
+ /**
+ * @param create tells whether to create the database*/
+ public void setConnectionCreate (String create) {
+ this.create = Boolean.valueOf(create).booleanValue();
+ }
+
+ /**
+ * @return whether to create the database */
+ public boolean getConnectionCreate() {
+ return create;
+ }
+
+ /**
+ * @see org.apache.jdo.impl.pm.PersistenceManagerFactoryImpl#setCFProperties
+ */
+ protected void setCFProperties(Properties p) {
+ if (null != cf) {
+ cf.setProperties(p);
+ }
+ }
+
+ /**
+ * @see org.apache.jdo.impl.pm.PersistenceManagerFactoryImpl#getCFFromProperties
+ */
+ protected void getCFFromProperties(Properties p) {
+ cf = new FOStoreConnectionFactory();
+ cf.setFromProperties(p);
+ }
+
+ //
+ // Implement Referenceable
+ //
+
+ /**
+ * Uses StringRefAddr's to store the information
+ */
+ public Reference getReference() throws NamingException {
+ Reference rc = new Reference(
+ FOStorePMF.class.getName(),
+ FOStorePMFFactory.class.getName(),
+ null);
+
+ Properties p = getAsProperties();
+ for (Enumeration e = p.propertyNames(); e.hasMoreElements();) {
+ String key = (String)e.nextElement();
+ String value = p.getProperty(key);
+ rc.add(new StringRefAddr(key, value));
+ }
+ return rc;
+ }
+
+ /**
+ * @return configuration information */
+ public String toString() {
+ return super.toString() +
+ "model: " + model + "\n" + // NOI18N
+ "storeManagers: " + storeManagers + "\n" + // NOI18N
+ "provisionalOIDs: " + provisionalOIDs + "\n" + // NOI18N
+ "cf: " + cf + "\n"; // NOI18N
+ }
+
+ /**
+ * @see PersistenceManagerFactoryImpl#getOptionArray
+ */
+ protected String[] getOptionArray() {
+ return optionArray;
+ }
+
+ /** A HashMap that associates PersistenceManagerFactory instances with a
+ * Properties instance.
+ */
+ protected static HashMap hashMapByFilteredProperties = new HashMap();
+
+ /**
+ * Construct a Properties instance from the given Properties. Only
+ * those property entries recognized by this implementation will be
+ * stored in the internal Properties instance.
+ *
+ * <P>This method attempts to find an existing PersistenceManagerFactory
+ * with the properties as specified in the parameter. Only the non-default
+ * properties are considered when trying to find a match.
+ *
+ * <P>This method cannot be implemented by the superclass because
+ */
+ public static PersistenceManagerFactoryImpl getPersistenceManagerFactory (Properties props) {
+ initPropsAccessors();
+ FOStoreConnectionFactory.initPropsAccessors();
+ Properties filtered = new Properties();
+ filterProperties (props, filtered, pmfAccessors);
+ filterProperties (props, filtered, propsAccessors);
+ filterProperties (props, filtered, fostorePropsAccessors);
+ filterProperties (props, filtered, FOStoreConnectionFactory.CFpropsAccessors);
+ FOStorePMF pmf = null;
+ synchronized (hashMapByFilteredProperties) {
+ pmf = (FOStorePMF) hashMapByFilteredProperties.get (filtered);
+ if (pmf != null) return pmf;
+ pmf = new FOStorePMF();
+ pmf.setFromProperties (filtered);
+ pmf.verifyConfiguration();
+ pmf.setConfigured();
+ hashMapByFilteredProperties.put (filtered, pmf);
+ pmf.configuredFrom = filtered;
+ }
+ return pmf;
+ }
+
+ /** Set the PMF class property for this PMF.
+ */
+ protected void setPMFClassProperty(Properties props) {
+ props.setProperty ("javax.jdo.PersistenceManagerFactoryClass", "org.apache.jdo.impl.fostore.FOStorePMF"); // NOI18N
+ }
+
+ /** Method called by the shudown hook to close pmf instances left open
+ * when the JVM exits.
+ */
+ protected void shutdown() {
+ super.shutdown();
+ close(true);
+ }
+}
Added: incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/FOStorePMFFactory.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/FOStorePMFFactory.java?rev=171355&view=auto
==============================================================================
--- incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/FOStorePMFFactory.java (added)
+++ incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/FOStorePMFFactory.java Sun May 22 11:40:13 2005
@@ -0,0 +1,65 @@
+/*
+ * 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 org.apache.jdo.impl.fostore;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Properties;
+
+import javax.naming.Context;
+import javax.naming.Name;
+import javax.naming.Reference;
+import javax.naming.spi.ObjectFactory;
+import javax.naming.StringRefAddr;
+
+/**
+* Creates a FOStorePMF when read in via JNDI.
+* <p>
+* This class is <code>public</code> so that JNDI can create instances.
+*
+* @author Dave Bristor
+*/
+public class FOStorePMFFactory implements ObjectFactory {
+
+ /**
+ * Uses StringRefAddr's to store the information
+ */
+ public Object getObjectInstance(
+ Object obj, Name name, Context ctx, Hashtable env) throws Exception {
+
+ FOStorePMF rc = null;
+
+ if (obj instanceof Reference) {
+ Reference ref = (Reference)obj;
+ if (ref.getClassName().equals(FOStorePMF.class.getName())) {
+ Properties p = new Properties();
+ for (Enumeration e = ref.getAll(); e.hasMoreElements();) {
+ StringRefAddr sra = (StringRefAddr)e.nextElement();
+ p.setProperty(sra.getType(), (String)sra.getContent());
+ }
+
+ rc = new FOStorePMF();
+ rc.setFromProperties(p);
+ }
+ }
+ return rc;
+ }
+}
Added: incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/FOStoreRemoteConnection.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/FOStoreRemoteConnection.java?rev=171355&view=auto
==============================================================================
--- incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/FOStoreRemoteConnection.java (added)
+++ incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/FOStoreRemoteConnection.java Sun May 22 11:40:13 2005
@@ -0,0 +1,136 @@
+/*
+ * 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.
+ */
+
+/*
+ * FOStoreRemoteClientImpl.java
+ *
+ * Created on June 18, 2001, 4:44 PM
+ */
+
+package org.apache.jdo.impl.fostore;
+
+import java.net.URL;
+import java.net.Socket;
+
+import java.io.DataOutputStream;
+import java.io.DataOutput;
+import java.io.OutputStream;
+import java.io.DataInput;
+import java.io.DataInputStream;
+import java.io.IOException;
+
+/**
+ * Represents a connection to a store that runs in a JVM separate from that of
+ * a client.
+ * <p>
+ * This class is <code>public</code> so that clients can access the value of
+ * <code>DEFAULT_PORT</code>.
+ *
+ * @author Craig Russell
+ * @version 1.0
+ */
+public class FOStoreRemoteConnection extends FOStoreClientConnectionImpl {
+
+ /** The default port number
+ */
+ public final static int DEFAULT_PORT = 9919;
+
+ /** The socket used to communicate with the remote server.
+ */
+ private Socket socket;
+
+ /** The DataInputStream from the socket for replies from the server.
+ */
+ private DataInput serverReplies;
+
+ /** The DataOutputStream from the socket for requests for the server.
+ */
+ private DataOutputStream clientRequests;
+
+ /** Creates new FOStoreRemoteConnection
+ * @param url the url of the server.
+ */
+ FOStoreRemoteConnection(URL url) {
+ super (url);
+ }
+
+ /** Connect to the data store. The user name and password are stored in
+ * the connectionId.
+ * @throws IOException if a network error occurs
+ */
+ public void connect() throws IOException {
+ String host = url.getHost();
+ int port = url.getPort();
+ if (port == -1)
+ port = DEFAULT_PORT;
+ if (logger.isDebugEnabled()) logger.debug("FOCCI:connect " + // NOI18N
+ " Host: " + host + // NOI18N
+ " Port: " + port); // NOI18N
+ socket = new Socket (host, port);
+ // we are connected; now send our greeting (login).
+ login();
+ }
+
+ /**
+ * Provides DataInput from which the client can read replies from
+ * the server.
+ * @return DataInput from which the client can read replies.
+ * @throws IOException if any problems.
+ */
+ public DataInput getInputFromServer() throws IOException {
+ if (serverReplies == null) {
+ serverReplies = new DataInputStream (socket.getInputStream());
+ }
+ return serverReplies;
+ }
+
+ /** Write bytes to the store. This is the only method to actually write
+ * data bytes from the Message to the server. As soon as the remote side
+ * has read the bytes, it processes the message and sends the reply.
+ * @param buffer the data buffer
+ * @param offset the offset within the buffer
+ * @param length the number of bytes to write
+ * @throws IOException if any problems.
+ */
+ public void sendToStore (byte[] buffer, int offset, int length) throws IOException {
+ if (clientRequests == null) {
+ OutputStream os = socket.getOutputStream();
+ clientRequests = new DataOutputStream (os);
+ }
+ clientRequests.writeInt (length - offset); // receiver needs to allocate a buffer this big
+ clientRequests.write (buffer, offset, length);
+ }
+
+ /** Close the database associated with this connection. This closes the socket
+ * associated, which causes the remote database to be closed.
+ * @throws IOException if any problems with the socket.
+ * @throws FOStoreDatabaseException if any problems with the database (not used here).
+ */
+ public void closeDatabase() throws IOException, FOStoreDatabaseException {
+ socket.close();
+ }
+
+ /**
+ * @return The path as given, with the leading '/' removed if there is one.
+ */
+ protected String localizePath(String path) {
+ // Use the correct path, not what Java gives you (see RFC1738)
+ if (path.startsWith("/")) { // NOI18N
+ path = path.substring(1);
+ }
+ return path;
+ }
+}
Added: incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/FOStoreSchemaUID.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/FOStoreSchemaUID.java?rev=171355&view=auto
==============================================================================
--- incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/FOStoreSchemaUID.java (added)
+++ incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/FOStoreSchemaUID.java Sun May 22 11:40:13 2005
@@ -0,0 +1,238 @@
+/*
+ * 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 org.apache.jdo.impl.fostore;
+
+import java.io.ByteArrayOutputStream;
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.security.DigestOutputStream;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+
+import java.util.HashMap;
+
+import javax.jdo.JDOFatalInternalException;
+import javax.jdo.JDOUserException;
+import javax.jdo.JDOFatalUserException;
+import javax.jdo.spi.JDOImplHelper;
+import javax.jdo.spi.PersistenceCapable;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.apache.jdo.util.I18NHelper;
+
+/**
+* A FOStoreSchemaUID is an internal name used to distinguish persistence
+* capable classes based on the structure of their persistent fields as
+* indicated by the enhancer. This is very similar to, and the implementation
+* is based on, the process of computing a serialVersionUID as described in
+* <a href="http://java.sun.com/products/jdk/1.2/docs/guide/serialization/spec/class.doc4.html"> Object Serialization Specification, Section 4.4, Stream Unique Identifiers</a>. // NOI18N
+*
+* @author Dave Bristor
+*/
+class FOStoreSchemaUID {
+ /** The 'value' of this FOStoreSchemaUID */
+ private final long fsuid;
+
+ /** Map from ClassLoader to a HashMap that in turn maps from Class to
+ * FOStoreSchemaUID.
+ */
+ private static final HashMap loaderMap = new HashMap();
+
+ /** I18N support. */
+ private static final I18NHelper msg = I18NHelper.getInstance(I18N.NAME);
+
+ /** Logger */
+ static final Log logger = LogFactory.getFactory().getInstance(
+ "org.apache.jdo.impl.fostore"); // NOI18N
+
+ private static final FOStoreSchemaUID NOT_PERSISTENT =
+ new FOStoreSchemaUID(0);
+
+ /** JDOImplHelper instance */
+ private static final JDOImplHelper helper =
+ (JDOImplHelper) AccessController.doPrivileged (
+ new PrivilegedAction () {
+ public Object run () {
+ try {
+ return JDOImplHelper.getInstance();
+ }
+ catch (SecurityException e) {
+ throw new JDOFatalUserException (msg.msg(
+ e.getMessage()), e); // NOI18N
+ }
+ }
+ }
+ );
+
+ private FOStoreSchemaUID(long value) {
+ this.fsuid = value;
+ }
+
+ private FOStoreSchemaUID(Class cls) {
+ this.fsuid = computeUID(cls);
+ }
+
+ /** Provides a FOStoreSchemaUID corresponding to the given class. Any
+ * class which
+ * <ul>
+ * <li>implements PersistenceCapable and</li>
+ * <li>is itself enhanced</li>
+ *</ul>
+ * has a distinct FOStoreSchemaUID. All other classes share a common
+ * FOStoreSchemaUID. (A class can be PersistenceCapable but not enhanced
+ * by virtue of being in an inheritance chain, in which a class which does
+ * not have a JDO model inherits a class that does have a JDO model.)
+ * <em>This should only be invoked by client code, never by server code,
+ * because it involves client-side concepts such as
+ * PersistenceCapable.</em>
+ * @param cls Class for which a FOStoreSchemaUID is needed.
+ * @param model FOStoreModel for determining whether cls was enhanced.
+ * @return FOStoreSchemaUID corresponding to given Class.
+ */
+ static synchronized FOStoreSchemaUID lookup(Class cls, FOStoreModel model) {
+ FOStoreSchemaUID rc = null;
+ if (! PersistenceCapable.class.isAssignableFrom(cls) ||
+ model.getJDOClass(cls) == null) {
+ rc = NOT_PERSISTENT;
+ } else {
+ HashMap classMap = (HashMap)loaderMap.get(cls.getClassLoader());
+ if (null == classMap) {
+ rc = new FOStoreSchemaUID(cls);
+ classMap = new HashMap();
+ classMap.put(cls, rc);
+ loaderMap.put(cls.getClassLoader(), classMap);
+ } else {
+ rc = (FOStoreSchemaUID)classMap.get(cls);
+ if (null == rc) {
+ rc = new FOStoreSchemaUID(cls);
+ classMap.put(cls, rc);
+ }
+ }
+ }
+ return rc;
+ }
+
+ private long computeUID(Class cls) {
+ long rc = 0;
+ try {
+ MessageDigest md = MessageDigest.getInstance("SHA"); // NOI18N
+ ByteArrayOutputStream baos = new ByteArrayOutputStream(512);
+ DigestOutputStream mdo = new DigestOutputStream(baos, md);
+ DataOutputStream data = new DataOutputStream(mdo);
+
+ computeUID(cls, data);
+
+ // Compute the hash value for cls
+ data.flush();
+ byte hasharray[] = md.digest();
+ for (int i = 0; i < Math.min(8, hasharray.length); i++) {
+ rc += (long)(hasharray[i] & 255) << (i * 8);
+ }
+
+ } catch (IOException ex) {
+ // Can't happen, but be deterministic anyway
+ rc = -1;
+ } catch (NoSuchAlgorithmException ex) {
+ throw new JDOFatalInternalException(
+ msg.msg("ERR_Algorithm"), ex); // NOI18N
+ }
+ return rc;
+ }
+
+ private void computeUID(Class cls, DataOutputStream out)
+ throws IOException {
+
+ if (logger.isDebugEnabled()) {
+ logger.debug("FSUID.computeUID: " + cls.getName()); // NOI18N
+ }
+
+ out.writeUTF(cls.getName());
+
+ // We don't need to sort these as the enhancer will have done that.
+ String names[] = helper.getFieldNames(cls);
+ Class types[] = helper.getFieldTypes(cls);
+ byte flags[] = helper.getFieldFlags(cls);
+ int length = names.length;
+
+ for (int i = 0; i < length; i++) {
+ out.writeUTF(names[i]);
+ out.writeUTF(types[i].getName());
+ out.writeByte(flags[i]);
+ }
+
+ Class spr = helper.getPersistenceCapableSuperclass(cls);
+ if (null != spr) {
+ if (logger.isDebugEnabled()) {
+ logger.debug("FSUID: spr for " + cls.getName() + // NOI18N
+ " is " + cls.getName()); // NOI18N
+ }
+ computeUID(spr, out);
+ }
+ }
+
+ public String toString() {
+ return "" + this.fsuid; // NOI18N
+ }
+
+ //
+ // Support for I/O
+ //
+
+ void write(DataOutput out) throws IOException {
+ out.writeLong(fsuid);
+ }
+
+ static FOStoreSchemaUID read(DataInput in) throws IOException {
+ return new FOStoreSchemaUID(in.readLong());
+ }
+
+ //
+ // Support for equality
+ //
+
+ public boolean equals(Object o) {
+ boolean rc = false;
+ if ((null != o) && (o instanceof FOStoreSchemaUID)) {
+ rc = (fsuid == ((FOStoreSchemaUID)o).fsuid);
+ }
+ return rc;
+ }
+
+ /**
+ * Computes a hashcode for this FOStoreSchemaUID. The result is the
+ * exclusive OR of the two halves of the primitive <code>long</code>
+ * value represented by this <code>Long</code> object. That is, the
+ * hashcode is the value of the expression:
+ * <blockquote><pre>
+ * (int)(this.longValue()^(this.longValue()>>>32))
+ * </pre></blockquote>
+ * This is the same algoritm as is used for java.lang.Long.
+ *
+ * @return a hash code value for this object.
+ */
+ public int hashCode() {
+ // Same as for java.lang.Long
+ return (int)(fsuid ^ (fsuid >> 32));
+ }
+}
Added: incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/FOStoreServerConnection.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/FOStoreServerConnection.java?rev=171355&view=auto
==============================================================================
--- incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/FOStoreServerConnection.java (added)
+++ incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/FOStoreServerConnection.java Sun May 22 11:40:13 2005
@@ -0,0 +1,115 @@
+/*
+ * 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 org.apache.jdo.impl.fostore;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+
+/**
+* A connection as used by a server/store. It provides a means of getting the
+* client's input, and of writing reply data back to the client.
+*
+* @author Dave Bristor
+*/
+interface FOStoreServerConnection extends FOStoreConnection {
+ /**
+ * Provides a DataInput from which the server can read the client's
+ * requests.
+ * @return DataInput for reading requests.
+ */
+ public FOStoreInput getInputFromClient();
+
+ /**
+ * Provides a DataOutput to which the server can write data for the
+ * client. This is not normally used for writing data associated with a
+ * single reply (use createReply for that purpose).
+ * @return FOStoreOutput for writing data to client.
+ */
+ public FOStoreOutput getOutputForClient();
+
+ /**
+ * Provides a Reply to which the server can write replies to the
+ * client's requests.
+ * @return Reply object for writing information about one reply.
+ */
+ public Reply createReply(RequestId requestId) throws IOException;
+
+ /**
+ * Adds the extent to this connections set of extents that have been
+ * changed during a transaction.
+ */
+ public boolean addExtent(DBExtent dbExtent);
+
+ /**
+ * Commits the work done in this connection.
+ */
+ public void commit() throws FOStoreDatabaseException;
+
+ /**
+ * Rolls back the work done in this connection.
+ */
+ public void rollback() throws FOStoreDatabaseException;
+
+ /**
+ * Sends all the reply data to the client.
+ */
+ public void sendToClient() throws IOException, FOStoreDatabaseException;
+
+ /**
+ * Provides the database to be used by the server using this connection.
+ * @return A database.
+ */
+ public FOStoreDatabase getDatabase();
+
+ /** Set client data stream. Only used in local case.
+ */
+ public void setClientInput (FOStoreInput in) throws IOException;
+
+ /** Process requests from client.
+ */
+ public void processRequests ();
+
+ /** Log in to the database.
+ */
+ public void openDatabase(String dbname, String user, long timestamp, byte[] secret, boolean create)
+ throws java.lang.InterruptedException, FOStoreDatabaseException;
+
+ /** Provide the output from the server to the client reply handler.
+ */
+ public DataInput getOutputFromServer();
+
+ /** Write the output from the server to the socket
+ */
+ public void writeOutputToClient() throws IOException;
+
+ /** Read the input stream from the socket.
+ */
+ public void readInputFromClient() throws IOException;
+
+ /** Close the database. Each open connection will perform this operation;
+ * only the last open connection to be closed will actually close the
+ * database.
+ */
+ public void closeDatabase() throws FOStoreDatabaseException;
+
+ /** Indicates whether or not it is OK to release a database after a
+ * message's contents are processed.
+ */
+ // XXX TBD The server connection and implementation needs refactoring
+ public void setOkToReleaseDatabase(boolean ok);
+}
Added: incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/FOStoreServerConnectionImpl.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/FOStoreServerConnectionImpl.java?rev=171355&view=auto
==============================================================================
--- incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/FOStoreServerConnectionImpl.java (added)
+++ incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/FOStoreServerConnectionImpl.java Sun May 22 11:40:13 2005
@@ -0,0 +1,355 @@
+/*
+ * 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.
+ */
+
+/*
+ * FOStoreServerConnectionImpl.java
+ *
+ * Created on June 7, 2001, 3:16 PM
+ */
+
+package org.apache.jdo.impl.fostore;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.DataInput;
+import java.io.ByteArrayInputStream;
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import java.net.Socket;
+
+import java.util.HashSet;
+import java.util.Iterator;
+
+import javax.jdo.JDOFatalInternalException;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.apache.jdo.util.I18NHelper;
+
+/**
+ *
+ * @author Craig Russell
+ * @version 1.0
+ */
+
+ /** This class implements the FOStoreServerConnection contract. It is used
+ * in two modes: local and remote. In local mode, the default constructor
+ * is used. In remote mode, the constructor that takes a Socket is used.
+ * The connection after construction does not contain any information about
+ * the data store. After the login request is successfully executed, the
+ * Database information is known. Subsequent requests know the Database.
+ */
+// XXX This class needs to be split into 2: one which handles the
+// socket-connected case, the other which handles the local case.
+class FOStoreServerConnectionImpl implements FOStoreServerConnection {
+
+ /** I18N support. */
+ private static final I18NHelper msg = I18NHelper.getInstance(I18N.NAME);
+
+ /** Logger */
+ static final Log logger = LogFactory.getFactory().getInstance(
+ "org.apache.jdo.impl.fostore"); // NOI18N
+
+ /** Used by server to write its replies.
+ */
+ private FOStoreOutput serverData = new FOStoreOutput();
+
+ /** Used by server to read client's requests.
+ */
+ private FOStoreInput clientDataInput;
+
+ /** The socket over which we communicate to the client.
+ */
+ private final Socket socket;
+
+ /** Root in filesystem at which database will be created.
+ */
+ private final String root;
+
+ /** The input stream from the socket. Set after connect; reset at
+ * socket.close().
+ */
+ private DataInputStream socketDataInputStream = null;
+
+ /** The output stream from the socket. Set after connect; reset at
+ * socket.close().
+ */
+ private OutputStream socketOutputStream = null;
+
+ /** The local database name.
+ */
+ private String dbname;
+
+ /** The local database
+ */
+ private FOStoreDatabase fodb;
+
+ /** Indicates if releaseDatabase can really do so.
+ */
+ private boolean okToReleaseDatabase = true;
+
+ /** Creates new FOStoreServerConnectionImpl for the local case.
+ */
+ public FOStoreServerConnectionImpl() {
+ this.socket = null;
+ this.root = null;
+ }
+
+ /** Creates new FOStoreServerConnectionImpl for the remote case.
+ */
+ public FOStoreServerConnectionImpl(Socket socket, String root) {
+ this.socket = socket;
+ this.root = root;
+ }
+
+ /**
+ * Commits the work done in this connection. The database must already
+ * be connected. Stores in the database (a) the extents that have been
+ * changed and (b) the database's DBInfo.
+ */
+ public void commit() throws FOStoreDatabaseException {
+ if (logger.isDebugEnabled()) logger.debug("FOSCI.commit"); // NOI18N
+ FOStoreDatabase db = getDatabase();
+
+ DBInfo dbInfo = db.getDBInfo();
+ dbInfo.storeDirtyExtents();
+ dbInfo.store();
+ db.commitChanges();
+ }
+
+ /**
+ * Rolls back the work done in this connection.
+ */
+ public void rollback() throws FOStoreDatabaseException {
+ FOStoreDatabase db = getDatabase();
+ db.getDBInfo().clearDirtyExtents();
+ db.rollbackChanges();
+ }
+
+ /**
+ * Provides a Reply to which the server can write replies to the
+ * client's requests.
+ * @return Reply object for writing information about one reply.
+ */
+ public Reply createReply(RequestId requestId) throws IOException {
+ return new Reply(requestId, serverData);
+ }
+
+ /**
+ * Provides a DataInput from which the server can read the client's
+ * requests.
+ * @return DataInput for reading requests.
+ */
+ public FOStoreInput getInputFromClient() {
+ return clientDataInput;
+ }
+
+ public void readInputFromClient() throws IOException {
+ if (socketDataInputStream == null) {
+ InputStream is = socket.getInputStream();
+ socketDataInputStream = new DataInputStream (is);
+ }
+ if (logger.isDebugEnabled()) {
+ logger.debug (
+ "FOSCI.readInputFromClient available: " + // NOI18N
+ socketDataInputStream.available());
+ }
+
+ int length = socketDataInputStream.readInt();
+ byte[] buffer = new byte[length];
+ socketDataInputStream.readFully(buffer);
+ setClientInput( new FOStoreInput (buffer, 0, length));
+ }
+
+ /**
+ * @see FOStoreServerConnection#sendToClient
+ */
+ public void sendToClient() throws IOException, FOStoreDatabaseException {
+ }
+
+ /**
+ * Adds the extent to this connections set of extents that have been
+ * changed during a transaction. They will be put to the database when
+ * sendToClient is invoked.
+ */
+ public boolean addExtent(DBExtent dbExtent) {
+ boolean rc = getDatabase().getDBInfo().makeExtentDirty(dbExtent);
+ if (logger.isDebugEnabled()) {
+ logger.debug("FOSCI.addExtent to: " + this + // NOI18N
+ " dbExtent: " + dbExtent + // NOI18N
+ "add rc: " + rc); // NOI18N
+ }
+ return rc;
+ }
+
+ /** Open the database if it exists, and verify the user authentication.
+ * If the database does not exist, create it.
+ */
+ public void openDatabase (String dbname, String user, long timestamp,
+ byte[] secret, boolean create)
+ throws FOStoreDatabaseException, InterruptedException {
+
+ if (logger.isDebugEnabled()) {
+ logger.debug("FOSCI.openDatabase " + dbname + // NOI18N
+ " user: " + user); // NOI18N
+ }
+
+ fodb = FOStoreDatabase.getDatabase(databasePath(dbname), create);
+ this.dbname = dbname;
+ fodb.verifyUserPassword(user, timestamp, secret);
+ }
+
+ /**
+ * Provides the database to be used by the server using this connection.
+ * @return A database.
+ */
+ public FOStoreDatabase getDatabase() {
+ try {
+ if (fodb == null) {
+ fodb = FOStoreDatabase.getDatabase(
+ databasePath(dbname), false);
+ }
+ return fodb;
+ } catch (InterruptedException ex) {
+ throw new JDOFatalInternalException(
+ msg.msg("ERR_GetDatabaseInterrupted"), ex); // NOI18N
+ } catch (FOStoreDatabaseException ex) {
+ throw new JDOFatalInternalException(
+ msg.msg("ERR_GetDatabaseException"), ex); // NOI18N
+ }
+ }
+
+ /**
+ * Provides a DataOutput to which the server can write data for the
+ * client. This is not normally used for writing data associated with a
+ * single reply (use createReply for that purpose).
+ * @return FOStoreOutput for writing data to client.
+ */
+ public FOStoreOutput getOutputForClient() {
+ return serverData;
+ }
+
+ /** Provides a DataInput from which the local client can read the server's
+ * replies. Reset for the next output request.
+ */
+ public DataInput getOutputFromServer() {
+ DataInput di = new DataInputStream(
+ new ByteArrayInputStream(
+ serverData.getBuf(), 0, serverData.getPos()));
+
+ serverData.reset(); // reset the output stream
+ return di;
+ }
+
+ /** Writes the output to the client socket. Reset for the next output
+ * request.
+ */
+ public void writeOutputToClient() throws IOException {
+ if (socketOutputStream == null) {
+ if (logger.isDebugEnabled()) {
+ logger.debug(
+ "FOSCI.writeOutputToClient getting socketOutputStream"); // NOI18N
+ }
+
+ socketOutputStream = socket.getOutputStream();
+ if (logger.isDebugEnabled()) {
+ logger.debug(
+ "FOSCI.writeOutputToClient got socketOutputStream"); // NOI18N
+ }
+ }
+
+ if (logger.isDebugEnabled()) {
+ logger.debug(
+ "FOSCI.writeOutputToClient writing socketOutputStream: " + // NOI18N
+ serverData.getPos() + " bytes"); // NOI18N
+ }
+
+ socketOutputStream.write(serverData.getBuf(), 0, serverData.getPos());
+ serverData.reset(); // reset the output stream
+ }
+
+ public void setClientInput (FOStoreInput fi) {
+ clientDataInput = fi;
+ }
+
+ public void processRequests() {
+ RequestHandler.handleRequests(this);
+ }
+
+ /** Indicates whether or not releaseDatabase can actually release the
+ * database.
+ */
+ public void setOkToReleaseDatabase(boolean ok) {
+ if (logger.isDebugEnabled()) {
+ logger.debug("FOSCI.setOk: " + ok); // NOI18N
+ }
+ this.okToReleaseDatabase = ok;
+ }
+
+ /** Release the database associated with this connection.
+ */
+ void releaseDatabase() throws InterruptedException {
+ if (okToReleaseDatabase && fodb != null) {
+ if (logger.isDebugEnabled()) {
+ logger.debug("FOSCI.releaseDatabase: releasing"); // NOI18N
+ }
+ FOStoreDatabase.releaseDatabase(fodb);
+ fodb = null;
+ }
+ }
+
+ /** Close the database associated with this connection.
+ */
+ public void closeDatabase() throws FOStoreDatabaseException {
+ try {
+ if (logger.isDebugEnabled()) {
+ logger.debug("FOSCI.closeDatabase " + dbname); // NOI18N
+ }
+ releaseDatabase();
+ FOStoreDatabase.closeDatabase(databasePath(dbname));
+ } catch (InterruptedException ex) {
+ throw new JDOFatalInternalException(
+ msg.msg("ERR_CloseDatabaseInterrupted"), ex); // NOI18N
+ }
+ }
+
+ /** Close this connection; release all resources.
+ */
+ public void close() throws FOStoreDatabaseException {
+ if (logger.isDebugEnabled()) {
+ logger.debug("FOSCI.close " + dbname); // NOI18N
+ }
+ closeDatabase();
+ }
+
+ /** @return A String for the databse's pathnamne. It is based on the
+ * given dbname, plus the root, if one was given when this connection was
+ * created.
+ */
+ private final String databasePath(String dbname) {
+ String rc;
+ if (null == root) {
+ rc = dbname;
+ } else {
+ rc = root + File.separator + dbname;
+ }
+ return rc;
+ }
+}