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.deployment;
023:
024: import java.io.File;
025: import java.io.FileInputStream;
026: import java.io.IOException;
027: import java.io.InputStream;
028: import java.net.URL;
029: import java.util.HashMap;
030: import java.util.Iterator;
031:
032: import javax.naming.Context;
033: import javax.naming.InitialContext;
034: import javax.naming.LinkRef;
035: import javax.naming.NamingException;
036:
037: import org.jboss.ejb.EjbUtil;
038: import org.jboss.metadata.ClientMetaData;
039: import org.jboss.metadata.EjbRefMetaData;
040: import org.jboss.metadata.EnvEntryMetaData;
041: import org.jboss.metadata.ResourceEnvRefMetaData;
042: import org.jboss.metadata.ResourceRefMetaData;
043: import org.jboss.metadata.XmlFileLoader;
044: import org.jboss.metadata.serviceref.ServiceRefDelegate;
045: import org.jboss.util.naming.Util;
046: import org.jboss.ws.integration.ServiceRefHandler;
047: import org.jboss.ws.integration.ServiceRefMetaData;
048: import org.jboss.ws.integration.URLLoaderAdapter;
049: import org.jboss.ws.integration.UnifiedVirtualFile;
050: import org.w3c.dom.Element;
051:
052: /**
053: * An XMBean resource implementation of a deployer for j2ee application
054: * client jars
055: *
056: * @author Scott.Stark@jboss.org
057: * @version $Revision: 61864 $
058: */
059: public class ClientDeployer extends SubDeployerSupport {
060: protected void startService() throws Exception {
061: // register with MainDeployer
062: super .startService();
063: }
064:
065: /**
066: * Implements the template method in superclass. This method stops all the
067: * applications in this server.
068: */
069: protected void stopService() throws Exception {
070: // deregister with MainDeployer
071: super .stopService();
072: }
073:
074: /**
075: * This method looks to the deployment for a META-INF/application-client.xml
076: * descriptor to identify a j2ee client jar.
077: *
078: * @param di The deployment info instance for the jar
079: * @return true if the deployment is a j2ee client jar, false otherwise
080: */
081: public boolean accepts(DeploymentInfo di) {
082: // To be accepted the deployment's root name must end in jar
083: String urlStr = di.url.getFile();
084: if (!urlStr.endsWith(".jar") && !urlStr.endsWith(".jar/")) {
085: return false;
086: }
087:
088: // However the jar must also contain an META-INF/application-client.xml
089: boolean accepts = false;
090: try {
091: URL dd = di.localCl
092: .findResource("META-INF/application-client.xml");
093: if (dd != null) {
094: log
095: .debug("Found a META-INF/application-client.xml file, di: "
096: + di);
097: accepts = true;
098: }
099: } catch (Exception ignore) {
100: }
101:
102: return accepts;
103: }
104:
105: /**
106: * Sub-classes should override this method to provide
107: * custom 'create' logic.
108: * <p/>
109: * This method issues a JMX notification of type SubDeployer.CREATE_NOTIFICATION.
110: */
111: public void create(DeploymentInfo di) throws DeploymentException {
112: super .create(di);
113: }
114:
115: /**
116: * Parse the application-client.xml and jboss-client.xml descriptors.
117: *
118: * @param di the application client jar deployment info
119: */
120: public void start(DeploymentInfo di) throws DeploymentException {
121: ClientMetaData metaData = null;
122: try {
123: InputStream in = null;
124: if (di.alternativeDD == null) {
125: in = di.localCl
126: .getResourceAsStream("META-INF/application-client.xml");
127: } else {
128: String contentsDir = new File(di.url.getPath())
129: .getParent();
130: in = new FileInputStream(contentsDir + "/"
131: + di.alternativeDD);
132: }
133:
134: if (in == null)
135: throw new DeploymentException(
136: "No META-INF/application-client.xml found");
137:
138: metaData = null;
139: XmlFileLoader xfl = new XmlFileLoader(true);
140: Element appClient = xfl.getDocument(in,
141: "META-INF/application-client.xml")
142: .getDocumentElement();
143: in.close();
144: metaData = new ClientMetaData();
145: metaData.setResourceClassLoader(di.localCl);
146: metaData.importClientXml(appClient);
147: di.metaData = metaData;
148:
149: // Look for a jboss-client.xml descriptor
150: in = di.localCl
151: .getResourceAsStream("META-INF/jboss-client.xml");
152: if (in != null) {
153: xfl = new XmlFileLoader(true);
154: Element jbossClient = xfl.getDocument(in,
155: "META-INF/jboss-client.xml")
156: .getDocumentElement();
157: in.close();
158: metaData.importJbossClientXml(jbossClient);
159: }
160: } catch (IOException e) {
161: throw new DeploymentException("Failed to parse metadata", e);
162: }
163:
164: try {
165: setupEnvironment(di, metaData);
166: } catch (Exception e) {
167: throw new DeploymentException("Failed to setup client ENC",
168: e);
169: }
170:
171: super .start(di);
172: }
173:
174: /**
175: * Sub-classes should override this method to provide
176: * custom 'stop' logic.
177: * <p/>
178: * This method issues a JMX notification of type SubDeployer.START_NOTIFICATION.
179: */
180: public void stop(DeploymentInfo di) throws DeploymentException {
181: // Teardown the JNDI context
182: ClientMetaData metaData = (ClientMetaData) di.metaData;
183: if (metaData != null) {
184: String appClientName = metaData.getJndiName();
185: log.info("Removing client ENC from: " + appClientName);
186: try {
187: InitialContext iniCtx = new InitialContext();
188: Util.unbind(iniCtx, appClientName);
189: } catch (NamingException e) {
190: throw new DeploymentException(
191: "Failed to remove client ENC", e);
192: }
193: }
194: super .stop(di);
195: }
196:
197: /**
198: * Sub-classes should override this method to provide
199: * custom 'destroy' logic.
200: * <p/>
201: * This method issues a JMX notification of type SubDeployer.DESTROY_NOTIFICATION.
202: */
203: public void destroy(DeploymentInfo di) throws DeploymentException {
204: super .destroy(di);
205: }
206:
207: private void setupEnvironment(DeploymentInfo di,
208: ClientMetaData metaData) throws Exception {
209: // Setup a JNDI context which contains
210: String appClientName = metaData.getJndiName();
211: InitialContext iniCtx = new InitialContext();
212: Context envCtx = Util.createSubcontext(iniCtx, appClientName);
213: log
214: .debug("Creating client ENC binding under: "
215: + appClientName);
216: // Bind environment properties
217: Iterator i = metaData.getEnvironmentEntries().iterator();
218: while (i.hasNext()) {
219: EnvEntryMetaData entry = (EnvEntryMetaData) i.next();
220: log.debug("Binding env-entry: " + entry.getName()
221: + " of type: " + entry.getType() + " to value:"
222: + entry.getValue());
223: EnvEntryMetaData.bindEnvEntry(envCtx, entry);
224: }
225:
226: // Bind EJB references
227: HashMap ejbRefs = metaData.getEjbReferences();
228: i = ejbRefs.values().iterator();
229: while (i.hasNext()) {
230: EjbRefMetaData ref = (EjbRefMetaData) i.next();
231: log.debug("Binding an EJBReference " + ref.getName());
232:
233: if (ref.getLink() != null) {
234: // Internal link
235: String linkName = ref.getLink();
236: String jndiName = EjbUtil.findEjbLink(server, di,
237: linkName);
238: log.debug("Binding " + ref.getName() + " to ejb-link: "
239: + linkName + " -> " + jndiName);
240: if (jndiName == null) {
241: String msg = "Failed to resolve ejb-link: "
242: + linkName + " make by ejb-name: "
243: + ref.getName();
244: throw new DeploymentException(msg);
245: }
246: log.debug("Link resolved to:" + jndiName);
247: Util.bind(envCtx, ref.getName(), new LinkRef(jndiName));
248: } else {
249: // Bind the bean level ejb-ref/jndi-name
250: if (ref.getJndiName() == null) {
251: throw new DeploymentException(
252: "ejb-ref "
253: + ref.getName()
254: + ", expected either ejb-link in ejb-jar.xml "
255: + "or jndi-name in jboss.xml");
256: }
257: log.debug("Binding " + ref.getName() + " to : "
258: + ref.getJndiName());
259: Util.bind(envCtx, ref.getName(), new LinkRef(ref
260: .getJndiName()));
261: }
262: }
263:
264: // Bind service references
265: UnifiedVirtualFile vfsRoot = new URLLoaderAdapter(di.url);
266: for (ServiceRefMetaData sref : metaData.getServiceReferences()
267: .values()) {
268: String refName = sref.getServiceRefName();
269: new ServiceRefDelegate().bindServiceRef(envCtx, refName,
270: vfsRoot, di.ucl, sref);
271: }
272:
273: // Bind resource references
274: HashMap resRefs = metaData.getResourceReferences();
275: i = resRefs.values().iterator();
276: while (i.hasNext()) {
277: ResourceRefMetaData ref = (ResourceRefMetaData) i.next();
278: String refName = ref.getRefName();
279: String jndiName = ref.getJndiName();
280:
281: if (ref.getType().equals("java.net.URL")) {
282: // URL bindings
283: String resURL = ref.getResURL();
284: if (resURL != null) {
285: log.debug("Binding '" + refName + "' to URL: "
286: + resURL);
287: URL url = new URL(resURL);
288: Util.bind(envCtx, refName, url);
289: } else {
290: log.debug("Linking '" + refName + "' to URL: "
291: + resURL);
292: LinkRef urlLink = new LinkRef(jndiName);
293: Util.bind(envCtx, refName, urlLink);
294: }
295: } else {
296: // A resource link
297: log.debug("Binding resource: " + refName
298: + " to JDNI as: " + jndiName);
299: Util.bind(envCtx, refName, new LinkRef(jndiName));
300: }
301: }
302:
303: // Bind resource env references
304: HashMap envRefs = metaData.getResourceEnvReferences();
305: i = envRefs.values().iterator();
306: while (i.hasNext()) {
307: ResourceEnvRefMetaData resRef = (ResourceEnvRefMetaData) i
308: .next();
309: String encName = resRef.getRefName();
310: String jndiName = resRef.getJndiName();
311: // Should validate the type...
312: log.debug("Binding env resource: " + encName
313: + " to JDNI as: " + jndiName);
314: Util.bind(envCtx, encName, new LinkRef(jndiName));
315: }
316: log.info("Client ENC bound under: " + appClientName);
317: }
318: }
|