001//
002// Name
003//      $RCSfile: ManagedObject.java,v $
004//
005// Copyright
006//      Copyright 2007-2012 Cloud Software Group, Inc. ALL RIGHTS RESERVED.
007//      Cloud Software Group, Inc. Confidential Information
008//
009// History
010//      $Revision: 1.1.2.22 $ $Date: 2012/04/10 20:26:55 $
011//
012
013package com.kabira.platform;
014
015import java.util.*;
016import com.kabira.platform.annotation.*;
017import java.util.concurrent.ConcurrentMap;
018
019/**
020  * Class to manipulate and find shared memory backed objects.
021  * To create a Java object that persists in shared memory, see the
022  * <code>&#64Managed</code> annotation.
023  * <p>
024  *  Example:
025  *<pre>&#64Managed
026public class Account {
027    public Account(String userName) {
028        super();
029        m_userName = userName;
030    }
031
032    public Account(String userName, Account referrer) {
033        this(userName);
034        allocateMailbox();
035        addToFriendList(referrer);
036    }
037
038    public void addToFriendList(Account friendlyAccount) {
039        ...
040    }
041
042    private void allocateMailbox() {
043        ...
044    }
045
046    private String m_userName;
047    private Account[] m_friendList;
048}</pre>
049 *  Some example usage of the above type:
050 <pre>
051    //
052    //  create a new account in shared memory:
053    //
054    Account newCustomer = new Account("Fred Rogers", referrer);
055    System.out.println("Added " + newCustomer.toString());
056
057    //
058    //  delete all expired accounts from shared memory.
059    //  Note extent access, and use of the delete() method
060    //  to delete the shared memory instance.
061    //
062    for (Account acc : ManagedObject.extent(Account.class)) {
063        if (acc.expireDate &lt; today) {
064            ManagedObject.delete(acc);
065        }
066    }
067 </pre>
068 *
069 *  @see com.kabira.platform.annotation.Managed
070 *  @see com.kabira.platform.Transaction
071 */
072@Managed
073public abstract class ManagedObject
074{
075        /**
076         * Returns all shared memory instances of a Managed type.
077         * <p>
078         * The <code>klass</code> parameter must be a <code>Managed</code>
079         * class, and is used to determine the extent to return.
080         * A Managed class is either annotated <code>&#64Managed</code>, or
081         * extends a class that is so annotated.
082         * <p>
083         * Consider the following example.  It returns all instances of
084         * <code>MyType</code> (including instances of its subtypes)
085         * with no locks held on the objects:
086    <pre>
087    //
088    // Iterate instances of MyType.class, returning all objects in the extent
089    //
090    for (MyType instance : ManagedObject.extent(MyType.class)) {
091        assert ( Transaction.hasReadLock(instance) == false );
092        assert ( Transaction.hasWriteLock(instance) == false );
093        ...
094    }</pre>
095         * @param klass extent class - instances of this type,
096         * and any subtypes that extend from this type, will be returned in
097         * the extent.
098         * @exception ManagedClassError Thrown if <code>klass</code>
099         *   is not Managed (or exactly ManagedObject).
100         * @return <code>Iterable</code> that will traverse all instances 
101         *   located in shared memory.
102         * @see com.kabira.platform.annotation.Managed
103         * @see com.kabira.platform.ManagedClassError
104         */
105        public static <T> java.lang.Iterable<T> extent(
106                final java.lang.Class<T> klass)
107                throws ManagedClassError
108        {
109                return ManagedObject.extent(klass, LockMode.NOLOCK);
110        }
111
112        /**
113          * Returns all shared memory instances of a Managed type,
114          * with an explicit transaction lock taken on each instance
115          * as it is iterated.
116          *<p>
117          * The <code>klass</code> parameter must be a Managed class,
118          * and is used to determine the extent to return.
119          *<p>
120          * The <code>objectLock</code> parameter is used to specify the
121          * transaction lock to take on objects returned during extent 
122          * iteration. The objects are locked as they are returned from the 
123          * <code>java.util.Iterator<T></code>, not when this method
124          * returns.
125          * <p>
126          * Consider the following example.  It returns all instances of
127          * <code>MyType</code> (including instances of its subtypes)
128          * with a READLOCK held on each instance:
129         <pre>
130    //
131    //  Iterate the ManagedObjectSet taking read locks on the objects
132    //
133    for (MyType mt : ManagedObject.extent( MyType.class, LockMode.READLOCK)) {
134        assert ( Transaction.hasReadLock(mt) == true );
135        ...
136    }</pre>
137          * @param klass extent class - instances of this type,
138          *   and any subtypes that extend from this type, will be returned
139          *   in the extent.
140          * @param objectLock object lock - all object instances
141          *   returned during extent iteration will have this transaction lock.
142          * @exception ManagedClassError Thrown if <code>klass</code>
143          *   is not marked Managed, or is exactly ManagedObject.
144          * @return <code>Iterable<klass></code> containing references to
145          *   all instances located in shared memory.
146          * @see com.kabira.platform.annotation.Managed
147          */
148        public static <T> java.lang.Iterable<T> extent(
149                final java.lang.Class<T> klass,
150                final LockMode objectLock)
151                throws ManagedClassError
152        {
153                checkManagedClass(klass, "extent");
154
155                if (klass.equals(ManagedObject.class))
156                {
157                        throw new ManagedClassError(
158                                "extent class cannot be "
159                                + ManagedObject.class.getName() + ".");
160                }
161
162                return new Extent<T>(klass.getName(), objectLock);
163        }
164
165        /** Returns a hash code based on the 
166          * underlying shared memory object.
167          */
168        public static int hashCode(Object o)
169        {
170                return java.util.Arrays.hashCode(
171                        ManagedObject.getObjectReference(o));
172        }
173
174        /** Returns true if both references are proxies to the same
175          * shared memory object.
176          *
177          * @throws ManagedClassError if o1 or o2 is not Managed.
178          */
179        public static boolean equals(Object o1, Object o2)
180                throws ManagedClassError
181        {
182                if (o1 == o2)
183                {
184                        return true;
185                }
186
187                if ((o1 == null) || (o2 == null))
188                {
189                        return false;
190                }
191
192                checkManagedObject(o1, "equals");
193                checkManagedObject(o2, "equals");
194
195                // FIX THIS: can we reduce two JNI calls to one?
196                // FIX THIS: this is inefficient - getObjectReference is a
197                // JNI native, because $m_objectReference is added at class
198                // load time. This should be generated at class load time.
199                return java.util.Arrays.equals(
200                        ManagedObject.getObjectReference(o1),
201                        ManagedObject.getObjectReference(o2));
202        }
203
204        /** Determines if the given object is an instance of a Managed class.
205          * Returns true only if the object, or a superclass, is marked
206          * &#64Managed.
207          */
208        public static boolean isManaged(Object o)
209        {
210                return isManagedClass(o.getClass());
211        }
212
213        /** Determines if the given class is Managed.
214          * Returns true only if the class, or a superclass, is marked
215          * &#64Managed.
216          */
217    @SuppressWarnings("deprecation")
218        public static boolean isManagedClass(Class<?> klass)
219        {
220                return (klass.isAnnotationPresent(Managed.class)
221                        || klass.isAnnotationPresent(Distributed.class));
222        }
223
224        /** If the given object is not Managed, throw a new ManagedClassError.
225          */
226        private static void checkManagedObject(Object o, String methodName)
227                throws ManagedClassError
228        {
229                checkManagedClass(o.getClass(), methodName);
230        }
231
232        /** If the given class is not Managed, throw a new ManagedClassError.
233          */
234        private static void checkManagedClass(Class klass, String methodName)
235                throws ManagedClassError
236        {
237                if (isManagedClass(klass) == false)
238                {
239                        throw new ManagedClassError("Method "
240                                + methodName + "() can only be applied to "
241                                + "Managed classes.");
242                }
243        }
244
245        /** Return the object reference as a byte array. Package-private.
246          * This may return a reference to the actual field, so the result
247          * should be treated as read-only.
248          * FIX THIS: inefficient to use a native for this.
249          */
250        static native byte[] getObjectReference(Object o);
251
252        /** Deletes a Managed object.
253          * @throws ManagedClassError if operand is not Managed.
254          */
255        public static void delete(Object operand)
256                throws ManagedClassError
257        {
258                checkManagedObject(operand, "delete");
259                _deleteSM(operand);
260        }
261
262        /** Returns the number of instances of the given class.
263          *<br>
264          * This count does not require transaction locks on the
265          * extent or any of the individual objects in the extent.
266          *<br>
267          * This means the number returned by cardinality() may 
268          * change even as observed within a single transaction.
269          * @throws ManagedClassError if klass is not Managed.
270          */
271        public static int cardinality(Class<?> operand)
272                throws ManagedClassError
273        {
274                checkManagedClass(operand, "cardinality");
275                return ManagedObject._cardinality(operand.getName());
276        }
277
278        /** Determines if the backing shared memory object has been deleted.
279          * @throws ManagedClassError if the operand object is not of a Managed
280          * class.
281          * @return true if the operand has been deleted, false otherwise. 
282          */
283        public static boolean isEmpty(Object operand)
284                throws ManagedClassError
285        {
286                if (operand == null)
287                {
288                        return true;
289                }
290                checkManagedObject(operand, "isEmpty");
291                return _isEmpty(operand);
292        }
293        
294        /** 
295         * Commit and abort triggers must be enabled in each transaction.
296         * This method enables triggers for all methods in TransactionTriggers
297         * (currently abort and commit).
298         */
299        static void enableTriggers(TransactionTriggers obj)
300        {
301            enableTriggers(ManagedObject.getObjectReference(obj));
302        }
303        native static void enableTriggers(byte[] objectReference);
304
305        /** Determines if the passed in object reference is local
306          * or distributed.
307          * @returns true if the passed in reference is local
308          */
309        private native static boolean isLocal(byte[] objectReference);
310
311        private native static boolean isLocalToJVM(byte[] objectReference);
312
313        private native static boolean _isEmpty(Object operand);
314
315        /** Creates the shared memory object.
316          *
317          * This method does not create shared memory for a JBA keyed type;
318          * the generated JBA constructor should do that instead. 
319          * This method returns the object reference as a byte array. If the
320          * type was not created, a "refNULL" is returned - a byte array
321          * of the appropriate size, with contents zero'ed out.
322          */
323        private static native byte[] createSMObject(String className);
324
325        /**
326          * Invoke post-create triggers.
327          * Does not create or update keys. 
328          */
329        private static native void postCreateTrigger(byte[] objRef);
330
331        /**
332          * Invoke all post-create work in the runtime.
333          */
334        private static native void completeSMObject(
335                byte[] objRef,
336                boolean callTriggers);
337        
338    /**
339          * An exception is being thrown from this constructor;
340      * destroy the (partially-created) shared memory object.
341          */
342        private static native void cancelSMObject(byte[] objRef);
343
344    /**
345     * Set the context class loader for this thread to this classes class
346     * loader.
347     * NOTE this assumes the context class loader is not set. This should
348     * only be called when attaching a Thread via JNI AttachCurrentThread.
349     */
350    private static void setContextClassLoader()
351    {
352        //
353        // FIX THIS: The IBM JVM asserts on this, commented out for now.
354        //
355        // assert(Thread.currentThread().getContextClassLoader() == null);
356        //
357        assert(ManagedObject.class.getClassLoader() != null);
358
359        Thread.currentThread().setContextClassLoader(
360                    ManagedObject.class.getClassLoader());
361    }
362
363        private static native void _deleteSM(Object operand);
364
365        private static native int _cardinality(String className);
366
367    //
368    // Dispatch operations
369    //
370        private native static Any sendTwoWay(
371        final Object object,
372        final int opDomainId,
373        final int opTypeId,
374        final AnyBuffer params);
375        private native static Any sendPinnedTwoWay(
376        final Object object,
377        final int opDomainId,
378        final int opTypeId,
379        final AnyBuffer params);
380        private native static void sendOneWay(
381        final Object object,
382        final int opDomainId,
383        final int opTypeId,
384        final AnyBuffer params);
385
386    //
387    // Method for Reflection support
388    //
389    static Object getObject(Object obj, String fieldName)
390    {
391        TypeDescriptor td = TypeDescriptor.getDescriptor(obj);
392        byte [] objRef = getObjectReference(obj);
393
394        int slotIndex = 0;
395        TypeDescriptor.FieldDescriptor slot = null;
396
397        for (TypeDescriptor.FieldDescriptor fd : td.m_fields)
398        {
399            if (fd.m_name.equals(fieldName))
400            {
401                slot = fd;
402                break;
403            }
404            slotIndex++;
405        }
406        assert( slot != null );
407
408        //
409        // We have to autobox the value based on the slot
410        //
411        switch (slot.m_typeId)
412        {
413        case TypeDescriptor.DSE_TYPEID_INT32:
414            return getIntegerRef(objRef, slotIndex);
415        case TypeDescriptor.DSE_TYPEID_INT64:
416            return getLongRef(objRef, slotIndex);
417        case TypeDescriptor.DSE_TYPEID_INT16:
418            return getShortRef(objRef, slotIndex);
419        case TypeDescriptor.DSE_TYPEID_WCHAR:
420            return getCharacterRef(objRef, slotIndex);
421        case TypeDescriptor.DSE_TYPEID_FLOAT:
422            return getFloatRef(objRef, slotIndex);
423        case TypeDescriptor.DSE_TYPEID_DOUBLE:
424            return getDoubleRef(objRef, slotIndex);
425        case TypeDescriptor.DSE_TYPEID_BOOLEAN:
426            return getBooleanRef(objRef, slotIndex);
427        case TypeDescriptor.DSE_TYPEID_CHAR:
428        case TypeDescriptor.DSE_TYPEID_OCTET:
429            return getByteRef(objRef, slotIndex);
430        }
431
432        //
433        // This handles String, Date and Managed objects
434        //
435        return getReference(objRef, slotIndex);
436    }
437    static void setObject(Object obj, String fieldName, Object v)
438    {
439        TypeDescriptor td = TypeDescriptor.getDescriptor(obj);
440        byte [] objRef = getObjectReference(obj);
441        int slotIndex = td.getSlotIndex(fieldName);
442
443        //
444        // We have to auto-unbox the instance and call the appropriate
445        // setter.
446        //
447        if (v instanceof Integer)
448        {
449            setInteger(((Integer)v).intValue(), objRef, slotIndex);
450        }
451        else if (v instanceof Long)
452        {
453            setLong(((Long)v).longValue(), objRef, slotIndex);
454        }
455        else if (v instanceof Short)
456        {
457            setShort(((Short)v).shortValue(), objRef, slotIndex);
458        }
459        else if (v instanceof Character)
460        {
461            setChar(((Character)v).charValue(), objRef, slotIndex);
462        }
463        else if (v instanceof Float)
464        {
465            setFloat(((Float)v).floatValue(), objRef, slotIndex);
466        }
467        else if (v instanceof Double)
468        {
469            setDouble(((Double)v).doubleValue(), objRef, slotIndex);
470        }
471        else if (v instanceof Boolean)
472        {
473            setBoolean(((Boolean)v).booleanValue(), objRef, slotIndex);
474        }
475        else if (v instanceof Byte)
476        {
477            setByte(((Byte)v).byteValue(), objRef, slotIndex);
478        }
479        else
480        {
481            //
482            // This handles String, Date and Managed objects
483            //
484            setReference(v, objRef, slotIndex);
485        }
486    }
487    static boolean getBoolean(Object obj, String fieldName)
488    {
489        TypeDescriptor td = TypeDescriptor.getDescriptor(obj);
490        Boolean b = getBooleanRef(getObjectReference(obj),
491                    td.getSlotIndex(fieldName));
492        return b.booleanValue();
493    }
494    static void setBoolean(Object obj, String fieldName, boolean b)
495    {
496        TypeDescriptor td = TypeDescriptor.getDescriptor(obj);
497        setBoolean(b, getObjectReference(obj), td.getSlotIndex(fieldName));
498    }
499    static byte getByte(Object obj, String fieldName)
500    {
501        TypeDescriptor td = TypeDescriptor.getDescriptor(obj);
502        Byte v = getByteRef(getObjectReference(obj),
503                    td.getSlotIndex(fieldName));
504        return v.byteValue();
505    }
506    static void setByte(Object obj, String fieldName, byte b)
507    {
508        TypeDescriptor td = TypeDescriptor.getDescriptor(obj);
509        setByte(b, getObjectReference(obj), td.getSlotIndex(fieldName));
510    }
511    static char getChar(Object obj, String fieldName)
512    {
513        TypeDescriptor td = TypeDescriptor.getDescriptor(obj);
514        Character v = getCharacterRef(getObjectReference(obj),
515                    td.getSlotIndex(fieldName));
516        return v.charValue();
517    }
518    static void setChar(Object obj, String fieldName, char c)
519    {
520        TypeDescriptor td = TypeDescriptor.getDescriptor(obj);
521        setChar(c, getObjectReference(obj), td.getSlotIndex(fieldName));
522    }
523    static double getDouble(Object obj, String fieldName)
524    {
525        TypeDescriptor td = TypeDescriptor.getDescriptor(obj);
526        return getDouble(getObjectReference(obj), td.getSlotIndex(fieldName));
527    }
528    static void setDouble(Object obj, String fieldName, double d)
529    {
530        TypeDescriptor td = TypeDescriptor.getDescriptor(obj);
531        setDouble(d, getObjectReference(obj), td.getSlotIndex(fieldName));
532    }
533    static float getFloat(Object obj, String fieldName)
534    {
535        TypeDescriptor td = TypeDescriptor.getDescriptor(obj);
536        return getFloat(getObjectReference(obj), td.getSlotIndex(fieldName));
537    }
538    static void setFloat(Object obj, String fieldName, float f)
539    {
540        TypeDescriptor td = TypeDescriptor.getDescriptor(obj);
541        setFloat(f, getObjectReference(obj), td.getSlotIndex(fieldName));
542    }
543    static int getInt(Object obj, String fieldName)
544    {
545        TypeDescriptor td = TypeDescriptor.getDescriptor(obj);
546        return getInteger(getObjectReference(obj), td.getSlotIndex(fieldName));
547    }
548    static void setInt(Object obj, String fieldName, int i)
549    {
550        TypeDescriptor td = TypeDescriptor.getDescriptor(obj);
551        setInteger(i, getObjectReference(obj), td.getSlotIndex(fieldName));
552    }
553    static long getLong(Object obj, String fieldName)
554    {
555        TypeDescriptor td = TypeDescriptor.getDescriptor(obj);
556        return getLong(getObjectReference(obj), td.getSlotIndex(fieldName));
557    }
558    static void setLong(Object obj, String fieldName, long l)
559    {
560        TypeDescriptor td = TypeDescriptor.getDescriptor(obj);
561        setLong(l, getObjectReference(obj), td.getSlotIndex(fieldName));
562    }
563    static short getShort(Object obj, String fieldName)
564    {
565        TypeDescriptor td = TypeDescriptor.getDescriptor(obj);
566        Short v = getShortRef(getObjectReference(obj),
567                    td.getSlotIndex(fieldName));
568        return v.shortValue();
569    }
570    static void setShort(Object obj, String fieldName, short s)
571    {
572        TypeDescriptor td = TypeDescriptor.getDescriptor(obj);
573        setShort(s, getObjectReference(obj), td.getSlotIndex(fieldName));
574    }
575
576        //
577        // field getters/setters:
578        //
579        private static native Boolean getBooleanRef(
580                byte[] objRef,
581                long slotNum);
582        private static native Byte getByteRef(
583                byte[] objRef,
584                long slotNum);
585        private static native Character getCharacterRef(
586                byte[] objRef,
587                long slotNum);
588        private static native Short getShortRef(
589                byte[] objRef,
590                long slotNum);
591        private static native int getInteger(
592                byte[] objRef,
593                long slotNum);
594        private static native Integer getIntegerRef(
595                byte[] objRef,
596                long slotNum);
597        private static native long getLong(
598                byte[] objRef,
599                long slotNum);
600        private static native Long getLongRef(
601                byte[] objRef,
602                long slotNum);
603        private static native float getFloat(
604                byte[] objRef,
605                long slotNum);
606        private static native Float getFloatRef(
607                byte[] objRef,
608                long slotNum);
609        private static native double getDouble(
610                byte[] objRef,
611                long slotNum);
612        private static native Double getDoubleRef(
613                byte[] objRef,
614                long slotNum);
615        private static native Object getReference(
616                byte[] objRef,
617                long slotNum);
618        private static Object getSerializable(
619                byte[] objRef,
620                long slotNum) 
621        {
622            Any storedval = (Any)getReference(objRef, slotNum);
623            
624            if (storedval == null)
625            {
626                return null;
627            }
628            
629            return Any.deserializeAny(storedval);
630        }
631
632        private static native void setBoolean(
633                boolean val,
634                byte[] objRef,
635                long slotNum);
636        private static native void setBooleanRef(
637                Boolean val,
638                byte[] objRef,
639                long slotNum);
640        private static native void setByte(
641                byte val,
642                byte[] objRef,
643                long slotNum);
644        private static native void setByteRef(
645                Byte val,
646                byte[] objRef,
647                long slotNum);
648        private static native void setChar(
649                char val,
650                byte[] objRef,
651                long slotNum);
652        private static native void setCharacterRef(
653                Character val,
654                byte[] objRef,
655                long slotNum);
656        private static native void setShort(
657                short val,
658                byte[] objRef,
659                long slotNum);
660        private static native void setShortRef(
661                Short val,
662                byte[] objRef,
663                long slotNum);
664        private static native void setInteger(
665                int val,
666                byte[] objRef,
667                long slotNum);
668        private static native void setIntegerRef(
669                Integer val,
670                byte[] objRef,
671                long slotNum);
672        private static native void setLong(
673                long val,
674                byte[] objRef,
675                long slotNum);
676        private static native void setLongRef(
677                Long val,
678                byte[] objRef,
679                long slotNum);
680        private static native void setFloat(
681                float val,
682                byte[] objRef,
683                long slotNum);
684        private static native void setFloatRef(
685                Float val,
686                byte[] objRef,
687                long slotNum);
688        private static native void setDouble(
689                double val,
690                byte[] objRef,
691                long slotNum);
692        private static native void setDoubleRef(
693                Double val,
694                byte[] objRef,
695                long slotNum);
696        private static void setSerializable(
697                Object val,
698                byte[] objRef,
699                long slotNum)
700        {
701            if (val == null)
702            {
703                setReference(null, objRef, slotNum);
704            }
705            else
706            {
707                setReference(new Any(Any.serializeObject(val)), objRef, slotNum);
708            }
709        }
710        
711        private static native void setReference(
712                Object val,
713                byte[] objRef,
714                long slotNum);
715
716        //
717        // array-length operator:
718        //
719        private static native int _getArrayLength(
720                byte[] objref,
721                long slotNum,
722                int[] coords);
723
724        //
725        // Basic-type array getters/setters:
726        //
727        private static native void _setByteArray(
728                byte[] objref,
729                long slotNum,
730                int[] coords,
731                int pos,
732                byte val);
733        private static native void _setCharArray(
734                byte[] objref,
735                long slotNum,
736                int[] coords,
737                int pos,
738                char val);
739        private static native void _setDoubleArray(
740                byte[] objref,
741                long slotNum,
742                int[] coords,
743                int pos,
744                double val);
745        private static native void _setFloatArray(
746                byte[] objref,
747                long slotNum,
748                int[] coords,
749                int pos,
750                float val);
751        private static native void _setIntArray(
752                byte[] objref,
753                long slotNum,
754                int[] coords,
755                int pos,
756                int val);
757        private static native void _setLongArray(
758                byte[] objref,
759                long slotNum,
760                int[] coords,
761                int pos,
762                long val);
763        private static native void _setShortArray(
764                byte[] objref,
765                long slotNum,
766                int[] coords,
767                int pos,
768                short val);
769
770        private static native byte _getByteArray(
771                byte[] objref,
772                long slotNum,
773                int[] coords,
774                int pos);
775        private static native char _getCharArray(
776                byte[] objref,
777                long slotNum,
778                int[] coords,
779                int pos);
780        private static native float _getFloatArray(
781                byte[] objref,
782                long slotNum,
783                int[] coords,
784                int pos);
785        private static native int _getIntArray(
786                byte[] objref,
787                long slotNum,
788                int[] coords,
789                int pos);
790        private static native long _getLongArray(
791                byte[] objref,
792                long slotNum,
793                int[] coords,
794                int pos);
795        private static native short _getShortArray(
796                byte[] objref,
797                long slotNum,
798                int[] coords,
799                int pos);
800        private static native double _getDoubleArray(
801                byte[] objref,
802                long slotNum,
803                int[] coords,
804                int pos);
805
806        private static java.lang.Object _getSerializableArray(
807                byte[] objref,
808                long slotNum,
809                int[] coords,
810                int pos)
811        {
812            Object obj = _getReferenceArray(objref, slotNum, coords, pos);
813            
814            return Any.deserializeAny((Any)obj);
815        }
816        
817        private static void _setSerializableArray(
818                byte[] objref,
819                long slotNum,
820                int[] coords,
821                int pos,
822                java.lang.Object val)
823        {
824            _setReferenceArray(objref, slotNum, coords, pos, new Any(Any.serializeObject(val)));
825        }
826        
827        //
828        // Reference array getters/setters:
829        //
830        private static native java.lang.Object _getReferenceArray(
831                byte[] objref,
832                long slotNum,
833                int[] coords,
834                int pos);
835        private static native void _setReferenceArray(
836                byte[] objref,
837                long slotNum,
838                int[] coords,
839                int pos,
840                java.lang.Object val);
841
842        /**
843         * Used for field sets of @ByReference-annotated fields. This method
844         * is here in ManagedObject so we can keep it private - the classloader
845         * will modify the access flags.
846         */
847        private static Object getByRefMap(
848                Object container,
849                ConcurrentMap<Object, Reference> map)
850        {
851            return Reference.getReference(map, container);
852        }
853
854        /**
855         * Used for field sets of @ByReference-annotated fields. This method
856         * is here in ManagedObject so we can keep it private - the classloader
857         * will modify the access flags.
858         */
859        private static void setByRefMap(
860                Object container,
861                Object val,
862                ConcurrentMap<Object, Reference> map)
863        {
864            Reference.setReference(map, container, val);
865        }
866        
867        /**
868         * Synthetic ByReference field maps are registered with the ReferenceManager
869         * so we can scan for orphaned Reference instances.
870         * This method is here so we can keep it marked private - the classloader
871         * will modify the access flags.
872         * Invoked by synthetic code added to static initializers.
873         */
874        private static void registerFieldMap(ConcurrentMap<Object, Reference> fieldMap)
875        {
876            Reference.registerFieldMap(fieldMap);
877        }
878
879        /** Private class returned from extent() methods (needed to use the
880          * for-each loop).
881          */
882        private static class Extent<T>
883                implements Iterable<T>
884        {
885                private String          m_typeName;
886                private LockMode        m_objectLockMode;
887                Extent(String typeName, LockMode objectLockMode)
888                {
889                        m_typeName = typeName;
890                        m_objectLockMode = objectLockMode;
891                }
892
893                public Iterator<T> iterator()
894                {
895                        return new ExtentIterator<T>(
896                                m_typeName,
897                                m_objectLockMode);
898                }
899        }
900
901        /** Class wrapping readonly access to a Managed extent.
902          */
903        private static class ExtentIterator<T extends Object>
904                implements java.util.Iterator<T>
905        {
906                private LockMode        m_objectLockMode;
907                private long            m_cHandle;
908                private T               m_next;
909
910                ExtentIterator(String typeName, LockMode objectLock)
911                {
912                        m_objectLockMode = objectLock;
913                        m_cHandle = _new(typeName);
914                        m_next = _next(m_cHandle);
915                }
916
917                protected void finalize()
918                {
919                        if (m_cHandle != 0)
920                        {
921                                _delete(m_cHandle);
922                        }
923                        m_cHandle = 0;
924                }
925
926                public boolean hasNext()
927                {
928                        return (m_next != null);
929                }
930
931                public T next()
932                {
933                        T   t = m_next;
934
935                        m_next = _next(m_cHandle);
936
937                        if (m_objectLockMode == LockMode.READLOCK)
938                        {
939                                Transaction.readLockObject(t);
940                        }
941                        else if (m_objectLockMode == LockMode.WRITELOCK)
942                        {
943                                Transaction.writeLockObject(t);
944                        }
945                        else
946                        {
947                                assert ( m_objectLockMode == LockMode.NOLOCK );
948                        }
949
950                        return t;
951                }
952
953                public void remove()
954                {
955                        throw new UnsupportedOperationException();
956                }
957
958                native long _new(String typeName);
959                native T _next(long cHandle);
960                native void _delete(long cHandle);
961        }
962}