001: /*
002: * Copyright (C) The MX4J Contributors.
003: * All rights reserved.
004: *
005: * This software is distributed under the terms of the MX4J License version 1.0.
006: * See the terms of the MX4J License in the documentation provided with this software.
007: */
008:
009: package mx4j.tools.remote.http;
010:
011: import java.io.IOException;
012: import java.util.HashMap;
013: import java.util.HashSet;
014: import java.util.Map;
015: import java.util.Set;
016:
017: import javax.management.remote.JMXConnectorServerFactory;
018: import javax.management.remote.JMXServiceURL;
019:
020: import mx4j.remote.ConnectionResolver;
021:
022: /**
023: * @version $Revision: 1.4 $
024: */
025: public abstract class HTTPResolver extends ConnectionResolver {
026: protected static final String DEFAULT_WEB_CONTAINER_CLASS = "mx4j.tools.remote.http.jetty.JettyWebContainer";
027:
028: // TODO: maybe worth to use weak references to hold web containers
029: private static Map webContainers = new HashMap();
030: private static Map deployedURLs = new HashMap();
031: private static final WebContainer EXTERNAL_WEB_CONTAINER = new ExternalWebContainer();
032:
033: public Object bindClient(Object client, Map environment)
034: throws IOException {
035: return client;
036: }
037:
038: protected String getEndpoint(JMXServiceURL address, Map environment) {
039: String transport = getEndpointProtocol(environment);
040: return transport + getEndpointPath(address);
041: }
042:
043: protected String getEndpointProtocol(Map environment) {
044: return "http";
045: }
046:
047: private String getEndpointPath(JMXServiceURL url) {
048: String address = url.toString();
049: String prefix = "service:jmx:" + url.getProtocol();
050: return address.substring(prefix.length());
051: }
052:
053: public Object createServer(JMXServiceURL url, Map environment)
054: throws IOException {
055: WebContainer result = null;
056: boolean useExternalWebContainer = environment == null ? false
057: : Boolean
058: .valueOf(
059: String
060: .valueOf(environment
061: .get(HTTPConnectorServer.USE_EXTERNAL_WEB_CONTAINER)))
062: .booleanValue();
063: if (!useExternalWebContainer) {
064: // Create and start an embedded web container
065: String webContainerClassName = environment == null ? null
066: : (String) environment
067: .get(HTTPConnectorServer.EMBEDDED_WEB_CONTAINER_CLASS);
068: // Not present, by default use Jetty
069: if (webContainerClassName == null
070: || webContainerClassName.length() == 0)
071: webContainerClassName = DEFAULT_WEB_CONTAINER_CLASS;
072:
073: result = findWebContainer(url, webContainerClassName);
074: if (result == null) {
075: result = createWebContainer(url, webContainerClassName,
076: environment);
077: if (result != null)
078: result.start(url, environment);
079: }
080:
081: // Nothing present, give up
082: if (result == null)
083: throw new IOException(
084: "Could not start embedded web container");
085: }
086: return result;
087: }
088:
089: private WebContainer findWebContainer(JMXServiceURL url,
090: String webContainerClassName) {
091: String key = createWebContainerKey(url, webContainerClassName);
092: return (WebContainer) webContainers.get(key);
093: }
094:
095: private String createWebContainerKey(JMXServiceURL url,
096: String webContainerClassName) {
097: return new StringBuffer(webContainerClassName).append("|")
098: .append(url.getHost()).append("|")
099: .append(url.getPort()).toString();
100: }
101:
102: public JMXServiceURL bindServer(Object server, JMXServiceURL url,
103: Map environment) throws IOException {
104: WebContainer webContainer = (WebContainer) server;
105: if (!isDeployed(webContainer, url)) {
106: if (webContainer != null)
107: webContainer.deploy(getServletClassName(), url,
108: environment);
109: if (!hasDeployed(webContainer)) {
110: // The jmxconnector web service has never been deployed, deploy it now
111: deploy(url, environment);
112: }
113: addDeployed(webContainer, url);
114: }
115: return url;
116: }
117:
118: protected abstract String getServletClassName();
119:
120: protected void deploy(JMXServiceURL address, Map environment)
121: throws IOException {
122: }
123:
124: public void unbindServer(Object server, JMXServiceURL address,
125: Map environment) throws IOException {
126: WebContainer webContainer = (WebContainer) server;
127: if (isDeployed(webContainer, address)) {
128: // First undeploy the jmxconnector web service, then undeploy the webContainer: otherwise the service cannot be undeployed
129: removeDeployed(webContainer, address);
130: if (!hasDeployed(webContainer)) {
131: undeploy(address, environment);
132: }
133: if (webContainer != null)
134: webContainer.undeploy(getServletClassName(), address,
135: environment);
136: }
137: }
138:
139: protected void undeploy(JMXServiceURL address, Map environment)
140: throws IOException {
141: }
142:
143: public void destroyServer(Object server, JMXServiceURL url,
144: Map environment) throws IOException {
145: WebContainer webContainer = (WebContainer) server;
146: if (webContainer != null && !hasDeployed(webContainer)) {
147: // No more deployed stuff here, shutdown also the web container
148: String key = createWebContainerKey(url, server.getClass()
149: .getName());
150: WebContainer container = (WebContainer) webContainers
151: .remove(key);
152: if (webContainer != container)
153: throw new IOException(
154: "Trying to stop the wrong web container: "
155: + server + " should be: " + container);
156: webContainer.stop();
157: }
158: }
159:
160: protected WebContainer createWebContainer(JMXServiceURL url,
161: String webContainerClassName, Map environment) {
162: ClassLoader loader = Thread.currentThread()
163: .getContextClassLoader();
164: if (environment != null) {
165: Object cl = environment
166: .get(JMXConnectorServerFactory.PROTOCOL_PROVIDER_CLASS_LOADER);
167: if (cl instanceof ClassLoader)
168: loader = (ClassLoader) cl;
169: }
170:
171: try {
172: WebContainer webContainer = (WebContainer) loader
173: .loadClass(webContainerClassName).newInstance();
174: String key = createWebContainerKey(url,
175: webContainerClassName);
176: webContainers.put(key, webContainer);
177: return webContainer;
178: } catch (Exception x) {
179: }
180: return null;
181: }
182:
183: private boolean isDeployed(WebContainer webContainer,
184: JMXServiceURL url) {
185: if (webContainer == null)
186: webContainer = EXTERNAL_WEB_CONTAINER;
187: Set urls = (Set) deployedURLs.get(webContainer);
188: if (urls == null)
189: return false;
190: return urls.contains(url);
191: }
192:
193: private boolean hasDeployed(WebContainer webContainer) {
194: if (webContainer == null)
195: webContainer = EXTERNAL_WEB_CONTAINER;
196: Set urls = (Set) deployedURLs.get(webContainer);
197: if (urls == null)
198: return false;
199: return !urls.isEmpty();
200: }
201:
202: private void addDeployed(WebContainer webContainer,
203: JMXServiceURL url) {
204: if (webContainer == null)
205: webContainer = EXTERNAL_WEB_CONTAINER;
206: Set urls = (Set) deployedURLs.get(webContainer);
207: if (urls == null) {
208: urls = new HashSet();
209: deployedURLs.put(webContainer, urls);
210: }
211: urls.add(url);
212: }
213:
214: private void removeDeployed(WebContainer webContainer,
215: JMXServiceURL url) {
216: if (webContainer == null)
217: webContainer = EXTERNAL_WEB_CONTAINER;
218: Set urls = (Set) deployedURLs.get(webContainer);
219: if (urls != null) {
220: urls.remove(url);
221: if (urls.isEmpty())
222: deployedURLs.remove(webContainer);
223: }
224: }
225:
226: private static class ExternalWebContainer implements WebContainer {
227: public void start(JMXServiceURL url, Map environment)
228: throws IOException {
229: }
230:
231: public void stop() throws IOException {
232: }
233:
234: public void deploy(String servletClassName, JMXServiceURL url,
235: Map environment) throws IOException {
236: }
237:
238: public void undeploy(String servletClassName,
239: JMXServiceURL url, Map environment) {
240: }
241:
242: public String toString() {
243: return "External WebContainer";
244: }
245: }
246: }
|