1 /*
   2  * Copyright (c) 1997, 2003, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package com.sun.corba.se.impl.oa.poa;
  27 
  28 import java.util.Set ;
  29 import java.util.HashSet ;
  30 import java.util.Map ;
  31 import java.util.HashMap ;
  32 import java.util.Iterator ;
  33 import java.util.Vector ;
  34 
  35 import org.omg.PortableServer.Servant ;
  36 import org.omg.PortableServer.POAPackage.WrongPolicy ;
  37 import org.omg.CORBA.INTERNAL ;
  38 
  39 /**  The ActiveObjectMap maintains associations between servants and
  40  * their keys.  There are two variants, to support whether or not
  41  * multiple IDs per servant are allowed.  This class suppots bidirectional
  42  * traversal of the key-servant association.  Access to an instance of this
  43  * class is serialized by the POA mutex.
  44  */
  45 public abstract class ActiveObjectMap
  46 {
  47     public static class Key {
  48         public byte[] id;
  49 
  50         Key(byte[] id) {
  51             this.id = id;
  52         }
  53 
  54         public String toString() {
  55             StringBuffer buffer = new StringBuffer();
  56             for(int i = 0; i < id.length; i++) {
  57                 buffer.append(Integer.toString((int) id[i], 16));
  58                 if (i != id.length-1)
  59                     buffer.append(":");
  60             }
  61             return buffer.toString();
  62         }
  63 
  64         public boolean equals(java.lang.Object key) {
  65             if (!(key instanceof Key))
  66                 return false;
  67             Key k = (Key) key;
  68             if (k.id.length != this.id.length)
  69                 return false;
  70             for(int i = 0; i < this.id.length; i++)
  71                 if (this.id[i] != k.id[i])
  72                     return false;
  73             return true;
  74         }
  75 
  76         // Use the same hash function as for String
  77         public int hashCode() {
  78             int h = 0;
  79             for (int i = 0; i < id.length; i++)
  80                 h = 31*h + id[i];
  81             return h;
  82         }
  83     }
  84 
  85     protected POAImpl poa ;
  86 
  87     protected ActiveObjectMap( POAImpl poa )
  88     {
  89         this.poa = poa ;
  90     }
  91 
  92     public static ActiveObjectMap create( POAImpl poa, boolean multipleIDsAllowed )
  93     {
  94         if (multipleIDsAllowed)
  95             return new MultipleObjectMap( poa ) ;
  96         else
  97             return new SingleObjectMap(poa ) ;
  98     }
  99 
 100     private Map keyToEntry = new HashMap() ;     // Map< Key, AOMEntry >
 101     private Map entryToServant = new HashMap() ; // Map< AOMEntry, Servant >
 102     private Map servantToEntry = new HashMap() ; // Map< Servant, AOMEntry >
 103 
 104     public final boolean contains(Servant value)
 105     {
 106         return servantToEntry.containsKey( value ) ;
 107     }
 108 
 109     public final boolean containsKey(Key key)
 110     {
 111         return keyToEntry.containsKey(key);
 112     }
 113 
 114     /** get Returbs the entry assigned to the key, or creates a new
 115     * entry in state INVALID if none is present.
 116     */
 117     public final AOMEntry get(Key key)
 118     {
 119         AOMEntry result = (AOMEntry)keyToEntry.get(key);
 120         if (result == null) {
 121             result = new AOMEntry( poa ) ;
 122             putEntry( key, result ) ;
 123         }
 124 
 125         return result ;
 126     }
 127 
 128     public final Servant getServant( AOMEntry entry )
 129     {
 130         return (Servant)entryToServant.get( entry ) ;
 131     }
 132 
 133     public abstract Key getKey(AOMEntry value) throws WrongPolicy ;
 134 
 135     public Key getKey(Servant value) throws WrongPolicy
 136     {
 137         AOMEntry entry = (AOMEntry)servantToEntry.get( value ) ;
 138         return getKey( entry ) ;
 139     }
 140 
 141     protected void putEntry( Key key, AOMEntry value )
 142     {
 143         keyToEntry.put( key, value ) ;
 144     }
 145 
 146     public final void putServant( Servant servant, AOMEntry value )
 147     {
 148         entryToServant.put( value, servant ) ;
 149         servantToEntry.put( servant, value ) ;
 150     }
 151 
 152     protected abstract void removeEntry( AOMEntry entry, Key key ) ;
 153 
 154     public final void remove( Key key )
 155     {
 156         AOMEntry entry = (AOMEntry)keyToEntry.remove( key ) ;
 157         Servant servant = (Servant)entryToServant.remove( entry ) ;
 158         if (servant != null)
 159             servantToEntry.remove( servant ) ;
 160 
 161         removeEntry( entry, key ) ;
 162     }
 163 
 164     public abstract boolean hasMultipleIDs(AOMEntry value) ;
 165 
 166     protected  void clear()
 167     {
 168         keyToEntry.clear();
 169     }
 170 
 171     public final Set keySet()
 172     {
 173         return keyToEntry.keySet() ;
 174     }
 175 }
 176 
 177 class SingleObjectMap extends ActiveObjectMap
 178 {
 179     private Map entryToKey = new HashMap() ;    // Map< AOMEntry, Key >
 180 
 181     public SingleObjectMap( POAImpl poa )
 182     {
 183         super( poa ) ;
 184     }
 185 
 186     public  Key getKey(AOMEntry value) throws WrongPolicy
 187     {
 188         return (Key)entryToKey.get( value ) ;
 189     }
 190 
 191     protected void putEntry(Key key, AOMEntry value)
 192     {
 193         super.putEntry( key, value);
 194 
 195         entryToKey.put( value, key ) ;
 196     }
 197 
 198     public  boolean hasMultipleIDs(AOMEntry value)
 199     {
 200         return false;
 201     }
 202 
 203     // This case does not need the key.
 204     protected void removeEntry(AOMEntry entry, Key key)
 205     {
 206         entryToKey.remove( entry ) ;
 207     }
 208 
 209     public  void clear()
 210     {
 211         super.clear() ;
 212         entryToKey.clear() ;
 213     }
 214 }
 215 
 216 class MultipleObjectMap extends ActiveObjectMap
 217 {
 218     private Map entryToKeys = new HashMap() ;   // Map< AOMEntry, Set< Key > >
 219 
 220     public MultipleObjectMap( POAImpl poa )
 221     {
 222         super( poa ) ;
 223     }
 224 
 225     public  Key getKey(AOMEntry value) throws WrongPolicy
 226     {
 227         throw new WrongPolicy() ;
 228     }
 229 
 230     protected void putEntry(Key key, AOMEntry value)
 231     {
 232         super.putEntry( key, value);
 233 
 234         Set set = (Set)entryToKeys.get( value ) ;
 235         if (set == null) {
 236             set = new HashSet() ;
 237             entryToKeys.put( value, set ) ;
 238         }
 239         set.add( key ) ;
 240     }
 241 
 242     public  boolean hasMultipleIDs(AOMEntry value)
 243     {
 244         Set set = (Set)entryToKeys.get( value ) ;
 245         if (set == null)
 246             return false ;
 247         return set.size() > 1 ;
 248     }
 249 
 250     protected void removeEntry(AOMEntry entry, Key key)
 251     {
 252         Set keys = (Set)entryToKeys.get( entry ) ;
 253         if (keys != null) {
 254             keys.remove( key ) ;
 255             if (keys.isEmpty())
 256                 entryToKeys.remove( entry ) ;
 257         }
 258     }
 259 
 260     public  void clear()
 261     {
 262         super.clear() ;
 263         entryToKeys.clear() ;
 264     }
 265 }