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 }