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