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: 476049 $ $Date: 2006-11-16 23:35:17 -0500 (Thu, 16 Nov 2006) $ 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 }