Source for gnu.CORBA.Interceptor.gnuIcCurrent

   1: /* gnuIcCurrent.java --
   2:    Copyright (C) 2005 Free Software Foundation, Inc.
   3: 
   4: This file is part of GNU Classpath.
   5: 
   6: GNU Classpath is free software; you can redistribute it and/or modify
   7: it under the terms of the GNU General Public License as published by
   8: the Free Software Foundation; either version 2, or (at your option)
   9: any later version.
  10: 
  11: GNU Classpath is distributed in the hope that it will be useful, but
  12: WITHOUT ANY WARRANTY; without even the implied warranty of
  13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14: General Public License for more details.
  15: 
  16: You should have received a copy of the GNU General Public License
  17: along with GNU Classpath; see the file COPYING.  If not, write to the
  18: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  19: 02110-1301 USA.
  20: 
  21: Linking this library statically or dynamically with other modules is
  22: making a combined work based on this library.  Thus, the terms and
  23: conditions of the GNU General Public License cover the whole
  24: combination.
  25: 
  26: As a special exception, the copyright holders of this library give you
  27: permission to link this library with independent modules to produce an
  28: executable, regardless of the license terms of these independent
  29: modules, and to copy and distribute the resulting executable under
  30: terms of your choice, provided that you also meet, for each linked
  31: independent module, the terms and conditions of the license of that
  32: module.  An independent module is a module which is not derived from
  33: or based on this library.  If you modify this library, you may extend
  34: this exception to your version of the library, but you are not
  35: obligated to do so.  If you do not wish to do so, delete this
  36: exception statement from your version. */
  37: 
  38: 
  39: package gnu.CORBA.Interceptor;
  40: 
  41: import gnu.CORBA.CDR.BufferedCdrOutput;
  42: import gnu.CORBA.Poa.ORB_1_4;
  43: 
  44: import org.omg.CORBA.Any;
  45: import org.omg.CORBA.BAD_INV_ORDER;
  46: import org.omg.CORBA.TCKind;
  47: import org.omg.CORBA.portable.InputStream;
  48: import org.omg.CORBA.portable.ObjectImpl;
  49: import org.omg.PortableInterceptor.Current;
  50: import org.omg.PortableInterceptor.CurrentHelper;
  51: import org.omg.PortableInterceptor.InvalidSlot;
  52: 
  53: import java.util.Hashtable;
  54: import java.util.Iterator;
  55: import java.util.Map;
  56: 
  57: /**
  58:  * Supports the "Interceptor current" concept, providing the slot value
  59:  * information for the current thread. When making the invocation, this
  60:  * information is copied to the Current, returned by ClientRequestInfo.
  61:  *
  62:  * There is only one instance of this class per ORB. It maintains a thread to
  63:  * information map.
  64:  *
  65:  * @author Audrius Meskauskas, Lithuania (AudriusA@Bioinformatics.org)
  66:  */
  67: public class gnuIcCurrent extends ObjectImpl implements Current
  68: {
  69:   /**
  70:    * Use serialVersionUID for interoperability.
  71:    */
  72:   private static final long serialVersionUID = 1;
  73: 
  74:   /**
  75:    * The ORB, controllin this Current. It provides data about the required size
  76:    * of the slot array.
  77:    */
  78:   final ORB_1_4 orb;
  79: 
  80:   /**
  81:    * The table, mapping threads to records.
  82:    */
  83:   private Hashtable threads = new Hashtable();
  84: 
  85:   /**
  86:    * An empty array when no slots are defined, computed once.
  87:    */
  88:   static final Any[] NO_SLOTS = new Any[ 0 ];
  89: 
  90:   /**
  91:    * Create the IC current.
  92:    */
  93:   public gnuIcCurrent(ORB_1_4 an_orb)
  94:   {
  95:     orb = an_orb;
  96:   }
  97: 
  98:   /**
  99:    * Get the array of POA current repository ids.
 100:    *
 101:    * @return a single member array, containing value, returned by the
 102:    * {@link CurrentHelper#id}, normally
 103:    * "IDL:omg.org/PortableInterceptor/Current:1.0".
 104:    */
 105:   public String[] _ids()
 106:   {
 107:     return new String[] { CurrentHelper.id() };
 108:   }
 109: 
 110:   /**
 111:    * Add the entry to the map.
 112:    */
 113:   public void put(Thread t, Any[] record)
 114:   {
 115:     synchronized (threads)
 116:       {
 117:         threads.put(t, record);
 118: 
 119:         // Remove non-running threads, avoiding memory leak.
 120:         if (threads.size() > 12)
 121:           {
 122:             Iterator it = threads.entrySet().iterator();
 123:             while (it.hasNext())
 124:               {
 125:                 Map.Entry e = (Map.Entry) it.next();
 126:                 Thread tx = (Thread) e.getKey();
 127:                 if (!tx.isAlive())
 128:                   {
 129:                     it.remove();
 130:                   }
 131:               }
 132:           }
 133:       }
 134:   }
 135: 
 136:   /**
 137:    * Check if this thread is registered.
 138:    */
 139:   public boolean has(Thread t)
 140:   {
 141:     synchronized (threads)
 142:       {
 143:         return threads.containsKey(t);
 144:       }
 145:   }
 146: 
 147:   /**
 148:    * Remove the entry from the map.
 149:    */
 150:   public void remove(Thread t)
 151:   {
 152:     synchronized (threads)
 153:       {
 154:         threads.remove(t);
 155:       }
 156:   }
 157: 
 158:   /**
 159:    * Get array of all slots, as it is applicable for the current thread. If the
 160:    * slots were not previously allocated, they are allocated during this call.
 161:    */
 162:   Any[] get_slots()
 163:   {
 164:     Any[] r;
 165:     synchronized (threads)
 166:       {
 167:         r = (Any[]) threads.get(Thread.currentThread());
 168:         if (r == null)
 169:           {
 170:             r = new Any[ orb.icSlotSize ];
 171: 
 172:             for (int i = 0; i < r.length; i++)
 173:               {
 174:                 Any a = orb.create_any();
 175:                 a.type(orb.get_primitive_tc(TCKind.tk_null));
 176:                 r [ i ] = a;
 177:               }
 178: 
 179:             put(Thread.currentThread(), r);
 180:           }
 181:         return r;
 182:       }
 183:   }
 184: 
 185:   /**
 186:        * Get copu array of all slots, as it is applicable for the current thread. If
 187:    * the slots were not previously allocated, they are allocated during this
 188:    * call.
 189:    */
 190:   public Any[] clone_slots()
 191:   {
 192:     if (orb.icSlotSize == 0)
 193:       {
 194:         return NO_SLOTS;
 195:       }
 196:     else
 197:       {
 198:         Any[] r = get_slots();
 199:         Any[] copy = new Any[ r.length ];
 200: 
 201:         BufferedCdrOutput buf = new BufferedCdrOutput();
 202:         buf.setOrb(orb);
 203: 
 204:         for (int i = 0; i < copy.length; i++)
 205:           {
 206:             r [ i ].write_value(buf);
 207:           }
 208: 
 209:         InputStream input = buf.create_input_stream();
 210: 
 211:         for (int i = 0; i < copy.length; i++)
 212:           {
 213:             copy [ i ] = orb.create_any();
 214:             copy [ i ].read_value(input, r [ i ].type());
 215:           }
 216: 
 217:         return copy;
 218:       }
 219:   }
 220: 
 221:   /**
 222:    * Get value for the slot with the given id. If the array of Currents has not
 223:    * been yet allocated for the current thread, it is allocated during the
 224:    * invocation of this method.
 225:    */
 226:   public Any get_slot(int slot_id) throws InvalidSlot, BAD_INV_ORDER
 227:   {
 228:     try
 229:       {
 230:         return get_slots() [ slot_id ];
 231:       }
 232:     catch (ArrayIndexOutOfBoundsException e)
 233:       {
 234:         throw new InvalidSlot("Slot " + slot_id);
 235:       }
 236:   }
 237: 
 238:   /**
 239:    * Set value for the slot with the given id. If the array of Currents has not
 240:    * been yet allocated for the current thread, it is allocated during the
 241:    * invocation of this method.
 242:    */
 243:   public void set_slot(int slot_id, Any data)
 244:     throws InvalidSlot, BAD_INV_ORDER
 245:   {
 246:     try
 247:       {
 248:         get_slots() [ slot_id ] = data;
 249:       }
 250:     catch (ArrayIndexOutOfBoundsException e)
 251:       {
 252:         throw new InvalidSlot("Slot " + slot_id);
 253:       }
 254:   }
 255: }