1 /***
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17 package org.apache.xbean.naming.context;
18
19 import java.util.Collections;
20 import java.util.HashMap;
21 import java.util.LinkedHashSet;
22 import java.util.Map;
23 import java.util.Set;
24 import java.util.concurrent.atomic.AtomicReference;
25
26 import javax.naming.Binding;
27 import javax.naming.Context;
28 import javax.naming.Name;
29 import javax.naming.NamingEnumeration;
30 import javax.naming.NamingException;
31 import javax.naming.OperationNotSupportedException;
32
33 /***
34 * @version $Rev$ $Date$
35 */
36 public class ContextFederation {
37 private final Context actualContext;
38 private final AtomicReference<Set<Context>> federatedContextRef = new AtomicReference<Set<Context>>(Collections.<Context>emptySet());
39 public static final int MAX_WRITE_ATTEMPTS = 10;
40
41 public ContextFederation(Context actualContext) {
42 this.actualContext = actualContext;
43 }
44
45 public void addContext(Context context) {
46 Set<Context> federatedContext;
47 Set<Context> newFederatedContext;
48 for (int i = 0; i < MAX_WRITE_ATTEMPTS; i++) {
49 federatedContext = getFederatedContexts();
50
51 newFederatedContext = new LinkedHashSet<Context>(federatedContext);
52 newFederatedContext.add(context);
53 newFederatedContext = Collections.unmodifiableSet(newFederatedContext);
54 if (federatedContextRef.compareAndSet(federatedContext, newFederatedContext)) {
55 return;
56 }
57 }
58 throw new RuntimeException("Unable to update federatedContextRef within " + MAX_WRITE_ATTEMPTS + " attempts");
59 }
60
61 public Set<Context> getFederatedContexts() {
62 return federatedContextRef.get();
63 }
64
65 public Object getFederatedBinding(String name) throws NamingException {
66 for (Context context : getFederatedContexts()) {
67
68 try {
69 Object value = context.lookup(name);
70 if (value != null) {
71 return value;
72 }
73 } catch (NamingException e) {
74
75 }
76 }
77 return null;
78 }
79
80 public Map<String, Object> getFederatedBindings() throws NamingException {
81 Map<String, Object> bindings = new HashMap<String, Object>();
82 for (Context context : getFederatedContexts()) {
83
84
85 NamingEnumeration namingEnumeration = context.listBindings("");
86
87
88 while (namingEnumeration.hasMoreElements()) {
89 Binding binding = (Binding) namingEnumeration.nextElement();
90 String name = binding.getName();
91
92
93 if (!bindings.containsKey(name)) {
94 bindings.put(name, binding.getObject());
95 }
96 }
97 }
98 return bindings;
99 }
100
101 protected boolean addBinding(String name, Object value, boolean rebind) throws NamingException {
102 for (Context context : getFederatedContexts()) {
103
104 try {
105 if (rebind) {
106 context.rebind(name, value);
107 } else {
108 context.bind(name, value);
109 }
110 return true;
111 } catch (OperationNotSupportedException ignored) {
112 }
113 }
114 return false;
115 }
116
117 protected boolean removeBinding(String name) throws NamingException {
118 for (Context context : getFederatedContexts()) {
119
120 try {
121 context.unbind(name);
122 return true;
123 } catch (OperationNotSupportedException ignored) {
124 }
125 }
126 return false;
127 }
128
129 public Object lookup(Name name) {
130 for (Context federatedContext : getFederatedContexts()) {
131 try {
132 Object value = federatedContext.lookup(name);
133 if (value instanceof Context) {
134 return new VirtualSubcontext(name, actualContext);
135 } else {
136 return value;
137 }
138 } catch (NamingException ignored) {
139 }
140 }
141 return null;
142 }
143
144 public ContextFederation createSubcontextFederation(String subcontextName, Context actualSubcontext) throws NamingException {
145 Name parsedSubcontextName = actualContext.getNameParser("").parse(subcontextName);
146
147 ContextFederation subcontextFederation = new ContextFederation(actualSubcontext);
148 for (Context federatedContext : getFederatedContexts()) {
149 VirtualSubcontext virtualSubcontext = new VirtualSubcontext(parsedSubcontextName, federatedContext);
150 subcontextFederation.addContext(virtualSubcontext);
151 }
152 return subcontextFederation;
153 }
154 }