/**
*
* Copyright 2003-2004 The Apache Software Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.geronimo.naming.enc;
import javax.naming.Context;
import javax.naming.LinkRef;
import javax.naming.Name;
import javax.naming.NamingException;
import javax.naming.Reference;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
/**
* @version $Rev: 355877 $ $Date: 2005-12-11 03:48:27 +0100 (Sun, 11 Dec 2005) $
*/
public final class EnterpriseNamingContext extends AbstractReadOnlyContext {
private final Map localBindings;
private final Map globalBindings;
public static Context createEnterpriseNamingContext(Map context) throws NamingException {
return new EnterpriseNamingContext(context);
}
public EnterpriseNamingContext(Map context) throws NamingException {
super("");
validateBindings(context);
preprocessBindings(context);
Node rootContext = buildTree(context);
Map localBindings = new HashMap(rootContext.size());
for (Iterator iterator = rootContext.entrySet().iterator(); iterator.hasNext();) {
Map.Entry entry = (Map.Entry) iterator.next();
String name = (String) entry.getKey();
Object value = entry.getValue();
if (value instanceof Node) {
Context nestedContext = new NestedEnterpriseNamingContext(name, (Node) value);
localBindings.put(name, nestedContext);
} else {
localBindings.put(name, value);
}
}
this.localBindings = Collections.unmodifiableMap(localBindings);
Map globalBindings = buildGlobalBindings("", localBindings);
this.globalBindings = Collections.unmodifiableMap(globalBindings);
}
private static void validateBindings(Map bindings) {
for (Iterator iterator = bindings.entrySet().iterator(); iterator.hasNext();) {
Map.Entry entry = (Map.Entry) iterator.next();
String name = (String) entry.getKey();
Object value = entry.getValue();
if (value instanceof Context) {
throw new IllegalArgumentException("EnterpriseNamingContext can not contain a nested Context object: name=" + name);
}
if (value instanceof LinkRef) {
throw new IllegalArgumentException("EnterpriseNamingContext can not contain a nested LinkRef object: name=" + name);
}
}
}
private static void preprocessBindings(Map bindings) {
for (Iterator iterator = new HashMap(bindings).entrySet().iterator(); iterator.hasNext();) {
Map.Entry entry = (Map.Entry) iterator.next();
String name = (String) entry.getKey();
Object value = entry.getValue();
if (value instanceof Reference) {
bindings.put(name, new CachingReference(name, (Reference)value));
}
}
}
private static Node buildTree(Map context) throws NamingException {
Node rootContext = new Node();
// ENC must always contain an env context
rootContext.put("env", new Node());
for (Iterator iterator = context.entrySet().iterator(); iterator.hasNext();) {
Map.Entry entry = (Map.Entry) iterator.next();
String name = (String) entry.getKey();
Object value = entry.getValue();
Node parentContext = rootContext;
Name compoundName = EnterpriseNamingContextNameParser.INSTANCE.parse(name);
for (Enumeration parts = compoundName.getAll(); parts.hasMoreElements(); ) {
String part = (String) parts.nextElement();
// the last element in the path is the name of the value
if (parts.hasMoreElements()) {
// nest context into parent
Node bindings = (Node) parentContext.get(part);
if (bindings == null) {
bindings = new Node();
parentContext.put(part, bindings);
}
parentContext = bindings;
}
}
parentContext.put(compoundName.get(compoundName.size() - 1), value);
}
return rootContext;
}
private static Map buildGlobalBindings(String nameInNamespace, Map context) {
String path = nameInNamespace;
if (path.length() > 0) {
path += "/";
}
Map globalBindings = new HashMap();
for (Iterator iterator = context.entrySet().iterator(); iterator.hasNext();) {
Map.Entry entry = (Map.Entry) iterator.next();
String name = (String) entry.getKey();
Object value = entry.getValue();
if (value instanceof NestedEnterpriseNamingContext) {
NestedEnterpriseNamingContext nestedContext = (NestedEnterpriseNamingContext)value;
globalBindings.putAll(buildGlobalBindings(nestedContext.getNameInNamespace(), nestedContext.localBindings));
}
globalBindings.put(path + name, value);
}
return globalBindings;
}
protected Map getGlobalBindings() {
return globalBindings;
}
protected Map getLocalBindings() {
return localBindings;
}
/**
* Nested context which shares the global bindings map.
*/
public final class NestedEnterpriseNamingContext extends AbstractReadOnlyContext {
private final Map localBindings;
public NestedEnterpriseNamingContext(String nameInNamespace, Node bindings) {
super(nameInNamespace);
if (nameInNamespace.length() == 0) throw new IllegalArgumentException("nameInNamespace is empty");
Map localBindings = new HashMap(bindings.size());
for (Iterator iterator = bindings.entrySet().iterator(); iterator.hasNext();) {
Map.Entry entry = (Map.Entry) iterator.next();
String name = (String) entry.getKey();
Object value = entry.getValue();
if (value instanceof Node) {
Context context = new NestedEnterpriseNamingContext(nameInNamespace + "/" + name, (Node) value);
localBindings.put(name, context);
} else {
localBindings.put(name, value);
}
}
this.localBindings = Collections.unmodifiableMap(localBindings);
}
protected Map getGlobalBindings() {
return globalBindings;
}
protected Map getLocalBindings() {
return localBindings;
}
}
/**
* Lame subclass of hashmap used to differentiate between a Map in the context an a nested element during tree building
*/
private static final class Node extends HashMap {
}
}