You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@commons.apache.org by fr...@apache.org on 2002/02/11 21:23:38 UTC
cvs commit: jakarta-commons-sandbox/simplestore/src/java/org/apache/commons/simplestore/persistence/impl TransactionImpl.java PersistentProxy.java PersistenceManager.java DBStorage.java AbstractStorage.java
froehlich 02/02/11 12:23:38
Added: simplestore/src/java/org/apache/commons/simplestore/persistence/impl
TransactionImpl.java PersistentProxy.java
PersistenceManager.java DBStorage.java
AbstractStorage.java
Log:
re-structured repository
Revision Changes Path
1.1 jakarta-commons-sandbox/simplestore/src/java/org/apache/commons/simplestore/persistence/impl/TransactionImpl.java
Index: TransactionImpl.java
===================================================================
/*
* The Apache Software License, Version 1.1
*
*
* Copyright (c) 2001 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution,
* if any, must include the following acknowledgment:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowledgment may appear in the software itself,
* if and wherever such third-party acknowledgments normally appear.
*
* 4. The names "Apache Cocoon" and "Apache Software Foundation" must
* not be used to endorse or promote products derived from this
* software without prior written permission. For written
* permission, please contact apache@apache.org.
*
* 5. Products derived from this software may not be called "Apache",
* nor may "Apache" appear in their name, without prior written
* permission of the Apache Software Foundation.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*/
package org.apache.commons.simplestore.persistence.impl;
import org.apache.commons.simplestore.cache.Cache;
import org.apache.commons.simplestore.cache.impl.SoftRefMemoryCache;
import org.apache.commons.simplestore.persistence.InternalTransaction;
import org.apache.commons.simplestore.persistence.MetaObject;
import java.util.HashMap;
import java.util.Set;
import java.util.Map;
import java.util.HashSet;
import java.util.Iterator;
/**
*@author Juozas Baliuka <a href="mailto:baliuka@mwm.lt">
* baliuka@mwm.lt</a>
*@version $Id: TransactionImpl.java,v 1.1 2002/02/11 20:23:38 froehlich Exp $
*/
public class TransactionImpl implements InternalTransaction {
private static Cache instances = SoftRefMemoryCache.getInstance(new HashMap(), 0x00);
int threadId = getCurrentThreadId();
InternalTransaction transaction;
Set objects;
Map attributes = new HashMap();
Map storedState = new HashMap();
boolean complete = true;
/**
* Creates new TransactionImpl
*
*@param transaction
*@param objects
*/
public TransactionImpl(InternalTransaction transaction, Set objects) {
this.objects = objects;
this.transaction = transaction;
}
public static InternalTransaction getInstance(InternalTransaction transaction) {
Number threadId = new Integer(getCurrentThreadId());
InternalTransaction tr = (InternalTransaction) instances.get(threadId);
if (tr != null) {
return tr;
}
tr = new TransactionImpl(transaction, new HashSet());
instances.put(threadId, tr);
return tr;
}
private static int getCurrentThreadId() {
return System.identityHashCode(Thread.currentThread());
}
public void setAttribute(String name, Object value) {
attributes.put(name, value);
}
public int getThreadId() {
return threadId;
}
public Object getAttribute(String name) {
return attributes.get(name);
}
public void commit() {
checkState();
checkState(!complete);
transaction.commit(objects);
complete = true;
storedState.clear();
}
public void begin() {
checkState();
checkState(complete);
transaction.begin(objects);
complete = false;
}
public void rollback() {
checkState();
checkState(!complete);
Iterator i = objects.iterator();
while(i.hasNext()){
MetaObject mo = (MetaObject)i.next();
mo.assign( (MetaObject)storedState.get( mo.getOID() ) );// NPE ?
}
storedState.clear();
transaction.rollback(objects);
complete = true;
}
public void add(MetaObject props) {
checkState();
if(objects.add(props)){
try{
storedState.put(props.getOID(),props.clone());
}catch( CloneNotSupportedException cnse ){
throw new UnsupportedOperationException(cnse.getMessage());
}
}
}
public void begin(Set objects) {
transaction.begin(objects);
}
public void rollback(Set objects) {
transaction.rollback(objects);
}
public void commit(Set objects) {
transaction.commit(objects);
}
public void removeAttribute(String name) {
attributes.remove(name);
}
void checkState(boolean b) {
if (!b) {
throw new IllegalStateException("Illegal Transaction state");
}
}
void checkState() {
int id = getCurrentThreadId();
if (threadId != id) {
throw new IllegalStateException("Accessed Transaction " + threadId + " in " + id);
}
}
}
1.1 jakarta-commons-sandbox/simplestore/src/java/org/apache/commons/simplestore/persistence/impl/PersistentProxy.java
Index: PersistentProxy.java
===================================================================
/*
* The Apache Software License, Version 1.1
*
*
* Copyright (c) 2001 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution,
* if any, must include the following acknowledgment:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowledgment may appear in the software itself,
* if and wherever such third-party acknowledgments normally appear.
*
* 4. The names "Apache Cocoon" and "Apache Software Foundation" must
* not be used to endorse or promote products derived from this
* software without prior written permission. For written
* permission, please contact apache@apache.org.
*
* 5. Products derived from this software may not be called "Apache",
* nor may "Apache" appear in their name, without prior written
* permission of the Apache Software Foundation.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*/
package org.apache.commons.simplestore.persistence.impl;
import org.apache.commons.simplestore.persistence.MetaObject;
import org.apache.commons.simplestore.persistence.Persistent;
import org.apache.commons.simplestore.persistence.TransactionManager;
import org.apache.commons.simplestore.persistence.MetaClass;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.io.Serializable;
import java.util.Map;
import java.util.Hashtable;
import java.util.HashMap;
/**
*@author Juozas Baliuka <a href="mailto:baliuka@mwm.lt">
* baliuka@mwm.lt</a>
*@version $Id: PersistentProxy.java,v 1.1 2002/02/11 20:23:38 froehlich Exp $
*/
public class PersistentProxy
implements MetaObject, InvocationHandler,Cloneable, Serializable {
private static Method HASH_CODE;
private static Method EQUALS;
private static Method TO_STRING;
private static Method GET_OID;
private static Method GET_META_OBJECT;
private static Map defaults = new Hashtable();
Map map = new HashMap();
Object oid = null;
Persistent object;
Class pClass;
TransactionManager transactionManager;
boolean dirty = false;
boolean deleted = false;
boolean newCreated;
/**
* Creates new ValueProxy
*
*@param pClass
*@param oid
*@param newCreated
*@param transactionManager
*/
public PersistentProxy(Class pClass, Object oid, boolean newCreated, TransactionManager transactionManager) {
this.oid = oid;
this.newCreated = newCreated;
this.transactionManager = transactionManager;
this.pClass = pClass;
}
// TODO : "next" interceptor as parameter
public static Persistent getPersitent(Class persistent, Object oid, boolean newCreated, TransactionManager transactionManager) {
PersistentProxy handler = new PersistentProxy(persistent, oid, newCreated, transactionManager);
Persistent p = (Persistent) Proxy.newProxyInstance(
Thread.currentThread().getContextClassLoader(), new Class[]{persistent, Persistent.class}, handler);
handler.object = p;
if (newCreated) {
MetaObject mo = p.getMetaObject();
transactionManager.getTransaction().add(mo);
}
return p;
}
// TODO must be converter interface
public static Object convertNumber(Number number, Class cls) {
if (cls.equals(Byte.class)) {
return new Byte(number.byteValue());
} else if (cls.equals(Short.class)) {
return new Short(number.shortValue());
} else if (cls.equals(Integer.class)) {
return new Integer(number.intValue());
} else if (cls.equals(Long.class)) {
return new Long(number.longValue());
} else if (cls.equals(Float.class)) {
return new Float(number.floatValue());
} else if (cls.equals(Double.class)) {
return new Double(number.doubleValue());
} else if (cls.equals(Boolean.class)) {
return new Boolean(number.intValue() != 0);
} else if (cls.equals(Character.TYPE)) {
return new Character(number.toString().charAt(0));
} else {
throw new UnsupportedOperationException("Number class = " + number.getClass().getName() + " Target Class " + cls.getName());
}
}
// TODO must be converter interface
public static Object convertPrimityve(Number number, Class cls) {
if (cls.equals(Byte.TYPE)) {
return new Byte(number.byteValue());
} else if (cls.equals(Short.TYPE)) {
return new Short(number.shortValue());
} else if (cls.equals(Integer.TYPE)) {
return new Integer(number.intValue());
} else if (cls.equals(Long.TYPE)) {
return new Long(number.longValue());
} else if (cls.equals(Float.TYPE)) {
return new Float(number.floatValue());
} else if (cls.equals(Double.TYPE)) {
return new Double(number.doubleValue());
} else if (cls.equals(Boolean.TYPE)) {
return new Boolean(number.intValue() != 0);
} else if (cls.equals(Character.TYPE)) {
return new Character(number.toString().charAt(0));
} else {
throw new UnsupportedOperationException("Number class = " + number.getClass().getName() + " Target Class " + cls.getName());
}
}
// TODO must be converter interface
public static Object convert(Object object, Class cls) {
try {
if (cls.isPrimitive()) {
if (object == null) {
return defaults.get(cls);
}
if (object instanceof Number) {
return convertPrimityve((Number) object, cls);
}
}
if (object == null) {
return null;
}
if (cls.isAssignableFrom(object.getClass())) {
return object;
}
// if( object instanceof String ){ ?????
// return org.apache.commons.beanutils.ConvertUtils.convert((String)object,cls);
// }
if (cls.isAssignableFrom(Number.class) && object instanceof Number) {
return convertNumber((Number) object, cls);
}
if (cls.equals(Boolean.class) && object instanceof Number) {
return new Boolean(((Number) object).intValue() != 0);
}
if (cls.equals(Character.TYPE)) {
return new Character(object.toString().charAt(0));
}
throw new UnsupportedOperationException(cls.getName() + ":" + object);
} catch (Throwable t) {
// TODO
t.printStackTrace();
throw new RuntimeException(t.getClass().getName() + ":" + t.getMessage());
}
}
public void setProperty(String name, Object value) {
Object old = map.put(name, value);
if (old == null || !old.equals(value)) {
dirty = true;
transactionManager.getTransaction().add(this);
}
}
public void setDirty(boolean dirty) {
this.dirty = dirty;
this.newCreated = false;
}
public boolean isDeleted() {
return deleted;
}
public boolean isNew() {
return newCreated;
}
public MetaObject getMetaObject() {
return this;
}
public Map getProperties() {
return map;
}
public Object getProperty(String name) {
return map.get(name);
}
public boolean isLoaded() {
return true;
}
public Class getPersistentClass() {
return pClass;
}
public Object getOID() {
return oid;
}
public boolean isDirty() {
return dirty;
}
public Persistent getObject() {
return object;
}
public Object handleEquals(Object obj) {
if (obj == null) {
return new Boolean(false);
}
if (!(obj instanceof Persistent)) {
return new Boolean(false);
}
Persistent object = (Persistent) obj;
if (oid == null) {
return new Boolean(oid == object.getOID());
} else {
return new Boolean(oid.equals(object.getOID()));
}
}
public Object invoke(Object obj, Method method, Object[] obj2) throws Throwable {
synchronized (this) {
if (GET_META_OBJECT.equals(method)) {
return this;
} else if (TO_STRING.equals(method)) {
return oid + "";
} else if (GET_OID.equals(method)) {
return oid;
} else if (HASH_CODE.equals(method)) {
if (oid == null) {
return new Integer(0);
}
return new Integer(oid.hashCode());
} else if (EQUALS.equals(method)) {
return handleEquals(obj2[0]);
} else {
return handleProperty(obj, method, obj2);
}
}
}
public Object handleProperty(Object obj, Method method, Object[] obj2) throws Throwable {
String name = method.getName();
if (name.startsWith("set")) {
setProperty(name.substring(3), obj2[0]);
return null;
} else if (name.startsWith("get") || name.startsWith("is")) {
if (method.getName().startsWith("get")) {
name = method.getName().substring(3);
} else {
name = method.getName().substring(2);
}
Object value = getProperty(name);
if (value == null && method.getReturnType().isPrimitive()) {
value = convert(value, method.getReturnType());
}
return value;
}
throw new IllegalStateException("pure method " + method.getName());
}
public void remove() {
deleted = true;
}
static {
try {
GET_OID = Persistent.class.getMethod("getOID", null);
GET_META_OBJECT = Persistent.class.getMethod("getMetaObject", null);
HASH_CODE = Object.class.getMethod("hashCode", null);
TO_STRING = Object.class.getMethod("toString", null);
EQUALS = Object.class.getMethod("equals", new Class[]{Object.class});
defaults.put(byte.class, new Byte((byte) 0));
defaults.put(short.class, new Short((short) 0));
defaults.put(int.class, new Integer(0));
defaults.put(long.class, new Long(0));
defaults.put(float.class, new Float(0));
defaults.put(double.class, new Double(0));
defaults.put(char.class, new Character('\u0000'));
defaults.put(boolean.class, new Boolean(false));
} catch (Exception e) {
e.printStackTrace();
throw new Error(e.getMessage());
}
}
public Object clone()throws CloneNotSupportedException{
PersistentProxy cln = (PersistentProxy)super.clone();
cln.dirty = false;
map = (Map)((HashMap)map).clone();
return cln;
}
public void assign(MetaObject mo) {
map.clear();
map.putAll(mo.getProperties());
oid = mo.getOID();
object = mo.getObject();
pClass = mo.getPersistentClass();
dirty = mo.isDirty();
deleted = mo.isDeleted();
newCreated = mo.isNew();
}
public MetaClass getMetaClass() {
throw new UnsupportedOperationException("Not implemented");
}
}
1.1 jakarta-commons-sandbox/simplestore/src/java/org/apache/commons/simplestore/persistence/impl/PersistenceManager.java
Index: PersistenceManager.java
===================================================================
/*
* The Apache Software License, Version 1.1
*
*
* Copyright (c) 2001 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution,
* if any, must include the following acknowledgment:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowledgment may appear in the software itself,
* if and wherever such third-party acknowledgments normally appear.
*
* 4. The names "Apache Cocoon" and "Apache Software Foundation" must
* not be used to endorse or promote products derived from this
* software without prior written permission. For written
* permission, please contact apache@apache.org.
*
* 5. Products derived from this software may not be called "Apache",
* nor may "Apache" appear in their name, without prior written
* permission of the Apache Software Foundation.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*/
package org.apache.commons.simplestore.persistence.impl;
import org.apache.commons.simplestore.cache.Cache;
import org.apache.commons.simplestore.cache.impl.SoftRefMemoryCache;
import org.apache.commons.simplestore.persistence.TransactionManager;
import org.apache.commons.simplestore.persistence.Storage;
import org.apache.commons.simplestore.persistence.Transaction;
import org.apache.commons.simplestore.persistence.StorageException;
import org.apache.commons.simplestore.persistence.Persistent;
import org.apache.commons.simplestore.persistence.MetaObject;
import java.util.HashMap;
import java.security.SecureRandom;
import java.util.Set;
import java.math.BigInteger;
/**
*@author Juozas Baliuka <a href="mailto:baliuka@mwm.lt">
* baliuka@mwm.lt</a>
*@version $Id: PersistenceManager.java,v 1.1 2002/02/11 20:23:38 froehlich Exp $
*/
public class PersistenceManager {
private static PersistenceManager pm;
private static SecureRandom seeder = new SecureRandom();
private Storage storage;
private TransactionManager transactionManager;
private Cache cache = SoftRefMemoryCache.getInstance(new HashMap(), 0xFF);
/**
* Creates new PersiatenceManager
*
*@param storage
*@param transactionManager
*/
protected PersistenceManager(Storage storage, TransactionManager transactionManager) {
this.storage = storage;
this.transactionManager = transactionManager;
}
public static PersistenceManager getPersistenceManager(Storage storage, TransactionManager transactions) {
if (pm == null) {
pm = new PersistenceManager(storage, transactions);
storage.setContext(pm.cache);
}
return pm;
}
public Transaction getTransaction() {
return transactionManager.getTransaction();
}
public Object getOID(Object pc) {
return ((Persistent) pc).getOID();
}
public Object createInstance(Class aclass) {
Object id = generateOID(aclass);
Persistent p = PersistentProxy.getPersitent(aclass, id, true, transactionManager);
cache.put(id, p);
return p;
}
public Object findInstance(Class clasz, Object oid) throws StorageException {
return storage.retrieveObject(clasz, oid);
}
public Set findAll(Class clasz) throws StorageException {
return storage.retrieveAll(clasz);
}
public void removeInstance(Object pc) {
MetaObject p = ((Persistent) pc).getMetaObject();
if (p != null) {
p.remove();
}
}
public void registerClass(Class clasz) throws StorageException {
storage.registerClass(clasz);
}
private synchronized Object generateOID(Class aclass) {
//TODO ADD interface OIDGenerator
byte[] bytes = new byte[8];
int value = seeder.nextInt();
int i = 0;
bytes[i++] = (byte) ((value >>> 24) & 0xFF);
bytes[i++] = (byte) ((value >>> 16) & 0xFF);
bytes[i++] = (byte) ((value >>> 8) & 0xFF);
bytes[i++] = (byte) (value & 0xFF);
value = (int) System.currentTimeMillis() & 0xFFFFFFFF;
bytes[i++] = (byte) ((value >>> 24) & 0xFF);
bytes[i++] = (byte) ((value >>> 16) & 0xFF);
bytes[i++] = (byte) ((value >>> 8) & 0xFF);
bytes[i++] = (byte) (value & 0xFF);
return new Long(new BigInteger(bytes).longValue());
}
}
1.1 jakarta-commons-sandbox/simplestore/src/java/org/apache/commons/simplestore/persistence/impl/DBStorage.java
Index: DBStorage.java
===================================================================
/*
* The Apache Software License, Version 1.1
*
*
* Copyright (c) 2001 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution,
* if any, must include the following acknowledgment:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowledgment may appear in the software itself,
* if and wherever such third-party acknowledgments normally appear.
*
* 4. The names "Apache Cocoon" and "Apache Software Foundation" must
* not be used to endorse or promote products derived from this
* software without prior written permission. For written
* permission, please contact apache@apache.org.
*
* 5. Products derived from this software may not be called "Apache",
* nor may "Apache" appear in their name, without prior written
* permission of the Apache Software Foundation.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*/
package org.apache.commons.simplestore.persistence.impl;
import org.apache.commons.simplestore.cache.Cache;
import org.apache.commons.simplestore.persistence.ObjectNotFound;
import org.apache.commons.simplestore.persistence.Persistent;
import org.apache.commons.simplestore.persistence.MetaObject;
import org.apache.commons.simplestore.persistence.StorageException;
import org.apache.commons.simplestore.persistence.InternalTransaction;
import java.lang.reflect.Proxy;
import java.lang.reflect.Method;
import java.util.Properties;
import java.util.Date;
import java.util.HashSet;
import java.sql.Date;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Types;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.ResourceBundle;
import java.util.Enumeration;
import java.util.Map;
import java.util.Set;
import java.util.List;
import java.util.ArrayList;
import javax.sql.DataSource;
// TODO Synchronization
/**
*@author Juozas Baliuka <a href="mailto:baliuka@mwm.lt">
* baliuka@mwm.lt</a>
*@version $Id: DBStorage.java,v 1.1 2002/02/11 20:23:38 froehlich Exp $
*/
public class DBStorage extends AbstractStorage {
private final static boolean DEBUG = true;
private final static String CONNECTION = "org.apache.commons.simplestore.jdbc.DBStorage.connection";
private static Properties procedures = new Properties();
private Cache cache = null;
private DataSource ds;
/**
* Creates new DBStorageManager
*
*@param ds
*/
public DBStorage(DataSource ds) {
this.ds = ds;
}
// TODO must be converter interface
public static Object toSQLType(Object object) {
if (object == null) {
return null;
}
if (object instanceof Boolean) {
boolean value = ((Boolean) object).booleanValue();
return (value ? new Short((short) 1) : new Short((short) 0));
}
if (object instanceof java.util.Date && !(object instanceof java.sql.Date)) {
return new java.sql.Date(((java.util.Date) object).getTime());
}
return object;
}
// TODO must be mapping interface
public static String toSQLName(String clName) {
String result = clName.substring(clName.lastIndexOf('.') + 1, clName.length());
StringBuffer sb = new StringBuffer();
char cbuff[] = result.toCharArray();
for (int i = 0; i < cbuff.length; i++) {
if (Character.isUpperCase(cbuff[i])) {
if (i != 0) {
sb.append("_" + cbuff[i]);
} else {
sb.append(cbuff[i]);
}
} else {
sb.append(Character.toUpperCase(cbuff[i]));
}
}
return sb.toString();
}
// TODO must be mapping interface
public static String toPropertyName(String tblName) {
final String result = tblName;
final StringBuffer sb = new StringBuffer();
final char cbuff[] = result.toCharArray();
for (int i = 0; i < cbuff.length; i++) {
if (cbuff[i] == '_') {
sb.append(Character.toUpperCase(cbuff[++i]));
} else {
if (i == 0) {
sb.append(Character.toUpperCase(cbuff[i]));
} else {
sb.append(Character.toLowerCase(cbuff[i]));
}
}
}
return sb.toString();
}
// TODO : must be more simple
public static int excecute(Connection connection, String sql, Object[] args, ResultSetHandler eh) throws StorageException {
int result = 0;
try {
final PreparedStatement statement = connection.prepareStatement(sql);
ResultSet rs = null;
if (DEBUG) {
System.out.println(sql);
}
try {
if (args != null) {
for (int i = 1; i <= args.length; i++) {
if (args[i - 1] == null) {
statement.setNull(i, Types.OTHER);
} else {
statement.setObject(i, args[i - 1]);
}
}
}
if ( statement.execute() ) {
rs = statement.getResultSet();
} else {
return statement.getUpdateCount();
}
do {
if (rs != null && eh != null) {
ResultSetMetaData rsmd = rs.getMetaData();
int cnt = rsmd.getColumnCount();
while (rs.next()) {
result++;
for (int i = 1; i <= cnt; i++) {
String name = rsmd.getColumnName(i);
Object val = rs.getObject(i);
eh.nextResult(i, name, val, rsmd.getColumnType(i));
}
}
}
if (statement.getMoreResults()) {
rs = statement.getResultSet();
} else {
break;
}
} while (rs != null);
} finally {
if (rs != null) {
rs.close();
}
if (statement != null) {
statement.close();
}
}
} catch (SQLException se) {
throw new StorageException(sql, se);
}
return result;
}
public void setContext(Cache cache) {
this.cache = cache;
}
public Class getReturnType(Class clasz, String name) throws Throwable {
try {
return clasz.getMethod(name, null).getReturnType();
} catch (NoSuchMethodException nsme) {
throw new NoSuchMethodException("Method " + name + " not found in class " + clasz.getName() + " " + nsme.getMessage());
}
}
public void registerClass(Class clasz) {
try {
ResourceBundle bundle = ResourceBundle.getBundle(clasz.getName() + "Procedures");
Enumeration enum = bundle.getKeys();
while (enum.hasMoreElements()) {
Object key = enum.nextElement();
procedures.setProperty(key.toString(), bundle.getString(key.toString()));
}
} catch (Exception e) {
e.printStackTrace();
}
}
public Object retrieveObject(final Class clasz, Object id) throws StorageException {
final InternalTransaction transaction = getTransaction();
Persistent result = (Persistent) cache.get(id);
if (result != null) {
transaction.add(result.getMetaObject());
return result;
}
final Connection connection = getConnection();
// TODO : ID must be in some mapping
final String sql = "SELECT * FROM " + toSQLName(clasz.getName()) + " WHERE ID=?";
result = (Persistent) PersistentProxy.getPersitent(clasz, id, false, this);
final MetaObject pc = result.getMetaObject();
final Map map = pc.getProperties();
ResultSetHandler rsh =
new ResultSetHandler() {
public void nextResult(int index, String name, Object value, int type) throws StorageException {
try {
if (value != null) {
String property = toPropertyName(name);
if (property.equals("Id")) {
return;
}
map.put(property, PersistentProxy.convert(value, getReturnType(clasz, "get" + property)));
}
} catch (Throwable t) {
t.printStackTrace();
throw new StorageException(t.getMessage(), t);
}
}
};
if ( excecute(connection, sql, new Object[]{id}, rsh) == 0 ) {
throw new ObjectNotFound(pc.getOID().toString(), null);
}
transaction.add(pc);
cache.put(id, result);
return result;
}
public Set retrieveAll(final Class clasz) throws StorageException {
final Connection connection = getConnection();
// TODO : INTERNAL_OID must be in some mapping
final String sql = "SELECT ID AS INTERNAL_OID, * FROM " + toSQLName(clasz.getName());
final Set objects = new HashSet();
final InternalTransaction transaction = getTransaction();
excecute(connection, sql, null, new QueryHandler(objects, clasz));
return objects;
}
public Set query(final Class clasz, String proc, Object[] args) throws StorageException {
final Connection connection = getConnection();
final Set objects = new HashSet();
final InternalTransaction transaction = getTransaction();
proc = procedures.getProperty(proc);
excecute(connection, proc, args, new QueryHandler(objects, clasz));
return objects;
}
public void storeObject(MetaObject properties) throws StorageException {
final Connection connection = getConnection();
final Class clasz = properties.getPersistentClass();
final String name = toSQLName(clasz.getName());
final Method methods[] = clasz.getMethods();
final List values = new ArrayList(methods.length / 2 + 1);
final Map map = properties.getProperties();
final StringBuffer names = new StringBuffer(methods.length * 10);
for (int i = 0; i < methods.length; i++) {
String mName = methods[i].getName();
if (mName.startsWith("set")) {
mName = mName.substring(3);
Object value = toSQLType(map.get(mName));
names.append(toSQLName(mName));
names.append("=?,");
values.add(value);
}
}
names.setCharAt(names.length() - 1, ' ');
// TODO : ID must be in some mapping
names.append("WHERE ID=?");
values.add(properties.getOID());
final String sql = "UPDATE " + name + " SET " + names;
if( excecute(connection, sql, values.toArray(), null ) == 0 ){
throw new ObjectNotFound(properties.getOID().toString(), null);
}
}
// TODO : mot very meanigful here
public void close() {
try {
Connection connection = (Connection) getTransaction().getAttribute(CONNECTION);
if (connection != null) {
connection.close();
}
} catch (Exception e) {
e.printStackTrace();
// TODO
}
}
protected void createObject(MetaObject properties) throws StorageException {
final Connection connection = getConnection();
final Class clasz = properties.getPersistentClass();
final Object id = properties.getOID();
final Method methods[] = clasz.getMethods();
final Map map = properties.getProperties();
final List values = new ArrayList(methods.length / 2 + 1);
String names = "";
String params = "";
values.add(id);
for (int i = 0; i < methods.length; i++) {
String name = methods[i].getName();
if (name.startsWith("set")) {
name = name.substring(3);
Object value = toSQLType(map.get(name));
if (value == null) {
continue;
}
names += "," + toSQLName(name);
values.add(value);
params += ",?";
}
}
//TODO : ID !!!
final String sql = "INSERT INTO " + toSQLName(clasz.getName()) + "(ID" + names + ")VALUES(?" + params + ")";
excecute(connection, sql, values.toArray(), null);
}
protected void removeObject(MetaObject obj) throws StorageException {
final Connection connection = getConnection();
final String name = toSQLName(obj.getPersistentClass().getName());
final Object id = obj.getOID();
// TODO : ID must be in some mapping
final String sql = "DELETE FROM " + name + " WHERE ID=?";
if( excecute(connection, sql, new Object[]{id}, null) == 0 ){
throw new ObjectNotFound(obj.getOID().toString(), null);
}
}
protected void internalCommit() throws StorageException {
try {
Connection connection = getConnection();
try {
connection.commit();
} finally {
connection.close();
}
} catch (SQLException se) {
throw new StorageException(se.getMessage(), se);
}
}
protected void internalRollback() throws StorageException {
try {
Connection connection = getConnection();
try {
connection.rollback();
} finally {
connection.close();
}
} catch (SQLException se) {
throw new StorageException(se.getMessage(), se);
}
}
protected void internalBegin() throws StorageException {
try {
Connection connection = ds.getConnection();
getTransaction().setAttribute(CONNECTION, connection);
} catch (SQLException se) {
throw new StorageException(se.getMessage(), se);
}
}
private Connection getConnection() {
Connection connection = (Connection) getTransaction().getAttribute(CONNECTION);
if (connection == null) {
throw new IllegalStateException("Transaction not Started");
}
return connection;
}
class QueryHandler implements ResultSetHandler {
Map map;
Set objects;
Class clasz;
InternalTransaction transaction = getTransaction();
QueryHandler(Set objects, Class clasz) {
this.objects = objects;
this.clasz = clasz;
}
public void nextResult(int index, String name, Object value, int type) throws StorageException {
try {
if (index == 1) {
Persistent p = (Persistent) cache.get(value);
if (p != null) {
map = null;
objects.add(p);
transaction.add(p.getMetaObject());
return;
}
p = PersistentProxy.getPersitent(clasz, value, false, DBStorage.this);
MetaObject pc = p.getMetaObject();
map = pc.getProperties();
objects.add(p);
transaction.add(pc);
return;
}
String property = toPropertyName(name);
// TODO : ID must be in some mapping
if (property.equals("Id") || map == null) {
return;
}
map.put(property, PersistentProxy.convert(value, getReturnType(clasz, "get" + property)));
} catch (Throwable t) {
t.printStackTrace();
throw new StorageException(t.getMessage(), t);
}
}
}
interface ResultSetHandler {
public void nextResult(int index, String name, Object value, int type) throws StorageException;
}
}
1.1 jakarta-commons-sandbox/simplestore/src/java/org/apache/commons/simplestore/persistence/impl/AbstractStorage.java
Index: AbstractStorage.java
===================================================================
/*
* The Apache Software License, Version 1.1
*
*
* Copyright (c) 2001 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution,
* if any, must include the following acknowledgment:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowledgment may appear in the software itself,
* if and wherever such third-party acknowledgments normally appear.
*
* 4. The names "Apache Cocoon" and "Apache Software Foundation" must
* not be used to endorse or promote products derived from this
* software without prior written permission. For written
* permission, please contact apache@apache.org.
*
* 5. Products derived from this software may not be called "Apache",
* nor may "Apache" appear in their name, without prior written
* permission of the Apache Software Foundation.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*/
package org.apache.commons.simplestore.persistence.impl;
import org.apache.commons.simplestore.persistence.Storage;
import org.apache.commons.simplestore.persistence.InternalTransaction;
import org.apache.commons.simplestore.persistence.TransactionManager;
import org.apache.commons.simplestore.persistence.MetaObject;
import org.apache.commons.simplestore.persistence.StorageException;
import java.util.Map;
import java.util.HashMap;
import java.util.Set;
import java.util.Iterator;
/**
*@author Juozas Baliuka <a href="mailto:baliuka@mwm.lt">
* baliuka@mwm.lt</a>
*@version $Id: AbstractStorage.java,v 1.1 2002/02/11 20:23:38 froehlich Exp $
*/
public abstract class AbstractStorage
implements Storage, InternalTransaction, TransactionManager {
Map attributes = new HashMap();
public void setAttribute(String name, Object value) {
attributes.put(name, value);
}
public InternalTransaction getTransaction() {
return TransactionImpl.getInstance(this);
}
public Object getAttribute(String name) {
return attributes.get(name);
}
public void begin(Set objects) {
try {
internalBegin();
} catch (Throwable t) {
// TODO
t.printStackTrace();
throw new RuntimeException(t.getClass() + ":" + t.getMessage());
}
}
public void add(MetaObject props) {
((InternalTransaction) getTransaction()).add(props);
}
public void commit() {
try {
getTransaction().commit();
internalCommit();
} catch (Throwable t) {
// TODO
t.printStackTrace();
throw new RuntimeException(t.getClass() + ":" + t.getMessage());
}
}
public void begin() {
try {
getTransaction().begin();
internalBegin();
} catch (Throwable t) {
// TODO
throw new RuntimeException(t.getClass() + ":" + t.getMessage());
}
}
public void rollback(Set objects) {
try {
//TODO implement roolback
internalRollback();
objects.clear();
} catch (Throwable t) {
throw new RuntimeException(t.getClass() + ":" + t.getMessage());
}
}
public void rollback() {
try {
getTransaction().rollback();
internalRollback();
} catch (Throwable t) {
// TODO
throw new RuntimeException(t.getClass() + ":" + t.getMessage());
}
}
public void commit(Set objects) {
try {
Iterator iterator = objects.iterator();
while (iterator.hasNext()) {
MetaObject pp = (MetaObject) iterator.next();
if (pp.isNew()) {
createObject(pp);
}
if (pp.isDirty() && !pp.isNew()) {
storeObject(pp);
}
if (pp.isDeleted()) {
removeObject(pp);
}
pp.setDirty(false);
}
objects.clear();
internalCommit();
} catch (Throwable t) {
// TODO
t.printStackTrace();
throw new RuntimeException("Error");
}
}
public void removeAttribute(String name) {
attributes.remove(name);
}
protected abstract void createObject(MetaObject properties) throws StorageException;
protected abstract void removeObject(MetaObject properties) throws StorageException;
protected abstract void internalCommit() throws StorageException;
protected abstract void internalRollback() throws StorageException;
protected abstract void internalBegin() throws StorageException;
}
--
To unsubscribe, e-mail: <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>