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.net.MalformedURLException;
22 import java.net.URI;
23 import java.net.URL;
24 import java.util.HashMap;
25 import java.util.Map;
26 import java.util.Set;
27 import java.util.HashSet;
28
29 import javax.naming.Reference;
30 import javax.xml.namespace.QName;
31
32 import org.apache.geronimo.common.DeploymentException;
33 import org.apache.geronimo.common.UnresolvedReferenceException;
34 import org.apache.geronimo.gbean.AbstractNameQuery;
35 import org.apache.geronimo.gbean.GBeanInfo;
36 import org.apache.geronimo.gbean.GBeanInfoBuilder;
37 import org.apache.geronimo.j2ee.deployment.Module;
38 import org.apache.geronimo.j2ee.j2eeobjectnames.NameFactory;
39 import org.apache.geronimo.kernel.GBeanNotFoundException;
40 import org.apache.geronimo.kernel.config.Configuration;
41 import org.apache.geronimo.kernel.repository.Environment;
42 import org.apache.geronimo.naming.deployment.AbstractNamingBuilder;
43 import org.apache.geronimo.naming.deployment.ResourceEnvironmentBuilder;
44 import org.apache.geronimo.naming.deployment.ResourceEnvironmentSetter;
45 import org.apache.geronimo.naming.reference.ResourceReference;
46 import org.apache.geronimo.xbeans.geronimo.naming.GerPatternType;
47 import org.apache.geronimo.xbeans.geronimo.naming.GerResourceRefDocument;
48 import org.apache.geronimo.xbeans.geronimo.naming.GerResourceRefType;
49 import org.apache.geronimo.xbeans.j2ee.ResourceRefType;
50 import org.apache.xmlbeans.QNameSet;
51 import org.apache.xmlbeans.XmlObject;
52
53 /**
54 * @version $Rev: 470597 $ $Date: 2006-11-02 15:30:55 -0800 (Thu, 02 Nov 2006) $
55 */
56 public class ResourceRefBuilder extends AbstractNamingBuilder implements ResourceEnvironmentSetter {
57 private static final QName GER_RESOURCE_REF_QNAME = GerResourceRefDocument.type.getDocumentElementName();
58 private static final QNameSet GER_RESOURCE_REF_QNAME_SET = QNameSet.singleton(GER_RESOURCE_REF_QNAME);
59
60 private final QNameSet resourceRefQNameSet;
61
62 private static final String JAXR_CONNECTION_FACTORY_CLASS = "javax.xml.registry.ConnectionFactory";
63 private static final String JAVAX_MAIL_SESSION_CLASS = "javax.mail.Session";
64
65 public ResourceRefBuilder(Environment defaultEnvironment, String[] eeNamespaces) {
66 super(defaultEnvironment);
67
68 resourceRefQNameSet = buildQNameSet(eeNamespaces, "resource-ref");
69 }
70
71 protected boolean willMergeEnvironment(XmlObject specDD, XmlObject plan) {
72 return specDD.selectChildren(resourceRefQNameSet).length > 0;
73 }
74
75 public void buildNaming(XmlObject specDD, XmlObject plan, Configuration localConfiguration, Configuration remoteConfiguration, Module module, Map componentContext) throws DeploymentException {
76 XmlObject[] resourceRefsUntyped = convert(specDD.selectChildren(resourceRefQNameSet), J2EE_CONVERTER, ResourceRefType.type);
77 XmlObject[] gerResourceRefsUntyped = plan == null? NO_REFS: plan.selectChildren(GER_RESOURCE_REF_QNAME_SET);
78 Map refMap = mapResourceRefs(gerResourceRefsUntyped);
79 ClassLoader cl = module.getEarContext().getClassLoader();
80
81 for (int i = 0; i < resourceRefsUntyped.length; i++) {
82 ResourceRefType resourceRef = (ResourceRefType) resourceRefsUntyped[i];
83 String name = resourceRef.getResRefName().getStringValue().trim();
84 String type = resourceRef.getResType().getStringValue().trim();
85 GerResourceRefType gerResourceRef = (GerResourceRefType) refMap.get(name);
86 Class iface;
87 try {
88 iface = cl.loadClass(type);
89 } catch (ClassNotFoundException e) {
90 throw new DeploymentException("could not load class " + type, e);
91 }
92 if (iface == URL.class) {
93 if (gerResourceRef == null || !gerResourceRef.isSetUrl()) {
94 throw new DeploymentException("No url supplied to resolve: " + name);
95 }
96 try {
97
98 getJndiContextMap(componentContext).put(ENV + name, new URL(gerResourceRef.getUrl()));
99 } catch (MalformedURLException e) {
100 throw new DeploymentException("Could not convert " + gerResourceRef.getUrl() + " to URL", e);
101 }
102 } else {
103
104 String j2eeType;
105
106
107 if (JAVAX_MAIL_SESSION_CLASS.equals(type)) {
108 j2eeType = NameFactory.JAVA_MAIL_RESOURCE;
109 } else if (JAXR_CONNECTION_FACTORY_CLASS.equals(type)) {
110 j2eeType = NameFactory.JAXR_CONNECTION_FACTORY;
111 } else {
112 j2eeType = NameFactory.JCA_MANAGED_CONNECTION_FACTORY;
113 }
114 try {
115 AbstractNameQuery containerId = getResourceContainerId(name, j2eeType, null, gerResourceRef);
116
117 try {
118 localConfiguration.findGBean(containerId);
119 } catch (GBeanNotFoundException e) {
120 throw new UnresolvedReferenceException("Resource", false, containerId.toString(), localConfiguration.getId().toString());
121 }
122
123 Reference ref = new ResourceReference(localConfiguration.getId(), containerId, iface);
124 getJndiContextMap(componentContext).put(ENV + name, ref);
125 } catch (UnresolvedReferenceException e) {
126
127 StringBuffer errorMessage = new StringBuffer("Unable to resolve resource reference '");
128 errorMessage.append(name);
129 errorMessage.append("' (");
130 if (e.isMultiple()) {
131 errorMessage.append("Found multiple matching resources. Try being more specific in a resource-ref mapping in your Geronimo deployment plan.");
132 } else if (gerResourceRef == null) {
133 errorMessage.append("Could not auto-map to resource. Try adding a resource-ref mapping to your Geronimo deployment plan.");
134 } else if (gerResourceRef.isSetResourceLink()) {
135 errorMessage.append("Could not find resource '");
136 errorMessage.append(gerResourceRef.getResourceLink());
137 errorMessage.append("'. Perhaps it has not yet been configured, or your application does not have a dependency declared for that resource module?");
138 } else {
139 errorMessage.append("Could not find the resource specified in your Geronimo deployment plan:");
140 errorMessage.append(gerResourceRef.getPattern());
141 }
142 errorMessage.append(")");
143
144 throw new DeploymentException(errorMessage.toString());
145 }
146 }
147 }
148
149 }
150
151 public void setResourceEnvironment(ResourceEnvironmentBuilder builder, XmlObject[] resourceRefs, GerResourceRefType[] gerResourceRefs) {
152 resourceRefs = convert(resourceRefs, J2EE_CONVERTER, ResourceRefType.type);
153 Map refMap = mapResourceRefs(gerResourceRefs);
154 Set unshareableResources = new HashSet();
155 Set applicationManagedSecurityResources = new HashSet();
156 for (int i = 0; i < resourceRefs.length; i++) {
157 ResourceRefType resourceRefType = (ResourceRefType) resourceRefs[i];
158
159 String type = resourceRefType.getResType().getStringValue().trim();
160
161 if (!URL.class.getName().equals(type)
162 && !"javax.mail.Session".equals(type)
163 && !JAXR_CONNECTION_FACTORY_CLASS.equals(type)) {
164
165 GerResourceRefType gerResourceRef = (GerResourceRefType) refMap.get(resourceRefType.getResRefName().getStringValue());
166 AbstractNameQuery containerId = getResourceContainerId(getStringValue(resourceRefType.getResRefName()), NameFactory.JCA_MANAGED_CONNECTION_FACTORY, null, gerResourceRef);
167
168 if ("Unshareable".equals(getStringValue(resourceRefType.getResSharingScope()))) {
169 unshareableResources.add(containerId);
170 }
171 if ("Application".equals(getStringValue(resourceRefType.getResAuth()))) {
172 applicationManagedSecurityResources.add(containerId);
173 }
174 }
175 }
176 builder.setUnshareableResources(unshareableResources);
177 builder.setApplicationManagedSecurityResources(applicationManagedSecurityResources);
178 }
179
180 private Map mapResourceRefs(XmlObject[] refs) {
181 Map refMap = new HashMap();
182 if (refs != null) {
183 for (int i = 0; i < refs.length; i++) {
184 GerResourceRefType ref = (GerResourceRefType) refs[i].copy().changeType(GerResourceRefType.type);
185 refMap.put(ref.getRefName().trim(), ref);
186 }
187 }
188 return refMap;
189 }
190
191 private AbstractNameQuery getResourceContainerId(String name, String type, URI moduleURI, GerResourceRefType gerResourceRef) {
192 AbstractNameQuery containerId;
193 String module = moduleURI == null ? null : moduleURI.toString();
194 if (gerResourceRef == null) {
195 containerId = buildAbstractNameQuery(null, module, name, type, NameFactory.RESOURCE_ADAPTER_MODULE);
196 } else if (gerResourceRef.isSetResourceLink()) {
197 containerId = buildAbstractNameQuery(null, module, gerResourceRef.getResourceLink().trim(), type, NameFactory.RESOURCE_ADAPTER_MODULE);
198 } else {
199
200 GerPatternType patternType = gerResourceRef.getPattern();
201 containerId = buildAbstractNameQuery(patternType, type, NameFactory.RESOURCE_ADAPTER_MODULE, null);
202 }
203 return containerId;
204 }
205
206 public QNameSet getSpecQNameSet() {
207 return resourceRefQNameSet;
208 }
209
210 public QNameSet getPlanQNameSet() {
211 return GER_RESOURCE_REF_QNAME_SET;
212 }
213
214 public static final GBeanInfo GBEAN_INFO;
215
216 static {
217 GBeanInfoBuilder infoBuilder = GBeanInfoBuilder.createStatic(ResourceRefBuilder.class, NameFactory.MODULE_BUILDER);
218 infoBuilder.addAttribute("eeNamespaces", String[].class, true, true);
219 infoBuilder.addAttribute("defaultEnvironment", Environment.class, true, true);
220
221 infoBuilder.setConstructor(new String[] {"defaultEnvironment", "eeNamespaces"});
222
223 GBEAN_INFO = infoBuilder.getBeanInfo();
224 }
225
226 public static GBeanInfo getGBeanInfo() {
227 return GBEAN_INFO;
228 }
229 }