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 }