Coverage Report - org.apache.ojb.broker.core.proxy.AbstractProxyFactory
 
Classes in this File Line Coverage Branch Coverage Complexity
AbstractProxyFactory
N/A
N/A
4.1
 
 1  
 package org.apache.ojb.broker.core.proxy;
 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.lang.reflect.Constructor;
 19  
 import java.lang.reflect.InvocationTargetException;
 20  
 import java.lang.reflect.Modifier;
 21  
 import java.util.Collection;
 22  
 import java.util.List;
 23  
 import java.util.Set;
 24  
 
 25  
 import org.apache.ojb.broker.Identity;
 26  
 import org.apache.ojb.broker.ManageableCollection;
 27  
 import org.apache.ojb.broker.PBKey;
 28  
 import org.apache.ojb.broker.PersistenceBrokerException;
 29  
 import org.apache.ojb.broker.metadata.MetadataException;
 30  
 import org.apache.ojb.broker.query.Query;
 31  
 import org.apache.ojb.broker.util.configuration.impl.OjbConfigurator;
 32  
 import org.apache.ojb.broker.util.logging.Logger;
 33  
 import org.apache.ojb.broker.util.logging.LoggerFactory;
 34  
 
 35  
 /**
 36  
  * Abstract implementation for the ProxyFactory
 37  
  *
 38  
  * @author andrew.clute
 39  
  * @version $Id:
 40  
  */
 41  
 public abstract class AbstractProxyFactory implements ProxyFactory
 42  
 {
 43  
     /*
 44  
     arminw:
 45  
     Do we need a serializable ProxyFactory implementation? If yes, we have to fix this class.
 46  
     TODO: ProxyFactory is declared as Serializable but Constructor class is not, but used without transient keyword.
 47  
     */
 48  
 
 49  
     private static Logger log = LoggerFactory.getLogger(AbstractProxyFactory.class);
 50  
     private static transient ProxyFactory singleton;
 51  
 
 52  
     /** The indirection handler class */
 53  
     private Class _indirectionHandlerClass;
 54  
     /** The constructor used for creating indirection handler instances (shortcut) */
 55  
     private transient Constructor _indirectionHandlerConstructor;
 56  
     /** The constructor used for creating list proxies */
 57  
     private Constructor _listProxyConstructor;
 58  
     /** The constructor used for creating set proxies */
 59  
     private Constructor _setProxyConstructor;
 60  
     /** The constructor used for creating collection proxies */
 61  
     private Constructor _collectionProxyConstructor;
 62  
 
 63  
     private static ProxyConfiguration getProxyConfiguration()
 64  
     {
 65  
         return (ProxyConfiguration) OjbConfigurator.getInstance().getConfigurationFor(null);
 66  
     }
 67  
 
 68  
     /**
 69  
      * Returns the constructor of the indirection handler class.
 70  
      *
 71  
      * @return The constructor for indirection handlers
 72  
      */
 73  
     private synchronized Constructor getIndirectionHandlerConstructor()
 74  
     {
 75  
         if(_indirectionHandlerConstructor == null)
 76  
         {
 77  
             Class[] paramType = {PBKey.class, Identity.class};
 78  
 
 79  
             try
 80  
             {
 81  
                 _indirectionHandlerConstructor = getIndirectionHandlerClass().getConstructor(paramType);
 82  
             }
 83  
             catch(NoSuchMethodException ex)
 84  
             {
 85  
                 throw new MetadataException("The class "
 86  
                         + _indirectionHandlerClass.getName()
 87  
                         + " specified for IndirectionHandlerClass"
 88  
                         + " is required to have a public constructor with signature ("
 89  
                         + PBKey.class.getName()
 90  
                         + ", "
 91  
                         + Identity.class.getName()
 92  
                         + ").");
 93  
             }
 94  
         }
 95  
         return _indirectionHandlerConstructor;
 96  
     }
 97  
 
 98  
     /**
 99  
      * Returns the indirection handler class.
 100  
      *
 101  
      * @return The class for indirection handlers
 102  
      */
 103  
     public Class getIndirectionHandlerClass()
 104  
     {
 105  
         if(_indirectionHandlerClass == null)
 106  
         {
 107  
             setIndirectionHandlerClass(getProxyConfiguration().getIndirectionHandlerClass());
 108  
         }
 109  
 
 110  
         return _indirectionHandlerClass;
 111  
     }
 112  
 
 113  
     /**
 114  
      * Sets the indirection handler class.
 115  
      *
 116  
      * @param indirectionHandlerClass The class for indirection handlers
 117  
      */
 118  
     public void setIndirectionHandlerClass(Class indirectionHandlerClass)
 119  
     {
 120  
         if(indirectionHandlerClass == null)
 121  
         {
 122  
             //throw new MetadataException("No IndirectionHandlerClass specified.");
 123  
             /**
 124  
              * andrew.clute
 125  
              * Allow the default IndirectionHandler for the given ProxyFactory implementation
 126  
              * when the parameter is not given
 127  
              */
 128  
             indirectionHandlerClass = getDefaultIndirectionHandlerClass();
 129  
         }
 130  
         if(indirectionHandlerClass.isInterface()
 131  
                 || Modifier.isAbstract(indirectionHandlerClass.getModifiers())
 132  
                 || !getIndirectionHandlerBaseClass().isAssignableFrom(indirectionHandlerClass))
 133  
         {
 134  
             throw new MetadataException("Illegal class "
 135  
                     + indirectionHandlerClass.getName()
 136  
                     + " specified for IndirectionHandlerClass. Must be a concrete subclass of "
 137  
                     + getIndirectionHandlerBaseClass().getName());
 138  
         }
 139  
         _indirectionHandlerClass = indirectionHandlerClass;
 140  
     }
 141  
 
 142  
     /**
 143  
      * Creates a new indirection handler instance.
 144  
      *
 145  
      * @param brokerKey The associated {@link PBKey}.
 146  
      * @param id The subject's ids
 147  
      * @return The new instance
 148  
      */
 149  
     public IndirectionHandler createIndirectionHandler(PBKey brokerKey, Identity id)
 150  
     {
 151  
         Object args[] = {brokerKey, id};
 152  
 
 153  
         try
 154  
         {
 155  
             return (IndirectionHandler) getIndirectionHandlerConstructor().newInstance(args);
 156  
         }
 157  
         catch(InvocationTargetException ex)
 158  
         {
 159  
             throw new PersistenceBrokerException("Exception while creating a new indirection handler instance", ex);
 160  
         }
 161  
         catch(InstantiationException ex)
 162  
         {
 163  
             throw new PersistenceBrokerException("Exception while creating a new indirection handler instance", ex);
 164  
         }
 165  
         catch(IllegalAccessException ex)
 166  
         {
 167  
             throw new PersistenceBrokerException("Exception while creating a new indirection handler instance", ex);
 168  
         }
 169  
     }
 170  
 
 171  
     /**
 172  
      * Retrieves the constructor that is used by OJB to create instances of the given collection proxy
 173  
      * class.
 174  
      *
 175  
      * @param proxyClass The proxy class
 176  
      * @param baseType The required base type of the proxy class
 177  
      * @param typeDesc The type of collection proxy
 178  
      * @return The constructor
 179  
      */
 180  
     private static Constructor retrieveCollectionProxyConstructor(Class proxyClass, Class baseType, String typeDesc)
 181  
     {
 182  
         if(proxyClass == null)
 183  
         {
 184  
             throw new MetadataException("No " + typeDesc + " specified.");
 185  
         }
 186  
         if(proxyClass.isInterface() || Modifier.isAbstract(proxyClass.getModifiers()) || !baseType.isAssignableFrom(proxyClass))
 187  
         {
 188  
             throw new MetadataException("Illegal class "
 189  
                     + proxyClass.getName()
 190  
                     + " specified for "
 191  
                     + typeDesc
 192  
                     + ". Must be a concrete subclass of "
 193  
                     + baseType.getName());
 194  
         }
 195  
 
 196  
         Class[] paramType = {PBKey.class, Class.class, Query.class};
 197  
 
 198  
         try
 199  
         {
 200  
             return proxyClass.getConstructor(paramType);
 201  
         }
 202  
         catch(NoSuchMethodException ex)
 203  
         {
 204  
             throw new MetadataException("The class "
 205  
                     + proxyClass.getName()
 206  
                     + " specified for "
 207  
                     + typeDesc
 208  
                     + " is required to have a public constructor with signature ("
 209  
                     + PBKey.class.getName()
 210  
                     + ", "
 211  
                     + Class.class.getName()
 212  
                     + ", "
 213  
                     + Query.class.getName()
 214  
                     + ").");
 215  
         }
 216  
     }
 217  
 
 218  
     /**
 219  
      * Returns the list proxy class.
 220  
      *
 221  
      * @return The class used for list proxies
 222  
      */
 223  
     public Class getListProxyClass()
 224  
     {
 225  
         return getListProxyConstructor().getDeclaringClass();
 226  
     }
 227  
 
 228  
     /**
 229  
      * Returns the constructor of the list proxy class.
 230  
      *
 231  
      * @return The constructor for list proxies
 232  
      */
 233  
     private Constructor getListProxyConstructor()
 234  
     {
 235  
         if(_listProxyConstructor == null)
 236  
         {
 237  
             setListProxyClass(getProxyConfiguration().getListProxyClass());
 238  
         }
 239  
         return _listProxyConstructor;
 240  
     }
 241  
 
 242  
     /**
 243  
      * Dets the proxy class to use for collection classes that implement the {@link java.util.List} interface.
 244  
      * Notes that the proxy class must implement the {@link java.util.List} interface, and have a constructor
 245  
      * of the signature ({@link org.apache.ojb.broker.PBKey}, {@link java.lang.Class}, {@link org.apache.ojb.broker.query.Query}).
 246  
      *
 247  
      * @param listProxyClass The proxy class
 248  
      */
 249  
     public void setListProxyClass(Class listProxyClass)
 250  
     {
 251  
         _listProxyConstructor = retrieveCollectionProxyConstructor(listProxyClass, List.class, "ListProxyClass");
 252  
     }
 253  
 
 254  
     /**
 255  
      * Returns the set proxy class.
 256  
      *
 257  
      * @return The class used for set proxies
 258  
      */
 259  
     public Class getSetProxyClass()
 260  
     {
 261  
         return getSetProxyConstructor().getDeclaringClass();
 262  
     }
 263  
 
 264  
     /**
 265  
      * Returns the constructor of the set proxy class.
 266  
      *
 267  
      * @return The constructor for set proxies
 268  
      */
 269  
     private Constructor getSetProxyConstructor()
 270  
     {
 271  
         if(_setProxyConstructor == null)
 272  
         {
 273  
             setSetProxyClass(getProxyConfiguration().getSetProxyClass());
 274  
         }
 275  
         return _setProxyConstructor;
 276  
     }
 277  
 
 278  
     /**
 279  
      * Dets the proxy class to use for collection classes that implement the {@link Set} interface.
 280  
      *
 281  
      * @param setProxyClass The proxy class
 282  
      */
 283  
     public void setSetProxyClass(Class setProxyClass)
 284  
     {
 285  
         _setProxyConstructor = retrieveCollectionProxyConstructor(setProxyClass, Set.class, "SetProxyClass");
 286  
     }
 287  
 
 288  
     /**
 289  
      * Returns the collection proxy class.
 290  
      *
 291  
      * @return The class used for collection proxies
 292  
      */
 293  
     public Class getCollectionProxyClass()
 294  
     {
 295  
         return getCollectionProxyConstructor().getDeclaringClass();
 296  
     }
 297  
 
 298  
     /**
 299  
      * Returns the constructor of the generic collection proxy class.
 300  
      *
 301  
      * @return The constructor for collection proxies
 302  
      */
 303  
     private Constructor getCollectionProxyConstructor()
 304  
     {
 305  
         if(_collectionProxyConstructor == null)
 306  
         {
 307  
             setCollectionProxyClass(getProxyConfiguration().getCollectionProxyClass());
 308  
         }
 309  
         return _collectionProxyConstructor;
 310  
     }
 311  
 
 312  
     /**
 313  
      * Dets the proxy class to use for generic collection classes implementing the {@link java.util.Collection} interface.
 314  
      *
 315  
      * @param collectionProxyClass The proxy class
 316  
      */
 317  
     public void setCollectionProxyClass(Class collectionProxyClass)
 318  
     {
 319  
         _collectionProxyConstructor = retrieveCollectionProxyConstructor(collectionProxyClass, Collection.class, "CollectionProxyClass");
 320  
         // we also require the class to be a subclass of ManageableCollection
 321  
         if(!ManageableCollection.class.isAssignableFrom(collectionProxyClass))
 322  
         {
 323  
             throw new MetadataException("Illegal class "
 324  
                     + collectionProxyClass.getName()
 325  
                     + " specified for CollectionProxyClass. Must be a concrete subclass of "
 326  
                     + ManageableCollection.class.getName());
 327  
         }
 328  
     }
 329  
 
 330  
     /**
 331  
      * Determines which proxy to use for the given collection class (list, set or generic collection proxy).
 332  
      *
 333  
      * @param collectionClass The collection class
 334  
      * @return The constructor of the proxy class
 335  
      */
 336  
     private Constructor getCollectionProxyConstructor(Class collectionClass)
 337  
     {
 338  
         if(List.class.isAssignableFrom(collectionClass))
 339  
         {
 340  
             return getListProxyConstructor();
 341  
         }
 342  
         else if(Set.class.isAssignableFrom(collectionClass))
 343  
         {
 344  
             return getSetProxyConstructor();
 345  
         }
 346  
         else
 347  
         {
 348  
             return getCollectionProxyConstructor();
 349  
         }
 350  
     }
 351  
 
 352  
     /**
 353  
      * Create a Collection Proxy for a given query.
 354  
      *
 355  
      * @param brokerKey The key of the persistence broker
 356  
      * @param query The query
 357  
      * @param collectionClass The class to build the proxy for
 358  
      * @return The collection proxy
 359  
      */
 360  
     public ManageableCollection createCollectionProxy(PBKey brokerKey, Query query, Class collectionClass)
 361  
     {
 362  
         Object args[] = {brokerKey, collectionClass, query};
 363  
 
 364  
         try
 365  
         {
 366  
             return (ManageableCollection) getCollectionProxyConstructor(collectionClass).newInstance(args);
 367  
         }
 368  
         catch(InstantiationException ex)
 369  
         {
 370  
             throw new PersistenceBrokerException("Exception while creating a new collection proxy instance", ex);
 371  
         }
 372  
         catch(InvocationTargetException ex)
 373  
         {
 374  
             throw new PersistenceBrokerException("Exception while creating a new collection proxy instance", ex);
 375  
         }
 376  
         catch(IllegalAccessException ex)
 377  
         {
 378  
             throw new PersistenceBrokerException("Exception while creating a new collection proxy instance", ex);
 379  
         }
 380  
     }
 381  
 
 382  
     /**
 383  
      * Get the real Object
 384  
      *
 385  
      * @param objectOrProxy
 386  
      * @return Object
 387  
      */
 388  
     public final Object getRealObject(Object objectOrProxy)
 389  
     {
 390  
         if(isNormalOjbProxy(objectOrProxy))
 391  
         {
 392  
             String msg;
 393  
 
 394  
             try
 395  
             {
 396  
                 return getIndirectionHandler(objectOrProxy).getRealSubject();
 397  
             }
 398  
             catch(ClassCastException e)
 399  
             {
 400  
                 // shouldn't happen but still ...
 401  
                 msg = "The InvocationHandler for the provided Proxy was not an instance of " + IndirectionHandler.class.getName();
 402  
                 log.error(msg);
 403  
                 throw new PersistenceBrokerException(msg, e);
 404  
             }
 405  
             catch(IllegalArgumentException e)
 406  
             {
 407  
                 msg = "Could not retrieve real object for given Proxy: " + objectOrProxy;
 408  
                 log.error(msg);
 409  
                 throw new PersistenceBrokerException(msg, e);
 410  
             }
 411  
             catch(PersistenceBrokerException e)
 412  
             {
 413  
                 log.error("Could not retrieve real object for given Proxy: " + objectOrProxy);
 414  
                 throw e;
 415  
             }
 416  
         }
 417  
         else if(isVirtualOjbProxy(objectOrProxy))
 418  
         {
 419  
             try
 420  
             {
 421  
                 return ((VirtualProxy) objectOrProxy).getRealSubject();
 422  
             }
 423  
             catch(PersistenceBrokerException e)
 424  
             {
 425  
                 log.error("Could not retrieve real object for VirtualProxy: " + objectOrProxy);
 426  
                 throw e;
 427  
             }
 428  
         }
 429  
         else
 430  
         {
 431  
             return objectOrProxy;
 432  
         }
 433  
     }
 434  
 
 435  
     /**
 436  
      * Get the real Object for already materialized Handler
 437  
      *
 438  
      * @param objectOrProxy
 439  
      * @return Object or null if the Handel is not materialized
 440  
      */
 441  
     public Object getRealObjectIfMaterialized(Object objectOrProxy)
 442  
     {
 443  
         if(isNormalOjbProxy(objectOrProxy))
 444  
         {
 445  
             String msg;
 446  
 
 447  
             try
 448  
             {
 449  
                 IndirectionHandler handler = getIndirectionHandler(objectOrProxy);
 450  
 
 451  
                 return handler.alreadyMaterialized() ? handler.getRealSubject() : null;
 452  
             }
 453  
             catch(ClassCastException e)
 454  
             {
 455  
                 // shouldn't happen but still ...
 456  
                 msg = "The InvocationHandler for the provided Proxy was not an instance of " + IndirectionHandler.class.getName();
 457  
                 log.error(msg);
 458  
                 throw new PersistenceBrokerException(msg, e);
 459  
             }
 460  
             catch(IllegalArgumentException e)
 461  
             {
 462  
                 msg = "Could not retrieve real object for given Proxy: " + objectOrProxy;
 463  
                 log.error(msg);
 464  
                 throw new PersistenceBrokerException(msg, e);
 465  
             }
 466  
             catch(PersistenceBrokerException e)
 467  
             {
 468  
                 log.error("Could not retrieve real object for given Proxy: " + objectOrProxy);
 469  
                 throw e;
 470  
             }
 471  
         }
 472  
         else if(isVirtualOjbProxy(objectOrProxy))
 473  
         {
 474  
             try
 475  
             {
 476  
                 VirtualProxy proxy = (VirtualProxy) objectOrProxy;
 477  
 
 478  
                 return proxy.alreadyMaterialized() ? proxy.getRealSubject() : null;
 479  
             }
 480  
             catch(PersistenceBrokerException e)
 481  
             {
 482  
                 log.error("Could not retrieve real object for VirtualProxy: " + objectOrProxy);
 483  
                 throw e;
 484  
             }
 485  
         }
 486  
         else
 487  
         {
 488  
             return objectOrProxy;
 489  
         }
 490  
     }
 491  
 
 492  
     /**
 493  
      * Get the real Class
 494  
      *
 495  
      * @param objectOrProxy
 496  
      * @return Class
 497  
      */
 498  
     public Class getRealClass(Object objectOrProxy)
 499  
     {
 500  
         IndirectionHandler handler;
 501  
 
 502  
         if(isNormalOjbProxy(objectOrProxy))
 503  
         {
 504  
             String msg;
 505  
 
 506  
             try
 507  
             {
 508  
                 handler = getIndirectionHandler(objectOrProxy);
 509  
                 /*
 510  
                  arminw:
 511  
                  think we should return the real class
 512  
                  */
 513  
                 // return handler.getIdentity().getObjectsTopLevelClass();
 514  
                 return handler.getIdentity().getObjectsRealClass();
 515  
             }
 516  
             catch(ClassCastException e)
 517  
             {
 518  
                 // shouldn't happen but still ...
 519  
                 msg = "The InvocationHandler for the provided Proxy was not an instance of " + IndirectionHandler.class.getName();
 520  
                 log.error(msg);
 521  
                 throw new PersistenceBrokerException(msg, e);
 522  
             }
 523  
             catch(IllegalArgumentException e)
 524  
             {
 525  
                 msg = "Could not retrieve real object for given Proxy: " + objectOrProxy;
 526  
                 log.error(msg);
 527  
                 throw new PersistenceBrokerException(msg, e);
 528  
             }
 529  
         }
 530  
         else if(isVirtualOjbProxy(objectOrProxy))
 531  
         {
 532  
             handler = VirtualProxy.getIndirectionHandler((VirtualProxy) objectOrProxy);
 533  
             /*
 534  
              arminw:
 535  
              think we should return the real class
 536  
              */
 537  
             // return handler.getIdentity().getObjectsTopLevelClass();
 538  
             return handler.getIdentity().getObjectsRealClass();
 539  
         }
 540  
         else
 541  
         {
 542  
             return objectOrProxy.getClass();
 543  
         }
 544  
     }
 545  
 
 546  
     /**
 547  
      * Determines whether the given object is an OJB proxy.
 548  
      *
 549  
      * @return <code>true</code> if the object is an OJB proxy
 550  
      */
 551  
     public boolean isNormalOjbProxy(Object proxyOrObject)
 552  
     {
 553  
         return proxyOrObject instanceof OJBProxy;
 554  
     }
 555  
 
 556  
     /**
 557  
      * Determines whether the given object is an OJB virtual proxy.
 558  
      *
 559  
      * @return <code>true</code> if the object is an OJB virtual proxy
 560  
      */
 561  
     public boolean isVirtualOjbProxy(Object proxyOrObject)
 562  
     {
 563  
         return proxyOrObject instanceof VirtualProxy;
 564  
     }
 565  
 
 566  
     /**
 567  
      * Returns <tt>true</tt> if the given object is a {@link java.lang.reflect.Proxy}
 568  
      * or a {@link VirtualProxy} instance.
 569  
      */
 570  
     public boolean isProxy(Object proxyOrObject)
 571  
     {
 572  
         return isNormalOjbProxy(proxyOrObject) || isVirtualOjbProxy(proxyOrObject);
 573  
     }
 574  
 
 575  
     /**
 576  
      * Returns the IndirectionHandler associated with a dynamic proxy. Each
 577  
      * subclass is responsible for it's execution
 578  
      */
 579  
     protected abstract IndirectionHandler getDynamicIndirectionHandler(Object obj);
 580  
 
 581  
     /**
 582  
      * Returns the invocation handler object of the given proxy object.
 583  
      *
 584  
      * @param obj The object
 585  
      * @return The invocation handler if the object is an OJB proxy, or <code>null</code>
 586  
      *         otherwise
 587  
      */
 588  
     public IndirectionHandler getIndirectionHandler(Object obj)
 589  
     {
 590  
         if(obj == null)
 591  
         {
 592  
             return null;
 593  
         }
 594  
         else if(isNormalOjbProxy(obj))
 595  
         {
 596  
             return getDynamicIndirectionHandler(obj);
 597  
         }
 598  
         else if(isVirtualOjbProxy(obj))
 599  
         {
 600  
             return VirtualProxy.getIndirectionHandler((VirtualProxy) obj);
 601  
         }
 602  
         else
 603  
         {
 604  
             return null;
 605  
         }
 606  
 
 607  
     }
 608  
 
 609  
     /**
 610  
      * Determines whether the object is a materialized object, i.e. no proxy or a
 611  
      * proxy that has already been loaded from the database.
 612  
      *
 613  
      * @param object The object to test
 614  
      * @return <code>true</code> if the object is materialized
 615  
      */
 616  
     public boolean isMaterialized(Object object)
 617  
     {
 618  
         IndirectionHandler handler = getIndirectionHandler(object);
 619  
 
 620  
         return handler == null || handler.alreadyMaterialized();
 621  
     }
 622  
 
 623  
     /** Return CollectionProxy for item is item is a CollectionProxy, otherwise return null */
 624  
     public CollectionProxy getCollectionProxy(Object item)
 625  
     {
 626  
         if(isCollectionProxy(item))
 627  
         {
 628  
             return (CollectionProxy) item;
 629  
         }
 630  
         else
 631  
         {
 632  
             return null;
 633  
         }
 634  
     }
 635  
 
 636  
     /**
 637  
      * Reports if item is a CollectionProxy.
 638  
      *
 639  
      * TODO: Provide handling for pluggable collection proxy implementations
 640  
      */
 641  
     public boolean isCollectionProxy(Object item)
 642  
     {
 643  
         return (item instanceof CollectionProxy);
 644  
     }
 645  
 
 646  
     /**
 647  
      * Materialization-safe version of toString. If the object is a yet-unmaterialized proxy,
 648  
      * then only the text "unmaterialized proxy for ..." is returned and the proxy is NOT
 649  
      * materialized. Otherwise, the normal toString method is called. This useful e.g. for
 650  
      * logging etc.
 651  
      *
 652  
      * @param proxy The object for which a string representation shall be generated
 653  
      * @return The string representation
 654  
      */
 655  
     public String toString(Object proxy)
 656  
     {
 657  
         IndirectionHandler handler = getIndirectionHandler(proxy);
 658  
         if((handler != null) && handler.alreadyMaterialized())
 659  
         {
 660  
             return "unmaterialized proxy for " + handler.getIdentity();
 661  
         }
 662  
         else
 663  
         {
 664  
             return proxy.toString();
 665  
         }
 666  
     }
 667  
 
 668  
     public synchronized static ProxyFactory getProxyFactory()
 669  
     {
 670  
         /*
 671  
         TODO: Check usage of singleton.
 672  
         arminw: Think the ProxyFactory instance can be a singleton, because the proxy stuff
 673  
         will never change while runtime.
 674  
         */
 675  
         if(singleton == null)
 676  
         {
 677  
             Class proxyFactoryClass = null;
 678  
             try
 679  
             {
 680  
                 proxyFactoryClass = getProxyConfiguration().getProxyFactoryClass();
 681  
                 singleton = (ProxyFactory) proxyFactoryClass.newInstance();
 682  
             }
 683  
             catch(InstantiationException e)
 684  
             {
 685  
                 throw new MetadataException("Illegal class " + proxyFactoryClass.getName() + " specified for ProxyFactoryClass.");
 686  
             }
 687  
             catch(IllegalAccessException e)
 688  
             {
 689  
                 throw new MetadataException("Illegal class " + proxyFactoryClass.getName() + " specified for ProxyFactoryClass.");
 690  
             }
 691  
         }
 692  
         return singleton;
 693  
     }
 694  
 
 695  
 }