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: */package org.apache.geronimo.connector.deployment.jsr88;
017:
018: import java.util.ArrayList;
019: import java.util.Arrays;
020: import java.util.Collections;
021: import java.util.HashSet;
022: import java.util.Iterator;
023: import java.util.LinkedHashMap;
024: import java.util.List;
025: import java.util.Map;
026: import java.util.Set;
027: import javax.enterprise.deploy.model.DDBean;
028: import javax.enterprise.deploy.model.XpathEvent;
029: import javax.enterprise.deploy.model.XpathListener;
030: import javax.enterprise.deploy.spi.DConfigBean;
031: import javax.enterprise.deploy.spi.exceptions.ConfigurationException;
032: import org.apache.geronimo.deployment.plugin.DConfigBeanSupport;
033: import org.apache.geronimo.deployment.service.jsr88.EnvironmentData;
034: import org.apache.geronimo.xbeans.geronimo.GerAdminobjectInstanceType;
035: import org.apache.geronimo.xbeans.geronimo.GerAdminobjectType;
036: import org.apache.geronimo.xbeans.geronimo.GerConnectorType;
037: import org.apache.geronimo.xbeans.geronimo.GerResourceadapterType;
038: import org.apache.xmlbeans.SchemaTypeLoader;
039: import org.apache.xmlbeans.XmlCursor;
040:
041: /**
042: * Represents /connector in a Geronimo Connector deployment plan.
043: * Corresponds to /connector in the J2EE deployment plan.
044: *
045: * @version $Rev: 476049 $ $Date: 2006-11-16 20:35:17 -0800 (Thu, 16 Nov 2006) $
046: */
047: public class ConnectorDCB extends DConfigBeanSupport {
048: private DDBean resourceAdapterDDBean;
049: private ResourceAdapter[] resourceAdapter = new ResourceAdapter[0];
050: private AdminObjectDCB[] adminobjects = new AdminObjectDCB[0];
051: private EnvironmentData environment;
052:
053: public ConnectorDCB(DDBean connectorDDBean,
054: final GerConnectorType connector) {
055: super (connectorDDBean, connector);
056: DDBean[] list = connectorDDBean.getChildBean("resourceadapter");
057: if (list.length > 0) {
058: resourceAdapterDDBean = list[0];
059: }
060: //todo: do something if resourceAdapterDDBean is null
061: loadExistingData(connector);
062:
063: // Make sure we're told if /connector/resourceadapter is replaced!
064: connectorDDBean.addXpathListener("resourceadapter",
065: new XpathListener() {
066: public void fireXpathEvent(XpathEvent event) {
067: if (event.isRemoveEvent()) {
068: resourceAdapterDDBean = null; //todo: all our info was just invalidated
069: } else if (event.isAddEvent()) {
070: resourceAdapterDDBean = event.getBean(); //todo: reload defaults from DDBean
071: } else {
072: System.out
073: .println("Detected change to J2EE DD /connector/resourceadapter property "
074: + event.getChangeEvent()
075: .getPropertyName());
076: }
077: }
078: });
079: }
080:
081: public String[] getXpaths() {
082: return getXPathsForJ2ee_1_4(new String[][] { {
083: "resourceadapter", "adminobject", }, });
084: }
085:
086: public DConfigBean getDConfigBean(DDBean bean)
087: throws ConfigurationException {
088: if (getXpaths()[0].equals(bean.getXpath())) { // "adminobject"
089: String aoInterface = bean.getText("adminobject-interface")[0];
090: String aoClass = bean.getText("adminobject-class")[0];
091: // Check whether we've seen this one before
092: for (int i = 0; i < adminobjects.length; i++) {
093: if (adminobjects[i].getAdminObjectClass().equals(
094: aoClass)
095: && adminobjects[i].getAdminObjectInterface()
096: .equals(aoInterface)) {
097: return adminobjects[i];
098: }
099: }
100: // Haven't seen it; create a new DConfigBean
101: GerAdminobjectType ao = getConnector().addNewAdminobject();
102: AdminObjectDCB dcb = new AdminObjectDCB(bean, ao);
103: AdminObjectDCB[] list = new AdminObjectDCB[adminobjects.length + 1];
104: System.arraycopy(adminobjects, 0, list, 0,
105: adminobjects.length);
106: list[adminobjects.length] = dcb;
107: return dcb;
108: } else {
109: throw new ConfigurationException(
110: "No DConfigBean matching DDBean " + bean.getXpath());
111: }
112: }
113:
114: private void loadExistingData(GerConnectorType connector) {
115: //todo: Handle the import children
116: //todo: Handle the hidden-classes children
117: //todo: Handle the non-overridable-classes children
118: // Handle the dependency children
119: // ArtifactType[] deps = connector.getDependencyArray();
120: // if(deps != null && deps.length > 0) {
121: // dependency = new Artifact[deps.length];
122: // for (int i = 0; i < deps.length; i++) {
123: // dependency[i] = new Artifact(deps[i]);
124: // }
125: // }
126: // Handle the resource adapter children
127: GerResourceadapterType[] adapters = connector
128: .getResourceadapterArray();
129: if (adapters == null || adapters.length == 0) {
130: // Make sure there's at least one connector/resourceadapter element
131: if (resourceAdapterDDBean != null) {
132: resourceAdapter = new ResourceAdapter[1];
133: resourceAdapter[0] = new ResourceAdapter(
134: resourceAdapterDDBean, connector
135: .addNewResourceadapter());
136: }
137: } else {
138: resourceAdapter = new ResourceAdapter[adapters.length];
139: for (int i = 0; i < adapters.length; i++) {
140: GerResourceadapterType adapter = adapters[i];
141: resourceAdapter[i] = new ResourceAdapter(
142: resourceAdapterDDBean, adapter);
143: }
144: }
145: // Handle the AdminObject children
146: GerAdminobjectType[] admins = connector.getAdminobjectArray();
147: DDBean[] data = getDDBean().getChildBean(getXpaths()[0]);
148: List ddBeans = data == null ? Collections.EMPTY_LIST
149: : new ArrayList(Arrays.asList(data)); // resourceadapter/adminobject
150:
151: Map dcbs = new LinkedHashMap();
152: if (admins == null) {
153: adminobjects = new AdminObjectDCB[0];
154: } else {
155: // Match up each Geronimo adminobject with a ra.xml adminobject and create DConfigBeans accordingly
156: for (int i = 0; i < admins.length; i++) {
157: GerAdminobjectType admin = admins[i];
158: String aoClass = admin.getAdminobjectClass();
159: String aoIface = admin.getAdminobjectInterface();
160: AdminObjectDCB dcb = (AdminObjectDCB) dcbs.get("class "
161: + aoClass + " iface " + aoIface);
162: if (dcb != null) {
163: // this is a second Geronimo adminobject block of the same type; there will not be a matching DDBean any more
164: // merge the adminobject-instance entries instead!!!
165: if (admin.getAdminobjectInstanceArray().length > 0) {
166: GerAdminobjectType old = dcb.getAdminObject();
167: GerAdminobjectInstanceType[] array = admin
168: .getAdminobjectInstanceArray();
169: int oldCount = dcb.getAdminObjectInstance().length;
170: for (int j = 0; j < array.length; j++) {
171: GerAdminobjectInstanceType instance = array[j];
172: XmlCursor source = instance.newCursor();
173: XmlCursor dest = old.newCursor();
174: dest.toEndToken();
175: if (!source.moveXml(dest)) {
176: throw new RuntimeException(
177: "Unable to move admin object instance");
178: }
179: source.dispose();
180: dest.dispose();
181: dcb
182: .addAdminObjectInstance(old
183: .getAdminobjectInstanceArray(oldCount
184: + j));
185: }
186: }
187: continue;
188: }
189: DDBean target = null;
190: for (int j = 0; j < ddBeans.size(); j++) {
191: DDBean ddBean = (DDBean) ddBeans.get(j);
192: String ddClass = ddBean
193: .getText("adminobject-class")[0];
194: String ddIface = ddBean
195: .getText("adminobject-interface")[0];
196: if (ddClass.equals(aoClass)
197: && ddIface.equals(aoIface)) {
198: target = ddBean;
199: ddBeans.remove(j);
200: break;
201: }
202: }
203: if (target == null) {
204: System.out
205: .println("Geronimo connector deployment plan has admin object with interface '"
206: + aoIface
207: + "' and class '"
208: + aoClass
209: + "' but the ra.xml does not have a matching adminobject declared. Deleting this adminobject from the Geronimo plan.");
210: continue;
211: }
212: dcb = new AdminObjectDCB(target, admin);
213: dcbs.put("class " + aoClass + " iface " + aoIface, dcb);
214: }
215: }
216: // There are some admin object types in ra.xml with no matching instances; create DConfigBeans for those
217: for (int i = 0; i < ddBeans.size(); i++) {
218: DDBean ddBean = (DDBean) ddBeans.get(i);
219: String ddClass = ddBean.getText("adminobject-class")[0];
220: String ddIface = ddBean.getText("adminobject-interface")[0];
221: GerAdminobjectType admin = connector.addNewAdminobject();
222: dcbs.put("class " + ddClass + " iface " + ddIface,
223: new AdminObjectDCB(ddBean, admin));
224: }
225: List adminResults = new ArrayList();
226: for (Iterator it = dcbs.keySet().iterator(); it.hasNext();) {
227: String key = (String) it.next();
228: DConfigBean value = (DConfigBean) dcbs.get(key);
229: adminResults.add(value);
230: }
231: adminobjects = (AdminObjectDCB[]) adminResults
232: .toArray(new AdminObjectDCB[adminResults.size()]);
233:
234: //todo: Handle the GBean children
235: }
236:
237: GerConnectorType getConnector() {
238: return (GerConnectorType) getXmlObject();
239: }
240:
241: // ----------------------- JavaBean Properties for /connector ----------------------
242:
243: //todo: the following child elements
244: // gbean*
245:
246: public EnvironmentData getEnvironment() {
247: return environment;
248: }
249:
250: public void setEnvironment(EnvironmentData environment) {
251: EnvironmentData old = this .environment;
252: this .environment = environment;
253: if ((old == null && environment == null)
254: || (old != null && old == environment)) {
255: return;
256: }
257: if (old != null) {
258: getConnector().unsetEnvironment();
259: }
260: if (environment != null) {
261: environment.configure(getConnector().addNewEnvironment());
262: }
263: pcs.firePropertyChange("environment", old, environment);
264: }
265:
266: public ResourceAdapter[] getResourceAdapter() {
267: return resourceAdapter;
268: }
269:
270: public void setResourceAdapter(ResourceAdapter[] resourceAdapter) {
271: ResourceAdapter[] old = this .resourceAdapter;
272: Set before = new HashSet();
273: for (int i = 0; i < old.length; i++) {
274: before.add(old[i]);
275: }
276: this .resourceAdapter = resourceAdapter;
277: // Handle current or new resource adapters
278: for (int i = 0; i < resourceAdapter.length; i++) {
279: ResourceAdapter adapter = resourceAdapter[i];
280: if (adapter.getResourceAdapter() == null) {
281: adapter.configure(resourceAdapterDDBean, getConnector()
282: .addNewResourceadapter());
283: } else {
284: before.remove(adapter);
285: }
286: }
287: // Handle removed resource adapters
288: for (Iterator it = before.iterator(); it.hasNext();) {
289: ResourceAdapter adapter = (ResourceAdapter) it.next();
290: GerResourceadapterType all[] = getConnector()
291: .getResourceadapterArray();
292: for (int i = 0; i < all.length; i++) {
293: if (all[i] == adapter) {
294: getConnector().removeResourceadapter(i);
295: break;
296: }
297: }
298: }
299: pcs.firePropertyChange("resourceAdapter", old, resourceAdapter);
300: }
301:
302: public ResourceAdapter getResourceAdapter(int index) {
303: return resourceAdapter[index];
304: }
305:
306: public void setResourceAdapter(int index, ResourceAdapter ra) {
307: ResourceAdapter[] old = this .resourceAdapter;
308: resourceAdapter[index] = ra;
309: if (ra.getResourceAdapter() == null) {
310: ra.configure(resourceAdapterDDBean, getConnector()
311: .addNewResourceadapter());
312: }
313: pcs.firePropertyChange("resourceAdapter", old, resourceAdapter);
314: }
315:
316: // ----------------------- End of JavaBean Properties ----------------------
317:
318: protected SchemaTypeLoader getSchemaTypeLoader() {
319: return Connector15DCBRoot.SCHEMA_TYPE_LOADER;
320: }
321: }
|