Coverage Report - org.apache.ojb.odmg.NamedRootsMap
 
Classes in this File Line Coverage Branch Coverage Complexity
NamedRootsMap
N/A
N/A
2.6
NamedRootsMap$NamedEntry
N/A
N/A
2.6
 
 1  
 package org.apache.ojb.odmg;
 2  
 
 3  
 /* Copyright 2002-2005 The Apache Software Foundation
 4  
  *
 5  
  * Licensed under the Apache License, Version 2.0 (the "License");
 6  
  * you may not use this file except in compliance with the License.
 7  
  * You may obtain a copy of the License at
 8  
  *
 9  
  *     http://www.apache.org/licenses/LICENSE-2.0
 10  
  *
 11  
  * Unless required by applicable law or agreed to in writing, software
 12  
  * distributed under the License is distributed on an "AS IS" BASIS,
 13  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 14  
  * See the License for the specific language governing permissions and
 15  
  * limitations under the License.
 16  
  */
 17  
 
 18  
 import java.io.Serializable;
 19  
 import java.util.HashMap;
 20  
 import java.util.Iterator;
 21  
 import java.util.Map;
 22  
 
 23  
 import org.apache.commons.lang.SerializationUtils;
 24  
 import org.apache.ojb.broker.Identity;
 25  
 import org.apache.ojb.broker.PersistenceBroker;
 26  
 import org.apache.ojb.broker.PersistenceBrokerException;
 27  
 import org.apache.ojb.broker.core.proxy.ProxyHelper;
 28  
 import org.apache.ojb.broker.metadata.ClassDescriptor;
 29  
 import org.apache.ojb.broker.util.ObjectModification;
 30  
 import org.apache.ojb.broker.util.logging.Logger;
 31  
 import org.apache.ojb.broker.util.logging.LoggerFactory;
 32  
 import org.odmg.ClassNotPersistenceCapableException;
 33  
 import org.odmg.ObjectNameNotFoundException;
 34  
 import org.odmg.ObjectNameNotUniqueException;
 35  
 import org.odmg.Transaction;
 36  
 
 37  
 /**
 38  
  * ODMG NamedRoots implementation.
 39  
  * this implementation stores the (name, Identity) pairs in
 40  
  * a database table.
 41  
  * therefore the NamedRootsMap underlies the same transaction management
 42  
  * as all other persistent objects
 43  
  *
 44  
  * @author Thomas Mahler
 45  
  * @version $Id: NamedRootsMap.java,v 1.1 2007-08-24 22:17:37 ewestfal Exp $
 46  
  */
 47  
 public class NamedRootsMap
 48  
 {
 49  
     private Logger log = LoggerFactory.getLogger(NamedRootsMap.class);
 50  
     private TransactionImpl tx;
 51  
     private HashMap tempBindings;
 52  
     private Map deletionMap;
 53  
     private Map insertMap;
 54  
 
 55  
     NamedRootsMap(TransactionImpl tx)
 56  
     {
 57  
         this.tx = tx;
 58  
         this.tempBindings = new HashMap();
 59  
     }
 60  
 
 61  
     private void addForDeletion(NamedEntry entry)
 62  
     {
 63  
         if(deletionMap == null)
 64  
         {
 65  
             deletionMap = new HashMap();
 66  
         }
 67  
         deletionMap.put(entry.getName(), entry);
 68  
     }
 69  
 
 70  
     private void addForInsert(NamedEntry entry)
 71  
     {
 72  
         if(insertMap == null)
 73  
         {
 74  
             insertMap = new HashMap();
 75  
         }
 76  
         insertMap.put(entry.getName(), entry);
 77  
         if(deletionMap != null) deletionMap.remove(entry.getName());
 78  
     }
 79  
 
 80  
     /**
 81  
      * Have to be performed after the "normal" objects be written
 82  
      * to DB and before method {@link #performInsert()}.
 83  
      */
 84  
     public void performDeletion()
 85  
     {
 86  
         if(deletionMap == null)
 87  
             return;
 88  
         else
 89  
         {
 90  
             PersistenceBroker broker = tx.getBroker();
 91  
             Iterator it = deletionMap.values().iterator();
 92  
             while(it.hasNext())
 93  
             {
 94  
                 NamedEntry namedEntry = (NamedEntry) it.next();
 95  
                 broker.delete(namedEntry);
 96  
             }
 97  
         }
 98  
     }
 99  
 
 100  
     /**
 101  
      * Have to be performed after the "normal" objects be written
 102  
      * to DB and after method {@link #performDeletion()}.
 103  
      */
 104  
     public void performInsert()
 105  
     {
 106  
         if(insertMap == null)
 107  
             return;
 108  
         else
 109  
         {
 110  
             PersistenceBroker broker = tx.getBroker();
 111  
             Iterator it = insertMap.values().iterator();
 112  
             while(it.hasNext())
 113  
             {
 114  
                 NamedEntry namedEntry = (NamedEntry) it.next();
 115  
                 namedEntry.prepareForStore(broker);
 116  
                 broker.store(namedEntry, ObjectModification.INSERT);
 117  
             }
 118  
         }
 119  
     }
 120  
 
 121  
     public void afterWriteCleanup()
 122  
     {
 123  
         if(deletionMap != null) deletionMap.clear();
 124  
         if(insertMap != null) insertMap.clear();
 125  
     }
 126  
 
 127  
     private void localBind(String key, NamedEntry entry) throws ObjectNameNotUniqueException
 128  
     {
 129  
         if(tempBindings.containsKey(key))
 130  
         {
 131  
             throw new ObjectNameNotUniqueException("Object key already in use, the key '"
 132  
                     + key + "' is not unique");
 133  
         }
 134  
         else
 135  
         {
 136  
             tempBindings.put(key, entry);
 137  
         }
 138  
     }
 139  
 
 140  
     private void localUnbind(String key)
 141  
     {
 142  
         tempBindings.remove(key);
 143  
     }
 144  
 
 145  
     private NamedEntry localLookup(String key)
 146  
     {
 147  
         return (NamedEntry) tempBindings.get(key);
 148  
     }
 149  
 
 150  
     /**
 151  
      * Return a named object associated with the specified key.
 152  
      */
 153  
     Object lookup(String key) throws ObjectNameNotFoundException
 154  
     {
 155  
         Object result = null;
 156  
         NamedEntry entry = localLookup(key);
 157  
         // can't find local bound object
 158  
         if(entry == null)
 159  
         {
 160  
             try
 161  
             {
 162  
                 PersistenceBroker broker = tx.getBroker();
 163  
                 // build Identity to lookup entry
 164  
                 Identity oid = broker.serviceIdentity().buildIdentity(NamedEntry.class, key);
 165  
                 entry = (NamedEntry) broker.getObjectByIdentity(oid);
 166  
             }
 167  
             catch(Exception e)
 168  
             {
 169  
                 log.error("Can't materialize bound object for key '" + key + "'", e);
 170  
             }
 171  
         }
 172  
         if(entry == null)
 173  
         {
 174  
             log.info("No object found for key '" + key + "'");
 175  
         }
 176  
         else
 177  
         {
 178  
             Object obj = entry.getObject();
 179  
             // found a persistent capable object associated with that key
 180  
             if(obj instanceof Identity)
 181  
             {
 182  
                 Identity objectIdentity = (Identity) obj;
 183  
                 result = tx.getBroker().getObjectByIdentity(objectIdentity);
 184  
                 // lock the persistance capable object
 185  
                 RuntimeObject rt = new RuntimeObject(result, objectIdentity, tx, false);
 186  
                 tx.lockAndRegister(rt, Transaction.READ, tx.getRegistrationList());
 187  
             }
 188  
             else
 189  
             {
 190  
                 // nothing else to do
 191  
                 result = obj;
 192  
             }
 193  
         }
 194  
         if(result == null) throw new ObjectNameNotFoundException("Can't find named object for name '" + key + "'");
 195  
         return result;
 196  
     }
 197  
 
 198  
     /**
 199  
      * Remove a named object
 200  
      */
 201  
     void unbind(String key)
 202  
     {
 203  
         NamedEntry entry = new NamedEntry(key, null, false);
 204  
         localUnbind(key);
 205  
         addForDeletion(entry);
 206  
     }
 207  
 
 208  
     public void bind(Object object, String name) throws ObjectNameNotUniqueException
 209  
     {
 210  
         boolean useIdentity = true;
 211  
         PersistenceBroker broker = tx.getBroker();
 212  
         ClassDescriptor cld = null;
 213  
         try
 214  
         {
 215  
             cld = broker.getClassDescriptor(ProxyHelper.getRealClass(object));
 216  
         }
 217  
         catch(PersistenceBrokerException e)
 218  
         {
 219  
         }
 220  
 
 221  
         // if null a non-persistent capable object was specified
 222  
         if(cld == null)
 223  
         {
 224  
             useIdentity = false;
 225  
             if(!(object instanceof Serializable))
 226  
             {
 227  
                 throw new ClassNotPersistenceCapableException(
 228  
                         "Can't bind named object, because it's not Serializable. Name=" + name + ", object=" + object);
 229  
             }
 230  
         }
 231  
         else
 232  
         {
 233  
             RuntimeObject rt = new RuntimeObject(object, tx);
 234  
             // if the object is already persistet, check for read
 235  
             // lock to make sure
 236  
             // that the used object is a valid version
 237  
             // else persist the specified named object
 238  
             if(!rt.isNew())
 239  
             {
 240  
                 tx.lockAndRegister(rt, Transaction.READ, tx.getRegistrationList());
 241  
             }
 242  
             else
 243  
             {
 244  
                 tx.makePersistent(rt);
 245  
             }
 246  
         }
 247  
         NamedEntry oldEntry = localLookup(name);
 248  
         if(oldEntry == null)
 249  
         {
 250  
             Identity oid = broker.serviceIdentity().buildIdentity(NamedEntry.class, name);
 251  
             oldEntry = (NamedEntry) broker.getObjectByIdentity(oid);
 252  
         }
 253  
         if(oldEntry != null)
 254  
         {
 255  
             throw new ObjectNameNotUniqueException("The name of the specified named object already exist, name=" + name);
 256  
         }
 257  
 
 258  
         NamedEntry entry = new NamedEntry(name, object, useIdentity);
 259  
         addForInsert(entry);
 260  
         localBind(name, entry);
 261  
     }
 262  
 
 263  
 
 264  
 
 265  
     //==============================================
 266  
     // inner class
 267  
     //==============================================
 268  
     /**
 269  
      * represents an entry to the named roots table.
 270  
      * maps names (Strings) to OJB Identities
 271  
      */
 272  
     public static final class NamedEntry implements Serializable
 273  
     {
 274  
         static final long serialVersionUID = 6179717896336300342L;
 275  
         /**
 276  
          * the name under which an object is registered in the NamedRoots Map
 277  
          */
 278  
         private String name;
 279  
         /**
 280  
          * the serialized Identity representing the named Object
 281  
          */
 282  
         private byte[] oid;
 283  
 
 284  
         private transient Object object;
 285  
         private transient boolean useIdentity;
 286  
 
 287  
         public NamedEntry()
 288  
         {
 289  
         }
 290  
 
 291  
         NamedEntry(final String aName, final Object object, final boolean useIdentity)
 292  
         {
 293  
             this.name = aName;
 294  
             this.object = object;
 295  
             this.useIdentity = useIdentity;
 296  
         }
 297  
 
 298  
         /**
 299  
          * This has to be called before this object will be persistet.
 300  
          */
 301  
         public void prepareForStore(PersistenceBroker broker)
 302  
         {
 303  
             if(object != null)
 304  
             {
 305  
                 if(useIdentity)
 306  
                 {
 307  
                     Identity oid = broker.serviceIdentity().buildIdentity(object);
 308  
                     this.oid = SerializationUtils.serialize(oid);
 309  
                 }
 310  
                 else
 311  
                 {
 312  
                     this.oid = SerializationUtils.serialize((Serializable) object);
 313  
                 }
 314  
             }
 315  
         }
 316  
 
 317  
         public String getName()
 318  
         {
 319  
             return name;
 320  
         }
 321  
 
 322  
         public void setName(String name)
 323  
         {
 324  
             this.name = name;
 325  
         }
 326  
 
 327  
         public byte[] getOid()
 328  
         {
 329  
             return oid;
 330  
         }
 331  
 
 332  
         public void setOid(byte[] oid)
 333  
         {
 334  
             this.oid = oid;
 335  
         }
 336  
 
 337  
         Object getObject()
 338  
         {
 339  
             if(object != null)
 340  
             {
 341  
                 return object;
 342  
             }
 343  
             else
 344  
             {
 345  
                 return oid != null ? SerializationUtils.deserialize(oid) : null;
 346  
             }
 347  
         }
 348  
     }
 349  
 }