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.console.jmsmanager.wizard; 018 019 import java.io.File; 020 import java.io.FileInputStream; 021 import java.io.IOException; 022 import java.io.InputStream; 023 import java.io.Serializable; 024 import java.util.ArrayList; 025 import java.util.HashSet; 026 import java.util.Iterator; 027 import java.util.List; 028 import java.util.Properties; 029 import java.util.Set; 030 import java.util.zip.ZipEntry; 031 import java.util.zip.ZipInputStream; 032 import javax.portlet.PortletRequest; 033 import javax.xml.parsers.DocumentBuilder; 034 import javax.xml.parsers.DocumentBuilderFactory; 035 import javax.xml.parsers.ParserConfigurationException; 036 import org.apache.commons.logging.Log; 037 import org.apache.commons.logging.LogFactory; 038 import org.apache.geronimo.console.util.PortletManager; 039 import org.apache.geronimo.kernel.util.XmlUtil; 040 import org.w3c.dom.Document; 041 import org.w3c.dom.Element; 042 import org.w3c.dom.Node; 043 import org.w3c.dom.NodeList; 044 import org.xml.sax.SAXException; 045 046 /** 047 * Loads data on JMS providers known to the console. Reads from a properties 048 * file on the class path. 049 * 050 * @version $Rev: 476061 $ $Date: 2006-11-17 01:36:50 -0500 (Fri, 17 Nov 2006) $ 051 */ 052 public class JMSProviderData implements Serializable { 053 private final static Log log = LogFactory.getLog(JMSProviderData.class); 054 private String name; 055 private final String raURI; 056 private final String dependency; 057 private String defaultTransaction; 058 private ConfigPropertyData[] instanceConfigProperties; 059 private ConnectionDefinition[] connectionDefinitions; 060 private AdminObjectDefinition[] adminObjectDefinitions; 061 062 public JMSProviderData(String name, String raURI, String dependency) { 063 this.name = name; 064 this.raURI = raURI; 065 this.dependency = dependency; 066 } 067 068 public String getName() { 069 return name; 070 } 071 072 public String getRaURI() { 073 return raURI; 074 } 075 076 public String getDependency() { 077 return dependency; 078 } 079 080 public String getDefaultTransaction() { 081 return defaultTransaction; 082 } 083 084 public ConfigPropertyData[] getInstanceConfigProperties() { 085 return instanceConfigProperties; 086 } 087 088 public ConnectionDefinition[] getConnectionDefinitions() { 089 return connectionDefinitions; 090 } 091 092 public AdminObjectDefinition[] getAdminObjectDefinitions() { 093 return adminObjectDefinitions; 094 } 095 096 public static class ConfigPropertyData implements Serializable { 097 private final String name; 098 private final String type; 099 private final String defaultValue; 100 private final String description; 101 102 public ConfigPropertyData(String name, String type, String defaultValue, String description) { 103 this.name = name; 104 this.type = type; 105 this.defaultValue = defaultValue; 106 this.description = description; 107 } 108 109 public String getName() { 110 return name; 111 } 112 113 public String getType() { 114 return type; 115 } 116 117 public String getDefaultValue() { 118 return defaultValue; 119 } 120 121 public String getDescription() { 122 return description; 123 } 124 } 125 126 public static class ConnectionDefinition implements Serializable { 127 private final String connectionFactoryInterface; 128 private final ConfigPropertyData[] configProperties; 129 130 public ConnectionDefinition(String connectionFactoryInterface, ConfigPropertyData[] configProperties) { 131 this.connectionFactoryInterface = connectionFactoryInterface; 132 this.configProperties = configProperties; 133 } 134 135 public String getConnectionFactoryInterface() { 136 return connectionFactoryInterface; 137 } 138 139 public ConfigPropertyData[] getConfigProperties() { 140 return configProperties; 141 } 142 } 143 144 public static class AdminObjectDefinition implements Serializable { 145 private final String adminObjectInterface; 146 private final String adminObjectClass; 147 private final ConfigPropertyData[] configProperties; 148 149 public AdminObjectDefinition(String adminObjectInterface, String adminObjectClass, ConfigPropertyData[] configProperties) { 150 this.adminObjectInterface = adminObjectInterface; 151 this.adminObjectClass = adminObjectClass; 152 this.configProperties = configProperties; 153 } 154 155 public String getAdminObjectInterface() { 156 return adminObjectInterface; 157 } 158 159 public String getAdminObjectClass() { 160 return adminObjectClass; 161 } 162 163 public ConfigPropertyData[] getConfigProperties() { 164 return configProperties; 165 } 166 } 167 168 169 // *************** Static methods to access the data **************** 170 171 private static List all = null; 172 public static JMSProviderData[] getAllProviders() { 173 if(all == null) { 174 loadProviders(); 175 } 176 return (JMSProviderData[]) all.toArray(new JMSProviderData[all.size()]); 177 } 178 179 public static JMSProviderData getProviderByName(String name) { 180 if(all == null) { 181 loadProviders(); 182 } 183 for (int i = 0; i < all.size(); i++) { 184 JMSProviderData data = (JMSProviderData) all.get(i); 185 if(data.getName().equals(name)) { 186 return data; 187 } 188 } 189 return null; 190 } 191 192 public static JMSProviderData getProviderData(String rar, PortletRequest request) throws IOException { 193 if(all == null) { 194 loadProviders(); 195 } 196 for (int i = 0; i < all.size(); i++) { 197 JMSProviderData data = (JMSProviderData) all.get(i); 198 if(data.getRaURI().equals(rar)) { 199 if(data.instanceConfigProperties == null) { 200 loadRARData(data, request); 201 } 202 return data; 203 } 204 } 205 JMSProviderData data = new JMSProviderData(null, rar, null); 206 loadRARData(data, request); 207 all.add(data); 208 return data; 209 } 210 211 private static void loadRARData(JMSProviderData data, PortletRequest request) throws IOException { 212 File url = PortletManager.getRepositoryEntry(request, data.getRaURI()); 213 if(url == null) { 214 throw new IOException("Unable to locate entry "+data.getRaURI()+" in repository"); 215 } 216 ZipInputStream in = new ZipInputStream(new FileInputStream(url)); 217 ZipEntry entry; 218 Document doc = null; 219 try { 220 while((entry = in.getNextEntry()) != null) { 221 if(entry.getName().equals("META-INF/ra.xml")) { 222 DocumentBuilderFactory factory = XmlUtil.newDocumentBuilderFactory(); 223 factory.setValidating(false); 224 DocumentBuilder builder = factory.newDocumentBuilder(); 225 doc = builder.parse(in); 226 in.close(); 227 in = null; 228 break; 229 } else in.closeEntry(); 230 } 231 } catch (ParserConfigurationException e) { 232 log.error("Unable to read META-INF/ra.xml in RAR file '"+data.getRaURI()+"'", e); 233 } catch (SAXException e) { 234 log.error("Unable to read META-INF/ra.xml in RAR file '"+data.getRaURI()+"'", e); 235 } finally { 236 if (in != null) 237 try { 238 in.close(); 239 } catch (IOException ignore) { 240 } 241 } 242 if(doc == null) { 243 throw new IOException("Unable to locate META-INF/ra.xml in RAR file '"+data.getRaURI()+"'"); 244 } 245 Element root = doc.getDocumentElement(); 246 if(data.getName() == null) { 247 NodeList displays = getChildren(root, "display-name"); 248 if(displays != null && displays.getLength() > 0) { 249 data.name = getText(displays.item(0)); 250 } 251 } 252 Element ra = (Element) getChildren(root, "resourceadapter").item(0); 253 data.instanceConfigProperties = loadConfigs(ra); 254 Element outbound = (Element) getChildren(ra, "outbound-resourceadapter").item(0); 255 data.defaultTransaction = getTransactionSetting(getChildText(outbound, "transaction-support")); 256 data.connectionDefinitions = loadConnections(outbound); 257 data.adminObjectDefinitions = loadAdmins(ra); 258 } 259 260 private static String getTransactionSetting(String text) { 261 if(text == null) { 262 return null; 263 } 264 if(text.equals("XATransaction")) return "xa"; 265 if(text.equals("LocalTransaction")) return "local"; 266 if(text.equals("NoTransaction")) return "none"; 267 return null; 268 } 269 270 private static ConfigPropertyData[] loadConfigs(Element parent) { 271 NodeList configs = getChildren(parent, "config-property"); 272 if(configs == null || configs.getLength() == 0) { 273 return new ConfigPropertyData[0]; 274 } 275 ConfigPropertyData[] results = new ConfigPropertyData[configs.getLength()]; 276 for (int i = 0; i < results.length; i++) { 277 Element root = (Element) configs.item(i); 278 results[i] = new ConfigPropertyData(getChildText(root, "config-property-name"), 279 getChildText(root, "config-property-type"), getChildText(root, "config-property-value"), 280 getChildText(root, "description")); 281 } 282 return results; 283 } 284 285 private static NodeList getChildren(Element parent, String child) { 286 final List list = new ArrayList(); 287 NodeList nodes = parent.getChildNodes(); 288 for(int i=0; i<nodes.getLength(); i++) { 289 Node node = nodes.item(i); 290 if(node.getNodeType() == Node.ELEMENT_NODE && node.getNodeName().equals(child)) { 291 list.add(node); 292 } 293 } 294 return new NodeList() { 295 public Node item(int index) { 296 return (Node) list.get(index); 297 } 298 299 public int getLength() { 300 return list.size(); 301 } 302 }; 303 } 304 305 private static ConnectionDefinition[] loadConnections(Element outbound) { 306 NodeList defs = getChildren(outbound, "connection-definition"); 307 if(defs == null || defs.getLength() == 0) { 308 return new ConnectionDefinition[0]; 309 } 310 ConnectionDefinition[] results = new ConnectionDefinition[defs.getLength()]; 311 for (int i = 0; i < results.length; i++) { 312 Element def = (Element) defs.item(i); 313 results[i] = new ConnectionDefinition(getChildText(def, "connectionfactory-interface"), loadConfigs(def)); 314 } 315 return results; 316 } 317 318 private static AdminObjectDefinition[] loadAdmins(Element ra) { 319 NodeList defs = getChildren(ra, "adminobject"); 320 if(defs == null || defs.getLength() == 0) { 321 return new AdminObjectDefinition[0]; 322 } 323 AdminObjectDefinition[] results = new AdminObjectDefinition[defs.getLength()]; 324 for (int i = 0; i < results.length; i++) { 325 Element def = (Element) defs.item(i); 326 results[i] = new AdminObjectDefinition(getChildText(def, "adminobject-interface"), 327 getChildText(def, "adminobject-class"), loadConfigs(def)); 328 } 329 return results; 330 } 331 332 private static String getChildText(Element root, String name) { 333 NodeList list = getChildren(root, name); 334 if(list == null || list.getLength() == 0) { 335 return null; 336 } 337 return getText(list.item(0)); 338 } 339 340 private static String getText(Node node) { 341 StringBuffer buf = null; 342 NodeList list = node.getChildNodes(); 343 if(list != null) { 344 for(int i=0; i<list.getLength(); i++) { 345 Node current = list.item(i); 346 if(current.getNodeType() == Node.TEXT_NODE) { 347 if(buf == null) { 348 buf = new StringBuffer(); 349 } 350 buf.append(current.getNodeValue()); 351 } 352 } 353 } 354 return buf == null ? null : buf.toString(); 355 } 356 357 358 private static void loadProviders() { 359 InputStream in = JMSProviderData.class.getResourceAsStream("/jms-resource-providers.properties"); 360 if(in == null) { 361 log.error("Unable to locate JMS provider properties file"); 362 return; 363 } 364 Properties props = new Properties(); 365 try { 366 props.load(in); 367 } catch (IOException e) { 368 log.error("Unable to read JMS provider properties file", e); 369 } finally { 370 // load could fail, ensure stream is closed. 371 try { 372 in.close(); 373 } catch (IOException ignore) { 374 // ignore 375 } 376 } 377 Set set = new HashSet(); 378 // Find the names of the provider entries 379 for (Iterator it = props.keySet().iterator(); it.hasNext();) { 380 String key = (String) it.next(); 381 int start = key.indexOf('.'); 382 int end = key.indexOf('.', start+1); 383 if(start < 0 || end < 0) { 384 continue; 385 } 386 set.add(key.substring(start+1, end)); 387 } 388 List list = new ArrayList(set.size()); 389 for (Iterator it = set.iterator(); it.hasNext();) { 390 String key = (String) it.next(); 391 String name = props.getProperty("provider."+key+".name"); 392 String rar = props.getProperty("provider."+key+".rar"); 393 String dep = props.getProperty("provider."+key+".dependency"); 394 list.add(new JMSProviderData(name, rar, dep)); 395 } 396 all = list; 397 } 398 }