001 /** 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017 package org.apache.xbean.naming.context; 018 019 import org.apache.xbean.naming.reference.CachingReference; 020 021 import javax.naming.Context; 022 import javax.naming.NamingException; 023 import javax.naming.OperationNotSupportedException; 024 import javax.naming.Name; 025 import java.util.Collections; 026 import java.util.HashMap; 027 import java.util.Iterator; 028 import java.util.Map; 029 030 /** 031 * 032 * @version $Rev: 417891 $ $Date: 2006-06-28 15:45:07 -0700 (Wed, 28 Jun 2006) $ 033 */ 034 public class ImmutableContext extends AbstractContext { 035 private final Map localBindings; 036 private final Map absoluteIndex; 037 038 public ImmutableContext(Map bindings) throws NamingException { 039 this("", bindings, true); 040 } 041 042 public ImmutableContext(Map bindings, boolean cacheReferences) throws NamingException { 043 this("", bindings, cacheReferences); 044 } 045 046 public ImmutableContext(String nameInNamespace, Map bindings, boolean cacheReferences) throws NamingException { 047 super(nameInNamespace, ContextAccess.UNMODIFIABLE); 048 049 if (cacheReferences) { 050 bindings = CachingReference.wrapReferences(bindings); 051 } 052 053 Map localBindings = ContextUtil.createBindings(bindings, this); 054 this.localBindings = Collections.unmodifiableMap(localBindings); 055 056 Map globalBindings = ImmutableContext.buildAbsoluteIndex("", localBindings); 057 this.absoluteIndex = Collections.unmodifiableMap(globalBindings); 058 } 059 060 private static Map buildAbsoluteIndex(String nameInNamespace, Map bindings) { 061 String path = nameInNamespace; 062 if (path.length() > 0) { 063 path += "/"; 064 } 065 066 Map globalBindings = new HashMap(); 067 for (Iterator iterator = bindings.entrySet().iterator(); iterator.hasNext();) { 068 Map.Entry entry = (Map.Entry) iterator.next(); 069 String name = (String) entry.getKey(); 070 Object value = entry.getValue(); 071 if (value instanceof ImmutableContext.NestedImmutableContext) { 072 ImmutableContext.NestedImmutableContext nestedContext = (ImmutableContext.NestedImmutableContext)value; 073 globalBindings.putAll(ImmutableContext.buildAbsoluteIndex(nestedContext.getNameInNamespace(), nestedContext.localBindings)); 074 } 075 globalBindings.put(path + name, value); 076 } 077 return globalBindings; 078 } 079 080 protected Object getDeepBinding(String name) { 081 return absoluteIndex.get(name); 082 } 083 084 protected Map getBindings() { 085 return localBindings; 086 } 087 088 protected final void addDeepBinding(String name, Object value, boolean createIntermediateContexts) throws NamingException { 089 throw new OperationNotSupportedException("Context is immutable"); 090 } 091 092 protected final boolean addBinding(String name, Object value, boolean rebind) throws NamingException { 093 throw new OperationNotSupportedException("Context is immutable"); 094 } 095 096 protected final void removeDeepBinding(Name name, boolean pruneEmptyContexts) throws NamingException { 097 throw new OperationNotSupportedException("Context is immutable"); 098 } 099 100 protected final boolean removeBinding(String name, boolean removeNotEmptyContext) throws NamingException { 101 throw new OperationNotSupportedException("Context is immutable"); 102 } 103 104 public boolean isNestedSubcontext(Object value) { 105 if (value instanceof NestedImmutableContext) { 106 NestedImmutableContext context = (NestedImmutableContext) value; 107 return this == context.getImmutableContext(); 108 } 109 return false; 110 } 111 112 public Context createNestedSubcontext(String path, Map bindings) { 113 return new NestedImmutableContext(path, bindings); 114 } 115 116 /** 117 * Nested context which shares the absolute index map in MapContext. 118 */ 119 public final class NestedImmutableContext extends AbstractContext { 120 private final Map localBindings; 121 private final String pathWithSlash; 122 123 public NestedImmutableContext(String path, Map bindings) { 124 super(ImmutableContext.this.getNameInNamespace(path), ContextAccess.UNMODIFIABLE); 125 126 if (!path.endsWith("/")) path += "/"; 127 this.pathWithSlash = path; 128 129 this.localBindings = Collections.unmodifiableMap(bindings); 130 } 131 132 protected Object getDeepBinding(String name) { 133 String absoluteName = pathWithSlash + name; 134 return absoluteIndex.get(absoluteName); 135 } 136 137 protected Map getBindings() { 138 return localBindings; 139 } 140 141 protected final void addDeepBinding(String name, Object value, boolean createIntermediateContexts) throws NamingException { 142 throw new OperationNotSupportedException("Context is immutable"); 143 } 144 145 protected final boolean addBinding(String name, Object value, boolean rebind) throws NamingException { 146 throw new OperationNotSupportedException("Context is immutable"); 147 } 148 149 protected final void removeDeepBinding(Name name, boolean pruneEmptyContexts) throws NamingException { 150 throw new OperationNotSupportedException("Context is immutable"); 151 } 152 153 protected final boolean removeBinding(String name, boolean removeNotEmptyContext) throws NamingException { 154 throw new OperationNotSupportedException("Context is immutable"); 155 } 156 157 public boolean isNestedSubcontext(Object value) { 158 if (value instanceof NestedImmutableContext) { 159 NestedImmutableContext context = (NestedImmutableContext) value; 160 return getImmutableContext() == context.getImmutableContext(); 161 } 162 return false; 163 } 164 165 public Context createNestedSubcontext(String path, Map bindings) { 166 return new NestedImmutableContext(path, bindings); 167 } 168 169 protected ImmutableContext getImmutableContext() { 170 return ImmutableContext.this; 171 } 172 } 173 }