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 [4/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/DumpHandler.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/DumpHandler.java?rev=171355&view=auto
==============================================================================
--- incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/DumpHandler.java (added)
+++ incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/DumpHandler.java Sun May 22 11:40:13 2005
@@ -0,0 +1,261 @@
+/*
+ * 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;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.TreeSet;
+
+import org.apache.jdo.util.I18NHelper;
+
+
+/**
+* Process dump requests. A dump request provides information about the
+* store. Currently, two options are supported:
+* <ul>
+* <li>dbInfo: Provide information about all classes stored in the store.</li>
+* <li>ClassMetadata: Provide the stored metadata information for the class
+* <code>className</code>.</li>
+* </ul>
+*
+* @see org.apache.jdo.impl.fostore.DumpOption
+* @author Markus Fuchs
+*/
+// This is server-side code. It does not need to live in the client.
+class DumpHandler extends RequestHandler {
+
+ /** Maps <code>DumpOptions</code> to
+ * <code>DumpOptionSubHandlers</code>. The option table must match
+ * the <code>optionTable</code> in <code>Dumper</code>.
+ * <p>
+ * Because the <code>DumpOptionSubHandler</code> are bound to
+ * the state of the enclosing <code>DumpHander</code> instance, the
+ * <code>optionTable</code> has to be non-static. */
+ private static HashMap optionTable = new HashMap();
+
+ /** List of results. A SubRequest might report more than one result. */
+ private final ArrayList results = new ArrayList();
+
+ /** Return status. */
+ private Status status;
+
+ /** I18N support. */
+ private static final I18NHelper msg = I18NHelper.getInstance(I18N.NAME);
+
+ /** Initializes the <code>optionTable</code>.
+ * The option table must match the <code>optionTable</code> in
+ * <code>Dumper</code>.
+ * @see Dumper
+ */
+ // Note that there is no entry for DumpOption.CLASS_INSTANCES: that option
+ // is handled entirely by the Dumper on the client side, with help of
+ // FOStoreStoreManager.getExtent.
+ private void initOptionTable() {
+ optionTable.put(DumpOption.DBINFO,
+ new DBInfoHandler());
+ optionTable.put(DumpOption.CLASS_METADATA,
+ new ClassMetadataHandler());
+ optionTable.put(DumpOption.CLASS_SUBCLASSES,
+ new ClassSubclassesHandler());
+ }
+
+ private DumpHandler(Reply reply, int length,
+ FOStoreServerConnection con) {
+
+ super(reply, length, con);
+ initOptionTable();
+ }
+
+ public static final HandlerFactory factory =
+ new HandlerFactory() {
+ public RequestHandler getHandler(Reply reply, int length,
+ FOStoreServerConnection con) {
+ return new DumpHandler(reply, length, con);
+ }};
+
+ RequestFinisher handleRequest()
+ throws IOException, FOStoreDatabaseException {
+
+ FOStoreInput in = con.getInputFromClient();
+ FOStoreDatabase db = con.getDatabase();
+
+ // read arguments
+ DumpOption option = DumpOption.read(in);
+ String className = in.readUTF();
+
+ DumpOptionSubHandler h =
+ (DumpOptionSubHandler) optionTable.get(option);
+ if (null == h) {
+ reply.setStatus(Status.FATAL,msg.msg("ERR_NoSubHandler", option)); // NOI18N
+ } else {
+ h.run(db, className);
+
+ int size = results.size();
+ reply.writeInt(size);
+ if (size > 0) {
+ for (int i = 0; i < size; i++) {
+ Object o = results.get(i);
+ if (null != o) {
+ reply.writeUTF(o.toString());
+ }
+ }
+ }
+ reply.setStatus(status);
+ }
+
+ return null;
+ }
+
+ /**
+ * Abstract class for dumping database information. The server creates
+ * instances of subclasses and then invoke <code>run</code>. Subclasses
+ * implement <code>run</code> method to do the real work.
+ */
+ abstract class DumpOptionSubHandler {
+
+ /** Must be implemented to dump particular kind of info.
+ */
+ protected abstract void run(FOStoreDatabase db, String className)
+ throws IOException, FOStoreDatabaseException;
+ }
+
+ /**
+ * OptionHandler that dumps DBInfo.
+ */
+ class DBInfoHandler extends DumpOptionSubHandler {
+ protected void run(FOStoreDatabase db, String className)
+ throws IOException, FOStoreDatabaseException {
+
+ results.add(db.getDBInfo());
+ status = Status.OK;
+ }
+ }
+
+ /**
+ * Abstract OptionHandler that assists in dumping information about
+ * classes.
+ */
+ abstract class ClassHandler extends DumpOptionSubHandler {
+ protected void run(FOStoreDatabase db, String className)
+ throws IOException, FOStoreDatabaseException {
+
+ if (null == className) {
+ reply.setStatus(
+ Status.ERROR,
+ msg.msg("MSG_MissingParameter", className)); //NOI18N
+ } else {
+ _run(db, className);
+ }
+ }
+
+ DBClass[] getDBClasses(FOStoreDatabase db, String className)
+ throws IOException, FOStoreDatabaseException {
+
+ DBClass rc[] = null;
+
+ // look for class info in store
+ DBInfo dbInfo = db.getDBInfo();
+ ArrayList found = new ArrayList();
+ for (Iterator i = dbInfo.getDBClasses(); i.hasNext();) {
+ DBClass dbClass = (DBClass)i.next();
+ if (className.equals(dbClass.getName())) {
+ found.add(dbClass);
+ }
+ }
+ int size = found.size();
+ if (size > 0) {
+ rc = new DBClass[size];
+ for (int i = 0; i < size; i++) {
+ rc[i] = (DBClass)found.get(i);
+ }
+ }
+ return rc;
+ }
+
+ /** Subclasses must implement, to dump their particular kind of info.
+ */
+ abstract void _run(FOStoreDatabase db, String className)
+ throws IOException, FOStoreDatabaseException;
+ }
+
+
+ /**
+ * OptionHandler that dumps metadata about a class.
+ */
+ class ClassMetadataHandler extends ClassHandler {
+ protected void _run(FOStoreDatabase db, String className)
+ throws IOException, FOStoreDatabaseException {
+
+ DBClass dbClasses[] = getDBClasses(db, className);
+ for (int i = 0; i < dbClasses.length; i++) {
+ results.add(dbClasses[i]);
+ }
+ status = Status.OK;
+ }
+ }
+
+ /**
+ * OptionHandler that dumps information about the subclasses of a class.
+ */
+ class ClassSubclassesHandler extends ClassHandler {
+ protected void _run(FOStoreDatabase db, String className)
+ throws IOException, FOStoreDatabaseException {
+
+ // Sort results in String order.
+ TreeSet sorted = new TreeSet();
+
+ DBClass dbClasses[] = getDBClasses(db, className);
+ if (null == dbClasses || 0 == dbClasses.length){
+ results.add(
+ msg.msg("MSG_DbClassNotFound", className)); // NOI18N
+ } else {
+ // For each DBClass known by className, get all of its
+ // subclasses.
+ for (int i = 0; i < dbClasses.length; i++) {
+ String result = null;
+ CLID clid = dbClasses[i].getCLID();
+ OID ssOID = DBInfo.getSubclassSetOID(clid);
+ SubclassSet sl = (SubclassSet)db.getIfExists(ssOID);
+ if (null == sl) {
+ result = msg.msg("MSG_NoSubclasses", className); // NOI18N
+ } else {
+ result = msg.msg("MSG_Subclasses", className); // NOI18N
+ // Get results into the TreeSet
+ for (Iterator j = sl.iterator(); j.hasNext();) {
+ CLID subCLID = (CLID)j.next();
+ OID subDBClassOID = DBInfo.getDBClassOID(subCLID);
+ DBClass subDBClass =
+ (DBClass)db.get(subDBClassOID);
+ sorted.add("\n\t" + subDBClass.getName()); // NOI18N
+ }
+
+ // Put sorted subclasses from TreeSet to string
+ for (Iterator k = sorted.iterator(); k.hasNext();) {
+ result += (String)k.next();
+ }
+ }
+ results.add(result);
+ }
+ }
+ status = Status.OK;
+ }
+ }
+}
Added: incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/DumpOption.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/DumpOption.java?rev=171355&view=auto
==============================================================================
--- incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/DumpOption.java (added)
+++ incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/DumpOption.java Sun May 22 11:40:13 2005
@@ -0,0 +1,134 @@
+/*
+ * 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;
+import java.util.HashMap;
+
+import javax.jdo.JDOUserException;
+
+import org.apache.jdo.util.I18NHelper;
+
+
+/** Diagnostic code to identify a dump request to the store. Currently,
+* there are the following options supported:
+* <ul>
+* <li>DBINFO: Provide information about all classes in the store.</li>
+* <li>CLASS_METADATA: Provide metadata information about a special class.</li>
+* <li>CLASS_INSTANCES: List all instances of a special class.</li>
+* </ul>
+*
+* @author Markus Fuchs
+*/
+class DumpOption {
+ /** Value of this DumpOption. */
+ private final int value;
+
+ /** String name of this option. */
+ private final String name;
+
+ /** Map from name to DumpOption. */
+ private static final HashMap options = new HashMap();
+
+ /** Provide information about all classes in the store. */
+ static final DumpOption DBINFO =
+ new DumpOption(1, "dbInfo"); // NOI18N
+
+ /** Provide metadata information about a particular class.*/
+ static final DumpOption CLASS_METADATA =
+ new DumpOption(2, "classMetadata"); // NOI18N
+
+ /** List all instances of a particular class. */
+ static final DumpOption CLASS_INSTANCES =
+ new DumpOption(3, "classInstances"); // NOI18N
+
+ /** List all subclasses of a particular class. */
+ static final DumpOption CLASS_SUBCLASSES =
+ new DumpOption(4, "classSubclasses"); // NOI18N
+
+ /** I18N support. */
+ private static final I18NHelper msg = I18NHelper.getInstance(I18N.NAME);
+
+ /**
+ * Create a DumpOption with the given value and name.
+ */
+ private DumpOption(int value, String name) {
+ this.value = value;
+ this.name = name;
+ options.put(name, this);
+ }
+
+ /** Provide a DumpOption given a name. */
+ static DumpOption forName(String name) {
+ DumpOption rc = (DumpOption)options.get(name);
+ if (null == rc) {
+ throw new JDOUserException(
+ msg.msg("EXC_BadValue", name)); // NOI18N
+ }
+ return rc;
+ }
+
+ //
+ // I/O support
+ //
+
+ /**
+ * Write this DumpOption's value.
+ */
+ void write(DataOutput out) throws IOException {
+ out.writeUTF(name);
+ }
+
+ /**
+ * Return the instance of a DumpOption that corresponds to the value read
+ * from the DataInput.
+ * @throws IOException if there is an IOException reading the value.
+ * <em>or</em> if the value read does not correspond to a DumpOption.
+ */
+ static DumpOption read(DataInput in) throws IOException {
+ String optionName = in.readUTF();
+ DumpOption rc = forName(optionName);
+ if (null == rc) {
+ throw new IOException(
+ msg.msg("EXC_BadValue", optionName)); // NOI18N
+ }
+ return rc;
+ }
+
+ //
+ // Override java.lang.Object methods
+ //
+
+ public String toString() {
+ return name;
+ }
+
+ public boolean equals(Object o) {
+ boolean rc = false;
+ if ((null != o) && (o instanceof DumpOption)) {
+ rc = (value == ((DumpOption)o).value);
+ }
+ return rc;
+ }
+
+ public int hashCode() {
+ // Same as for java.lang.Integer
+ return value;
+ }
+}
Added: incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/DumpRequest.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/DumpRequest.java?rev=171355&view=auto
==============================================================================
--- incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/DumpRequest.java (added)
+++ incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/DumpRequest.java Sun May 22 11:40:13 2005
@@ -0,0 +1,109 @@
+/*
+ * 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.HashSet;
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+
+import javax.jdo.Extent;
+import javax.jdo.JDOHelper;
+import javax.jdo.JDOUserException;
+import javax.jdo.PersistenceManager;
+
+import org.apache.jdo.pm.PersistenceManagerInternal;
+import org.apache.jdo.state.StateManagerInternal;
+
+
+/**
+ * Represents a request to dump information from the store.
+ *
+ * @author Markus Fuchs
+ */
+//
+// This is client-side code. It does not need to live in the server.
+//
+class DumpRequest extends AbstractRequest {
+ /** The DumpOption.
+ */
+ private final DumpOption option;
+
+ /** The name of the class queried by this request.
+ */
+ private final String className;
+
+ /** Returned dump information.
+ */
+ private String dump;
+
+ DumpRequest(DumpOption option, String className, Message m,
+ FOStorePMF pmf) {
+
+ super(m, pmf);
+ this.option = option;
+ this.className = className;
+ }
+
+ protected void doRequestBody() throws IOException {
+ //
+ // The format of this request is:
+ //
+ // int: option code
+ // String: className
+ //
+
+ option.write(out);
+ out.writeUTF((null != className) ? className : ""); // NOI18N
+ if (logger.isDebugEnabled()) {
+ logger.debug("DR.dRB: " + option // NOI18N
+ + " class=" + className); // NOI18N
+ }
+ }
+
+ public void handleReply(Status status, DataInput in, int length) throws IOException {
+ //
+ // The format of the reply is:
+ // int: number of objects (<= one)
+ // String: information dump
+ //
+ // The status might be Status.WARN, in which case either
+ // * The class to be queried wasn't found.
+ // * The className parameter was null.
+
+ int count = in.readInt();
+ if (logger.isDebugEnabled()) {
+ logger.debug("DR.hR/0: count=" + count); // NOI18N
+ }
+
+ StringBuffer results = new StringBuffer();
+ for (int i = 0; i < count; i++) {
+ results.append(in.readUTF());
+ }
+ dump = results.toString();
+
+ if (logger.isDebugEnabled()) {
+ logger.debug("DR.hR/1: dump=" + dump); // NOI18N
+ }
+ }
+
+ String getDump() {
+ return dump;
+ }
+}
Added: incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/Dumper.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/Dumper.java?rev=171355&view=auto
==============================================================================
--- incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/Dumper.java (added)
+++ incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/Dumper.java Sun May 22 11:40:13 2005
@@ -0,0 +1,280 @@
+/*
+ * 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.File;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.StringTokenizer;
+
+import javax.jdo.Extent;
+import javax.jdo.JDOUserException;
+import javax.jdo.PersistenceManager;
+
+import org.apache.jdo.impl.pm.PersistenceManagerWrapper;
+import org.apache.jdo.pm.PersistenceManagerInternal;
+import org.apache.jdo.util.I18NHelper;
+
+
+/**
+* Provides information such as metadata, extents, objects about the store.
+* <pre>
+* FOStore dumper program usage:
+* -DdumpOption=OPTION -DclassNames=CLASSNAMES
+* OPTION parameter can be one of the following:
+* dbInfo: prints general information about the store.
+* classMetadata: prints the metadata for the classes CLASSNAMES.
+* classInstances: prints all instances of the classes CLASSNAMES.
+* classSubclasses: prints all information about the subclasses
+* of the classes CLASSNAMES.
+* </pre>
+* This class is <code>public</code> because it has a <code>main</code> entry
+* point for running as a standalone program.
+*
+* @author Markus Fuchs
+* @author Dave Bristor
+*/
+public class Dumper {
+
+ /** Maps <code>DumpOptions</code> to
+ * <code>DumpOptionSubRequests</code>. The option table must match
+ * the <code>optionTable</code> in <code>DumpHandler</code>.
+ * <p>
+ * Because there is no non-static state to be shared between
+ * <code>Dumper</code> and the <code>DumpOptionSubRequest</code>s,
+ * the <code>optionTable</code> can be initilialzed only once.
+ * @see org.apache.jdo.impl.fostore.DumpOption
+ */
+ private static final HashMap optionTable = new HashMap();
+
+ private static FOStorePMF pmf;
+
+ /** Class names to dump informations about. */
+ private static String classNames;
+
+ /** I18N support. */
+ private static final I18NHelper msg = I18NHelper.getInstance(I18N.NAME);
+
+ /**
+ * Initializes the <code>optionTable</code>.
+ * The option table must match the <code>optionTable</code> in
+ * <code>DumpHandler</code>.
+ * @see org.apache.jdo.impl.fostore.DumpHandler
+ */
+ static {
+ optionTable.put(DumpOption.DBINFO,
+ new DBInfoRequest());
+ optionTable.put(DumpOption.CLASS_METADATA,
+ new ClassMetadataRequest());
+ optionTable.put(DumpOption.CLASS_INSTANCES,
+ new ClassInstancesRequest());
+ optionTable.put(DumpOption.CLASS_SUBCLASSES,
+ new ClassSubclassesRequest());
+ }
+
+ /**
+ * Given a command line argument that specifies what information
+ * to dump, gets that information from the database and prints it
+ * on standard output.
+ * @param args the command line arguments
+ */
+ public static void main(String args[]) {
+
+ String optionName = System.getProperty("dumpOption"); // NOI18N
+ if (null == optionName) {
+ exit(msg.msg("MSG_MissingDumpOption")); // NOI18N
+ }
+ classNames = System.getProperty("classNames"); // NOI18N
+
+ try {
+ DumpOption option = DumpOption.forName(optionName);
+
+ DumpOptionSubRequest r =
+ (DumpOptionSubRequest)optionTable.get(option);
+ r.run();
+ } catch (Exception ex) {
+ exit(msg.msg("MSG_DumperException", ex)); // NOI18N
+ }
+ }
+
+ /**
+ * Abstract class for dumping database information. Clients create
+ * instances of subclasses and then invoke <code>run</code>. Subclasses
+ * implement <code>dump</code> method to do the real work.
+ */
+ static abstract class DumpOptionSubRequest {
+ protected PersistenceManager pm;
+ protected FOStoreStoreManager srm;
+ protected StringTokenizer st;
+
+ /** Called by clients to cause information to be dumped.
+ */
+ void run() {
+ try {
+ setupPMF();
+ pm = pmf.getPersistenceManager();
+ srm = (FOStoreStoreManager)pmf.getStoreManager(pm);
+ dump();
+ } catch (Exception ex) {
+ exit(msg.msg("MSG_DumperException", ex)); // NOI18N
+ }
+ }
+
+ /** Subclasses must implement, to dump their particular kind of info.
+ */
+ protected abstract void dump();
+ }
+
+ /**
+ * DumpRequest that can dump DBInfo.
+ */
+ static class DBInfoRequest extends DumpOptionSubRequest {
+ protected void dump() {
+ println(srm.dump(DumpOption.DBINFO, "")); // NOI18N
+ }
+ }
+
+ /**
+ * Abstract DumpRequest that assists in dumping
+ * information about classes.
+ */
+ static abstract class ClassRequest extends DumpOptionSubRequest {
+ protected void dump() {
+ StringTokenizer st =
+ new StringTokenizer(classNames, ","); // NOI18N
+ while (st.hasMoreElements()) {
+ subDump((String)st.nextElement());
+ }
+ }
+
+ /** Subclasses must implement, to dump their particular kind
+ * of info.
+ */
+ protected abstract void subDump(String className);
+ }
+
+ /**
+ * DumpRequest that dumps metadata about a class.
+ */
+ static class ClassMetadataRequest extends ClassRequest {
+ protected void subDump(String className) {
+ println(srm.dump(DumpOption.CLASS_METADATA, className));
+ }
+ }
+
+ /**
+ * DumpRequest that dumps information about the instances
+ * of a class.
+ */
+ static class ClassInstancesRequest extends ClassRequest {
+ protected void subDump(String className) {
+ int objCount = 0;
+ Class cls = null;
+ try {
+ cls = Class.forName(className);
+ } catch (ClassNotFoundException ex) {
+ throw new JDOUserException(
+ msg.msg("EXC_InstantiateClass", className)); // NOI18N
+ }
+
+ println("\n" + msg.msg("MSG_ExtentName", className)); // NOI18N
+ Extent e = pm.getExtent(cls, false);
+ for (Iterator i = e.iterator(); i.hasNext();) {
+ Object pc = i.next();
+ println("" + pc); // NOI18N
+ objCount++;
+ }
+ println(msg.msg("MSG_ExtentCount", className, // NOI18N
+ new Integer(objCount)));
+ }
+ }
+
+ /**
+ * DumpRequest that dumps information about the subclasses
+ * of a class.
+ */
+ static class ClassSubclassesRequest extends ClassRequest {
+ protected void subDump(String className) {
+ int objCount = 0;
+ Class cls = null;
+ try {
+ cls = Class.forName(className);
+ } catch (ClassNotFoundException ex) {
+ throw new JDOUserException(
+ msg.msg("EXC_InstantiateClass", className)); // NOI18N
+ }
+
+ println(srm.dump(DumpOption.CLASS_SUBCLASSES, className));
+ }
+ }
+
+ /** Print an error message and exit.
+ */
+ private static void exit(String message) {
+ println(message);
+ usage();
+ System.exit(1);
+ }
+
+ /** Print the usage message on standard output.
+ */
+ private static void usage() {
+ println(msg.msg("MSG_Usage")); // NOI18N
+ }
+
+ /**
+ * Configures a PMF with some basic properties, and creates the
+ * corresponding database.
+ */
+ private static void setupPMF() throws Exception {
+ pmf = new FOStorePMF();
+ pmf.setConnectionCreate(false);
+
+ pmf.setConnectionUserName(System.getProperty("user", // NOI18N
+ "fred")); // NOI18N
+ pmf.setConnectionPassword(System.getProperty("password", // NOI18N
+ "wombat")); // NOI18N
+
+ // Create url in string form.
+ String path = ""; // NOI18N
+
+ String dir = System.getProperty("dir"); // NOI18N
+ if (null == dir) {
+ dir = System.getProperty("user.dir"); // NOI18N
+ }
+
+ String name = System.getProperty("name"); // NOI18N
+ if (null == name) {
+ name = "FOStoreTestDB"; // NOI18N
+ }
+
+ path += dir + File.separator;
+ path += name;
+
+ path = "fostore:" + path; // NOI18N
+
+ pmf.setConnectionURL(path);
+ }
+
+ /** Print a message on the standard output.
+ * @param s the message to print.
+ */
+ private static void println(String s) {
+ System.out.println(s);
+ }
+
+}
Added: incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/FOStoreAbstractMethodException.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/FOStoreAbstractMethodException.java?rev=171355&view=auto
==============================================================================
--- incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/FOStoreAbstractMethodException.java (added)
+++ incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/FOStoreAbstractMethodException.java Sun May 22 11:40:13 2005
@@ -0,0 +1,31 @@
+/*
+ * 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 exception means that a subclass didn't override a method that it should
+ * have. When thrown, it means there is an implementation bug.
+ *
+ * @author Dave Bristor
+ */
+class FOStoreAbstractMethodException extends JDOFatalInternalException {
+ FOStoreAbstractMethodException(String msg) {
+ super(msg); // NOI18N
+ }
+}
Added: incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/FOStoreBtreeStorage.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/FOStoreBtreeStorage.java?rev=171355&view=auto
==============================================================================
--- incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/FOStoreBtreeStorage.java (added)
+++ incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/FOStoreBtreeStorage.java Sun May 22 11:40:13 2005
@@ -0,0 +1,142 @@
+/*
+ * 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.util.HashMap;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.netbeans.mdr.persistence.MOFID;
+import org.netbeans.mdr.persistence.ObjectResolver;
+import org.netbeans.mdr.persistence.StorageException;
+import org.netbeans.mdr.persistence.btreeimpl.btreestorage.BtreeFactory;
+import org.netbeans.mdr.persistence.btreeimpl.btreestorage.BtreeStorage;
+
+/**
+ * FOStore specific BtreeStorage subclass. This class manages MOFIDs for a
+ * FOStore datastore. A MOFID consists of two parts: a storageId of type
+ * String and a serial number of type long. When storing on disk the
+ * storageId is converted into a number and stored as 16-bit value. Only 48
+ * bits of the serial number get represented on disk. FOStore uses the
+ * serial number to encode the uid part of an OID and the storageId for the
+ * class id of an OID. The btree class MOFIDInfo converts a MOFID into a
+ * byte array of 8 bytes that is stored on disk. The two high order bytes
+ * represent the storageId. Class MOFIDInfo calls method storageIdToNumber
+ * to convert a String storageId into a number. The remaining 6 bytes
+ * represent the serial number.
+ *
+ * @author Michael Bouschen
+ * @since 1.1
+ * @version 1.1
+ */
+public class FOStoreBtreeStorage extends BtreeStorage {
+
+ /**
+ * Dummy ObjectResolver instance required by BtreeStorage create and
+ * open methods.
+ */
+ private static final ObjectResolver resolver = new Resolver();
+
+ /** Prefix for the storageId generated from an class id. */
+ private static final String CLID_PREFIX = "FOSTORE_CLID";
+
+ /** Length of class id prefix. */
+ private static final int CLID_PREFIX_LENGTH = 12;
+
+ /** Logger */
+ static final Log logger = LogFactory.getFactory().getInstance(
+ "org.apache.jdo.impl.fostore"); // NOI18N
+
+ /**
+ * Creates a new FOStoreBtreeStorage instance. The constructor creates
+ * or opens a storage based on the specified argument <code>isNew</code>.
+ * @param name the name of the storage.
+ * @param isNew true if the database is being created
+ */
+ public FOStoreBtreeStorage(String name, boolean isNew)
+ throws StorageException {
+ super(name);
+ if (isNew) {
+ create(true, resolver);
+ }
+ else {
+ open(false, resolver);
+ }
+ }
+
+ /**
+ * Returns Creates a MOFID based on the class id and uid taken from a
+ * FOStore OID. The storageId of the returned MOFID represents the
+ * class id and the serial number represents the uid.
+ * @param clid the class id
+ * @param uid the unique id
+ * @return MOFID representing class id and uid taken from FOStore OID.
+ */
+ public MOFID createMOFID(int clid, long uid) {
+ // Add FIRST_EXTERNAL_ID to avoid clashes with
+ // internal btree serial numbers
+ long serialNumber = uid + BtreeFactory.FIRST_EXTERNAL_ID;
+ // The prefix CLID_PREFIX check whether the storageId denotes a
+ // fostore class id. Add FIRST_EXTERNAL_CODE to avoid clashes with
+ // internal btree storageId codes
+ String storageId =
+ CLID_PREFIX + (clid + BtreeFactory.FIRST_EXTERNAL_CODE);
+ return new MOFID(serialNumber, storageId);
+ }
+
+ /**
+ * Converts a storageId to an int. If the specified storageId starts
+ * with CLID_PREFIX, then the storageId represents a class id. In this
+ * case use the class id as the numeric reresentation.
+ * @param storageId the storageId as String
+ * @return the numeric representation of the storageId
+ */
+ public int storageIdToNumber(String storageId) throws StorageException {
+ if (storageId.startsWith(CLID_PREFIX))
+ return Integer.parseInt(storageId.substring(CLID_PREFIX_LENGTH));
+ else
+ return super.storageIdToNumber(storageId);
+ }
+
+ /**
+ * Creates a storage id from an int. It returns the FOStore specific
+ * String representation for a storageId representing a class id.
+ * @param number the numberic representation of the storageId
+ * @return the storageId as String
+ */
+ public String numberToStorageId(int number) throws StorageException {
+ if (number >= BtreeFactory.FIRST_EXTERNAL_CODE)
+ return CLID_PREFIX + number;
+ else
+ return super.numberToStorageId(number);
+ }
+
+ /** Dummy implementation. */
+ static class Resolver implements ObjectResolver {
+
+ /** */
+ public Object resolve(String storageID, Object key) {
+ if (logger.isDebugEnabled()) {
+ logger.debug("FOStoreBtreeStorage: called Resolver.resolve(" +
+ storageID + ", " + key + ")");
+ }
+ return new Object();
+ }
+ }
+}
+
Added: incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/FOStoreClientConnection.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/FOStoreClientConnection.java?rev=171355&view=auto
==============================================================================
--- incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/FOStoreClientConnection.java (added)
+++ incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/FOStoreClientConnection.java Sun May 22 11:40:13 2005
@@ -0,0 +1,82 @@
+/*
+ * 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.IOException;
+
+/**
+ * Represents the connection as seen by the client. This contains two types
+ * of interface: that used by the ConnectionFactory, and that used by the
+ * Message. It provides a means for managing the data sent and received
+ * from the store, as well as for being managed in a pool.
+ *
+ * @author Dave Bristor
+ */
+interface FOStoreClientConnection extends FOStoreConnection {
+
+ /** Connect to the data source.
+ */
+ public void connect() throws IOException;
+
+ /**
+ * Provides DataInput from which the client can read replies from
+ * the server.
+ * @return DataInput from which the client can read replies.
+ */
+ public DataInput getInputFromServer() throws IOException;
+
+ /**
+ * Indicates that the client has finished writing. The data is sent to the
+ * server and processed there.
+ */
+ public void sendToStore(byte[] buffer, int start, int length) throws IOException;
+
+ /**
+ * Put this connection back into the connection pool managed by the
+ * ConnectionFactory.
+ */
+ public void close() throws IOException;
+
+ /** Set the connection id used to create this connection. This is used
+ * to determine which connection pool is used.
+ */
+ public void setConnectionId (FOStoreConnectionId connectionId);
+
+ /** Get the connection id used to create this connection. Connections
+ * are pooled based on this connection id.
+ */
+ public FOStoreConnectionId getConnectionId();
+
+ /** Set the connection id used to create this connection. This is used
+ * to determine which connection pool is used.
+ */
+ public void setConnectionFactory (FOStoreConnectionFactory connectionFactory);
+
+ /** Get the connection Factory used to create this connection. Connections
+ * are pooled based on this connection Factory.
+ */
+ public FOStoreConnectionFactory getConnectionFactory();
+
+ /** Close the database associated with this connection. In the remote case,
+ * close the socket.
+ */
+ public void closeDatabase() throws IOException, FOStoreDatabaseException ;
+
+}
Added: incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/FOStoreClientConnectionImpl.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/FOStoreClientConnectionImpl.java?rev=171355&view=auto
==============================================================================
--- incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/FOStoreClientConnectionImpl.java (added)
+++ incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/FOStoreClientConnectionImpl.java Sun May 22 11:40:13 2005
@@ -0,0 +1,152 @@
+/*
+ * 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.
+ */
+
+/*
+ * FOStoreClientConnectionImpl.java
+ *
+ * Created on June 7, 2001, 3:17 PM
+ */
+
+package org.apache.jdo.impl.fostore;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.OutputStream;
+
+import java.net.URLConnection;
+import java.net.URL;
+import java.net.Socket;
+
+import java.util.Date;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ * Implementation of the client side of a FOStore connection.
+ *
+ * @author Craig Russell
+ * @version 1.0
+ */
+abstract class FOStoreClientConnectionImpl extends URLConnection implements FOStoreClientConnection {
+
+ /** Message to handle connection-to-connection messages (login).
+ */
+ Message message = new Message();
+
+ FOStoreConnectionFactory connectionFactory;
+
+ FOStoreConnectionId connectionId;
+
+ /** Flag set while logging in. This flag, when set, causes close() to
+ * retain the connection instead of returning the connection to the pool.
+ */
+ private boolean loggingIn = true;
+
+ /** Logger */
+ static final Log logger = LogFactory.getFactory().getInstance(
+ "org.apache.jdo.impl.fostore"); // NOI18N
+
+ /** Creates new FOStoreClientConnectionImpl */
+ public FOStoreClientConnectionImpl(URL url) {
+ super (url);
+ if (logger.isDebugEnabled()) logger.debug("FOCCI<init>" + // NOI18N
+ " Host: " + url.getHost() + // NOI18N
+ " Port: " + url.getPort() + // NOI18N
+ " Path: " + url.getPath()); // NOI18N
+ }
+
+ /**
+ * Return this connection to the connection pool.
+ */
+ public void close() throws IOException {
+ if (!loggingIn) {
+ if (logger.isDebugEnabled()) {
+ logger.debug ("FOCCI.close: closing"); // NOI18N
+ }
+ connectionFactory.closeConnection(this);
+ } else {
+ if (logger.isDebugEnabled()) {
+ logger.debug ("FOCCI.close: loggingIn; not closing"); // NOI18N
+ }
+ }
+ }
+
+ /** Log in to the datastore. This will be done for both local and
+ * remote connections.
+ */
+ protected void login() throws IOException {
+ String path = localizePath(url.getPath());
+
+ if (logger.isDebugEnabled()) {
+ logger.debug("FOCCI:login " + // NOI18N
+ " Database: " + path + // NOI18N
+ " User: " + connectionId.getUser() + // NOI18N
+ " Password: " + connectionId.getPassword() + // NOI18N
+ " Create: " + connectionId.getCreate()); // NOI18N
+ }
+ LoginRequest logreq =
+ new LoginRequest(
+ message, connectionFactory.getPMF(),
+ path, connectionId.getUser(), connectionId.getPassword(),
+ connectionId.getCreate());
+ logreq.doRequest();
+ // false => NOT ok to close (this) connection
+ message.processInStore(this, false);
+ loggingIn = false;
+ }
+
+ public void setConnectionFactory(FOStoreConnectionFactory cf) {
+ this.connectionFactory = cf;
+ }
+
+ /** Get the connection Factory used to create this connection. Connections
+ * are pooled based on this connection Factory.
+ */
+ public FOStoreConnectionFactory getConnectionFactory() {
+ return connectionFactory;
+ }
+
+ /** Set the connection id used to create this connection. This is used
+ * to determine which connection pool is used.
+ */
+ public void setConnectionId (FOStoreConnectionId id) {
+ if (logger.isDebugEnabled()) {
+ logger.debug("FOCCI.setConnectionId(): " + // NOI18N
+ " URL: " + id.getUrl() + // NOI18N
+ " User: " + id.getUser() + // NOI18N
+ " Password: " + id.getPassword() + // NOI18N
+ " Create: " + id.getCreate()); // NOI18N
+ }
+ this.connectionId = id;
+ }
+
+ /** Get the connection id used to create this connection. The id
+ * encapsulates URL, user, and password. Connections
+ * are pooled based on this connection id.
+ */
+ public FOStoreConnectionId getConnectionId() {
+ return connectionId;
+ }
+
+ /**
+ * @return The path, modified as required for the kind of connection.
+ */
+ abstract protected String localizePath(String path);
+}
Added: incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/FOStoreConnection.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/FOStoreConnection.java?rev=171355&view=auto
==============================================================================
--- incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/FOStoreConnection.java (added)
+++ incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/FOStoreConnection.java Sun May 22 11:40:13 2005
@@ -0,0 +1,25 @@
+/*
+ * 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;
+
+/**
+* Tagging interface at root of all kinds of FOStore connections.
+*
+* @author Dave Bristor
+*/
+interface FOStoreConnection {
+}
Added: incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/FOStoreConnectionFactory.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/FOStoreConnectionFactory.java?rev=171355&view=auto
==============================================================================
--- incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/FOStoreConnectionFactory.java (added)
+++ incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/FOStoreConnectionFactory.java Sun May 22 11:40:13 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/fostore20/src/java/org/apache/jdo/impl/fostore/FOStoreConnectionId.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/FOStoreConnectionId.java?rev=171355&view=auto
==============================================================================
--- incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/FOStoreConnectionId.java (added)
+++ incubator/jdo/trunk/fostore20/src/java/org/apache/jdo/impl/fostore/FOStoreConnectionId.java Sun May 22 11:40:13 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
+ }
+ }
+
+}