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 }