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.HashMap; 021 import java.util.LinkedHashSet; 022 import java.util.Map; 023 import java.util.Set; 024 import java.util.concurrent.atomic.AtomicReference; 025 026 import javax.naming.Binding; 027 import javax.naming.Context; 028 import javax.naming.Name; 029 import javax.naming.NamingEnumeration; 030 import javax.naming.NamingException; 031 import javax.naming.NotContextException; 032 import javax.naming.OperationNotSupportedException; 033 034 /** 035 * @version $Rev$ $Date$ 036 */ 037 public class ContextFederation { 038 private final Context actualContext; 039 private final AtomicReference<Set<Context>> federatedContextRef = new AtomicReference<Set<Context>>(Collections.<Context>emptySet()); 040 public static final int MAX_WRITE_ATTEMPTS = 10; 041 042 public ContextFederation(Context actualContext) { 043 this.actualContext = actualContext; 044 } 045 046 public ContextFederation(Context actualContext, Set<Context> federatedContexts) { 047 this.actualContext = actualContext; 048 Set<Context> copy = new LinkedHashSet<Context>(federatedContexts); 049 federatedContextRef.set(Collections.unmodifiableSet(copy)); 050 } 051 052 public void addContext(Context context) { 053 Set<Context> federatedContext; 054 Set<Context> newFederatedContext; 055 for (int i = 0; i < MAX_WRITE_ATTEMPTS; i++) { 056 federatedContext = getFederatedContexts(); 057 058 newFederatedContext = new LinkedHashSet<Context>(federatedContext); 059 newFederatedContext.add(context); 060 newFederatedContext = Collections.unmodifiableSet(newFederatedContext); 061 if (federatedContextRef.compareAndSet(federatedContext, newFederatedContext)) { 062 return; 063 } 064 } 065 throw new RuntimeException("Unable to update federatedContextRef within " + MAX_WRITE_ATTEMPTS + " attempts"); 066 } 067 068 public void removeContext(Context context) { 069 Set<Context> federatedContext; 070 Set<Context> newFederatedContext; 071 for (int i = 0; i < MAX_WRITE_ATTEMPTS; i++) { 072 federatedContext = getFederatedContexts(); 073 074 newFederatedContext = new LinkedHashSet<Context>(federatedContext); 075 newFederatedContext.remove(context); 076 newFederatedContext = Collections.unmodifiableSet(newFederatedContext); 077 if (federatedContextRef.compareAndSet(federatedContext, newFederatedContext)) { 078 return; 079 } 080 } 081 throw new RuntimeException("Unable to update federatedContextRef within " + MAX_WRITE_ATTEMPTS + " attempts"); 082 } 083 084 public Set<Context> getFederatedContexts() { 085 return federatedContextRef.get(); 086 } 087 088 public Object getFederatedBinding(String name) throws NamingException { 089 for (Context context : getFederatedContexts()) { 090 091 try { 092 Object value = context.lookup(name); 093 if (value != null) { 094 return value; 095 } 096 } catch (NamingException e) { 097 // ignore 098 } 099 } 100 return null; 101 } 102 103 public Map<String, Object> getFederatedBindings(String name) throws NamingException { 104 Map<String, Object> bindings = new HashMap<String, Object>(); 105 for (Context context : getFederatedContexts()) { 106 107 // list federated context 108 try { 109 NamingEnumeration namingEnumeration = context.listBindings(name); 110 111 // add to bindings 112 while (namingEnumeration.hasMoreElements()) { 113 Binding binding = (Binding) namingEnumeration.nextElement(); 114 String bindingName = binding.getName(); 115 116 // don't overwrite existing bindings 117 if (!bindings.containsKey(bindingName)) { 118 bindings.put(bindingName, binding.getObject()); 119 } 120 } 121 } catch (NotContextException e) { 122 //this context does not include the supplied name 123 } 124 } 125 return bindings; 126 } 127 128 protected boolean addBinding(String name, Object value, boolean rebind) throws NamingException { 129 for (Context context : getFederatedContexts()) { 130 131 try { 132 if (rebind) { 133 context.rebind(name, value); 134 } else { 135 context.bind(name, value); 136 } 137 return true; 138 } catch (OperationNotSupportedException ignored) { 139 } 140 } 141 return false; 142 } 143 144 protected boolean removeBinding(String name) throws NamingException { 145 for (Context context : getFederatedContexts()) { 146 147 try { 148 context.unbind(name); 149 return true; 150 } catch (OperationNotSupportedException ignored) { 151 } 152 } 153 return false; 154 } 155 156 public Object lookup(Name name) { 157 for (Context federatedContext : getFederatedContexts()) { 158 try { 159 Object value = federatedContext.lookup(name); 160 if (value instanceof Context) { 161 return new VirtualSubcontext(name, actualContext); 162 } else { 163 return value; 164 } 165 } catch (NamingException ignored) { 166 } 167 } 168 return null; 169 } 170 171 public ContextFederation createSubcontextFederation(String subcontextName, Context actualSubcontext) throws NamingException { 172 Name parsedSubcontextName = actualContext.getNameParser("").parse(subcontextName); 173 174 ContextFederation subcontextFederation = new ContextFederation(actualSubcontext); 175 for (Context federatedContext : getFederatedContexts()) { 176 VirtualSubcontext virtualSubcontext = new VirtualSubcontext(parsedSubcontextName, federatedContext); 177 subcontextFederation.addContext(virtualSubcontext); 178 } 179 return subcontextFederation; 180 } 181 }