duke@1: /* ohair@158: * Copyright (c) 1998, 2007, Oracle and/or its affiliates. All rights reserved. duke@1: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. duke@1: * duke@1: * This code is free software; you can redistribute it and/or modify it duke@1: * under the terms of the GNU General Public License version 2 only, as ohair@158: * published by the Free Software Foundation. Oracle designates this duke@1: * particular file as subject to the "Classpath" exception as provided ohair@158: * by Oracle in the LICENSE file that accompanied this code. duke@1: * duke@1: * This code is distributed in the hope that it will be useful, but WITHOUT duke@1: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or duke@1: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License duke@1: * version 2 for more details (a copy is included in the LICENSE file that duke@1: * accompanied this code). duke@1: * duke@1: * You should have received a copy of the GNU General Public License version duke@1: * 2 along with this work; if not, write to the Free Software Foundation, duke@1: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. duke@1: * ohair@158: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA ohair@158: * or visit www.oracle.com if you need additional information or have any ohair@158: * questions. duke@1: */ duke@1: duke@1: /* duke@1: * Licensed Materials - Property of IBM duke@1: * RMI-IIOP v1.0 duke@1: * Copyright IBM Corp. 1998 1999 All Rights Reserved duke@1: * duke@1: */ duke@1: duke@1: package sun.rmi.rmic.iiop; duke@1: duke@1: import java.util.Hashtable; duke@1: duke@1: /** duke@1: * A NameContext enables detection of strings which differ only duke@1: * in case. duke@1: * duke@1: * @author Bryan Atsatt duke@1: */ duke@1: class NameContext { duke@1: duke@1: private Hashtable table; duke@1: private boolean allowCollisions; duke@1: duke@1: /** duke@1: * Get a context for the given name. Name may be null, in duke@1: * which case this method will return the default context. duke@1: */ duke@1: public static synchronized NameContext forName (String name, duke@1: boolean allowCollisions, duke@1: BatchEnvironment env) { duke@1: duke@1: NameContext result = null; duke@1: duke@1: // Do we need to use the default context? duke@1: duke@1: if (name == null) { duke@1: duke@1: // Yes. duke@1: duke@1: name = "null"; duke@1: } duke@1: duke@1: // Have we initialized our hashtable? duke@1: duke@1: if (env.nameContexts == null) { duke@1: duke@1: // Nope, so do it... duke@1: duke@1: env.nameContexts = new Hashtable(); duke@1: duke@1: } else { duke@1: duke@1: // Yes, see if we already have the requested duke@1: // context... duke@1: duke@1: result = (NameContext) env.nameContexts.get(name); duke@1: } duke@1: duke@1: // Do we have the requested context? duke@1: duke@1: if (result == null) { duke@1: duke@1: // Nope, so create and add it... duke@1: duke@1: result = new NameContext(allowCollisions); duke@1: duke@1: env.nameContexts.put(name,result); duke@1: } duke@1: duke@1: return result; duke@1: } duke@1: duke@1: /** duke@1: * Construct a context. duke@1: * @param allowCollisions true if case-sensitive name collisions duke@1: * are allowed, false if not. duke@1: */ duke@1: public NameContext (boolean allowCollisions) { duke@1: this.allowCollisions = allowCollisions; duke@1: table = new Hashtable(); duke@1: } duke@1: duke@1: /** duke@1: * Add a name to this context. If constructed with allowCollisions duke@1: * false and a collision occurs, this method will throw an exception duke@1: * in which the message contains the string: "name" and "collision". duke@1: */ duke@1: public void assertPut (String name) throws Exception { duke@1: duke@1: String message = add(name); duke@1: duke@1: if (message != null) { duke@1: throw new Exception(message); duke@1: } duke@1: } duke@1: duke@1: /** duke@1: * Add a name to this context.. duke@1: */ duke@1: public void put (String name) { duke@1: duke@1: if (allowCollisions == false) { duke@1: throw new Error("Must use assertPut(name)"); duke@1: } duke@1: duke@1: add(name); duke@1: } duke@1: duke@1: /** duke@1: * Add a name to this context. If constructed with allowCollisions duke@1: * false and a collision occurs, this method will return a message duke@1: * string, otherwise returns null. duke@1: */ duke@1: private String add (String name) { duke@1: duke@1: // First, create a key by converting name to lowercase... duke@1: duke@1: String key = name.toLowerCase(); duke@1: duke@1: // Does this key exist in the context? duke@1: duke@1: Name value = (Name) table.get(key); duke@1: duke@1: if (value != null) { duke@1: duke@1: // Yes, so they match if we ignore case. Do they match if duke@1: // we don't ignore case? duke@1: duke@1: if (!name.equals(value.name)) { duke@1: duke@1: // No, so this is a case-sensitive match. Are we duke@1: // supposed to allow this? duke@1: duke@1: if (allowCollisions) { duke@1: duke@1: // Yes, make sure it knows that it collides... duke@1: duke@1: value.collisions = true; duke@1: duke@1: } else { duke@1: duke@1: // No, so return a message string... duke@1: duke@1: return new String("\"" + name + "\" and \"" + value.name + "\""); duke@1: } duke@1: } duke@1: } else { duke@1: duke@1: // No, so add it... duke@1: duke@1: table.put(key,new Name(name,false)); duke@1: } duke@1: duke@1: return null; duke@1: } duke@1: duke@1: /** duke@1: * Get a name from the context. If it has collisions, the name duke@1: * will be converted as specified in section 5.2.7. duke@1: */ duke@1: public String get (String name) { duke@1: duke@1: Name it = (Name) table.get(name.toLowerCase()); duke@1: String result = name; duke@1: duke@1: // Do we need to mangle it? duke@1: duke@1: if (it.collisions) { duke@1: duke@1: // Yep, so do it... duke@1: duke@1: int length = name.length(); duke@1: boolean allLower = true; duke@1: duke@1: for (int i = 0; i < length; i++) { duke@1: duke@1: if (Character.isUpperCase(name.charAt(i))) { duke@1: result += "_"; duke@1: result += i; duke@1: allLower = false; duke@1: } duke@1: } duke@1: duke@1: if (allLower) { duke@1: result += "_"; duke@1: } duke@1: } duke@1: duke@1: return result; duke@1: } duke@1: duke@1: /** duke@1: * Remove all entries. duke@1: */ duke@1: public void clear () { duke@1: table.clear(); duke@1: } duke@1: duke@1: public class Name { duke@1: public String name; duke@1: public boolean collisions; duke@1: duke@1: public Name (String name, boolean collisions) { duke@1: this.name = name; duke@1: this.collisions = collisions; duke@1: } duke@1: } duke@1: }