001: /**
002: Licensed to the Apache Software Foundation (ASF) under one or more
003: contributor license agreements. See the NOTICE file distributed with
004: this work for additional information regarding copyright ownership.
005: The ASF licenses this file to You under the Apache License, Version 2.0
006: (the "License"); you may not use this file except in compliance with
007: the License. You may obtain a copy of the License at
008:
009: http://www.apache.org/licenses/LICENSE-2.0
010:
011: Unless required by applicable law or agreed to in writing, software
012: distributed under the License is distributed on an "AS IS" BASIS,
013: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: See the License for the specific language governing permissions and
015: limitations under the License.
016:
017: $Header:$
018: */package org.apache.beehive.controls.system.ejb.internal;
019:
020: import org.apache.beehive.controls.system.ejb.EJBInfo;
021: import org.w3c.dom.Document;
022: import org.w3c.dom.Element;
023: import org.w3c.dom.Node;
024:
025: import java.util.List;
026:
027: /**
028: * This class is used by the EJBControlAssembler to modify an ejb-jar.xml file's ejb-ref descriptors.
029: * The assembler will only invoke this class if the EJBControl's @EJBHome.ejbLink() annotation attribute
030: * has been set.
031: * <p/>
032: * The EjbJar assembler walks the ejb-jar.xml DOM tree looking for any session / entity beans
033: * which contain ejb-ref or ejb-local-ref elements. If an ejb-ref is found which matches the
034: * ejbRefName from the EJBInfo helper class it is removed and then re-created using the proper values.
035: */
036: public class EJBJarDescriptorHandler {
037:
038: /**
039: * Get an instance of this class.
040: * @return EJBJarDescriptorHandler instance.
041: */
042: public static EJBJarDescriptorHandler getInstance() {
043: return new EJBJarDescriptorHandler();
044: }
045:
046: /**
047: * Private constructor, use getInstance() to get an instance of this class.
048: */
049: private EJBJarDescriptorHandler() {
050: }
051:
052: /**
053: * Assemble entry point. Based on the type of EJBControl build a list of
054: * DOM elements of the property type (either session or entity) and process
055: * each entry in the list.
056: *
057: * @param document DOM tree of an ejb-jar.xml file.
058: * @param ejbInfo Contains information about the EJB control.
059: * @param ejbLinkValue The ejb-link value for the EJBs.
060: */
061: public void assemble(Document document, EJBInfo ejbInfo,
062: String ejbLinkValue) {
063: Element ejbJarType = document.getDocumentElement();
064: Element entBeansType = DomUtils.getChildElementByName(
065: ejbJarType, "enterprise-beans");
066:
067: String beanType = ejbInfo.getBeanType();
068: if (!("Session".equals(beanType) || "Entity".equals(beanType))) {
069: throw new UnsupportedOperationException(
070: "Unknown EJBControl type: " + ejbInfo.getBeanType()
071: + beanType
072: + " Expected 'Session' or 'Entity'");
073: }
074:
075: /* TODO: Currently, we update all session and entity bean entries with a ejb ref, even
076: if the control is not used from the ejb. We should probably only add an ejb ref
077: to a given session or entity bean if the control is referenced by it. */
078: List sessionEjbList = DomUtils.getChildElementsByName(
079: entBeansType, "session");
080: insertEJBRefsInEJBJar(document, ejbInfo, ejbLinkValue,
081: sessionEjbList);
082:
083: List entityEjbList = DomUtils.getChildElementsByName(
084: entBeansType, "entity");
085: insertEJBRefsInEJBJar(document, ejbInfo, ejbLinkValue,
086: entityEjbList);
087: }
088:
089: /**
090: * Insert EJB references in all of the descriptors of the EJB's in the supplied list
091: *
092: * @param document DOM tree of an ejb-jar.xml file.
093: * @param ejbInfo Contains information about the EJB control.
094: * @param ejbLinkValue The ejb-link value for the EJBs.
095: * @param ejbList The list of EJB's
096: */
097: private void insertEJBRefsInEJBJar(Document document,
098: EJBInfo ejbInfo, String ejbLinkValue, List ejbList) {
099: for (Object ejb : ejbList) {
100: if (ejbInfo.isLocal())
101: insertEJBLocalRefInEJBJar((Element) ejb, ejbInfo,
102: ejbLinkValue, document);
103: else
104: insertEJBRefInEJBJar((Element) ejb, ejbInfo,
105: ejbLinkValue, document);
106: }
107: }
108:
109: /**
110: * Insert a remote ejb-ref into the specified EJB's descriptor, if an ejb-ref already
111: * exists with the same name, remove it before adding a new ref.
112: *
113: * @param ejb Root DOM element of the EJB descriptor.
114: * @param ei EJBInfo helper.
115: * @param ejbLinkValue New ejb-link value.
116: * @param ejbDoc The ejb-jar DOM root.
117: */
118: private void insertEJBRefInEJBJar(Element ejb, EJBInfo ei,
119: String ejbLinkValue, Document ejbDoc) {
120:
121: List ejbRefArray = DomUtils.getChildElementsByName(ejb,
122: "ejb-ref");
123: String insertedEjbRefName = ei.getRefName();
124:
125: Node nextSibling = null;
126: for (int j = ejbRefArray.size() - 1; j >= 0; j--) {
127: Element ejbRef = (Element) ejbRefArray.get(j);
128: String ejbRefName = DomUtils.getChildElementText(ejbRef,
129: "ejb-ref-name");
130: if (insertedEjbRefName.equals(ejbRefName)) {
131: nextSibling = ejbRef.getNextSibling();
132: ejb.removeChild(ejbRef);
133: break;
134: }
135: }
136:
137: // insert a new <ejb-ref> entry and fill in the values
138: Element insertedEjbRef = ejbDoc.createElement("ejb-ref");
139: if (nextSibling != null) {
140: ejb.insertBefore(insertedEjbRef, nextSibling);
141: } else {
142: ejb
143: .insertBefore(insertedEjbRef,
144: findEjbRefInsertPoint(ejb));
145: }
146:
147: Element ejbRefName = ejbDoc.createElement("ejb-ref-name");
148: ejbRefName.setTextContent(insertedEjbRefName);
149: insertedEjbRef.appendChild(ejbRefName);
150:
151: Element ejbRefType = ejbDoc.createElement("ejb-ref-type");
152: ejbRefType.setTextContent(ei.getBeanType());
153: insertedEjbRef.appendChild(ejbRefType);
154:
155: Element homeType = ejbDoc.createElement("home");
156: homeType.setTextContent(ei.getHomeInterface().getName());
157: insertedEjbRef.appendChild(homeType);
158:
159: Element remoteType = ejbDoc.createElement("remote");
160: remoteType.setTextContent(ei.getBeanInterface().getName());
161: insertedEjbRef.appendChild(remoteType);
162:
163: Element ejbLink = ejbDoc.createElement("ejb-link");
164: ejbLink.setTextContent(ejbLinkValue);
165: insertedEjbRef.appendChild(ejbLink);
166: }
167:
168: /**
169: * Insert a local ejb-ref into the specified EJB's descriptor, if an ejb-ref already
170: * exists with the same name, remove it before adding a new ref.
171: *
172: * @param ejb Root DOM element of the EJB descriptor.
173: * @param ei EJBInfo helper.
174: * @param ejbLinkValue New ejb-link value.
175: * @param ejbDoc The ejb-jar DOM root.
176: */
177: private void insertEJBLocalRefInEJBJar(Element ejb, EJBInfo ei,
178: String ejbLinkValue, Document ejbDoc) {
179:
180: List ejbLocalRefArray = DomUtils.getChildElementsByName(ejb,
181: "ejb-local-ref");
182: String insertedEjbRefName = ei.getRefName();
183:
184: Node nextSibling = null;
185: for (int j = ejbLocalRefArray.size() - 1; j >= 0; j--) {
186: Element ejbLocalRef = (Element) ejbLocalRefArray.get(j);
187: String ejbRefName = DomUtils.getChildElementText(
188: ejbLocalRef, "ejb-ref-name");
189: if (insertedEjbRefName.equals(ejbRefName)) {
190: nextSibling = ejbLocalRef.getNextSibling();
191: ejb.removeChild(ejbLocalRef);
192: break;
193: }
194: }
195:
196: // insert a new <ejb-local-ref> entry and fill in the values
197: Element insertedEjbLocalRef = ejbDoc
198: .createElement("ejb-local-ref");
199: if (nextSibling != null) {
200: ejb.insertBefore(insertedEjbLocalRef, nextSibling);
201: } else {
202: ejb.insertBefore(insertedEjbLocalRef,
203: findEjbLocalRefInsertPoint(ejb));
204: }
205:
206: Element ejbRefName = ejbDoc.createElement("ejb-ref-name");
207: ejbRefName.setTextContent(insertedEjbRefName);
208: insertedEjbLocalRef.appendChild(ejbRefName);
209:
210: Element ejbRefType = ejbDoc.createElement("ejb-ref-type");
211: ejbRefType.setTextContent(ei.getBeanType());
212: insertedEjbLocalRef.appendChild(ejbRefType);
213:
214: Element homeType = ejbDoc.createElement("local-home");
215: homeType.setTextContent(ei.getHomeInterface().getName());
216: insertedEjbLocalRef.appendChild(homeType);
217:
218: Element localType = ejbDoc.createElement("local");
219: localType.setTextContent(ei.getBeanInterface().getName());
220: insertedEjbLocalRef.appendChild(localType);
221:
222: Element ejbLink = ejbDoc.createElement("ejb-link");
223: ejbLink.setTextContent(ejbLinkValue);
224: insertedEjbLocalRef.appendChild(ejbLink);
225: }
226:
227: /**
228: * ejb-refs must be inserted before any ejb-local-ref tags.
229: *
230: * @param parent The 'session' or 'entity' XML element.
231: * @return A suitable node to insert the ejb-ref BEFORE.
232: */
233: private Node findEjbRefInsertPoint(Element parent) {
234:
235: Element e = DomUtils.getChildElementByName(parent,
236: "ejb-local-ref");
237: if (e != null)
238: return e;
239:
240: return findEjbLocalRefInsertPoint(parent);
241: }
242:
243: /**
244: * The local ref must be inserted into the ejb-jar file at the proper
245: * location based on the ejb-jar schema definition. Check for elements which
246: * can immediatly FOLLOW an ejb-ref from the closest to farthest as
247: * defined by the schema.
248: *
249: * @param parent The 'session' or 'entity' XML element.
250: * @return A suitable node to insert the ejb-local-ref BEFORE.
251: */
252: private Node findEjbLocalRefInsertPoint(Element parent) {
253:
254: Element e = DomUtils.getChildElementByName(parent,
255: "service-ref");
256: if (e != null)
257: return e;
258:
259: e = DomUtils.getChildElementByName(parent, "resource-ref");
260: if (e != null)
261: return e;
262:
263: e = DomUtils.getChildElementByName(parent, "resource-env-ref");
264: if (e != null)
265: return e;
266:
267: e = DomUtils.getChildElementByName(parent,
268: "message-destination-ref");
269: if (e != null)
270: return e;
271:
272: e = DomUtils.getChildElementByName(parent, "security-role-ref");
273: if (e != null)
274: return e;
275:
276: e = DomUtils.getChildElementByName(parent, "security-identity");
277: if (e != null)
278: return e;
279:
280: // only applies to entity beans
281: e = DomUtils.getChildElementByName(parent, "query");
282: if (e != null)
283: return e;
284:
285: return null;
286: }
287: }
|