001: /*
002: * JBoss, Home of Professional Open Source.
003: * Copyright 2006, Red Hat Middleware LLC, and individual contributors
004: * as indicated by the @author tags. See the copyright.txt file in the
005: * distribution for a full listing of individual contributors.
006: *
007: * This is free software; you can redistribute it and/or modify it
008: * under the terms of the GNU Lesser General Public License as
009: * published by the Free Software Foundation; either version 2.1 of
010: * the License, or (at your option) any later version.
011: *
012: * This software is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015: * Lesser General Public License for more details.
016: *
017: * You should have received a copy of the GNU Lesser General Public
018: * License along with this software; if not, write to the Free
019: * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
021: */
022: package org.jboss.ejb;
023:
024: import java.net.URL;
025: import java.net.MalformedURLException;
026:
027: import java.util.Iterator;
028: import java.util.StringTokenizer;
029:
030: import javax.management.MBeanServer;
031:
032: import org.jboss.deployment.DeploymentInfo;
033: import org.jboss.deployment.MainDeployerMBean;
034: import org.jboss.logging.Logger;
035: import org.jboss.metadata.ApplicationMetaData;
036: import org.jboss.metadata.BeanMetaData;
037: import org.jboss.metadata.MessageDestinationMetaData;
038: import org.jboss.metadata.WebMetaData;
039: import org.jboss.util.Strings;
040:
041: /** Utility methods for resolving ejb-ref and ejb-local-ref within the
042: * scope of a deployment.
043: *
044: * @author <a href="mailto:criege@riege.com">Christian Riege</a>
045: * @author Scott.Stark@jboss.org
046: *
047: * @version $Revision: 57209 $
048: */
049: public final class EjbUtil {
050: private static final Logger log = Logger.getLogger(EjbUtil.class);
051:
052: /**
053: * Resolves an <ejb-link> target for an <ejb-ref> entry and
054: * returns the name of the target in the JNDI tree.
055: *
056: * @param di DeploymentInfo
057: * @param link Content of the <ejb-link> entry.
058: *
059: * @return The JNDI Entry of the target bean; <code>null</code> if
060: * no appropriate target could be found.
061: */
062: public static String findEjbLink(MBeanServer server,
063: DeploymentInfo di, String link) {
064: return resolveLink(server, di, link, false);
065: }
066:
067: /**
068: * Resolves an <ejb-link> target for an <ejb-local-ref> entry
069: * and returns the name of the target in the JNDI tree.
070: *
071: * @param di DeploymentInfo
072: * @param link Content of the <ejb-link> entry.
073: *
074: * @return The JNDI Entry of the target bean; <code>null</code> if
075: * no appropriate target could be found.
076: */
077: public static String findLocalEjbLink(MBeanServer server,
078: DeploymentInfo di, String link) {
079: return resolveLink(server, di, link, true);
080: }
081:
082: /**
083: * Resolves a <message-destination> target for a <message-destination-link>
084: * entry and returns the name of the target in the JNDI tree.
085: *
086: * @param di DeploymentInfo
087: * @param link Content of the <message-driven-link> entry.
088: *
089: * @return The JNDI Entry of the target; <code>null</code> if
090: * no appropriate target could be found.
091: */
092: public static MessageDestinationMetaData findMessageDestination(
093: MBeanServer server, DeploymentInfo di, String link) {
094: return resolveMessageDestination(server, di, link);
095: }
096:
097: private static String resolveLink(MBeanServer server,
098: DeploymentInfo di, String link, boolean isLocal) {
099: if (link == null) {
100: return null;
101: }
102:
103: if (log.isTraceEnabled()) {
104: log.trace("resolveLink( {" + di + "}, {" + link + "}, {"
105: + isLocal + "}");
106: }
107:
108: if (di == null) {
109: // We should throw an IllegalArgumentException here probably?
110: return null;
111: }
112:
113: if (link.indexOf('#') != -1) {
114: // <ejb-link> is specified in the form path/file.jar#Bean
115: return resolveRelativeLink(server, di, link, isLocal);
116: } else {
117: // <ejb-link> contains a Bean Name, scan the DeploymentInfo tree
118: DeploymentInfo top = di;
119: while (top.parent != null) {
120: top = top.parent;
121: }
122:
123: return resolveAbsoluteLink(top, link, isLocal);
124: }
125: }
126:
127: private static String resolveRelativeLink(MBeanServer server,
128: DeploymentInfo di, String link, boolean isLocal) {
129:
130: String path = link.substring(0, link.indexOf('#'));
131: String ejbName = link.substring(link.indexOf('#') + 1);
132: String us = di.url.toString();
133:
134: // Remove the trailing slash for unpacked deployments
135: if (us.charAt(us.length() - 1) == '/')
136: us = us.substring(0, us.length() - 1);
137:
138: String ourPath = us.substring(0, us.lastIndexOf('/'));
139:
140: if (log.isTraceEnabled()) {
141: log.trace("Resolving relative link: " + link);
142: log.trace("Looking for: '" + link
143: + "', we're located at: '" + ourPath + "'");
144: }
145:
146: for (StringTokenizer st = new StringTokenizer(path, "/"); st
147: .hasMoreTokens();) {
148: String s = st.nextToken();
149: if (s.equals("..")) {
150: ourPath = ourPath
151: .substring(0, ourPath.lastIndexOf('/'));
152: } else {
153: ourPath += "/" + s;
154: }
155: }
156:
157: URL target = null;
158:
159: try {
160: target = Strings.toURL(ourPath);
161: } catch (MalformedURLException mue) {
162: log.warn("Can't construct URL for: " + ourPath);
163: return null;
164: }
165:
166: DeploymentInfo targetInfo = null;
167: try {
168: targetInfo = (DeploymentInfo) server.invoke(
169: MainDeployerMBean.OBJECT_NAME, "getDeployment",
170: new Object[] { target }, new String[] { URL.class
171: .getName() });
172: } catch (Exception e) {
173: log.warn("Got Exception when looking for DeploymentInfo: "
174: + e);
175: return null;
176: }
177:
178: if (targetInfo == null) {
179: log.warn("Can't locate deploymentInfo for target: "
180: + target);
181: return null;
182: }
183:
184: if (log.isTraceEnabled()) {
185: log
186: .trace("Found appropriate DeploymentInfo: "
187: + targetInfo);
188: }
189:
190: String linkTarget = null;
191: if (targetInfo.metaData instanceof ApplicationMetaData) {
192: ApplicationMetaData appMD = (ApplicationMetaData) targetInfo.metaData;
193: BeanMetaData beanMD = appMD.getBeanByEjbName(ejbName);
194:
195: if (beanMD != null) {
196: linkTarget = getJndiName(beanMD, isLocal);
197: } else {
198: log.warn("No Bean named '" + ejbName + "' found in '"
199: + path + "'!");
200: }
201: } else {
202: log.warn("DeploymentInfo " + targetInfo
203: + " is not an EJB .jar " + "file!");
204: }
205:
206: return linkTarget;
207: }
208:
209: private static String resolveAbsoluteLink(DeploymentInfo di,
210: String link, boolean isLocal) {
211: if (log.isTraceEnabled()) {
212: log.trace("Resolving absolute link, di: " + di);
213: }
214:
215: String ejbName = null;
216:
217: // Search current DeploymentInfo
218: if (di.metaData instanceof ApplicationMetaData) {
219: // Look in the ejb module for a match
220: ApplicationMetaData appMD = (ApplicationMetaData) di.metaData;
221: BeanMetaData beanMD = appMD.getBeanByEjbName(link);
222: if (beanMD != null) {
223: ejbName = getJndiName(beanMD, isLocal);
224: if (log.isTraceEnabled()) {
225: log.trace("Found Bean: " + beanMD
226: + ", resolves to: " + ejbName);
227: }
228:
229: return ejbName;
230: } else if (log.isTraceEnabled()) {
231: // Dump the ejb module ejbNames
232: log.trace("No match for ejb-link: " + link
233: + ", module names:");
234: Iterator iter = appMD.getEnterpriseBeans();
235: while (iter.hasNext()) {
236: beanMD = (BeanMetaData) iter.next();
237: String beanEjbName = getJndiName(beanMD, isLocal);
238: log.trace("... ejbName: " + beanEjbName);
239: }
240: }
241: }
242:
243: // Search each subcontext
244: Iterator it = di.subDeployments.iterator();
245: while (it.hasNext() && ejbName == null) {
246: DeploymentInfo child = (DeploymentInfo) it.next();
247: ejbName = resolveAbsoluteLink(child, link, isLocal);
248: }
249:
250: return ejbName;
251: }
252:
253: private static String getJndiName(BeanMetaData beanMD,
254: boolean isLocal) {
255: String jndiName = null;
256: if (isLocal) {
257: // Validate that there is a local home associated with this bean
258: String localHome = beanMD.getLocalHome();
259: if (localHome != null)
260: jndiName = beanMD.getLocalJndiName();
261: else {
262: log.warn("LocalHome jndi name requested for: '"
263: + beanMD.getEjbName()
264: + "' but there is no LocalHome class");
265: }
266: } else {
267: jndiName = beanMD.getJndiName();
268: }
269: return jndiName;
270: }
271:
272: private static MessageDestinationMetaData resolveMessageDestination(
273: MBeanServer server, DeploymentInfo di, String link) {
274: if (link == null)
275: return null;
276:
277: if (log.isTraceEnabled())
278: log.trace("resolveLink( {" + di + "}, {" + link + "})");
279:
280: if (di == null)
281: // We should throw an IllegalArgumentException here probably?
282: return null;
283:
284: if (link.indexOf('#') != -1)
285: // link is specified in the form path/file.jar#Bean
286: return resolveRelativeMessageDestination(server, di, link);
287: else {
288: // link contains a Bean Name, scan the DeploymentInfo tree
289: DeploymentInfo top = di;
290: while (top.parent != null)
291: top = top.parent;
292:
293: return resolveAbsoluteMessageDestination(top, link);
294: }
295: }
296:
297: private static MessageDestinationMetaData resolveRelativeMessageDestination(
298: MBeanServer server, DeploymentInfo di, String link) {
299: String path = link.substring(0, link.indexOf('#'));
300: String destinationName = link.substring(link.indexOf('#') + 1);
301: String us = di.url.toString();
302:
303: // Remove the trailing slash for unpacked deployments
304: if (us.charAt(us.length() - 1) == '/')
305: us = us.substring(0, us.length() - 1);
306:
307: String ourPath = us.substring(0, us.lastIndexOf('/'));
308:
309: if (log.isTraceEnabled()) {
310: log.trace("Resolving relative message-destination-link: "
311: + link);
312: log.trace("Looking for: '" + link
313: + "', we're located at: '" + ourPath + "'");
314: }
315:
316: for (StringTokenizer st = new StringTokenizer(path, "/"); st
317: .hasMoreTokens();) {
318: String s = st.nextToken();
319: if (s.equals(".."))
320: ourPath = ourPath
321: .substring(0, ourPath.lastIndexOf('/'));
322: else
323: ourPath += "/" + s;
324: }
325:
326: URL target = null;
327: try {
328: target = Strings.toURL(ourPath);
329: } catch (MalformedURLException mue) {
330: log.warn("Can't construct URL for: " + ourPath);
331: return null;
332: }
333:
334: DeploymentInfo targetInfo = null;
335: try {
336: targetInfo = (DeploymentInfo) server.invoke(
337: MainDeployerMBean.OBJECT_NAME, "getDeployment",
338: new Object[] { target }, new String[] { URL.class
339: .getName() });
340: } catch (Exception e) {
341: log.warn("Got Exception when looking for DeploymentInfo: "
342: + e);
343: return null;
344: }
345:
346: if (targetInfo == null) {
347: log.warn("Can't locate deploymentInfo for target: "
348: + target);
349: return null;
350: }
351:
352: if (log.isTraceEnabled())
353: log
354: .trace("Found appropriate DeploymentInfo: "
355: + targetInfo);
356:
357: if (targetInfo.metaData instanceof ApplicationMetaData) {
358: ApplicationMetaData appMD = (ApplicationMetaData) targetInfo.metaData;
359: return appMD.getMessageDestination(destinationName);
360: } else if (targetInfo.metaData instanceof WebMetaData) {
361: WebMetaData webMD = (WebMetaData) targetInfo.metaData;
362: return webMD.getMessageDestination(destinationName);
363: } else {
364: log.warn("DeploymentInfo " + targetInfo
365: + " is not an EJB .jar " + "file!");
366: return null;
367: }
368: }
369:
370: private static MessageDestinationMetaData resolveAbsoluteMessageDestination(
371: DeploymentInfo di, String link) {
372: if (log.isTraceEnabled())
373: log.trace("Resolving absolute link, di: " + di);
374:
375: // Search current DeploymentInfo
376: if (di.metaData instanceof ApplicationMetaData) {
377: ApplicationMetaData appMD = (ApplicationMetaData) di.metaData;
378: MessageDestinationMetaData mdMD = appMD
379: .getMessageDestination(link);
380: if (mdMD != null)
381: return mdMD;
382: } else if (di.metaData instanceof WebMetaData) {
383: WebMetaData webMD = (WebMetaData) di.metaData;
384: return webMD.getMessageDestination(link);
385: }
386:
387: // Search each subcontext
388: Iterator it = di.subDeployments.iterator();
389: while (it.hasNext()) {
390: DeploymentInfo child = (DeploymentInfo) it.next();
391: MessageDestinationMetaData mdMD = resolveAbsoluteMessageDestination(
392: child, link);
393: if (mdMD != null)
394: return mdMD;
395: }
396:
397: // Not found
398: return null;
399: }
400: }
|