View Javadoc

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                  // ignore
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              // list federated context
85              NamingEnumeration namingEnumeration = context.listBindings("");
86  
87              // add to bindings
88              while (namingEnumeration.hasMoreElements()) {
89                  Binding binding = (Binding) namingEnumeration.nextElement();
90                  String name = binding.getName();
91  
92                  // don't overwrite existing bindings
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 }