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