View Javadoc

1   /**
2    *
3    *  Licensed to the Apache Software Foundation (ASF) under one or more
4    *  contributor license agreements.  See the NOTICE file distributed with
5    *  this work for additional information regarding copyright ownership.
6    *  The ASF licenses this file to You under the Apache License, Version 2.0
7    *  (the "License"); you may not use this file except in compliance with
8    *  the License.  You may obtain a copy of the License at
9    *
10   *     http://www.apache.org/licenses/LICENSE-2.0
11   *
12   *  Unless required by applicable law or agreed to in writing, software
13   *  distributed under the License is distributed on an "AS IS" BASIS,
14   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   *  See the License for the specific language governing permissions and
16   *  limitations under the License.
17   */
18  
19  package org.apache.geronimo.connector.deployment;
20  
21  import java.util.HashMap;
22  import java.util.Iterator;
23  import java.util.Map;
24  
25  import javax.naming.Reference;
26  import javax.xml.namespace.QName;
27  
28  import org.apache.geronimo.common.DeploymentException;
29  import org.apache.geronimo.common.UnresolvedReferenceException;
30  import org.apache.geronimo.gbean.AbstractNameQuery;
31  import org.apache.geronimo.gbean.GBeanInfo;
32  import org.apache.geronimo.gbean.GBeanInfoBuilder;
33  import org.apache.geronimo.j2ee.deployment.Module;
34  import org.apache.geronimo.j2ee.j2eeobjectnames.NameFactory;
35  import org.apache.geronimo.kernel.GBeanNotFoundException;
36  import org.apache.geronimo.kernel.config.Configuration;
37  import org.apache.geronimo.kernel.repository.Environment;
38  import org.apache.geronimo.naming.deployment.AbstractNamingBuilder;
39  import org.apache.geronimo.naming.reference.ResourceReference;
40  import org.apache.geronimo.xbeans.geronimo.naming.GerMessageDestinationDocument;
41  import org.apache.geronimo.xbeans.geronimo.naming.GerMessageDestinationType;
42  import org.apache.geronimo.xbeans.geronimo.naming.GerPatternType;
43  import org.apache.geronimo.xbeans.geronimo.naming.GerResourceEnvRefDocument;
44  import org.apache.geronimo.xbeans.geronimo.naming.GerResourceEnvRefType;
45  import org.apache.geronimo.xbeans.j2ee.MessageDestinationRefType;
46  import org.apache.geronimo.xbeans.j2ee.MessageDestinationType;
47  import org.apache.geronimo.xbeans.j2ee.ResourceEnvRefType;
48  import org.apache.xmlbeans.QNameSet;
49  import org.apache.xmlbeans.XmlObject;
50  
51  /**
52   * @version $Rev: 470597 $ $Date: 2006-11-02 15:30:55 -0800 (Thu, 02 Nov 2006) $
53   */
54  public class AdminObjectRefBuilder extends AbstractNamingBuilder {
55      private  final QNameSet adminOjbectRefQNameSet;
56      private final QNameSet messageDestinationQNameSet;
57      private final QNameSet messageDestinationRefQNameSet;
58  
59      private static final QName GER_ADMIN_OBJECT_REF_QNAME = GerResourceEnvRefDocument.type.getDocumentElementName();
60      private static final QNameSet GER_ADMIN_OBJECT_REF_QNAME_SET = QNameSet.singleton(GER_ADMIN_OBJECT_REF_QNAME);
61      private static final QName GER_MESSAGE_DESTINATION_QNAME = GerMessageDestinationDocument.type.getDocumentElementName();
62      private static final QNameSet GER_MESSAGE_DESTINATION_QNAME_SET = QNameSet.singleton(GER_MESSAGE_DESTINATION_QNAME);
63  
64      public AdminObjectRefBuilder(Environment defaultEnvironment, String[] eeNamespaces) {
65          super(defaultEnvironment);
66          adminOjbectRefQNameSet = buildQNameSet(eeNamespaces, "resource-env-ref");
67          messageDestinationQNameSet = buildQNameSet(eeNamespaces, "message-destination");
68          messageDestinationRefQNameSet = buildQNameSet(eeNamespaces, "message-destination-ref");
69      }
70  
71      protected boolean willMergeEnvironment(XmlObject specDD, XmlObject plan) {
72          return specDD.selectChildren(adminOjbectRefQNameSet).length > 0 || specDD.selectChildren(messageDestinationRefQNameSet).length > 0;
73      }
74  
75      public void initContext(XmlObject specDD, XmlObject plan, Configuration localConfiguration, Configuration remoteConfiguration, Module module) throws DeploymentException {
76          XmlObject[] specDestinations = convert(specDD.selectChildren(messageDestinationQNameSet), J2EE_CONVERTER, MessageDestinationType.type);
77          XmlObject[] gerDestinations = plan.selectChildren(GER_MESSAGE_DESTINATION_QNAME_SET);
78              Map nameMap = new HashMap();
79              for (int i = 0; i < gerDestinations.length; i++) {
80                  GerMessageDestinationType destination = (GerMessageDestinationType) gerDestinations[i].copy().changeType(GerMessageDestinationType.type);
81                  String name = destination.getMessageDestinationName().trim();
82                  nameMap.put(name, destination);
83                  boolean found = false;
84                  for (int j = 0; j < specDestinations.length; j++) {
85                      MessageDestinationType specDestination = (MessageDestinationType) specDestinations[j];
86                      if (specDestination.getMessageDestinationName().getStringValue().trim().equals(name)) {
87                          found = true;
88                          break;
89                      }
90                  }
91                  if (!found) {
92                      throw new DeploymentException("No spec DD message-destination for " + name);
93                  }
94              }
95              module.getRootEarContext().registerMessageDestionations(module.getName(), nameMap);
96      }
97  
98  
99      public void buildNaming(XmlObject specDD, XmlObject plan, Configuration localConfiguration, Configuration remoteConfiguration, Module module, Map componentContext) throws DeploymentException {
100         XmlObject[] resourceEnvRefsUntyped = convert(specDD.selectChildren(adminOjbectRefQNameSet), J2EE_CONVERTER, ResourceEnvRefType.type);
101         ClassLoader cl = module.getEarContext().getClassLoader();
102         XmlObject[] gerResourceEnvRefsUntyped = plan == null? NO_REFS: plan.selectChildren(GER_ADMIN_OBJECT_REF_QNAME_SET);
103         Map refMap = mapResourceEnvRefs(gerResourceEnvRefsUntyped);
104         for (int i = 0; i < resourceEnvRefsUntyped.length; i++) {
105             ResourceEnvRefType resourceEnvRef = (ResourceEnvRefType) resourceEnvRefsUntyped[i];
106             String name = resourceEnvRef.getResourceEnvRefName().getStringValue().trim();
107             String type = resourceEnvRef.getResourceEnvRefType().getStringValue().trim();
108             Class iface;
109             try {
110                 iface = cl.loadClass(type);
111             } catch (ClassNotFoundException e) {
112                 throw new DeploymentException("could not load class " + type, e);
113             }
114             GerResourceEnvRefType gerResourceEnvRef = (GerResourceEnvRefType) refMap.get(name);
115             try {
116                 AbstractNameQuery containerId = getAdminObjectContainerId(name, gerResourceEnvRef);
117                 Reference ref = buildAdminObjectReference(localConfiguration, containerId, iface);
118                 getJndiContextMap(componentContext).put(ENV + name, ref);
119             } catch (UnresolvedReferenceException e) {
120                 throw new DeploymentException("Unable to resolve resource env reference '" + name + "' (" + (e.isMultiple() ? "found multiple matching resources" : "no matching resources found") + ")");
121             }
122         }
123 
124         //message-destination-refs
125         XmlObject[] messageDestinationRefsUntyped = convert(specDD.selectChildren(messageDestinationRefQNameSet), J2EE_CONVERTER, MessageDestinationRefType.type);
126 
127         for (int i = 0; i < messageDestinationRefsUntyped.length; i++) {
128             MessageDestinationRefType messageDestinationRef = (MessageDestinationRefType) messageDestinationRefsUntyped[i];
129             String name = getStringValue(messageDestinationRef.getMessageDestinationRefName());
130             String linkName = getStringValue(messageDestinationRef.getMessageDestinationLink());
131             String type = getStringValue(messageDestinationRef.getMessageDestinationType());
132             Class iface;
133             try {
134                 iface = cl.loadClass(type);
135             } catch (ClassNotFoundException e) {
136                 throw new DeploymentException("could not load class " + type, e);
137             }
138             String moduleURI = null;
139             Map messageDestinations = module.getRootEarContext().getMessageDestinations();
140             GerMessageDestinationType destination = getMessageDestination(linkName, messageDestinations);
141             if (destination != null) {
142                 if (destination.isSetAdminObjectLink()) {
143                     if (destination.isSetAdminObjectModule()) {
144                         moduleURI = destination.getAdminObjectModule().trim();
145                     }
146                     linkName = destination.getAdminObjectLink().trim();
147                 }
148             } else {
149                 //well, we know for sure an admin object is not going to be defined in a modules that can have a message-destination
150                 int pos = linkName.indexOf('#');
151                 if (pos > -1) {
152                     //AMM -- the following line causes blowups; e.g. to look in DayTrader EJB module for a RA -- why is that?!?
153                     //moduleURI = linkName.substring(0, pos);
154                     linkName = linkName.substring(pos + 1);
155                 }
156             }
157 
158             //try to resolve ref based only matching resource-ref-name
159             //throws exception if it can't locate ref.
160             AbstractNameQuery containerId = buildAbstractNameQuery(null, moduleURI, linkName, NameFactory.JCA_ADMIN_OBJECT, NameFactory.RESOURCE_ADAPTER_MODULE);
161             Reference ref = buildAdminObjectReference(localConfiguration, containerId, iface);
162             getJndiContextMap(componentContext).put(ENV + name, ref);
163 
164         }
165 
166     }
167 
168     public static GerMessageDestinationType getMessageDestination(String messageDestinationLink, Map messageDestinations) throws DeploymentException {
169         GerMessageDestinationType destination = null;
170         int pos = messageDestinationLink.indexOf('#');
171         if (pos > -1) {
172             String targetModule = messageDestinationLink.substring(0, pos);
173             Map destinations = (Map) messageDestinations.get(targetModule);
174             // Hmmm...if we don't find the module then something is wrong in the deployment.
175             if (destinations == null) {
176                 StringBuffer sb = new StringBuffer();
177                 for (Iterator mapIterator = messageDestinations.keySet().iterator(); mapIterator.hasNext();) {
178                     sb.append(mapIterator.next()).append("\n");
179                 }
180                 throw new DeploymentException("Unknown module " + targetModule + " when processing message destination " + messageDestinationLink +
181                         "\nKnown modules in deployable unit are:\n" + sb.toString());
182             }
183             messageDestinationLink = messageDestinationLink.substring(pos + 1);
184             destination = (GerMessageDestinationType) destinations.get(messageDestinationLink);
185         } else {
186             for (Iterator iterator = messageDestinations.values().iterator(); iterator.hasNext();) {
187                 Map destinations = (Map) iterator.next();
188                 GerMessageDestinationType destinationTest = (GerMessageDestinationType) destinations.get(messageDestinationLink);
189                 if (destinationTest != null) {
190                     if (destination != null) {
191                         throw new DeploymentException("Duplicate message destination " + messageDestinationLink + " accessed from a message-destination-link without a module");
192                     }
193                     destination = destinationTest;
194                 }
195             }
196         }
197         return destination;
198     }
199 
200 
201     private Reference buildAdminObjectReference(Configuration localConfiguration, AbstractNameQuery containerId, Class iface) throws DeploymentException {
202         try {
203             localConfiguration.findGBean(containerId);
204         } catch (GBeanNotFoundException e) {
205             throw new DeploymentException("Can not resolve admin object ref " + containerId + " in configuration " + localConfiguration.getId());
206         }
207         return new ResourceReference(localConfiguration.getId(), containerId, iface);
208     }
209 
210     private static AbstractNameQuery getAdminObjectContainerId(String name, GerResourceEnvRefType gerResourceEnvRef) {
211         AbstractNameQuery containerId;
212         if (gerResourceEnvRef == null) {
213             containerId = buildAbstractNameQuery(null, null, name, NameFactory.JCA_ADMIN_OBJECT, NameFactory.RESOURCE_ADAPTER_MODULE);
214         } else if (gerResourceEnvRef.isSetMessageDestinationLink()) {
215             containerId = buildAbstractNameQuery(null, null, gerResourceEnvRef.getMessageDestinationLink().trim(), NameFactory.JCA_ADMIN_OBJECT, NameFactory.RESOURCE_ADAPTER_MODULE);
216         } else if (gerResourceEnvRef.isSetAdminObjectLink()) {
217             String moduleURI = null;
218             if (gerResourceEnvRef.isSetAdminObjectModule()) {
219                 moduleURI = gerResourceEnvRef.getAdminObjectModule().trim();
220             }
221             containerId = buildAbstractNameQuery(null, moduleURI, gerResourceEnvRef.getAdminObjectLink().trim(), NameFactory.JCA_ADMIN_OBJECT, NameFactory.RESOURCE_ADAPTER_MODULE);
222         } else {
223             //construct name from components
224             GerPatternType patternType = gerResourceEnvRef.getPattern();
225             containerId = buildAbstractNameQuery(patternType, NameFactory.JCA_ADMIN_OBJECT, NameFactory.RESOURCE_ADAPTER_MODULE, null);
226         }
227         return containerId;
228     }
229 
230     private static Map mapResourceEnvRefs(XmlObject[] refs) {
231         Map refMap = new HashMap();
232         if (refs != null) {
233             for (int i = 0; i < refs.length; i++) {
234                 GerResourceEnvRefType ref = (GerResourceEnvRefType) refs[i].copy().changeType(GerResourceEnvRefType.type);
235                 refMap.put(ref.getRefName().trim(), ref);
236             }
237         }
238         return refMap;
239     }
240 
241     public QNameSet getSpecQNameSet() {
242         return adminOjbectRefQNameSet;
243     }
244 
245     public QNameSet getPlanQNameSet() {
246         return GER_ADMIN_OBJECT_REF_QNAME_SET;
247     }
248 
249     public static final GBeanInfo GBEAN_INFO;
250 
251     static {
252         GBeanInfoBuilder infoBuilder = GBeanInfoBuilder.createStatic(AdminObjectRefBuilder.class, NameFactory.MODULE_BUILDER);
253         infoBuilder.addAttribute("eeNamespaces", String[].class, true, true);
254         infoBuilder.addAttribute("defaultEnvironment", Environment.class, true, true);
255 
256         infoBuilder.setConstructor(new String[] {"defaultEnvironment", "eeNamespaces"});
257 
258         GBEAN_INFO = infoBuilder.getBeanInfo();
259     }
260 
261     public static GBeanInfo getGBeanInfo() {
262         return GBEAN_INFO;
263     }
264 
265 }