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 }