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.io.InputStream; 020 import java.io.IOException; 021 import java.io.OutputStream; 022 import java.util.Map; 023 import java.util.HashMap; 024 import java.util.List; 025 import java.util.ArrayList; 026 import java.util.Iterator; 027 import java.util.Arrays; 028 import javax.enterprise.deploy.model.DDBeanRoot; 029 import javax.enterprise.deploy.model.DDBean; 030 import javax.enterprise.deploy.spi.DConfigBean; 031 import javax.enterprise.deploy.spi.exceptions.ConfigurationException; 032 import org.apache.geronimo.deployment.plugin.DConfigBeanRootSupport; 033 import org.apache.geronimo.xbeans.geronimo.GerConnectorDocument; 034 import org.apache.geronimo.xbeans.geronimo.GerAdminobjectInstanceType; 035 import org.apache.geronimo.xbeans.geronimo.GerConnectiondefinitionInstanceType; 036 import org.apache.geronimo.xbeans.geronimo.GerResourceadapterInstanceType; 037 import org.apache.geronimo.xbeans.geronimo.GerConfigPropertySettingType; 038 import org.apache.xmlbeans.XmlObject; 039 import org.apache.xmlbeans.XmlException; 040 import org.apache.xmlbeans.SchemaTypeLoader; 041 import org.apache.xmlbeans.XmlBeans; 042 import org.apache.xmlbeans.XmlCursor; 043 044 /** 045 * Represents "/" in a Geronimo Connector deployment plan (geronimo-ra.xml). 046 * The only function here is to navigate to an appropriate "Connector" 047 * DConfigBean. 048 * 049 * @version $Rev: 476049 $ $Date: 2006-11-16 23:35:17 -0500 (Thu, 16 Nov 2006) $ 050 */ 051 public class Connector15DCBRoot extends DConfigBeanRootSupport { 052 // This may be overcomplicated -- if we don't refer to J2EE types in our schemas 053 // then we should only need to use the GerConnectorDocument loader 054 static final SchemaTypeLoader SCHEMA_TYPE_LOADER = XmlBeans.typeLoaderUnion(new SchemaTypeLoader[] { 055 XmlBeans.typeLoaderForClassLoader(org.apache.geronimo.xbeans.j2ee.String.class.getClassLoader()), 056 XmlBeans.typeLoaderForClassLoader(GerConnectorDocument.class.getClassLoader()) 057 }); 058 059 private ConnectorDCB connector; 060 061 public Connector15DCBRoot(DDBeanRoot ddBean) { 062 super(ddBean, null); 063 setXmlObject(loadDefaultData(ddBean)); 064 } 065 066 private XmlObject loadDefaultData(DDBeanRoot root) { 067 InputStream in = root.getDeployableObject().getEntry("META-INF/geronimo-ra.xml"); 068 if(in == null) { 069 GerConnectorDocument doc = GerConnectorDocument.Factory.newInstance(); 070 DDBean[] list = root.getChildBean("connector"); 071 if(list.length > 0) { 072 connector = new ConnectorDCB(list[0], doc.addNewConnector()); 073 } 074 return doc; 075 } else { 076 try { 077 GerConnectorDocument result = GerConnectorDocument.Factory.parse(in); 078 in.close(); 079 DDBean[] list = root.getChildBean("connector"); 080 if(list.length > 0) { 081 connector = new ConnectorDCB(list[0], result.getConnector()); 082 } 083 return result; 084 } catch (XmlException e) { 085 throw new RuntimeException("Unable to load default Geronimo RA data", e); 086 } catch (IOException e) { 087 throw new RuntimeException("Unable to load default Geronimo RA data", e); 088 } 089 } 090 } 091 092 GerConnectorDocument getConnectorDocument() { 093 return (GerConnectorDocument) getXmlObject(); 094 } 095 096 public String[] getXpaths() { 097 return getXPathsForJ2ee_1_4(new String[][]{{"connector",},}); 098 } 099 100 public DConfigBean getDConfigBean(DDBean bean) throws ConfigurationException { 101 if (getXpaths()[0].equals(bean.getXpath())) { // "connector" 102 return connector; 103 } else { 104 throw new ConfigurationException("No DConfigBean matching DDBean "+bean.getXpath()); 105 } 106 } 107 108 protected SchemaTypeLoader getSchemaTypeLoader() { 109 return SCHEMA_TYPE_LOADER; 110 } 111 112 /** 113 * When loaded, reset the cached "connector" child 114 */ 115 public void fromXML(InputStream inputStream) throws XmlException, IOException { 116 DDBean ddb = connector.getDDBean(); 117 super.fromXML(inputStream); 118 if(getConnectorDocument().getConnector() != null) { 119 connector = new ConnectorDCB(ddb, getConnectorDocument().getConnector()); 120 } else { 121 connector = new ConnectorDCB(ddb, getConnectorDocument().addNewConnector()); 122 } 123 //todo: fire some kind of notification for the DDBeans to catch? 124 } 125 126 /** 127 * A little trickery -- on a save event, temporarily remove any config-property-setting 128 * elements with a null value, and then immediately replace them again. This is because 129 * we don't want to write them out as null, but we also want to keep the objects in 130 * sync 1:1 with the config params declared in the J2EE deployment descriptor. 131 */ 132 public void toXML(OutputStream outputStream) throws IOException { 133 List parents = new ArrayList(); 134 clearNulls(parents); 135 try { 136 super.toXML(outputStream); 137 } finally { 138 for (int i = 0; i < parents.size(); i++) { 139 Object parent = parents.get(i); 140 ConfigHolder instance = (ConfigHolder) parent; 141 instance.reconfigure(); 142 } 143 } 144 } 145 146 private void clearNulls(List parents) { 147 ResourceAdapter[] adapters = connector.getResourceAdapter(); 148 for (int i = 0; i < adapters.length; i++) { 149 ResourceAdapter adapter = adapters[i]; 150 if(adapter.getResourceAdapterInstance() != null) { 151 parents.add(adapter.getResourceAdapterInstance()); 152 adapter.getResourceAdapterInstance().clearNullSettings(); 153 } 154 ConnectionDefinition defs[] = adapter.getConnectionDefinition(); 155 for (int j = 0; j < defs.length; j++) { 156 ConnectionDefinition def = defs[j]; 157 ConnectionDefinitionInstance instances[] = def.getConnectionInstances(); 158 for (int k = 0; k < instances.length; k++) { 159 ConnectionDefinitionInstance instance = instances[k]; 160 parents.add(instance); 161 instance.clearNullSettings(); 162 } 163 } 164 } 165 try { 166 DDBean[] adminDDBs = connector.getDDBean().getChildBean(connector.getXpaths()[0]); 167 if(adminDDBs == null) adminDDBs = new DDBean[0]; 168 for (int i = 0; i < adminDDBs.length; i++) { 169 DDBean ddb = adminDDBs[i]; 170 AdminObjectDCB dcb = (AdminObjectDCB) connector.getDConfigBean(ddb); 171 AdminObjectInstance[] instances = dcb.getAdminObjectInstance(); 172 for (int j = 0; j < instances.length; j++) { 173 AdminObjectInstance instance = instances[j]; 174 parents.add(instance); 175 instance.clearNullSettings(); 176 } 177 } 178 } catch (ConfigurationException e) { 179 e.printStackTrace(); 180 } 181 } 182 }