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