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/03/19 02:06:01 UTC
svn commit: r158176 [20/79] - in incubator/jdo/trunk/ri11: ./ src/ src/conf/
src/java/ src/java/org/ src/java/org/apache/ src/java/org/apache/jdo/
src/java/org/apache/jdo/ejb/ src/java/org/apache/jdo/enhancer/
src/java/org/apache/jdo/impl/ src/java/org/apache/jdo/impl/enhancer/
src/java/org/apache/jdo/impl/enhancer/classfile/
src/java/org/apache/jdo/impl/enhancer/core/
src/java/org/apache/jdo/impl/enhancer/generator/
src/java/org/apache/jdo/impl/enhancer/meta/
src/java/org/apache/jdo/impl/enhancer/meta/model/
src/java/org/apache/jdo/impl/enhancer/meta/prop/
src/java/org/apache/jdo/impl/enhancer/meta/util/
src/java/org/apache/jdo/impl/enhancer/util/
src/java/org/apache/jdo/impl/fostore/ src/java/org/apache/jdo/impl/jdoql/
src/java/org/apache/jdo/impl/jdoql/jdoqlc/
src/java/org/apache/jdo/impl/jdoql/scope/
src/java/org/apache/jdo/impl/jdoql/tree/ src/java/org/apache/jdo/impl/model/
src/java/org/apache/jdo/impl/model/java/
src/java/org/apache/jdo/impl/model/java/runtime/
src/java/org/apache/jdo/impl/model/jdo/
src/java/org/apache/jdo/impl/model/jdo/caching/
src/java/org/apache/jdo/impl/model/jdo/util/
src/java/org/apache/jdo/impl/model/jdo/xml/
src/java/org/apache/jdo/impl/pm/ src/java/org/apache/jdo/impl/sco/
src/java/org/apache/jdo/impl/state/ src/java/org/apache/jdo/jdoql/
src/java/org/apache/jdo/jdoql/tree/ src/java/org/apache/jdo/model/
src/java/org/apache/jdo/model/java/ src/java/org/apache/jdo/model/jdo/
src/java/org/apache/jdo/pm/ src/java/org/apache/jdo/sco/
src/java/org/apache/jdo/state/ src/java/org/apache/jdo/store/
src/java/org/apache/jdo/util/ test/ test/conf/ test/enhancer/
test/enhancer/sempdept/ test/enhancer/sempdept/src/
test/enhancer/sempdept/src/empdept/ 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/ xdocs/
Added: incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/fostore/FOStoreConnectionFactory.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/fostore/FOStoreConnectionFactory.java?view=auto&rev=158176
==============================================================================
--- incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/fostore/FOStoreConnectionFactory.java (added)
+++ incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/fostore/FOStoreConnectionFactory.java Fri Mar 18 17:02:29 2005
@@ -0,0 +1,715 @@
+/*
+ * 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.PrintWriter;
+import java.io.Serializable;
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.UnknownHostException;
+import java.net.ConnectException;
+import java.net.URL;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+
+import javax.jdo.JDOFatalException;
+import javax.jdo.JDOFatalInternalException;
+import javax.jdo.JDOFatalDataStoreException;
+import javax.jdo.JDOUserException;
+import javax.jdo.JDOFatalUserException;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.apache.jdo.pm.Accessor;
+import org.apache.jdo.util.I18NHelper;
+import org.apache.jdo.util.Pool;
+
+/**
+ * A connection factory for FOStore. Allows both same- and remote-address
+ * space connections. For the same address space-connections, the URL must
+ * not include the Host (Server) parameter. For remote address space
+ * connections, the URL's protocol is ignored.
+ * <p>
+ * This class is <code>public</code> so that clients can create instances of it
+ * with <code>new</code>.
+ *
+ * @author Dave Bristor
+ */
+public class FOStoreConnectionFactory implements Serializable {
+ private String url;
+ private String userName;
+ private String password;
+ private String driverName;
+ private boolean create;
+
+ private FOStorePMF pmf;
+
+ private int loginTimeout;
+
+ private transient PrintWriter logWriter;
+
+ /** Connections are created by the FOStoreURLStreamHandler.
+ */
+ private final FOStoreURLStreamHandler streamHandler =
+ FOStoreURLStreamHandler.getInstance();
+
+ /** Connections are pooled. Each unique combination of url,
+ * user, password has its own pool. The hashmap associates
+ * a FOStoreConnectionId with its pool of connections.
+ */
+ private final HashMap connectionMap = new HashMap();
+
+ /** For now, set the pool size to 1.
+ */
+ // XXX this needs to be configurable...
+ private static final int poolSize = 1;
+
+ private FOStoreConnectionId defaultConnectionId;
+
+ private FOStoreConnectionId userConnectionId;
+
+ /** True until setConfigured has been invoked. Allows properties to be
+ * set if true.
+ */
+ private boolean configurable = true;
+
+ /** This table maps from names to CFAccessors. The names are the same as the
+ * persistence manager factory's property names, but with
+ * org.apache.jdo.FOStoreConnectionFactory.option prepended.
+ */
+ protected static HashMap CFpropsAccessors = new HashMap(9);
+
+ /** 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
+
+ /**
+ * First time a FOStoreConnectionFactory is created, initialize accessors
+ * which are used to store/save instances via JNDI.
+ */
+ public FOStoreConnectionFactory() {
+ if (logger.isDebugEnabled()) logger.debug("FOCF()"); // NOI18N
+ initPropsAccessors();
+ }
+
+ /** Set the url, user, and password into the ConnectionIds for this
+ * connection factory.
+ */
+ private void setConfigured() {
+ if (logger.isDebugEnabled()) {
+ logger.debug("FOCF.setConfigured: URL: " + url); // NOI18N
+ }
+ configurable = false;
+ defaultConnectionId =
+ new FOStoreConnectionId(url, userName, password, create);
+ userConnectionId = new FOStoreConnectionId(url, null, null, false);
+ }
+
+ private void assertConfigurable() {
+ if (configurable) return;
+ throw new JDOUserException (
+ msg.msg("EXC_AssertConfigurableFailure")); // NOI18N
+ }
+
+ /**
+ * Provides a connection to the database using the given userName and
+ * password. The first time a connection is made, the
+ * factory can no longer be configured.
+ * @return A FOStoreClientConnection
+ */
+ public synchronized FOStoreClientConnection getConnection(
+ String user, String password) {
+ setConfigured(); // initializes userConnectionId with url.
+ FOStoreConnection rc = null;
+
+ if (logger.isDebugEnabled()) {
+ logger.debug("FOCF.getConnection(" + user + ", " +
+ password + "): " + hashCode()); // NOI18N
+ }
+ // We reuse the same userConnectionId until we need to create a new
+ // Pool for it. The we create a new one for next time.
+ FOStoreConnectionId connectionId = userConnectionId;
+ connectionId.setUser (user);
+ connectionId.setPassword (password);
+
+ // Try to find the existing connection in the pool.
+ // First time we get here, database is not yet open and connections
+ // are not yet created/in-pool.
+ Pool pool = (Pool) connectionMap.get (connectionId);
+ if (null == pool) {
+ pool = createPool (connectionId);
+ userConnectionId = new FOStoreConnectionId (url, null, null);
+ }
+ try {
+ // blocks until a connection is available.
+ return (FOStoreClientConnection) pool.get();
+ } catch (InterruptedException ex) {
+ throw new JDOFatalInternalException(
+ msg.msg("ERR_PoolGet"), ex); // NOI18N
+ }
+ }
+
+ /** Create a new pool of connections for this combination of url, user,
+ * and password. This might be either the default or for a specific user.
+ */
+ Pool createPool (FOStoreConnectionId id) {
+ Pool pool = new Pool(poolSize);
+ if (connectionMap.put (id, pool) != null) {
+ throw new JDOFatalInternalException (
+ msg.msg("ERR_DuplicatePool")); // NOI18N
+ }
+ try {
+ if (logger.isDebugEnabled()) {
+ logger.debug("FOCF: first time; filling pool"); // NOI18N
+ }
+ for (int i = 0; i < poolSize; i++) {
+ FOStoreClientConnection connection =
+ createConnection(id);
+ pool.put(connection);
+ }
+ } catch (InterruptedException ex) {
+ throw new JDOFatalInternalException(
+ msg.msg("ERR_PoolPutFill"), ex); // NOI18N
+ }
+ return pool;
+ }
+
+ /**
+ * Provides a connection to the database using the configured userName,
+ * password, and url. The first time a connection is made, the
+ * factory can no longer be configured.
+ * @return A FOStoreClientConnection
+ */
+ public synchronized FOStoreClientConnection getConnection() {
+ setConfigured();
+ FOStoreConnection rc = null;
+
+ if (logger.isDebugEnabled()) {
+ logger.debug("FOCF.getConnection(): " + hashCode()); // NOI18N
+ }
+
+ // First time we get here, database is not yet open and connections
+ // are not yet created/in-pool.
+
+ Pool pool = (Pool) connectionMap.get (defaultConnectionId);
+ if (null == pool) {
+ pool = createPool (defaultConnectionId);
+ }
+ try {
+ // blocks until a connection is available.
+ return (FOStoreClientConnection) pool.get();
+ } catch (InterruptedException ex) {
+ throw new JDOFatalInternalException(
+ msg.msg("ERR_PoolGet"), ex); // NOI18N
+ }
+ }
+
+ /**
+ * This method requires permission to perform the following requests:
+ * Create new URL with the specified StreamHandler.
+ * Delete old database id create flag is set to true.
+ */
+ private FOStoreClientConnection createConnection(
+ final FOStoreConnectionId id) {
+ final FOStoreConnectionFactory cf = this;
+ return (FOStoreClientConnection) AccessController.doPrivileged (
+ new PrivilegedAction () {
+ public Object run () {
+ URL uRL = null;
+ try {
+ uRL = new URL (null, url, streamHandler);
+ FOStoreClientConnection connection =
+ (FOStoreClientConnection) streamHandler.openConnection(uRL);
+ connection.setConnectionFactory(cf);
+ connection.setConnectionId(id);
+ connection.connect();
+ return connection;
+ } catch (SecurityException se) {
+ throw new JDOFatalUserException(
+ msg.msg("EXC_CannotSpecifyStreamHandler"), se); //NOI18N
+ } catch (UnknownHostException ioe) {
+ throw new JDOFatalUserException (
+ msg.msg("EXC_UnknownHostException", uRL.getHost()), ioe); // NOI18N
+ } catch (ConnectException ioe) {
+ int port = uRL.getPort();
+ if (port == -1)
+ port = FOStoreRemoteConnection.DEFAULT_PORT;
+ throw new JDOFatalUserException(
+ msg.msg("EXC_ConnectException", // NOI18N
+ uRL.getHost(), new Integer(port)),
+ ioe);
+ } catch (IOException ioe) {
+ throw new JDOFatalUserException (
+ msg.msg("EXC_CannotCreateConnection", url), ioe); // NOI18N
+ }
+ }
+ }
+ );
+ }
+
+
+ /**
+ * Returns a connection to the pool
+ * @param connection Connection to be returned to the pool.
+ */
+ void closeConnection(FOStoreClientConnection connection) {
+ FOStoreConnectionId id = connection.getConnectionId();
+ Pool pool = (Pool) connectionMap.get(id);
+ try {
+ pool.put(connection);
+ } catch (InterruptedException ex) {
+ throw new JDOFatalInternalException(
+ msg.msg("ERR_CloseConnectionpoolPut"), ex); // NOI18N
+ }
+ }
+
+ /**
+ * Close the database. This really means close all connections that
+ * have been opened. Closing the last connection on a database actually
+ * closes the database, whether local or remote.
+ */
+ public synchronized void closeDatabase() {
+ Object timer = Tester.startTime();
+ try {
+ for (Iterator hmi = connectionMap.values().iterator();
+ hmi.hasNext();) {
+
+ Pool dbPool = (Pool) hmi.next();
+ // we know that there are poolSize entries in each pool
+ for (int i = 0; i < poolSize; ++i) {
+ FOStoreClientConnection focci =
+ (FOStoreClientConnection) dbPool.get();
+ focci.closeDatabase();
+ }
+ }
+ if (logger.isTraceEnabled()) {
+ Tester.printTime(timer, "Time to close database"); // NOI18N
+ }
+ } catch (FOStoreDatabaseException ex) {
+ throw new FOStoreFatalInternalException(
+ this.getClass(),
+ "close", msg.msg("ERR_CannotClose", url), ex); // NOI18N
+ } catch (IOException ex) {
+ throw new FOStoreFatalInternalException(
+ this.getClass(),
+ "close", msg.msg("ERR_CannotClose", url), ex); // NOI18N
+ } catch (InterruptedException ex) {
+ throw new FOStoreFatalInternalException(
+ this.getClass(),
+ "close", msg.msg("ERR_CannotClose", url), ex); // NOI18N
+ }
+ if (logger.isDebugEnabled()) {
+ logger.debug("FOCF: closed " + url); // NOI18N
+ }
+ }
+
+ /**
+ * Sets name of the driver for connections
+ * @param driverName driver name
+ */
+ public void setDriverName(String driverName){
+ assertConfigurable();
+ this.driverName = driverName;
+ }
+
+ /**
+ * Provides PersistenceManagerFactory for connections
+ * @return PMF
+ */
+ public FOStorePMF getPMF() {
+ return pmf;
+ }
+
+ /**
+ * Sets PersistenceManagerFactory for connections
+ * @param pmf PersistenceManagerFactory
+ */
+ public void setPMF(FOStorePMF pmf){
+ assertConfigurable();
+ this.pmf = pmf;
+ }
+
+ /**
+ * Provides name of driver used for connections
+ * @return driver name
+ */
+ public String getDriverName() {
+ return driverName;
+ }
+
+ /**
+ * Sets connection URL
+ * @param url connection URL
+ */
+ public void setURL(String url) {
+ assertConfigurable();
+ this.url = url;
+ }
+
+ /**
+ * Returns connection URL
+ * @return connection URL
+ */
+ public String getURL() {
+ return url;
+ }
+
+ /**
+ * Sets database user
+ * @param userName database user
+ */
+ public void setUserName(String userName) {
+ assertConfigurable();
+ this.userName = userName;
+ }
+
+ /**
+ * Returns database user name
+ * @return current database user name
+ */
+ public String getUserName() {
+ return userName;
+ }
+
+ /**
+ * Sets database user password
+ * @param password database user password
+ */
+ public void setPassword(String password) {
+ assertConfigurable();
+ this.password = password;
+ }
+
+ /**
+ * Sets minimum number of connections in the connection pool
+ * @param minPool minimum number of connections
+ */
+ public void setMinPool(int minPool) {
+ assertConfigurable();
+ }
+
+ /**
+ * Returns minimum number of connections in the connection pool
+ * @return connection minPool
+ */
+ public int getMinPool() {
+ return 1;
+ }
+
+ /**
+ * Sets maximum number of connections in the connection pool
+ * @param maxPool maximum number of connections
+ */
+ public void setMaxPool(int maxPool) {
+ assertConfigurable();
+ }
+
+ /**
+ * Returns maximum number of connections in the connection pool
+ * @return connection maxPool
+ */
+ public int getMaxPool() {
+ return 1;
+ }
+
+ /**
+ * Sets the amount of time, in milliseconds, between the connection
+ * manager's attempts to get a pooled connection.
+ * @param msInterval the interval between attempts to get a database
+ * connection, in milliseconds.
+ *
+ */
+ public void setMsInterval(int msInterval) { }
+
+ /**
+ * Returns the amount of time, in milliseconds, between the connection
+ * manager's attempts to get a pooled connection.
+ * @return the length of the interval between tries in milliseconds
+ */
+ public int getMsInterval() {
+ return 0;
+ }
+
+ /**
+ * Sets the number of milliseconds to wait for an available connection
+ * from the connection pool before throwing an exception
+ * @param msWait number in milliseconds
+ */
+ public void setMsWait(int msWait) {
+ assertConfigurable();
+ }
+
+ /**
+ * Returns the number of milliseconds to wait for an available connection
+ * from the connection pool before throwing an exception
+ * @return number in milliseconds
+ */
+ public int getMsWait() {
+ return 0;
+ }
+
+ /**
+ * Sets the LogWriter to which messages should be sent
+ * @param logWriter logWriter
+ */
+ public void setLogWriter(PrintWriter logWriter) {
+ this.logWriter = logWriter;
+ }
+
+ /**
+ * Returns the LogWriter to which messages should be sent
+ * @return logWriter
+ */
+ public PrintWriter getLogWriter() {
+ return logWriter;
+ }
+
+ /**
+ * Sets the number of seconds to wait for a new connection to be
+ * established to the data source
+ * @param loginTimeout wait time in seconds
+ */
+ public void setLoginTimeout(int loginTimeout) {
+ assertConfigurable();
+ this.loginTimeout = loginTimeout;
+ }
+
+ /**
+ * Returns the number of seconds to wait for a new connection to be
+ * established to the data source
+ * @return wait time in seconds
+ */
+ public int getLoginTimeout() {
+ return loginTimeout;
+ }
+
+ /**
+ * Sets whether to create the database.
+ * @param create whether to create the database.
+ */
+ public void setCreate(boolean create) {
+ assertConfigurable();
+ this.create = create;
+ }
+
+ /**
+ * Sets whether to create the database.
+ * @param create whether to create the database.
+ */
+ public void setCreate(String create) {
+ assertConfigurable();
+ this.create = Boolean.valueOf (create).booleanValue();
+ }
+
+ /**
+ * Returns whether to create the database.
+ * @return whether to create the database
+ */
+ public boolean getCreate() {
+ return create;
+ }
+
+ //
+ // Support for JNDI: we want to save/restore a FOStoreConnectionFactory
+ // via JNDI, and have the stored representation be via properties.
+ //
+
+ /** CFAccessor implementation instances allow copying values to/from a
+ * FOStoreConnectionFactory
+ * and a Properties. They do the proper type translation too.
+ */
+ interface CFAccessor extends Accessor {
+ /** @return String form of a value in a FOStoreConnectionFactory.
+ */
+ public String get(FOStoreConnectionFactory focf);
+
+ /** @return String form of a value in a FOStoreConnectionFactory if
+ * is not a default value.
+ */
+ public String getNonDefault(FOStoreConnectionFactory focf);
+
+ /** @param s String form of a value in a FOStoreConnectionFactory.
+ */
+ public void set(FOStoreConnectionFactory focf, String s);
+ }
+
+ // Initialize the property accessors map.
+ protected static void initPropsAccessors() {
+ synchronized (CFpropsAccessors) {
+ if (CFpropsAccessors.size() == 0) {
+
+ CFpropsAccessors.put(
+ "org.apache.jdo.FOStoreConnectionFactory.option.URL", // NOI18N
+ new CFAccessor() {
+ public String get(FOStoreConnectionFactory focf) { return focf.getURL(); }
+ public String getNonDefault(FOStoreConnectionFactory focf) { return focf.getURL(); }
+ public String getDefault() {return null;}
+ public void set(FOStoreConnectionFactory focf, String s) { focf.setURL(s); }
+ });
+ CFpropsAccessors.put(
+ "org.apache.jdo.FOStoreConnectionFactory.option.UserName", // NOI18N
+ new CFAccessor() {
+ public String get(FOStoreConnectionFactory focf) { return focf.getUserName(); }
+ public String getNonDefault(FOStoreConnectionFactory focf) { return focf.getUserName(); }
+ public String getDefault() {return null;}
+ public void set(FOStoreConnectionFactory focf, String s) { focf.setUserName(s); }
+ });
+ CFpropsAccessors.put(
+ "org.apache.jdo.FOStoreConnectionFactory.option.Password", // NOI18N
+ new CFAccessor() {
+ public String get(FOStoreConnectionFactory focf) { return FOStorePMF.doEncrypt(focf.password); }
+ public String getNonDefault(FOStoreConnectionFactory focf) { return FOStorePMF.doEncrypt(focf.password); }
+ public String getDefault() {return null;}
+ public void set(FOStoreConnectionFactory focf, String s) { focf.setPassword(FOStorePMF.doDecrypt(s)); }
+ });
+ CFpropsAccessors.put(
+ "org.apache.jdo.FOStoreConnectionFactory.option.DriverName", // NOI18N
+ new CFAccessor() {
+ public String get(FOStoreConnectionFactory focf) { return focf.getDriverName(); }
+ public String getNonDefault(FOStoreConnectionFactory focf) { return focf.getDriverName(); }
+ public String getDefault() {return null;}
+ public void set(FOStoreConnectionFactory focf, String s) { focf.setDriverName(s); }
+ });
+ CFpropsAccessors.put(
+ "org.apache.jdo.FOStoreConnectionFactory.option.LoginTimeout", // NOI18N
+ new CFAccessor() {
+ public String get(FOStoreConnectionFactory focf) { return focf.getDriverName(); }
+ public String getNonDefault(FOStoreConnectionFactory focf) { return focf.getDriverName(); }
+ public String getDefault() {return null;}
+ public void set(FOStoreConnectionFactory focf, String s) { focf.setDriverName(s); }
+ });
+ CFpropsAccessors.put(
+ "javax.jdo.FOStoreConnectionFactory.option.MinPool", // NOI18N
+ new CFAccessor() {
+ public String get(FOStoreConnectionFactory focf) { return Integer.toString(focf.getMinPool()); }
+ public String getNonDefault(FOStoreConnectionFactory focf) { return (focf.getMinPool()==1)?null:Integer.toString(focf.getMinPool()); }
+ public String getDefault() { return "1"; } // NOI18N
+ public void set(FOStoreConnectionFactory focf, String s) { focf.setMinPool(toInt(s)); }
+ });
+ CFpropsAccessors.put(
+ "javax.jdo.FOStoreConnectionFactory.option.MaxPool", // NOI18N
+ new CFAccessor() {
+ public String get(FOStoreConnectionFactory focf) { return Integer.toString(focf.getMaxPool()); }
+ public String getNonDefault(FOStoreConnectionFactory focf) { return (focf.getMaxPool()==1)?null:Integer.toString(focf.getMaxPool()); }
+ public String getDefault() { return "1"; } // NOI18N
+ public void set(FOStoreConnectionFactory focf, String s) { focf.setMaxPool(toInt(s)); }
+ });
+ CFpropsAccessors.put(
+ "javax.jdo.FOStoreConnectionFactory.option.MsWait", // NOI18N
+ new CFAccessor() {
+ public String get(FOStoreConnectionFactory focf) { return Integer.toString(focf.getMsWait()); }
+ public String getNonDefault(FOStoreConnectionFactory focf) { return (focf.getMsWait()==0)?null:Integer.toString(focf.getMsWait()); }
+ public String getDefault() { return "0"; } // NOI18N
+ public void set(FOStoreConnectionFactory focf, String s) { focf.setMsWait(toInt(s)); }
+ });
+ CFpropsAccessors.put(
+ "javax.jdo.FOStoreConnectionFactory.option.Create", // NOI18N
+ new CFAccessor() {
+ public String get(FOStoreConnectionFactory focf) { return new Boolean(focf.getCreate()).toString(); }
+ public String getNonDefault(FOStoreConnectionFactory focf) { return (!focf.getCreate())?null:"true"; } // NOI18N
+ public String getDefault() { return "false"; } // NOI18N
+ public void set(FOStoreConnectionFactory focf, String s) { focf.setCreate(Boolean.valueOf(s).booleanValue()); }
+ });
+ }
+ }
+ }
+
+ /**
+ * It should *never* be the case that our translation process encounters
+ * a NumberFormatException. If so, tell the user in the JDO-approved
+ * manner.
+ */
+ private static int toInt(String s) {
+ int rc = 0;
+ try {
+ rc = new Integer(s).intValue();
+ } catch (NumberFormatException ex) {
+ throw new JDOFatalInternalException(
+ msg.msg("ERR_Badformat")); // NOI18N
+ }
+ return rc;
+ }
+
+ /**
+ * Sets properties as per the property values in the connection factory.
+ * For each CFAccessor in the given HashMap, gets the corresponding value
+ * from the FOStoreConnectionFactory and puts it in the given
+ * Properties object.
+ */
+ void setProperties(Properties p) {
+ Set s = CFpropsAccessors.entrySet();
+ for (Iterator i = s.iterator(); i.hasNext();) {
+ Map.Entry e = (Map.Entry)i.next();
+ String key = (String)e.getKey();
+ CFAccessor a = (CFAccessor)e.getValue();
+ String value = (String)a.getNonDefault(this);
+ if (null != value) {
+ p.put(key, value);
+ }
+ }
+ }
+
+ /**
+ * Configures a FOStoreConnectionFactory from the given Properties.
+ * For each Accessor in the given HashMap, gets the corresponding value
+ * from the Properties and sets that value in the PMF.
+ * This is public so that a test program can create a
+ * FOSToreConnectionFactory, and configure it from a Properties object.
+ */
+ public void setFromProperties(Properties p) {
+ Set s = CFpropsAccessors.entrySet();
+ for (Iterator i = s.iterator(); i.hasNext();) {
+ Map.Entry e = (Map.Entry)i.next();
+ String key = (String)e.getKey();
+ String value = p.getProperty(key);
+ if (null != value) {
+ CFAccessor a = (CFAccessor)e.getValue();
+ if (logger.isDebugEnabled()) {
+ logger.debug("FOStoreConnectionFactory setting property: " + key + " to: " + value); // NOI18N
+ }
+ a.set(this, value);
+ }
+ }
+ }
+
+ /**
+ * Returns true if this connection factory has been configured with a URL.
+ */
+ public boolean isConfigured() {
+ if (logger.isDebugEnabled())
+ logger.debug("FOStoreConnectionFactory url is: " + url); // NOI18N
+ return (url != null);
+ }
+
+ public String toString() {
+ return "" + // NOI18N
+ "FOCF.url: " + url + "\n" + // NOI18N
+ "FOCF.userName: " + userName + "\n" + // NOI18N
+ "FOCF.password: " + password + "\n" + // NOI18N
+ "FOCF.driverName: " + driverName + "\n" + // NOI18N
+ "FOCF.loginTimeout: " + loginTimeout; // NOI18N
+ }
+}
Added: incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/fostore/FOStoreConnectionId.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/fostore/FOStoreConnectionId.java?view=auto&rev=158176
==============================================================================
--- incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/fostore/FOStoreConnectionId.java (added)
+++ incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/fostore/FOStoreConnectionId.java Fri Mar 18 17:02:29 2005
@@ -0,0 +1,180 @@
+/*
+ * 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.
+ */
+
+/*
+ * FOStoreConnectionId.java
+ *
+ * Created on June 15, 2001, 1:30 PM
+ */
+
+package org.apache.jdo.impl.fostore;
+
+/**
+ * Represents the information required to connect to a database.
+ * @author Craig Russell
+ * @version 1.0
+ */
+class FOStoreConnectionId {
+
+ /** The URL of this connection. Must not be null.
+ */
+ private String url;
+
+ /** The user id of this connection. May be null.
+ */
+ private String user;
+
+ /** The password of this connection. May be null.
+ */
+ private String password;
+
+ /** The flag telling whether to create.
+ */
+ private boolean create;
+
+ /** Creates new FOStoreConnectionId.
+ * @param url the URL of the connection.
+ * @param user the user id of the connection.
+ * @param password the password of the connection.
+ * @param create the flag whether to create the database.
+ */
+ public FOStoreConnectionId(String url, String user, String password, boolean create) {
+ if (url == null) {
+ throw new NullPointerException();
+ }
+ this.url = url;
+ this.user = user;
+ this.password = password;
+ this.create = create;
+ }
+
+
+ /** Creates new FOStoreConnectionId.
+ * @param url the URL of the connection.
+ * @param user the user id of the connection.
+ * @param password the password of the connection.
+ */
+ public FOStoreConnectionId(String url, String user, String password) {
+ if (url == null) {
+ throw new NullPointerException();
+ }
+ this.url = url;
+ this.user = user;
+ this.password = password;
+ this.create = false;
+ }
+
+ public void setUrl (String url) {
+ if (url == null) {
+ throw new NullPointerException();
+ }
+ this.url = url;
+ }
+
+ public String getUrl () {
+ return url;
+ }
+
+ public void setUser (String user) {
+ this.user = user;
+ }
+
+ public String getUser() {
+ return user;
+ }
+
+ public void setPassword (String password) {
+ this.password = password;
+ }
+
+ public String getPassword () {
+ return password;
+ }
+
+ public void setCreate (boolean create) {
+ this.create = create;
+ }
+
+ public boolean getCreate() {
+ return create;
+ }
+
+ /** Combine the hashCodes of URL, user, and password.
+ * @return the combined hashCode.
+ * Note that the create flag is not part of the hashCode.
+ */
+ public int hashCode () {
+ int urlHashCode = url.hashCode();
+ int userHashCode = user==null?0:user.hashCode();
+ int passwordHashCode = password==null?0:password.hashCode();
+ return urlHashCode + userHashCode + passwordHashCode;
+ }
+
+ /** Returns true if this represents the same URL,
+ * user, and password as the other.
+ * @param other another connection id.
+ * @return true if this represents the same URL,
+ * user, and password as the other.
+ * Note that the create flag is not part of the identity.
+ */
+ public boolean equals (Object other) {
+ if (this.getClass() != other.getClass()) return false;
+ FOStoreConnectionId foci = (FOStoreConnectionId) other;
+ return this.url.equals(foci.url)
+ & ((this.user!=null&foci.user!=null)?this.user.equals(foci.user):this.user==foci.user)
+ & ((this.password!=null&foci.password!=null)?this.password.equals(foci.password):this.password==foci.password);
+ }
+
+ // XXX this 'main' really belongs in a test class...
+ public static void main (String argv[]) {
+ FOStoreConnectionId id0 = new FOStoreConnectionId("url", null, null); // NOI18N
+ FOStoreConnectionId id1 = new FOStoreConnectionId("url", "1", null); // NOI18N
+ FOStoreConnectionId id2 = new FOStoreConnectionId("url", null, "2"); // NOI18N
+ FOStoreConnectionId id3 = new FOStoreConnectionId("url", "1", "2"); // NOI18N
+ FOStoreConnectionId id4 = new FOStoreConnectionId("url2", "1", "2"); // NOI18N
+ FOStoreConnectionId id5 = new FOStoreConnectionId("url2", "1", "2", true); // NOI18N
+ try {
+ FOStoreConnectionId id = new FOStoreConnectionId (null, null, null);
+ System.out.println ("Failure."); // NOI18N
+ return;
+ } catch (NullPointerException npe) {
+ // good catch
+ } catch (Throwable t) {
+ System.out.println ("Failure."); // NOI18N
+ return;
+ }
+ if (!id0.equals(id1)
+ & (!id0.equals(id2))
+ & (!id0.equals(id3))
+ & (!id0.equals(id4))
+ & (!id1.equals(id0))
+ & (!id2.equals(id0))
+ & (!id3.equals(id0))
+ & (!id4.equals(id0))
+ & (id0.equals(id0))
+ & (id1.equals(id1))
+ & (id2.equals(id2))
+ & (id3.equals(id3))
+ & (id4.equals(id4))
+ & (id4.equals(id5))
+ ) {
+ System.out.println ("Success."); // NOI18N
+ } else {
+ System.out.println ("Failure."); // NOI18N
+ }
+ }
+
+}
Added: incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/fostore/FOStoreConnector.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/fostore/FOStoreConnector.java?view=auto&rev=158176
==============================================================================
--- incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/fostore/FOStoreConnector.java (added)
+++ incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/fostore/FOStoreConnector.java Fri Mar 18 17:02:29 2005
@@ -0,0 +1,277 @@
+/*
+ * 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.IOException;
+
+import javax.jdo.JDOException;
+import javax.jdo.JDODataStoreException;
+import javax.jdo.JDOFatalInternalException;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.apache.jdo.store.Connector;
+import org.apache.jdo.util.I18NHelper;
+
+/**
+* FOStoreConnector represents a connection to the FOStoreDatabase.
+*
+* @author Dave Bristor
+*/
+class FOStoreConnector implements Connector {
+ /** @see org.apache.jdo.store.Connector#setRollbackOnly */
+ private boolean rollbackOnly = false;
+
+ /** 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
+
+ /**
+ * Message in which this Connector buffers requests for the store.
+ */
+ private final Message message;
+
+ /**
+ * Datasource to which this Connector writes its Message.
+ */
+ private final FOStorePMF pmf;
+
+ /**
+ * Connection for interacting with store.
+ */
+ FOStoreClientConnection connection = null;
+
+ /**
+ * True if we can release this connection after flushing. By default we
+ * can; affected by transactions beginning and ending and their types.
+ */
+ private boolean okToReleaseConnection = true;
+
+ /** True if flush is in progress. */
+ private boolean busy = false;
+
+ FOStoreConnector(FOStorePMF pmf) {
+ this.pmf = pmf;
+ this.message = new Message(this);
+ }
+
+ //
+ // Implement Connector
+ //
+
+ /**
+ * @see org.apache.jdo.store.Connector#begin
+ */
+ public void begin(boolean optimistic) {
+ assertNotRollbackOnly();
+
+ // If transaction is optimistic, then we can release the connection as
+ // soon as data is flushed. If it's datastore, then we can't release
+ // the connection until after commit/rollback.
+ this.okToReleaseConnection = optimistic;
+
+ if (logger.isDebugEnabled()) {
+ logger.debug(
+ "FOConnector.begin: okToReleaseConnection=" + // NOI18N
+ okToReleaseConnection);
+ }
+
+ try {
+ RequestFactory rf = pmf.getRequestFactory();
+ BeginTxRequest request =
+ rf.getBeginTxRequest(message, pmf, optimistic);
+ request.doRequest();
+ } catch (IOException ex) {
+ throw new FOStoreFatalIOException(
+ getClass(), "update", ex); // NOI18N
+ } catch (JDOException ex) {
+ throw ex;
+ } catch (Exception ex) {
+ throw new FOStoreFatalInternalException(
+ getClass(), "update", ex); // NOI18N
+ }
+ }
+
+ /**
+ * @see org.apache.jdo.store.Connector#beforeCompletion
+ */
+ public void beforeCompletion() {
+ assertNotRollbackOnly();
+
+ // Nothing to do.
+ }
+
+ /**
+ * Get a connection, process the message by using that connection to
+ * interact with the database, read back the reply, release the
+ connection.
+ * @see org.apache.jdo.store.Connector#flush
+ */
+ public void flush() {
+ assertNotRollbackOnly();
+ assertNotBusy("flush"); // NOI18N
+ busy = true;
+
+ try {
+
+ if (logger.isDebugEnabled()) {
+ logger.debug(
+ "FOConnector.flush: " + // NOI18N
+ "okToReleaseConnection=" + okToReleaseConnection + // NOI18N
+ ", connection=" + connection); // NOI18N
+ }
+
+ if (message.hasRequests()) {
+ if (logger.isTraceEnabled()) message.dump();
+
+ if (connection == null) {
+ FOStoreConnectionFactory cf =
+ (FOStoreConnectionFactory)pmf.getConnectionFactory();
+ connection = (FOStoreClientConnection)cf.getConnection();
+ }
+
+ // Now send the message and process it in the store
+ try {
+ message.processInStore(connection, okToReleaseConnection);
+ } finally {
+ if (okToReleaseConnection) {
+ connection = null;
+ }
+ }
+ }
+ } finally {
+ busy = false;
+ }
+ }
+
+ /**
+ * Add a CommitRequest to the connector's message, and send it to the
+ * store. Then close the connection.
+ * @see org.apache.jdo.store.Connector#commit
+ */
+ public synchronized void commit() {
+ assertNotRollbackOnly();
+ assertNotBusy("commit"); // NOI18N
+
+ try {
+ if (logger.isDebugEnabled()) {
+ logger.debug("FOConnector.commit"); // NOI18N
+ }
+
+ RequestFactory rf = pmf.getRequestFactory();
+ CommitRequest request = rf.getCommitRequest(message, pmf);
+
+ request.doRequest();
+ } catch (IOException ex) {
+ throw new FOStoreFatalIOException(
+ this.getClass(), "commit", ex); // NOI18N
+ } catch (JDOException ex) {
+ throw ex;
+ } catch (Exception ex) {
+ throw new FOStoreFatalInternalException(
+ getClass(), "commit", ex); // NOI18N
+ } finally {
+ // Now that we've commited, we can release the connection.
+ okToReleaseConnection = true;
+ flush();
+ }
+ }
+
+ /**
+ * If rollbackOnly is set, then the store has already done a
+ * rollback, so we don't do one now (but neither do we throw an
+ * exception, as do other methds).
+ * @see org.apache.jdo.store.Connector#rollback
+ * @see org.apache.jdo.impl.fostore.ReplyHandler#processReplies
+ */
+ public synchronized void rollback() {
+ assertNotBusy("rollback"); // NOI18N
+ if (logger.isDebugEnabled()) {
+ logger.debug(
+ "FOConnector.rollback, RBO=" + rollbackOnly); // NOI18N
+ }
+
+ if (! rollbackOnly) {
+ try {
+ RequestFactory rf = pmf.getRequestFactory();
+ RollbackRequest request = rf.getRollbackRequest(message, pmf);
+
+ request.doRequest();
+ } catch (IOException ex) {
+ throw new FOStoreFatalIOException(
+ this.getClass(), "rollback", ex); // NOI18N
+ } catch (JDOException ex) {
+ throw ex;
+ } catch (Exception ex) {
+ throw new FOStoreFatalInternalException(
+ getClass(), "rollback", ex); // NOI18N
+ } finally {
+ // Now that we've rolled back, we can release the connection.
+ okToReleaseConnection = true;
+ flush();
+ }
+ }
+ }
+
+ /**
+ * @see org.apache.jdo.store.Connector#setRollbackOnly
+ */
+ public void setRollbackOnly() {
+ rollbackOnly = true;
+ }
+
+ /**
+ * @see org.apache.jdo.store.Connector#getRollbackOnly
+ */
+ public boolean getRollbackOnly() {
+ return rollbackOnly;
+ }
+
+ //
+ // Implementation
+ //
+
+ /**
+ * Provides the Message which this this connector uses to send data to the
+ * store.
+ */
+ Message getMessage() {
+ assertNotRollbackOnly();
+ assertNotBusy("getMessage"); // NOI18N
+
+ return message;
+ }
+
+ private void assertNotRollbackOnly() {
+ if (rollbackOnly) {
+ throw new JDODataStoreException(
+ msg.msg("EXC_RollbackOnly")); // NOI18N
+ }
+ }
+
+ private void assertNotBusy(String methodName) {
+ if (busy) {
+ throw new FOStoreFatalInternalException(
+ getClass(), methodName,
+ msg.msg("EXC_Busy")); // NOI18N
+ }
+ }
+}
Added: incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/fostore/FOStoreDatabase.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/fostore/FOStoreDatabase.java?view=auto&rev=158176
==============================================================================
--- incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/fostore/FOStoreDatabase.java (added)
+++ incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/fostore/FOStoreDatabase.java Fri Mar 18 17:02:29 2005
@@ -0,0 +1,574 @@
+/*
+ * 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.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.InputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.File;
+import java.security.AccessController;
+import java.security.PrivilegedExceptionAction;
+import java.security.PrivilegedActionException;
+import java.util.Set;
+import java.util.HashMap;
+
+import javax.jdo.JDOFatalUserException;
+import javax.jdo.JDOFatalException;
+import javax.jdo.JDOFatalDataStoreException;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.apache.jdo.util.I18NHelper;
+import org.apache.jdo.util.Pool;
+import org.netbeans.mdr.persistence.Storage;
+import org.netbeans.mdr.persistence.SinglevaluedIndex;
+import org.netbeans.mdr.persistence.StorageBadRequestException;
+import org.netbeans.mdr.persistence.StorageException;
+import org.netbeans.mdr.persistence.Streamable;
+
+/**
+* File/Object Store Database, using an underlying Btree implementation.
+*
+* @author Dave Bristor
+*/
+class FOStoreDatabase {
+
+ /** We manage a map of pools of databases by database name.
+ */
+ private static final HashMap databaseMap = new HashMap();
+
+ private static final int poolSize = 1;
+
+ // We delegate all calls to this storage. Not final, because for
+ // rollback's sake we have to close and then make a new storage.
+ private FOStoreBtreeStorage storage;
+
+ // Map from provisional IDs to real, datastore-created, durable IDs.
+ //
+ // XXX TBD Remote: Provisional CLID's are per client (PMF).
+ // That is because each client will independently generate its
+ // own set of provisional ID's. One way to manage this might be for
+ // each client to send a "hello" message when it first connects, with
+ // something like it's IP address and process id. Future communications
+ // from that same client will contain that same info. A "goodbye" message
+ // would be nice, too, so that the store can remove any tables that will
+ // not ever be used again.
+ private final HashMap provisionalCLIDs = new HashMap();
+
+ // Same as above, but for OIDs.
+ private final HashMap provisionalOIDs = new HashMap();
+
+ /** Count the number of connections open on this database. When the last
+ * connection closes, then really close the database.
+ */
+ private int openConnections = 0;
+
+ private DBInfo dbInfo = null;
+ /** Pool for this database.
+ */
+ private Pool pool = null;
+
+ /** 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
+
+ /** Find an open database of the given name. If it is not already open,
+ * open it and put it into the pool.
+ */
+ public synchronized static FOStoreDatabase getDatabase (String dbname,
+ boolean create)
+ throws InterruptedException, FOStoreDatabaseException {
+ Pool pool = (Pool) databaseMap.get(dbname);
+ FOStoreDatabase db = null;
+ if (pool == null) {
+ try {
+ db = new FOStoreDatabase (dbname, create);
+ } catch (FOStoreDatabaseException fode) {
+ if (logger.isDebugEnabled()) {
+ logger.debug(
+ "FODB:getDatabase exception for new database " + // NOI18N
+ dbname + " create: " + create); // NOI18N
+ }
+ throw (fode);
+ }
+ pool = new Pool (poolSize);
+ databaseMap.put (dbname, pool);
+ pool.put (db);
+ db.setPool(pool);
+ }
+ if (logger.isDebugEnabled()) {
+ logger.debug("FODB:getDatabase found pool for database " + dbname); // NOI18N
+ }
+ db = (FOStoreDatabase) pool.get();
+ return db;
+ }
+
+ /** Release the database for other connections to use.
+ */
+ public synchronized static void releaseDatabase (FOStoreDatabase db)
+ throws InterruptedException {
+
+ db.pool.put (db);
+ }
+
+ /**
+ * Create an FODatabase and create/open the files.
+ * @param name name of database, which is used to name the files
+ * @param isNew true if the database is being created
+ */
+ FOStoreDatabase(String name, boolean isNew)
+ throws FOStoreDatabaseException {
+ // first verify that the directory exists
+ // if not, there is no way to continue
+ // Note, the filename might include a mixture of \ and / as
+ // path separator, make them all / for the lookup
+ int slashIndex = name.replace('\\', '/').lastIndexOf('/');
+ if (slashIndex != -1) { // at least one / in pathname
+ String dirName = name.substring(0, slashIndex);
+ File dir = new File(dirName); // NOI18N
+ if (!existsFile(dir)) {
+ throw new JDOFatalDataStoreException (
+ msg.msg("ERR_DirectoryDoesNotExist", name)); // NOI18N
+ }
+ }
+ // XXX the DBInfo is not a singleton; change this code
+ // and DBInfo to support multiple Databases in one VM.
+ if (isNew) {
+ // We must remove a database if one does exist. This means delete
+ // both the .btd and .btx files.
+ String extensions[] = {"btd", "btx"}; // NOI18N
+ boolean found = false;
+ for (int i = 0; i < extensions.length; i++) {
+ File f = new File(name + "." + extensions[i]); // NOI18N
+ if (existsFile(f)) {
+ if (! found) {
+ if (logger.isDebugEnabled()) {
+ logger.debug("FODB: Deleting existing database " +
+ name); // NOI18N
+ }
+ found = true;
+ }
+ deleteFile(f);
+ }
+ }
+ storage = createBtreeStorage(name, true);
+ dbInfo = new DBInfo(this);
+ dbInfo.store();
+ commitChanges();
+ if (logger.isDebugEnabled()) {
+ logger.debug("FODB: Created database " + name); // NOI18N
+ }
+ } else {
+ storage = createBtreeStorage(name, false);
+ dbInfo = DBInfo.get(this);
+ if (logger.isDebugEnabled()) {
+ logger.debug(
+ "FODB: Opened existing database " + name); // NOI18N
+ }
+ }
+ }
+
+ /** Verify that this user is authorized to use this database.
+ */
+ public void verifyUserPassword (String user, long timestamp, byte[] secret) {
+ // XXX look up Authentication objects and verify this user is authorized.
+ addConnection();
+ }
+
+ /** Get the DBInfo for this database.
+ */
+ public DBInfo getDBInfo() {
+ return dbInfo;
+ }
+
+ /** Associates the specified value with the specified key in this index.
+ * @return true if there was an item in this index that was associated
+ * with the key prior to this call
+ * @param key
+ * @param value
+ * @throws FOStoreDatabaseException
+ */
+ public boolean put(OID key, Object value) throws FOStoreDatabaseException {
+ try {
+ Object keyValue = key.keyValue(storage);
+// Uncomment the next lines to simulate a fatal error during login.
+// if (null != keyValue)
+// throw new NullPointerException("fodb: NPE on purpose"); // YYY
+ return storage.getPrimaryIndex().put(keyValue, value);
+ } catch (StorageException ex) {
+ throw new FOStoreDatabaseException(ex);
+ }
+ }
+
+ /** Replaces the original value associated with the specified key in this
+ * index with new value. If no value was associated with this key prior
+ * to this call StorageBadRequestException is thrown.
+ * @param key
+ * @param value
+ * @throws FOStoreDatabaseException
+ */
+ public void replace(OID key, Object value)
+ throws FOStoreDatabaseException {
+
+ try {
+ Object keyValue = key.keyValue(storage);
+ storage.getPrimaryIndex().replace(keyValue, value);
+ } catch (StorageException ex) {
+ throw new FOStoreDatabaseException(ex);
+ }
+ }
+
+ /** Returns the value to which this index maps the specified key.
+ * StorageBadRequestException is thrown if there is no value for the key.
+ * @return value associated with specified key
+ * @param key
+ * @throws FOStoreDatabaseException
+ */
+ public Object get(OID key)
+ throws FOStoreDatabaseException {
+
+ try {
+ Object keyValue = key.keyValue(storage);
+ return storage.getPrimaryIndex().get(keyValue);
+ } catch (StorageException ex) {
+ throw new FOStoreDatabaseException(ex);
+ }
+ }
+
+ /** Returns the value to which this index maps the specified key
+ * or null if there is no value for this key.
+ * @return value associated with specified key or null
+ * @param key
+ * @throws FOStoreDatabaseException
+ */
+ public Object getIfExists (OID key) throws FOStoreDatabaseException {
+ try {
+ Object keyValue = key.keyValue(storage);
+ return storage.getPrimaryIndex().getIfExists(keyValue);
+ } catch (StorageException ex) {
+ throw new FOStoreDatabaseException(ex);
+ }
+ }
+
+ /** Returns the unique name of the index in the Storage.
+ * @return The name of this index.
+ */
+ public String getName() {
+ return storage.getName();
+ }
+
+ /** Returns a set view of the keys contained in this index.
+ * Returned set is read only and may not be modified.
+ * @return keys contained in this index
+ * @throws FOStoreDatabaseException
+ */
+ public Set keySet() throws FOStoreDatabaseException {
+ try {
+ return storage.getPrimaryIndex().keySet();
+ } catch (StorageException ex) {
+ throw new FOStoreDatabaseException(ex);
+ }
+ }
+
+ /** Adds the specified value to values associated in this index with the
+ * specified key. If the index puts limit on number of values associated
+ * with one key and adding value would break this limit, it thorows
+ * StorageBadRequestException.
+ * @param key
+ * @param value
+ * @throws FOStoreDatabaseException
+ */
+ public void add(OID key, Object value) throws FOStoreDatabaseException {
+ try {
+ Object keyValue = key.keyValue(storage);
+ storage.getPrimaryIndex().add(keyValue, value);
+ } catch (StorageException ex) {
+ throw new FOStoreDatabaseException(ex);
+ }
+ }
+
+ /** Removes all values assosiated in the index with specified key.
+ * @return true if this index changed as a result of this call
+ * @param key
+ * @throws FOStoreDatabaseException
+ */
+ public boolean remove (OID key) throws FOStoreDatabaseException {
+ try {
+ Object keyValue = key.keyValue(storage);
+ return storage.getPrimaryIndex().remove(keyValue);
+ } catch (StorageException ex) {
+ throw new FOStoreDatabaseException(ex);
+ }
+ }
+
+ public void commitChanges() throws FOStoreDatabaseException {
+ if (logger.isDebugEnabled()) logger.debug("FODB.commitChanges"); // NOI18N
+
+ // Need to have privileges to perform this operation.
+ final FOStoreBtreeStorage storage1 = storage;
+ try {
+ AccessController.doPrivileged (
+ new PrivilegedExceptionAction () {
+ public Object run () throws StorageException {
+ storage1.commitChanges();
+ return null;
+ }
+ }
+ );
+ } catch (PrivilegedActionException ex) {
+ throw new FOStoreDatabaseException(
+ (StorageException)ex.getException());
+ }
+
+ }
+
+ /** Increment the openConnections to allow proper close when the last
+ * connection closes the database.
+ */
+ public synchronized void addConnection() {
+ openConnections++;
+ }
+
+ /** Decrement the open connections counter and close the database when
+ * it reaches zero.
+ */
+ public synchronized void close() throws FOStoreDatabaseException {
+ if (--openConnections > 0) {
+ if (logger.isDebugEnabled()) {
+ logger.debug("FODB.close: " + getName() + // NOI18N
+ " count still " + openConnections); // NOI18N
+ }
+ try {
+ releaseDatabase(this);
+ } catch (InterruptedException ex) {
+ // ignore
+ }
+ return;
+ }
+ // count has reached zero. Now really close the database.
+ if (logger.isDebugEnabled()) {
+ logger.debug(
+ "FODB.close: count reached zero." + getName()); // NOI18N
+ }
+
+ closeBtreeStorage(storage);
+ databaseMap.remove(getName());
+ pool = null;
+ }
+
+ public static synchronized void closeDatabase (String dbname)
+ throws FOStoreDatabaseException, InterruptedException {
+
+ Pool pool = (Pool) databaseMap.get(dbname);
+ if (pool == null) {
+ throw new JDOFatalDataStoreException (
+ msg.msg("ERR_CloseDatabase", dbname)); // NOI18N
+ }
+ FOStoreDatabase fodb = (FOStoreDatabase) pool.get();
+ fodb.close();
+ }
+
+ public void rollbackChanges() throws FOStoreDatabaseException {
+ if (logger.isDebugEnabled()) logger.debug("FODB.rollbackChanges"); // NOI18N
+
+ // The btree doesn't *really* rollback. But closing it and
+ // getting a new one works fine.
+ final String name = storage.getName();
+ closeBtreeStorage(storage);
+
+ storage = createBtreeStorage(name, false);
+ dbInfo = DBInfo.get(this);
+ }
+
+ static Block createBlock(FOStoreInput in, int length) {
+ return new Block(in, length);
+ }
+
+ /**
+ * Establishes a mapping in this database from provisional to real
+ * CLIDs. The mapping lasts as long as the server is running, that is, it
+ * is not durable.
+ * @param pCLID A provisional CLID.
+ * @param rCLID The non-provisional, datastore CLID corresponding to
+ * provCLID.
+ * @exception JDOFatalException Thrown if the given CLID is not provisional.
+ */
+ // If you change this code, please see also method of same name in FOStorePMF.
+ public synchronized void mapProvisionalCLIDToReal(
+ CLID pCLID, CLID rCLID) {
+
+ if (! pCLID.isProvisional()) {
+ throw new JDOFatalException(msg.msg("ERR_CLIDNotProv", pCLID)); // NOI18N
+ }
+ if (null == provisionalCLIDs.get(pCLID)) {
+ provisionalCLIDs.put(pCLID, rCLID);
+ }
+ if (logger.isDebugEnabled()) {
+ logger.debug(
+ "FODB.mapProvCLIDToReal: " + pCLID + " -> " + rCLID); // NOI18N
+ }
+ }
+
+ /**
+ * Provides a datastore CLID corresponding to the given provisional CLID.
+ * @param provCLID A provisional CLID for which there
+ * @return A non-provisional, datastore CLID corresponding to provCLID, or
+ * null if the given provCLID is not mapped to a datastore CLID.
+ * @exception JDOFatalException Thrown if the given CLID is not provisional.
+ */
+ // If you change this code, see method of same name in FOStorePMF.
+ public CLID getRealCLIDFromProvisional(CLID provCLID) {
+ if (! provCLID.isProvisional()) {
+ throw new JDOFatalException(msg.msg("ERR_CLIDNotProv", provCLID)); // NOI18N
+ }
+ return (CLID)provisionalCLIDs.get(provCLID);
+ }
+
+ /**
+ * Establishes a mapping in this database from provisional to real
+ * OIDs. The mapping lasts as long as the server is running, that is, it
+ * is not durable.
+ * @param pOID A provisional OID.
+ * @param rOID The non-provisional, datastore OID corresponding to
+ * pOID.
+ * @exception JDOFatalException Thrown if the given OID is not provisional.
+ */
+ // If you change this code, please see also method of same name in FOStorePMF.
+ synchronized void mapProvisionalOIDToReal(
+ OID pOID, OID rOID) {
+
+ if (! pOID.isProvisional()) {
+ throw new JDOFatalException(msg.msg("ERR_OIDNotProv", pOID)); // NOI18N
+ }
+ if (null == provisionalOIDs.get(pOID)) {
+ provisionalOIDs.put(pOID, rOID);
+ }
+ }
+
+ /**
+ * Provides a datastore OID corresponding to the given provisional OID.
+ * @param pOID A provisional OID for which there
+ * @return A non-provisional, datastore OID corresponding to pOID or null
+ * if the given pOID is not mapped to a datastore OID.
+ * @exception JDOFatalException Thrown if the given OID is not provisional.
+ */
+ // If you change this code, see method of same name in FOStorePMF.
+ OID getRealOIDFromProvisional(OID pOID) {
+ if (! pOID.isProvisional()) {
+ throw new JDOFatalException(msg.msg("ERR_OIDNotProv", pOID)); // NOI18N
+ }
+ return (OID)provisionalOIDs.get(pOID);
+ }
+
+ private void setPool (Pool pool) {
+ this.pool = pool;
+ }
+
+ /**
+ * Helper method to create a BtreeStorage. This method excutes the
+ * storage operation in a doPrivileged block and handles possible
+ * exceptions.
+ * @param name name of database, which is used to name the files
+ * @param isNew true if the database is being created
+ * @return new database
+ * @exception FOStoreDatabaseException wraps a StorageException thrown
+ * by the create call.
+ * @exception JDOFatalUserException wraps a possible SecurityException.
+ */
+ private FOStoreBtreeStorage createBtreeStorage(final String name,
+ final boolean isNew)
+ throws FOStoreDatabaseException, JDOFatalUserException
+ {
+ try {
+ return (FOStoreBtreeStorage) AccessController.doPrivileged (
+ new PrivilegedExceptionAction () {
+ public Object run () throws StorageException {
+ return new FOStoreBtreeStorage(name, isNew);
+ }
+ });
+ } catch (SecurityException ex) {
+ throw new JDOFatalUserException(msg.msg(
+ "EXC_SecurityExceptionOnCreateBtreeStorage"), ex); //NOI18N
+ } catch (PrivilegedActionException ex) {
+ throw new FOStoreDatabaseException(
+ (StorageException)ex.getException());
+ }
+ }
+
+ /**
+ * Helper method to close a BtreeStorage.
+ * @param storage the database to be closed
+ * @exception FOStoreDatabaseException wraps a StorageException thrown
+ * by the close call.
+ */
+ private void closeBtreeStorage(final FOStoreBtreeStorage storage)
+ throws FOStoreDatabaseException
+ {
+ try {
+ AccessController.doPrivileged (
+ new PrivilegedExceptionAction () {
+ public Object run () throws StorageException {
+ storage.shutDown();
+ storage.close();
+ return null;
+ }
+ });
+ } catch (SecurityException ex) {
+ throw new JDOFatalUserException(msg.msg(
+ "EXC_SecurityExceptionOnCloseBtreeStorage"), ex); //NOI18N
+ } catch (PrivilegedActionException ex) {
+ throw new FOStoreDatabaseException(
+ (StorageException)ex.getException());
+ }
+ }
+
+ /**
+ * Helper method to check whether a file exists. This method delegates
+ * to File.exists and handles possible SecurityExceptions.
+ * @param file the file to be checked
+ * @return <code>true</code> if the specified file exists.
+ */
+ private boolean existsFile(File file) {
+ try {
+ return file.exists();
+ } catch (SecurityException ex) {
+ throw new JDOFatalUserException(msg.msg(
+ "EXC_CannotReadFile", file.getName()), ex); //NOI18N
+ }
+ }
+
+ /**
+ * Helper method to delete a file. This method delegates to File.delete
+ * and handles possible SecurityExceptions.
+ * @param file the file to be deleted
+ */
+ private void deleteFile(File file) {
+ try {
+ file.delete();
+ } catch (SecurityException ex) {
+ throw new JDOFatalUserException(msg.msg(
+ "EXC_CannotDeleteFile", file.getName()), ex); //NOI18N
+ }
+ }
+}
Added: incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/fostore/FOStoreDatabaseException.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/fostore/FOStoreDatabaseException.java?view=auto&rev=158176
==============================================================================
--- incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/fostore/FOStoreDatabaseException.java (added)
+++ incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/fostore/FOStoreDatabaseException.java Fri Mar 18 17:02:29 2005
@@ -0,0 +1,56 @@
+/*
+ * 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 org.netbeans.mdr.persistence.StorageException;
+
+/**
+* This provides an insulation layer between BtreeDatabase and FOStore.
+*
+* @author Dave Bristor
+*/
+class FOStoreDatabaseException extends StorageException {
+ private final StorageException ex;
+
+ FOStoreDatabaseException(StorageException ex) {
+ this.ex = ex;
+ }
+
+ public String getLocalizedMessage() {
+ return ex.getLocalizedMessage();
+ }
+
+ public String getMessage() {
+ return ex.getMessage();
+ }
+
+ public void printStackTrace() {
+ ex.printStackTrace();
+ }
+
+ public void printStackTrace(java.io.PrintStream s) {
+ ex.printStackTrace(s);
+ }
+
+ public void printStackTrace(java.io.PrintWriter s) {
+ ex.printStackTrace(s);
+ }
+
+ public String toString() {
+ return ex.toString();
+ }
+}
Added: incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/fostore/FOStoreExtent.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/fostore/FOStoreExtent.java?view=auto&rev=158176
==============================================================================
--- incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/fostore/FOStoreExtent.java (added)
+++ incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/fostore/FOStoreExtent.java Fri Mar 18 17:02:29 2005
@@ -0,0 +1,304 @@
+/*
+ * 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.IOException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+
+import javax.jdo.Extent;
+import javax.jdo.JDOHelper;
+import javax.jdo.JDOException;
+import javax.jdo.JDOUserException;
+import javax.jdo.PersistenceManager;
+import javax.jdo.Transaction;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.apache.jdo.pm.PersistenceManagerInternal;
+import org.apache.jdo.state.StateManagerInternal;
+import org.apache.jdo.util.I18NHelper;
+
+/**
+ * Represents a request to get the extent of a class and possibly its
+ * subclasses.
+ *
+ * @author Dave Bristor
+ */
+//
+// This is client-side code. It does not need to live in the server.
+//
+/**
+ * This is an in-memory extent.
+ */
+class FOStoreExtent implements Extent {
+private final FOStoreConnector connector;
+private final RequestFactory rf;
+
+ /** Iterators requested by user. */
+ private final HashSet iterators = new HashSet();
+
+ /** Class specified by user. */
+ private final Class cls;
+
+ /** If true, extent includes subclasses of user's class. */
+ private final boolean subclasses;
+
+ /** Persistence manager on which getExtent was invoked by user. */
+ private final PersistenceManagerInternal pm;
+
+ /** 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
+
+ FOStoreExtent(Class cls, boolean subclasses,
+ PersistenceManagerInternal pm,
+ RequestFactory rf,
+ FOStoreConnector connector) {
+
+ this.cls = cls;
+ this.subclasses = subclasses;
+ this.pm = pm;
+ this.rf = rf;
+ this.connector = connector;
+ }
+
+ //
+ // Implement Extent
+ //
+
+ /**
+ * @see javax.jdo.Extent#iterator
+ */
+ public Iterator iterator() {
+ pm.assertReadAllowed();
+ Iterator rc = new FOStoreExtentIterator(this);
+ iterators.add(rc);
+ return rc;
+ }
+
+ /**
+ * @see javax.jdo.Extent#hasSubclasses
+ */
+ public boolean hasSubclasses() {
+ return subclasses;
+ }
+
+ /**
+ * @see javax.jdo.Extent#getCandidateClass
+ */
+ public Class getCandidateClass() {
+ return cls;
+ }
+
+ /**
+ * @see javax.jdo.Extent#getPersistenceManager
+ */
+ public PersistenceManager getPersistenceManager() {
+ return pm.getCurrentWrapper();
+ }
+
+ /**
+ * @see javax.jdo.Extent#closeAll
+ */
+ public void closeAll() {
+ for (Iterator i = iterators.iterator(); i.hasNext();) {
+ Iterator extentIterator = (Iterator)i.next();
+ if (logger.isDebugEnabled()) {
+ logger.debug("Extent.closeAll: removing " + extentIterator); // NOI18N
+ }
+ i.remove(); // remove first because close also removes it
+ close(extentIterator);
+ }
+ }
+
+ /**
+ * @see javax.jdo.Extent#close
+ */
+ public void close(Iterator it) {
+ if (it instanceof FOStoreExtentIterator) {
+ FOStoreExtentIterator fit = (FOStoreExtentIterator)it;
+ fit.close();
+ if (iterators.contains(fit)) {
+ if (logger.isDebugEnabled()) {
+ logger.debug("Extent.close: removing " + fit); // NOI18N
+ }
+ // this will be true only if not executing closeAll.
+ iterators.remove(fit);
+ }
+ }
+ }
+
+ /**
+ * Iterates over the elements in a FOStoreExtent.
+ */
+ class FOStoreExtentIterator implements Iterator {
+ /** Instances that have been retrieved from store. */
+ // We have our own copy and do not use those from the enclosing
+ // FOStoreExtent, because we use a GetInstancesRequest to re-fill
+ // the ArrayList if needed.
+ private ArrayList instances;
+ private ArrayList oids;
+ private int maxInstances;
+
+ /** Index into instances. */
+ private int instanceIndex = 0;
+
+ /** Index into oids. */
+ private int oidsIndex = 0;
+
+ /** Index into extent as a whole.*/
+ private int index = 0;
+
+ /** Size of extent (number of instances + number of oids). */
+ private final int size;
+
+ /** If false, then can get next object, otherwise
+ * next() always throws NoSuchElementException and
+ * hasNext() always returns false. */
+ private boolean closed = false;
+
+ private Object nextObject = null;
+
+ FOStoreExtentIterator(FOStoreExtent extent) {
+ try {
+ Message message = connector.getMessage();
+ GetExtentRequest request =
+ rf.getGetExtentRequest(extent, cls, subclasses, message, pm);
+ request.doRequest();
+ connector.flush();
+ instances = request.getInstances();
+ oids = request.getOIDs();
+ maxInstances = request.getMaxInstances();
+ } catch (IOException ex) {
+ throw new FOStoreFatalIOException(
+ getClass(), "init", ex); // NOI18N
+ } catch (JDOException ex) {
+ throw ex;
+ } catch (Exception ex) {
+ throw new FOStoreFatalInternalException(
+ getClass(), "init", ex); // NOI18N
+ }
+
+ Collection insertedInstances = pm.getInsertedInstances();
+ for (Iterator it = insertedInstances.iterator(); it.hasNext();) {
+ Object o = it.next();
+ Class clz = o.getClass();
+ if (cls.equals(clz) || (subclasses && cls.isAssignableFrom(clz))) {
+ instances.add(o);
+ }
+ }
+
+ if (logger.isDebugEnabled()) {
+ logger.debug(
+ "FOStoreExtentIterator.<init>: cls=" + cls.getName() + // NOI18N
+ ", numInstances=" + instances.size()); // NOI18N
+ }
+
+ this.size = instances.size() + oids.size();
+ if (size == 0) {
+ close();
+ }
+ }
+
+ /**
+ * @see java.util.Iterator#hasNext
+ */
+ public boolean hasNext() {
+ // This code advances to the next not deleted
+ // instance, or until the iterator is closed.
+ // Iterator is closed in getNext() if there
+ // are no more instances available. nextObject
+ // is null at the beginning and after close().
+ while (! closed && (nextObject == null ||
+ JDOHelper.isDeleted(nextObject))) {
+ getNext();
+ }
+ return (nextObject != null);
+ }
+
+ /**
+ * @see java.util.Iterator#next
+ */
+ public Object next() {
+ if (nextObject == null && !hasNext()) {
+ throw new NoSuchElementException();
+ }
+
+ Object rc = nextObject;
+ nextObject = null;
+ return rc;
+ }
+
+ /** Get the next instance. Close the iterator if there are
+ * no more instances available.
+ */
+ private void getNext() {
+ if (index < size) {
+ if (instanceIndex >= instances.size()) {
+ if (logger.isDebugEnabled()) {
+ logger.debug(
+ "FOStoreExtentIterator.next get new instances"); // NOI18N
+ }
+ FOStoreStoreManager srm =
+ (FOStoreStoreManager)pm.getStoreManager();
+ instances = srm.getInstances(
+ oids, oidsIndex, maxInstances, pm, cls);
+ oidsIndex += instances.size();
+ if (logger.isDebugEnabled()) {
+ logger.debug(
+ "FOStoreExtent.next got " + // NOI18N
+ instances.size() + " instances"); // NOI18N
+ }
+ instanceIndex = 0;
+ }
+ nextObject = instances.get(instanceIndex);
+ instanceIndex++;
+ index++;
+
+ } else {
+ close();
+ }
+ }
+
+ /**
+ * Always throws UnsupportedOperationException.
+ */
+ public void remove() {
+ throw new UnsupportedOperationException(
+ msg.msg("EXC_RemoveNotSupported")); // NOI18N
+ }
+
+ /**
+ * Disallow getting further objects from this iterator.
+ */
+ void close() {
+ closed = true;
+ instances = null;
+ index = size;
+ nextObject = null;
+ }
+ }
+}
Added: incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/fostore/FOStoreFatalIOException.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/fostore/FOStoreFatalIOException.java?view=auto&rev=158176
==============================================================================
--- incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/fostore/FOStoreFatalIOException.java (added)
+++ incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/fostore/FOStoreFatalIOException.java Fri Mar 18 17:02:29 2005
@@ -0,0 +1,35 @@
+/*
+ * 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;
+
+/**
+* This is an exception which _should_ never be thrown, as it indicates an
+* error in I/O traffic between client and server. It most likely indicates a
+* bug in the implementation.
+*
+* @author Dave Bristor
+*/
+public class FOStoreFatalIOException extends FOStoreFatalInternalException {
+ /**
+ * @param clz Class in which the exception is thrown.
+ * @param methodName Name of the method from which the exception is
+ * thrown.
+ */
+ FOStoreFatalIOException(Class clz, String methodName, Exception nested) {
+ super(clz, methodName, nested);
+ }
+}
Added: incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/fostore/FOStoreFatalInternalException.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/fostore/FOStoreFatalInternalException.java?view=auto&rev=158176
==============================================================================
--- incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/fostore/FOStoreFatalInternalException.java (added)
+++ incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/fostore/FOStoreFatalInternalException.java Fri Mar 18 17:02:29 2005
@@ -0,0 +1,61 @@
+/*
+ * 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 javax.jdo.JDOFatalInternalException;
+
+/**
+* This is an exception which _should_ never be thrown, as it indicates an
+* error in the implementation, such as a bug that has been found.
+*
+* @author Dave Bristor
+*/
+public class FOStoreFatalInternalException extends JDOFatalInternalException {
+ /**
+ * @param clz Class in which the exception is thrown.
+ * @param methodName Name of the method from which the exception is
+ * thrown.
+ * @param msg The exception message.
+ */
+ FOStoreFatalInternalException(Class clz, String methodName, String msg) {
+ super(clz.getName() + "." + methodName + ": " + msg); // NOI18N
+ }
+
+ /**
+ * @param clz Class in which the exception is thrown.
+ * @param methodName Name of the method from which the exception is
+ * thrown.
+ */
+ FOStoreFatalInternalException(Class clz, String methodName,
+ Exception nested) {
+ super(clz.getName() + "." + methodName, // NOI18N
+ new Exception[] {nested}); // NOI18N
+ }
+
+ /**
+ * @param clz Class in which the exception is thrown.
+ * @param methodName Name of the method from which the exception is
+ * thrown.
+ * @param msg The exception message.
+ */
+ FOStoreFatalInternalException(Class clz, String methodName, String msg,
+ Exception nested) {
+
+ super(clz.getName() + "." + methodName + ": " + msg, // NOI18N
+ new Exception[] {nested}); // NOI18N
+ }
+}
Added: incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/fostore/FOStoreInput.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/fostore/FOStoreInput.java?view=auto&rev=158176
==============================================================================
--- incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/fostore/FOStoreInput.java (added)
+++ incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/fostore/FOStoreInput.java Fri Mar 18 17:02:29 2005
@@ -0,0 +1,135 @@
+/*
+ * 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.DataInput;
+import java.io.DataInputStream;
+import java.io.IOException;
+
+import org.apache.jdo.util.I18NHelper;
+
+
+/**
+* Extend ByteArrayInputStream so that we can get ahold of the byte array
+* and current position, and can change the current position.
+*
+* @author Dave Bristor
+*/
+class FOStoreInput extends ByteArrayInputStream implements DataInput {
+ private final DataInputStream dis;
+
+ /** I18N support. */
+ private static final I18NHelper msg = I18NHelper.getInstance(I18N.NAME);
+
+ FOStoreInput(byte data[], int off, int len) {
+ super(data, off, len);
+ dis = new DataInputStream(this);
+ }
+
+ byte[] getBuf() {
+ return buf;
+ }
+
+ int getPos() {
+ return pos;
+ }
+
+ void setPos(int pos) {
+ if (pos < 0 || pos > buf.length) {
+ throw new FOStoreFatalInternalException(
+ this.getClass(), "setPos", // NOI18N
+ msg.msg("ERR_InvalidSeekPos", // NOI18N
+ new Integer(pos), new Integer(buf.length)));
+ }
+ this.pos = pos;
+ }
+
+ // Advance pos by len, but don't break invariant required by
+ // ByteArrayInputStream (see ByteArrayInputStrea.pos's javadoc).
+ void advance(int len) {
+ if (pos + len <= count) {
+ pos += len;
+ } else {
+ pos = count;
+ }
+ }
+
+ //
+ // Implement DataInput
+ //
+
+ public boolean readBoolean() throws IOException {
+ return dis.readBoolean();
+ }
+
+ public byte readByte() throws IOException {
+ return dis.readByte();
+ }
+
+ public char readChar() throws IOException {
+ return dis.readChar();
+ }
+
+ public double readDouble() throws IOException {
+ return dis.readDouble();
+ }
+
+ public float readFloat() throws IOException {
+ return dis.readFloat();
+ }
+
+ public void readFully(byte[] b) throws IOException {
+ dis.readFully(b);
+ }
+
+ public void readFully(byte[] b, int off, int len) throws IOException {
+ dis.readFully(b, off, len);
+ }
+
+ public int readInt() throws IOException {
+ return dis.readInt();
+ }
+
+ public String readLine() throws IOException {
+ return dis.readLine();
+ }
+
+ public long readLong() throws IOException {
+ return dis.readLong();
+ }
+
+ public short readShort() throws IOException {
+ return dis.readShort();
+ }
+
+ public int readUnsignedByte() throws IOException {
+ return dis.readUnsignedByte();
+ }
+
+ public int readUnsignedShort() throws IOException {
+ return dis.readUnsignedShort();
+ }
+
+ public String readUTF() throws IOException {
+ return dis.readUTF();
+ }
+
+ public int skipBytes(int n) throws IOException {
+ return dis.skipBytes(n);
+ }
+}