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 java.util.Collections;
020 import java.util.Map;
021 import java.util.Set;
022
023 import javax.naming.Context;
024 import javax.naming.Name;
025 import javax.naming.NameAlreadyBoundException;
026 import javax.naming.NamingException;
027
028 /**
029 * @version $Rev$ $Date$
030 */
031 public abstract class AbstractFederatedContext extends AbstractContext {
032 private final ContextFederation contextFederation;
033 private final AbstractFederatedContext masterContext;
034
035 public AbstractFederatedContext() {
036 this("", ContextAccess.MODIFIABLE);
037 }
038
039 public AbstractFederatedContext(String nameInNamespace) {
040 this(nameInNamespace, ContextAccess.MODIFIABLE);
041 }
042
043 public AbstractFederatedContext(String nameInNamespace, ContextAccess contextAccess) {
044 super(nameInNamespace, contextAccess);
045 this.masterContext = this;
046 this.contextFederation = new ContextFederation(this);
047 }
048
049 public AbstractFederatedContext(String nameInNamespace, ContextAccess contextAccess, Set<Context> federatedContexts) {
050 super(nameInNamespace, contextAccess);
051 this.masterContext = this;
052 this.contextFederation = new ContextFederation(this, federatedContexts);
053 }
054
055 public AbstractFederatedContext(AbstractFederatedContext masterContext, String nameInNamespace) throws NamingException {
056 super(nameInNamespace, masterContext.getContextAccess());
057 this.masterContext = masterContext;
058 this.contextFederation = this.masterContext.contextFederation.createSubcontextFederation(nameInNamespace, this);
059 }
060
061 protected Object faultLookup(String stringName, Name parsedName) {
062 Object value = contextFederation.lookup(parsedName);
063 if (value != null) {
064 return value;
065 }
066 return super.faultLookup(stringName, parsedName);
067 }
068
069 @Override
070 protected Object getDeepBinding(String name) {
071 try {
072 Object value = contextFederation.getFederatedBinding(name);
073 if (value instanceof Context) {
074 return null;
075 }
076 return value;
077 } catch (NamingException e) {
078 return null;
079 }
080 }
081
082 @Override
083 protected Object getBinding(String name) throws NamingException {
084 Object value = contextFederation.getFederatedBinding(name);
085 if (value instanceof Context) {
086 return createNestedSubcontext(name, getBindings(name));
087 }
088 if (value == null) {
089 value = getWrapperBindings().get(name);
090 }
091 return value;
092 }
093
094 protected final Map<String, Object> getBindings() throws NamingException {
095 return getBindings("");
096 }
097
098 protected final Map<String, Object> getBindings(String name) throws NamingException {
099 Map<String, Object> bindings = contextFederation.getFederatedBindings(name);
100 bindings.putAll(getWrapperBindings());
101 return bindings;
102 }
103
104 protected abstract Map<String, Object> getWrapperBindings() throws NamingException;
105
106 protected boolean addBinding(String name, Object value, boolean rebind) throws NamingException {
107 if (!(value instanceof Context && !isNestedSubcontext(value))) {
108 return contextFederation.addBinding(name, value, rebind);
109 } else if (!isNestedSubcontext(value)) {
110 Context federatedContext = (Context) value;
111
112 // if we already have a context bound at the specified value
113 Object existingValue = getBinding(name);
114 if (existingValue != null) {
115 if (!(existingValue instanceof AbstractFederatedContext)) {
116 throw new NameAlreadyBoundException(name);
117 }
118
119 AbstractFederatedContext nestedContext = (AbstractFederatedContext) existingValue;
120 addFederatedContext(nestedContext, federatedContext);
121 return true;
122 } else {
123 AbstractFederatedContext nestedContext = (AbstractFederatedContext) createNestedSubcontext(name, Collections.<String, Object>emptyMap());
124 addFederatedContext(nestedContext, federatedContext);
125
126 // call back into this method using the new nested context
127 // this gives subclasses a chance to handle the binding
128 return addBinding(name, nestedContext, rebind);
129 }
130 }
131
132 return false;
133 }
134
135 protected boolean removeBinding(String name, boolean removeNotEmptyContext) throws NamingException {
136 return contextFederation.removeBinding(name);
137 }
138
139 protected static void addFederatedContext(AbstractFederatedContext wrappingContext, Context innerContext) throws NamingException {
140 wrappingContext.contextFederation.addContext(innerContext);
141 for (Map.Entry<String, Object> entry : wrappingContext.getWrapperBindings().entrySet()) {
142 String name = entry.getKey();
143 Object value = entry.getValue();
144 if (value instanceof AbstractFederatedContext) {
145 AbstractFederatedContext nestedContext = (AbstractFederatedContext) value;
146
147 Name parsedName = wrappingContext.getNameParser().parse(name);
148 Name nameInNamespace = wrappingContext.getNameInNamespace(parsedName);
149
150 VirtualSubcontext virtualSubcontext = new VirtualSubcontext(nameInNamespace, innerContext);
151 addFederatedContext(nestedContext, virtualSubcontext);
152 }
153 }
154 }
155
156 protected static void removeFederatedContext(AbstractFederatedContext wrappingContext, Context innerContext) throws NamingException {
157 wrappingContext.contextFederation.removeContext(innerContext);
158 for (Map.Entry<String, Object> entry : wrappingContext.getWrapperBindings().entrySet()) {
159 String name = entry.getKey();
160 Object value = entry.getValue();
161 if (value instanceof AbstractFederatedContext) {
162 AbstractFederatedContext nestedContext = (AbstractFederatedContext) value;
163
164 Name parsedName = wrappingContext.getNameParser().parse(name);
165 Name nameInNamespace = wrappingContext.getNameInNamespace(parsedName);
166
167 VirtualSubcontext virtualSubcontext = new VirtualSubcontext(nameInNamespace, innerContext);
168 removeFederatedContext(nestedContext, virtualSubcontext);
169 }
170 }
171 }
172
173 public boolean isNestedSubcontext(Object value) {
174 if (value instanceof AbstractFederatedContext) {
175 AbstractFederatedContext context = (AbstractFederatedContext) value;
176 return getMasterContext() == context.getMasterContext();
177 }
178 return false;
179 }
180
181 protected AbstractFederatedContext getMasterContext() {
182 return masterContext;
183 }
184 }