001: /*
002: * JBoss, Home of Professional Open Source.
003: * Copyright 2006, Red Hat Middleware LLC, and individual contributors
004: * as indicated by the @author tags. See the copyright.txt file in the
005: * distribution for a full listing of individual contributors.
006: *
007: * This is free software; you can redistribute it and/or modify it
008: * under the terms of the GNU Lesser General Public License as
009: * published by the Free Software Foundation; either version 2.1 of
010: * the License, or (at your option) any later version.
011: *
012: * This software is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015: * Lesser General Public License for more details.
016: *
017: * You should have received a copy of the GNU Lesser General Public
018: * License along with this software; if not, write to the Free
019: * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
021: */
022: package org.jboss.services.binding;
023:
024: import java.io.InputStream;
025: import java.net.URL;
026: import java.util.ArrayList;
027: import java.util.Collections;
028: import java.util.HashMap;
029: import java.util.Map;
030: import javax.management.ObjectName;
031:
032: import javax.xml.parsers.DocumentBuilder;
033: import javax.xml.parsers.DocumentBuilderFactory;
034: import org.w3c.dom.Document;
035: import org.w3c.dom.Element;
036: import org.w3c.dom.NodeList;
037:
038: import org.jboss.util.StringPropertyReplacer;
039: import org.jboss.logging.Logger;
040:
041: /**
042: * XML implementation of ServicesStore.
043: *
044: * <p>Reads/writes/manages the XML config file for the ServiceBinding Manager module
045: *
046: * @author <a href="mailto:bitpushr@rochester.rr.com">Mike Finn</a>.
047: * @author Scott.Stark@jboss.org
048: * @version $Revision: 57210 $
049: */
050: public class XMLServicesStore implements ServicesStore {
051: private final Logger log = Logger.getLogger(getClass());
052:
053: /** A thread-safe map of Map<ObjectName,ServiceConfig> keyed by server name.
054: */
055: private Map servers = Collections.synchronizedMap(new HashMap());
056:
057: /** This method is not usable in this implementation as XMLServiceStore is read-only
058: *
059: * @param serverName
060: * @param serviceName
061: * @param config
062: * @exception DuplicateServiceException never thrown
063: * @exception UnsupportedOperationException("XMLServiceStore is read-only") always thrown
064: */
065: public void addService(String serverName, ObjectName serviceName,
066: ServiceConfig config) throws DuplicateServiceException {
067: throw new UnsupportedOperationException(
068: "XMLServiceStore is read-only");
069: }
070:
071: /**
072: * Looks up a service, by server name and service name.
073: * If the server or service does not exist, a null object is returned.
074: *
075: * @param serverName The name of the server in the config file
076: * @param serviceName The name of the service (i.e. the JMX object name)
077: *
078: * @returns ServiceConfig object. Null if server or service is not found.
079: */
080: public ServiceConfig getService(String serverName,
081: ObjectName serviceName) {
082: Map serverMap = (Map) this .servers.get(serverName);
083: ServiceConfig config = null;
084: if (serverMap != null) {
085: config = (ServiceConfig) serverMap.get(serviceName);
086: }
087: return config;
088: }
089:
090: /** This method is not usable in this implementation as XMLServiceStore is read-only
091: *
092: * @param serverName
093: * @param serviceName
094: * @exception UnsupportedOperationException("XMLServiceStore is read-only") always thrown
095: */
096: public void removeService(String serverName, ObjectName serviceName) {
097: throw new UnsupportedOperationException(
098: "XMLServiceStore is read-only");
099: }
100:
101: /** Loads XML config file into memory and parses it into ServiceConfig
102: * objects.
103: *
104: * @throws Exception on any parse error
105: */
106: public void load(URL cfgURL) throws Exception {
107: DocumentBuilderFactory factory = DocumentBuilderFactory
108: .newInstance();
109: DocumentBuilder parser = factory.newDocumentBuilder();
110: InputStream cfgIS = cfgURL.openStream();
111: Document configDoc = parser.parse(cfgIS, cfgURL.toString());
112: Element serviceBindings = configDoc.getDocumentElement();
113: NodeList servers = serviceBindings
114: .getElementsByTagName("server");
115: int length = servers.getLength();
116: for (int s = 0; s < length; s++) {
117: Element server = (Element) servers.item(s);
118: parseServer(server);
119: }
120: }
121:
122: /** Store is a noop as this is a read-only store
123: */
124: public void store(URL cfgURL) throws Exception {
125: }
126:
127: /** Parse /service-bindings/server/service-config element into
128: a Map<ObjectName,ServiceConfig> objects that are stored in the servers
129: map keyed by server.name.
130: */
131: private void parseServer(Element server) throws Exception {
132: String serverName = server.getAttribute("name");
133: HashMap serverConfigurations = new HashMap();
134: NodeList serviceConfigs = server
135: .getElementsByTagName("service-config");
136: int length = serviceConfigs.getLength();
137: for (int c = 0; c < length; c++) {
138: Element config = (Element) serviceConfigs.item(c);
139: ServiceConfig serviceConfig = new ServiceConfig();
140: ObjectName serviceObjectName = parseConfig(config,
141: serviceConfig);
142: serverConfigurations.put(serviceObjectName, serviceConfig);
143: }
144: this .servers.put(serverName, serverConfigurations);
145: }
146:
147: /** Parse /service-bindings/server/service-config element into
148: the given ServiceConfig object.
149: */
150: private ObjectName parseConfig(Element config,
151: ServiceConfig serviceConfig) throws Exception {
152: String serviceName = config.getAttribute("name");
153: ObjectName serviceObjectName = new ObjectName(serviceName);
154: serviceConfig.setServiceName(serviceName);
155:
156: // Parse the delegate info
157: String delegateClass = config.getAttribute("delegateClass");
158: if (delegateClass.length() == 0)
159: delegateClass = "org.jboss.services.binding.AttributeMappingDelegate";
160: Element delegateConfig = null;
161: NodeList delegateConfigs = config
162: .getElementsByTagName("delegate-config");
163: if (delegateConfigs.getLength() > 0)
164: delegateConfig = (Element) delegateConfigs.item(0);
165: serviceConfig.setServiceConfigDelegateClassName(delegateClass);
166: serviceConfig.setServiceConfigDelegateConfig(delegateConfig);
167:
168: // Parse the service bindings
169: ArrayList bindingsArray = new ArrayList();
170: NodeList bindings = config.getElementsByTagName("binding");
171: int length = bindings.getLength();
172: for (int b = 0; b < length; b++) {
173: Element binding = (Element) bindings.item(b);
174: ServiceBinding sb = parseBinding(binding);
175: bindingsArray.add(sb);
176: }
177: ServiceBinding[] tmp = new ServiceBinding[bindingsArray.size()];
178: bindingsArray.toArray(tmp);
179: serviceConfig.setBindings(tmp);
180: return serviceObjectName;
181: }
182:
183: /** Parse /service-bindings/server/service-config/binding element into
184: a ServiceBinding object. Any attributes whose value contains a system
185: property reference of the form ${x} will be replaced with the correcsponding
186: System.getProperty("x") value if one exists.
187: */
188: private ServiceBinding parseBinding(Element binding)
189: throws Exception {
190: String name = binding.getAttribute("name");
191: if (name != null) {
192: name = StringPropertyReplacer.replaceProperties(name);
193: }
194: String hostName = binding.getAttribute("host");
195: if (hostName != null) {
196: hostName = StringPropertyReplacer
197: .replaceProperties(hostName);
198: }
199: if (hostName.length() == 0)
200: hostName = null;
201: String portStr = binding.getAttribute("port");
202: if (portStr != null) {
203: portStr = StringPropertyReplacer.replaceProperties(portStr);
204: }
205: if (portStr.length() == 0)
206: portStr = "0";
207: log.debug("parseBinding, name='" + name + "', host='"
208: + hostName + "'" + ", port='" + portStr + "'");
209: int port = Integer.parseInt(portStr);
210: ServiceBinding sb = new ServiceBinding(name, hostName, port);
211: return sb;
212: }
213: }
|