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>