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 }