/* * Copyright (c) 1997, 2003, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package org.jboss.com.sun.corba.se.impl.oa.poa; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; import org.omg.PortableServer.Servant; import org.omg.PortableServer.POAPackage.WrongPolicy; /** * The ActiveObjectMap maintains associations between servants and their keys. There are two variants, to support * whether or not multiple IDs per servant are allowed. This class suppots bidirectional traversal of the key-servant * association. Access to an instance of this class is serialized by the POA mutex. */ public abstract class ActiveObjectMap { public static class Key { public byte[] id; Key(byte[] id) { this.id = id; } public String toString() { StringBuffer buffer = new StringBuffer(); for (int i = 0; i < id.length; i++) { buffer.append(Integer.toString(id[i], 16)); if (i != id.length - 1) buffer.append(":"); } return buffer.toString(); } public boolean equals(java.lang.Object key) { if (!(key instanceof Key)) return false; Key k = (Key) key; if (k.id.length != this.id.length) return false; for (int i = 0; i < this.id.length; i++) if (this.id[i] != k.id[i]) return false; return true; } // Use the same hash function as for String public int hashCode() { int h = 0; for (int i = 0; i < id.length; i++) h = 31 * h + id[i]; return h; } } protected POAImpl poa; protected ActiveObjectMap(POAImpl poa) { this.poa = poa; } public static ActiveObjectMap create(POAImpl poa, boolean multipleIDsAllowed) { if (multipleIDsAllowed) return new MultipleObjectMap(poa); else return new SingleObjectMap(poa); } private Map<Key, AOMEntry> keyToEntry = new HashMap<Key, AOMEntry>(); private Map<AOMEntry, Servant> entryToServant = new HashMap<AOMEntry, Servant>(); private Map<Servant, AOMEntry> servantToEntry = new HashMap<Servant, AOMEntry>(); public final boolean contains(Servant value) { return servantToEntry.containsKey(value); } public final boolean containsKey(Key key) { return keyToEntry.containsKey(key); } /** * get Returbs the entry assigned to the key, or creates a new entry in state INVALID if none is present. */ public final AOMEntry get(Key key) { AOMEntry result = keyToEntry.get(key); if (result == null) { result = new AOMEntry(poa); putEntry(key, result); } return result; } public final Servant getServant(AOMEntry entry) { return entryToServant.get(entry); } public abstract Key getKey(AOMEntry value) throws WrongPolicy; public Key getKey(Servant value) throws WrongPolicy { AOMEntry entry = servantToEntry.get(value); return getKey(entry); } protected void putEntry(Key key, AOMEntry value) { keyToEntry.put(key, value); } public final void putServant(Servant servant, AOMEntry value) { entryToServant.put(value, servant); servantToEntry.put(servant, value); } protected abstract void removeEntry(AOMEntry entry, Key key); public final void remove(Key key) { AOMEntry entry = keyToEntry.remove(key); Servant servant = entryToServant.remove(entry); if (servant != null) servantToEntry.remove(servant); removeEntry(entry, key); } public abstract boolean hasMultipleIDs(AOMEntry value); protected void clear() { keyToEntry.clear(); } public final Set<Key> keySet() { return keyToEntry.keySet(); } } class SingleObjectMap extends ActiveObjectMap { private Map<AOMEntry, Key> entryToKey = new HashMap<AOMEntry, Key>(); public SingleObjectMap(POAImpl poa) { super(poa); } public Key getKey(AOMEntry value) throws WrongPolicy { return entryToKey.get(value); } protected void putEntry(Key key, AOMEntry value) { super.putEntry(key, value); entryToKey.put(value, key); } public boolean hasMultipleIDs(AOMEntry value) { return false; } // This case does not need the key. protected void removeEntry(AOMEntry entry, Key key) { entryToKey.remove(entry); } public void clear() { super.clear(); entryToKey.clear(); } } class MultipleObjectMap extends ActiveObjectMap { private Map<AOMEntry, Set<Key>> entryToKeys = new HashMap<AOMEntry, Set<Key>>(); public MultipleObjectMap(POAImpl poa) { super(poa); } public Key getKey(AOMEntry value) throws WrongPolicy { throw new WrongPolicy(); } protected void putEntry(Key key, AOMEntry value) { super.putEntry(key, value); Set<Key> set = entryToKeys.get(value); if (set == null) { set = new HashSet<Key>(); entryToKeys.put(value, set); } set.add(key); } public boolean hasMultipleIDs(AOMEntry value) { Set<Key> set = entryToKeys.get(value); if (set == null) return false; return set.size() > 1; } protected void removeEntry(AOMEntry entry, Key key) { Set<Key> keys = entryToKeys.get(entry); if (keys != null) { keys.remove(key); if (keys.isEmpty()) entryToKeys.remove(entry); } } public void clear() { super.clear(); entryToKeys.clear(); } }