mx4j/src/tools/mx4j/tools/remote/http HTTPClientInvoker.java,NONE,1.1 HTTPConnection.java,NONE,1.1 HTTPConnectionHandler.java,NONE,1.1 HTTPConnectionMBeanServerConnection.java,NONE,1.1 HTTPConnectionManager.java,NONE,1.1 HTTPConnector.java,NONE,1.1 HTTPConnectorServer.java,NONE,1.1 HTTPHeartBeat.java,NONE,1.1 HTTPRemoteNotificationClientHandler.java,NONE,1.1 HTTPResolver.java,NONE,1.1 HTTPServerInvoker.java,NONE,1.1 HTTPService.java,NONE,1.1 HTTPSubjectInvoker.java,NONE,1.1 WebContainer.java,NONE,1.1
Simone Bordet <[email protected]>
| Newsgroups | gmane.comp.java.mx4j.cvs |
|---|---|
| Message-ID | <[email protected]> |
Update of /cvsroot/mx4j/mx4j/src/tools/mx4j/tools/remote/http In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv25164/src/tools/mx4j/tools/remote/http Added Files: HTTPClientInvoker.java HTTPConnection.java HTTPConnectionHandler.java HTTPConnectionMBeanServerConnection.java HTTPConnectionManager.java HTTPConnector.java HTTPConnectorServer.java HTTPHeartBeat.java HTTPRemoteNotificationClientHandler.java HTTPResolver.java HTTPServerInvoker.java HTTPService.java HTTPSubjectInvoker.java WebContainer.java Log Message: Refactoring of JSR 160 JMXConnector and JMXConnectorServer for protocols that runs over HTTP: SOAP, Hessian and Burlap --- NEW FILE: HTTPServerInvoker.java --- /* * Copyright (C) MX4J. * All rights reserved. * * This software is distributed under the terms of the MX4J License version 1.0. * See the terms of the MX4J License in the documentation provided with this software. */ package mx4j.tools.remote.http; import java.io.IOException; import javax.management.InstanceNotFoundException; import javax.management.ListenerNotFoundException; import javax.management.MBeanServerConnection; import javax.management.NotificationListener; import javax.management.ObjectName; import javax.management.remote.NotificationResult; import javax.security.auth.Subject; import mx4j.remote.NotificationTuple; import mx4j.remote.RemoteNotificationServerHandler; import mx4j.tools.remote.AbstractServerInvoker; /** * Implementation of the HTTPConnector interface that forwards the calls * to an MBeanServerConnection object. * It handles remote notifications, but it does not handle unmarshalling of * arguments (and all related classloading problems). * * @author <a href="mailto:[email protected]">Simone Bordet</a> * @version $Revision: 1.1 $ */ public class HTTPServerInvoker extends AbstractServerInvoker implements HTTPConnection { private final RemoteNotificationServerHandler notificationHandler; public HTTPServerInvoker(MBeanServerConnection server, RemoteNotificationServerHandler handler) { super(server); this.notificationHandler = handler; } public String connect(Object credentials) throws IOException, SecurityException { return null; } public void close() throws IOException { NotificationTuple[] tuples = notificationHandler.close(); for (int i = 0; i < tuples.length; ++i) { NotificationTuple tuple = tuples[i]; try { getServer().removeNotificationListener(tuple.getObjectName(), tuple.getNotificationListener(), tuple.getNotificationFilter(), tuple.getHandback()); } catch (InstanceNotFoundException ignored) { } catch (ListenerNotFoundException ignored) { } } } public Integer addNotificationListener(ObjectName name, Object filter, Subject delegate) throws InstanceNotFoundException, IOException { Integer id = notificationHandler.generateListenerID(name, null); NotificationListener listener = notificationHandler.getServerNotificationListener(); getServer().addNotificationListener(name, listener, null, id); notificationHandler.addNotificationListener(id, new NotificationTuple(name, listener, null, id)); return id; } public void removeNotificationListeners(ObjectName name, Integer[] listenerIDs, Subject delegate) throws InstanceNotFoundException, ListenerNotFoundException, IOException { for (int i = 0; i < listenerIDs.length; ++i) { Integer id = listenerIDs[i]; NotificationTuple tuple = notificationHandler.removeNotificationListener(id); getServer().removeNotificationListener(name, tuple.getNotificationListener(), tuple.getNotificationFilter(), tuple.getHandback()); } } public NotificationResult fetchNotifications(long clientSequenceNumber, int maxNotifications, long timeout) throws IOException { return notificationHandler.fetchNotifications(clientSequenceNumber, maxNotifications, timeout); } } --- NEW FILE: HTTPConnector.java --- /* * Copyright (C) MX4J. * All rights reserved. * * This software is distributed under the terms of the MX4J License version 1.0. * See the terms of the MX4J License in the documentation provided with this software. */ package mx4j.tools.remote.http; import java.io.IOException; import java.net.MalformedURLException; import java.util.Map; import javax.management.remote.JMXServiceURL; import mx4j.remote.ConnectionNotificationEmitter; import mx4j.remote.ConnectionResolver; import mx4j.remote.HeartBeat; import mx4j.remote.RemoteNotificationClientHandler; import mx4j.tools.remote.AbstractJMXConnector; /** * @author <a href="mailto:[email protected]">Simone Bordet</a> * @version $ */ public abstract class HTTPConnector extends AbstractJMXConnector { private transient HTTPConnection connection; private transient String connectionId; private transient HeartBeat heartbeat; private transient RemoteNotificationClientHandler notificationHandler; protected HTTPConnector(JMXServiceURL address) throws IOException { super(address); } protected void doConnect(Map environment) throws IOException, SecurityException { JMXServiceURL address = getAddress(); String protocol = address.getProtocol(); ConnectionResolver resolver = ConnectionResolver.newConnectionResolver(protocol, environment); if (resolver == null) throw new MalformedURLException("Unsupported protocol: " + protocol); HTTPConnection temp = (HTTPConnection)resolver.lookupClient(address, environment); connection = (HTTPConnection)resolver.bindClient(temp, environment); Object credentials = environment == null ? null : environment.get(CREDENTIALS); connectionId = connection.connect(credentials); this.heartbeat = createHeartBeat(connection, getConnectionNotificationEmitter(), environment); this.notificationHandler = createRemoteNotificationClientHandler(connection, getConnectionNotificationEmitter(), heartbeat, environment); this.heartbeat.start(); this.notificationHandler.start(); } protected HeartBeat createHeartBeat(HTTPConnection connection, ConnectionNotificationEmitter emitter, Map environment) { return new HTTPHeartBeat(connection, emitter, environment); } protected RemoteNotificationClientHandler createRemoteNotificationClientHandler(HTTPConnection connection, ConnectionNotificationEmitter emitter, HeartBeat heartbeat, Map environment) { return new HTTPRemoteNotificationClientHandler(connection, emitter, heartbeat, environment); } protected void doClose() throws IOException { if (notificationHandler != null) notificationHandler.stop(); if (heartbeat != null) heartbeat.stop(); if (connection != null) connection.close(); } public String getConnectionId() throws IOException { return connectionId; } protected HTTPConnection getHTTPConnection() { return connection; } public RemoteNotificationClientHandler getRemoteNotificationClientHandler() { return notificationHandler; } } --- NEW FILE: HTTPClientInvoker.java --- /* * Copyright (C) MX4J. * All rights reserved. * * This software is distributed under the terms of the MX4J License version 1.0. * See the terms of the MX4J License in the documentation provided with this software. */ package mx4j.tools.remote.http; import java.io.IOException; import java.util.Set; import javax.management.AttributeList; import javax.management.AttributeNotFoundException; import javax.management.InstanceAlreadyExistsException; import javax.management.InstanceNotFoundException; import javax.management.IntrospectionException; import javax.management.InvalidAttributeValueException; import javax.management.ListenerNotFoundException; import javax.management.MBeanException; import javax.management.MBeanInfo; import javax.management.MBeanRegistrationException; import javax.management.NotCompliantMBeanException; import javax.management.ObjectInstance; import javax.management.ObjectName; import javax.management.ReflectionException; import javax.management.remote.NotificationResult; import javax.security.auth.Subject; /** * @author <a href="mailto:[email protected]">Simone Bordet</a> * @version $Revision: 1.1 $ */ public abstract class HTTPClientInvoker implements HTTPConnection { private String connectionId; protected abstract HTTPConnection getService(); public String connect(Object credentials) throws IOException, SecurityException { connectionId = getService().connect(credentials); return connectionId; } public void close() throws IOException { getService().close(); } public String getConnectionId() throws IOException { return connectionId; } public ObjectInstance createMBean(String className, ObjectName name, Object params, String[] signature, Subject delegate) throws ReflectionException, InstanceAlreadyExistsException, MBeanRegistrationException, MBeanException, NotCompliantMBeanException, IOException { return getService().createMBean(className, name, params, signature, delegate); } public ObjectInstance createMBean(String className, ObjectName name, ObjectName loaderName, Object params, String[] signature, Subject delegate) throws ReflectionException, InstanceAlreadyExistsException, MBeanRegistrationException, MBeanException, NotCompliantMBeanException, InstanceNotFoundException, IOException { return getService().createMBean(className, name, loaderName, params, signature, delegate); } public void unregisterMBean(ObjectName name, Subject delegate) throws InstanceNotFoundException, MBeanRegistrationException, IOException { getService().unregisterMBean(name, delegate); } public ObjectInstance getObjectInstance(ObjectName name, Subject delegate) throws InstanceNotFoundException, IOException { return getService().getObjectInstance(name, delegate); } public Set queryMBeans(ObjectName name, Object query, Subject delegate) throws IOException { return getService().queryMBeans(name, query, delegate); } public Set queryNames(ObjectName name, Object query, Subject delegate) throws IOException { return getService().queryNames(name, query, delegate); } public boolean isRegistered(ObjectName name, Subject delegate) throws IOException { return getService().isRegistered(name, delegate); } public Integer getMBeanCount(Subject delegate) throws IOException { return getService().getMBeanCount(delegate); } public Object getAttribute(ObjectName name, String attribute, Subject delegate) throws MBeanException, AttributeNotFoundException, InstanceNotFoundException, ReflectionException, IOException { return getService().getAttribute(name, attribute, delegate); } public AttributeList getAttributes(ObjectName name, String[] attributes, Subject delegate) throws InstanceNotFoundException, ReflectionException, IOException { return getService().getAttributes(name, attributes, delegate); } public void setAttribute(ObjectName name, Object attribute, Subject delegate) throws InstanceNotFoundException, AttributeNotFoundException, InvalidAttributeValueException, MBeanException, ReflectionException, IOException { getService().setAttribute(name, attribute, delegate); } public AttributeList setAttributes(ObjectName name, Object attributes, Subject delegate) throws InstanceNotFoundException, ReflectionException, IOException { return getService().setAttributes(name, attributes, delegate); } public Object invoke(ObjectName name, String operationName, Object params, String[] signature, Subject delegate) throws InstanceNotFoundException, MBeanException, ReflectionException, IOException { return getService().invoke(name, operationName, params, signature, delegate); } public String getDefaultDomain(Subject delegate) throws IOException { return getService().getDefaultDomain(delegate); } public String[] getDomains(Subject delegate) throws IOException { return getService().getDomains(delegate); } public MBeanInfo getMBeanInfo(ObjectName name, Subject delegate) throws InstanceNotFoundException, IntrospectionException, ReflectionException, IOException { return getService().getMBeanInfo(name, delegate); } public boolean isInstanceOf(ObjectName name, String className, Subject delegate) throws InstanceNotFoundException, IOException { return getService().isInstanceOf(name, className, delegate); } public void addNotificationListener(ObjectName name, ObjectName listener, Object filter, Object handback, Subject delegate) throws InstanceNotFoundException, IOException { getService().addNotificationListener(name, listener, filter, handback, delegate); } public void removeNotificationListener(ObjectName name, ObjectName listener, Subject delegate) throws InstanceNotFoundException, ListenerNotFoundException, IOException { getService().removeNotificationListener(name, listener, delegate); } public void removeNotificationListener(ObjectName name, ObjectName listener, Object filter, Object handback, Subject delegate) throws InstanceNotFoundException, ListenerNotFoundException, IOException { getService().removeNotificationListener(name, listener, filter, handback, delegate); } public Integer addNotificationListener(ObjectName name, Object filter, Subject delegate) throws InstanceNotFoundException, IOException { return getService().addNotificationListener(name, filter, delegate); } public void removeNotificationListeners(ObjectName name, Integer[] listenerIDs, Subject delegate) throws InstanceNotFoundException, ListenerNotFoundException, IOException { getService().removeNotificationListeners(name, listenerIDs, delegate); } public NotificationResult fetchNotifications(long clientSequenceNumber, int maxNotifications, long timeout) throws IOException { return getService().fetchNotifications(clientSequenceNumber, maxNotifications, timeout); } } --- NEW FILE: HTTPHeartBeat.java --- /* * Copyright (C) MX4J. * All rights reserved. * * This software is distributed under the terms of the MX4J License version 1.0. * See the terms of the MX4J License in the documentation provided with this software. */ package mx4j.tools.remote.http; import java.io.IOException; import java.util.Map; import mx4j.remote.AbstractHeartBeat; import mx4j.remote.ConnectionNotificationEmitter; /** * @author <a href="mailto:[email protected]">Simone Bordet</a> * @version $Revision: 1.1 $ */ public class HTTPHeartBeat extends AbstractHeartBeat { private final HTTPConnection connection; public HTTPHeartBeat(HTTPConnection connection, ConnectionNotificationEmitter emitter, Map environment) { super(emitter, environment); this.connection = connection; } protected void pulse() throws IOException { connection.getDefaultDomain(null); } } --- NEW FILE: HTTPConnectionManager.java --- /* * Copyright (C) MX4J. * All rights reserved. * * This software is distributed under the terms of the MX4J License version 1.0. * See the terms of the MX4J License in the documentation provided with this software. */ package mx4j.tools.remote.http; import java.io.IOException; import java.util.Map; import javax.management.MBeanServerConnection; import javax.security.auth.Subject; import mx4j.remote.DefaultRemoteNotificationServerHandler; import mx4j.remote.RemoteNotificationServerHandler; import mx4j.tools.remote.AbstractConnectionManager; import mx4j.tools.remote.AbstractJMXConnectorServer; import mx4j.tools.remote.Connection; /** * @author <a href="mailto:[email protected]">Simone Bordet</a> * @version $Revision: 1.1 $ */ public class HTTPConnectionManager extends AbstractConnectionManager { private final MBeanServerConnection mbeanServerConnection; private final String protocol; public HTTPConnectionManager(AbstractJMXConnectorServer server, String protocol, Map environment) { super(server, environment); this.mbeanServerConnection = server.getMBeanServer(); this.protocol = protocol; } public String getProtocol() { return protocol; } protected Connection doConnect(String connectionId, Subject subject) throws IOException { RemoteNotificationServerHandler notificationHandler = new DefaultRemoteNotificationServerHandler(getEnvironment()); HTTPConnection invoker = new HTTPServerInvoker(mbeanServerConnection, notificationHandler); HTTPConnection subjectInvoker = HTTPSubjectInvoker.newInstance(invoker, subject, getSecurityContext()); Connection handler = new HTTPConnectionHandler(subjectInvoker, this, connectionId); return handler; } /** * HTTPConnectionManager does not really manages connections, * so this method does nothing by default */ protected void doClose() throws IOException { } /** * HTTPConnectionManager does not really manages connections, * so this method does nothing by default */ protected void doCloseConnection(Connection connection) throws IOException { } } --- NEW FILE: HTTPResolver.java --- /* * Copyright (C) MX4J. * All rights reserved. * * This software is distributed under the terms of the MX4J License version 1.0. * See the terms of the MX4J License in the documentation provided with this software. */ package mx4j.tools.remote.http; import java.io.IOException; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; import javax.management.remote.JMXConnectorServerFactory; import javax.management.remote.JMXServiceURL; import mx4j.remote.ConnectionResolver; /** * @author <a href="mailto:[email protected]">Simone Bordet</a> * @version $Revision: 1.1 $ */ public abstract class HTTPResolver extends ConnectionResolver { // TODO: maybe worth to use weak references to hold web containers private static Map webContainers = new HashMap(); private static Map deployedURLs = new HashMap(); private static final WebContainer EXTERNAL_WEB_CONTAINER = new ExternalWebContainer(); public Object bindClient(Object client, Map environment) throws IOException { return client; } protected String getEndpoint(JMXServiceURL address, Map environment) { String transport = getEndpointProtocol(environment); return transport + getEndpointPath(address); } protected String getEndpointProtocol(Map environment) { return "http"; } private String getEndpointPath(JMXServiceURL url) { String address = url.toString(); String prefix = "service:jmx:" + url.getProtocol(); return address.substring(prefix.length()); } public Object createServer(JMXServiceURL url, Map environment) throws IOException { WebContainer result = null; boolean useExternalWebContainer = environment == null ? false : Boolean.valueOf(String.valueOf(environment.get(HTTPConnectorServer.USE_EXTERNAL_WEB_CONTAINER))).booleanValue(); if (!useExternalWebContainer) { // Create and start an embedded web container String webContainerClassName = environment == null ? null : (String)environment.get(HTTPConnectorServer.EMBEDDED_WEB_CONTAINER_CLASS); // Not present, by default use Jetty if (webContainerClassName == null || webContainerClassName.length() == 0) webContainerClassName = "mx4j.tools.remote.http.jetty.JettyWebContainer"; result = findWebContainer(url, webContainerClassName); if (result == null) { result = createWebContainer(url, webContainerClassName, environment); if (result != null) result.start(url, environment); } // Nothing present, give up if (result == null) throw new IOException("Could not start embedded web container"); } return result; } private WebContainer findWebContainer(JMXServiceURL url, String webContainerClassName) { String key = createWebContainerKey(url, webContainerClassName); return (WebContainer)webContainers.get(key); } private String createWebContainerKey(JMXServiceURL url, String webContainerClassName) { return new StringBuffer(webContainerClassName).append("|").append(url.getHost()).append("|").append(url.getPort()).toString(); } public JMXServiceURL bindServer(Object server, JMXServiceURL url, Map environment) throws IOException { WebContainer webContainer = (WebContainer)server; if (!isDeployed(webContainer, url)) { if (webContainer != null) webContainer.deploy(getServletClassName(), url, environment); if (!hasDeployed(webContainer)) { // The jmxconnector web service has never been deployed, deploy it now deploy(url, environment); } addDeployed(webContainer, url); } return url; } protected abstract String getServletClassName(); protected void deploy(JMXServiceURL address, Map environment) throws IOException { } public void unbindServer(Object server, JMXServiceURL address, Map environment) throws IOException { WebContainer webContainer = (WebContainer)server; if (isDeployed(webContainer, address)) { // First undeploy the jmxconnector web service, then undeploy the webContainer: otherwise the service cannot be undeployed removeDeployed(webContainer, address); if (!hasDeployed(webContainer)) { undeploy(address, environment); } if (webContainer != null) webContainer.undeploy(getServletClassName(), address, environment); } } protected void undeploy(JMXServiceURL address, Map environment) throws IOException { } public void destroyServer(Object server, JMXServiceURL url, Map environment) throws IOException { WebContainer webContainer = (WebContainer)server; if (webContainer != null && !hasDeployed(webContainer)) { // No more deployed stuff here, shutdown also the web container String key = createWebContainerKey(url, server.getClass().getName()); WebContainer container = (WebContainer)webContainers.remove(key); if (webContainer != container) throw new IOException("Trying to stop the wrong web container: " + server + " should be: " + container); webContainer.stop(); } } private WebContainer createWebContainer(JMXServiceURL url, String webContainerClassName, Map environment) { ClassLoader loader = Thread.currentThread().getContextClassLoader(); if (environment != null) { Object cl = environment.get(JMXConnectorServerFactory.PROTOCOL_PROVIDER_CLASS_LOADER); if (cl instanceof ClassLoader) loader = (ClassLoader)cl; } try { WebContainer webContainer = (WebContainer)loader.loadClass(webContainerClassName).newInstance(); String key = createWebContainerKey(url, webContainerClassName); webContainers.put(key, webContainer); return webContainer; } catch (Exception x) { } return null; } private boolean isDeployed(WebContainer webContainer, JMXServiceURL url) { if (webContainer == null) webContainer = EXTERNAL_WEB_CONTAINER; Set urls = (Set)deployedURLs.get(webContainer); if (urls == null) return false; return urls.contains(url); } private boolean hasDeployed(WebContainer webContainer) { if (webContainer == null) webContainer = EXTERNAL_WEB_CONTAINER; Set urls = (Set)deployedURLs.get(webContainer); if (urls == null) return false; return !urls.isEmpty(); } private void addDeployed(WebContainer webContainer, JMXServiceURL url) { if (webContainer == null) webContainer = EXTERNAL_WEB_CONTAINER; Set urls = (Set)deployedURLs.get(webContainer); if (urls == null) { urls = new HashSet(); deployedURLs.put(webContainer, urls); } urls.add(url); } private void removeDeployed(WebContainer webContainer, JMXServiceURL url) { if (webContainer == null) webContainer = EXTERNAL_WEB_CONTAINER; Set urls = (Set)deployedURLs.get(webContainer); if (urls != null) { urls.remove(url); if (urls.isEmpty()) deployedURLs.remove(webContainer); } } private static class ExternalWebContainer implements WebContainer { public void start(JMXServiceURL url, Map environment) throws IOException { } public void stop() throws IOException { } public void deploy(String servletClassName, JMXServiceURL url, Map environment) throws IOException { } public void undeploy(String servletClassName, JMXServiceURL url, Map environment) { } public String toString() { return "External WebContainer"; } } } --- NEW FILE: HTTPConnectorServer.java --- /* * Copyright (C) MX4J. * All rights reserved. * * This software is distributed under the terms of the MX4J License version 1.0. * See the terms of the MX4J License in the documentation provided with this software. */ package mx4j.tools.remote.http; import java.io.IOException; import java.net.MalformedURLException; import java.util.HashMap; import java.util.Map; import javax.management.MBeanServer; import javax.management.remote.JMXServiceURL; import mx4j.log.Log; import mx4j.log.Logger; import mx4j.remote.ConnectionResolver; import mx4j.tools.remote.AbstractJMXConnectorServer; import mx4j.tools.remote.ConnectionManager; /** * @author <a href="mailto:[email protected]">Simone Bordet</a> * @version $Revision: 1.1 $ */ public abstract class HTTPConnectorServer extends AbstractJMXConnectorServer { public static final String USE_EXTERNAL_WEB_CONTAINER = "jmx.remote.x.http.use.external.web.container"; public static final String EMBEDDED_WEB_CONTAINER_CLASS = "jmx.remote.x.http.embedded.web.container.class"; private static Map instances = new HashMap(); private WebContainer webContainer; private ConnectionManager connectionManager; public HTTPConnectorServer(JMXServiceURL url, Map environment, MBeanServer server) { super(url, environment, server); } protected void doStart() throws IOException, IllegalStateException { MBeanServer server = getMBeanServer(); if (server == null) throw new IllegalStateException("This JMXConnectorServer is not attached to an MBeanServer"); JMXServiceURL address = getAddress(); String protocol = address.getProtocol(); Map environment = getEnvironment(); ConnectionResolver resolver = ConnectionResolver.newConnectionResolver(protocol, environment); if (resolver == null) throw new MalformedURLException("Unsupported protocol: " + protocol); webContainer = (WebContainer)resolver.createServer(address, environment); setAddress(resolver.bindServer(webContainer, address, environment)); connectionManager = createConnectionManager(this, environment); // Here is where we give to clients the possibility to access us register(getAddress(), connectionManager); } protected abstract ConnectionManager createConnectionManager(AbstractJMXConnectorServer server, Map environment); private void register(JMXServiceURL url, ConnectionManager manager) throws IOException { synchronized (HTTPConnectorServer.class) { // TODO: must use weak references to connection managers, otherwise they're not GC'ed // TODO: in case the connector server is not stopped cleanly if (instances.get(url) != null) throw new IOException("A JMXConnectorServer is already serving at address " + url); instances.put(url, manager); } } private void unregister(JMXServiceURL url) throws IOException { synchronized (HTTPConnectorServer.class) { Object removed = instances.remove(url); if (removed == null) throw new IOException("No JMXConnectorServer is present for address " + url); } } static ConnectionManager find(JMXServiceURL address) { synchronized (HTTPConnectorServer.class) { ConnectionManager manager = (ConnectionManager)instances.get(address); if (manager != null) return manager; Logger logger = Log.getLogger(HTTPConnectorServer.class.getName()); if (logger.isEnabledFor(Logger.DEBUG)) logger.debug("Known HTTPConnectorServers bound at " + instances.keySet()); return null; } } protected void doStop() throws IOException { JMXServiceURL url = getAddress(); unregister(url); if (connectionManager != null) { connectionManager.close(); connectionManager = null; } String protocol = url.getProtocol(); Map environment = getEnvironment(); ConnectionResolver resolver = ConnectionResolver.newConnectionResolver(protocol, environment); if (resolver == null) throw new MalformedURLException("Unsupported protocol: " + protocol); resolver.unbindServer(webContainer, url, environment); resolver.destroyServer(webContainer, url, environment); } } --- NEW FILE: HTTPRemoteNotificationClientHandler.java --- /* * Copyright (C) MX4J. * All rights reserved. * * This software is distributed under the terms of the MX4J License version 1.0. * See the terms of the MX4J License in the documentation provided with this software. */ package mx4j.tools.remote.http; import java.io.IOException; import java.util.Map; import javax.management.remote.NotificationResult; import mx4j.remote.AbstractRemoteNotificationClientHandler; import mx4j.remote.ConnectionNotificationEmitter; import mx4j.remote.HeartBeat; /** * @author <a href="mailto:[email protected]">Simone Bordet</a> * @version $Revision: 1.1 $ */ public class HTTPRemoteNotificationClientHandler extends AbstractRemoteNotificationClientHandler { private final HTTPConnection connection; public HTTPRemoteNotificationClientHandler(HTTPConnection connection, ConnectionNotificationEmitter emitter, HeartBeat heartbeat, Map environment) { super(emitter, heartbeat, environment); this.connection = connection; } protected NotificationResult fetchNotifications(long sequence, int maxNumber, long timeout) throws IOException { return connection.fetchNotifications(sequence, maxNumber, timeout); } } --- NEW FILE: WebContainer.java --- /* * Copyright (C) MX4J. * All rights reserved. * * This software is distributed under the terms of the MX4J License version 1.0. * See the terms of the MX4J License in the documentation provided with this software. */ package mx4j.tools.remote.http; import java.io.IOException; import java.util.Map; import javax.management.remote.JMXServiceURL; /** * An Interface for the Web Container so that we can plug in any web container. * * @author <a href="mailto:[email protected]">Alireza Taherkordi</a> * @version $Revision: 1.1 $ */ public interface WebContainer { /** * Starts the web container */ public void start(JMXServiceURL url, Map environment) throws IOException; /** * Stops the web container */ public void stop() throws IOException; /** * Deploys the given servlet class mapping it to the URL specified by the given JMXServiceURL. */ public void deploy(String servletClassName, JMXServiceURL url, Map environment) throws IOException; /** * Undeploys the servlet mapped to the URL specified by the given JMXServiceURL. */ public void undeploy(String servletClassName, JMXServiceURL url, Map environment); } --- NEW FILE: HTTPConnection.java --- /* * Copyright (C) MX4J. * All rights reserved. * * This software is distributed under the terms of the MX4J License version 1.0. * See the terms of the MX4J License in the documentation provided with this software. */ package mx4j.tools.remote.http; import java.io.IOException; import javax.management.InstanceNotFoundException; import javax.management.ListenerNotFoundException; import javax.management.ObjectName; import javax.management.remote.NotificationResult; import javax.security.auth.Subject; import mx4j.tools.remote.JMXConnection; /** * @author <a href="mailto:[email protected]">Simone Bordet</a> * @version $Revision: 1.1 $ */ public interface HTTPConnection extends JMXConnection { /** * This method is called when a call initiated by {@link javax.management.remote.JMXConnector#connect} * arrives on server side. For HTTP connections, the socket is handled by the web container, but * the remote procedure call that arrives along with the HTTP request is parsed and then (normally) * forwarded to a JavaBean (that will implement this interface). * Implementations of this method will normally call {@link mx4j.tools.remote.ConnectionManager#connect}. * * @param credentials The credential for authentication * @return The connection id for the newly created connection * @throws IOException If a communication problem occurs * @throws SecurityException If the authentication fails */ public String connect(Object credentials) throws IOException, SecurityException; public Integer addNotificationListener(ObjectName name, Object filter, Subject delegate) throws InstanceNotFoundException, IOException; public void removeNotificationListeners(ObjectName name, Integer[] listenerIDs, Subject delegate) throws InstanceNotFoundException, ListenerNotFoundException, IOException; public NotificationResult fetchNotifications(long clientSequenceNumber, int maxNotifications, long timeout) throws IOException; } --- NEW FILE: HTTPSubjectInvoker.java --- /* * Copyright (C) MX4J. * All rights reserved. * * This software is distributed under the terms of the MX4J License version 1.0. * See the terms of the MX4J License in the documentation provided with this software. */ package mx4j.tools.remote.http; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.security.AccessControlContext; import javax.security.auth.Subject; import mx4j.tools.remote.SubjectInvoker; /** * @author <a href="mailto:[email protected]">Simone Bordet</a> * @version $Revision: 1.1 $ */ public class HTTPSubjectInvoker extends SubjectInvoker { public static HTTPConnection newInstance(HTTPConnection target, Subject subject, AccessControlContext context) { HTTPSubjectInvoker handler = new HTTPSubjectInvoker(target, subject, context); return (HTTPConnection)Proxy.newProxyInstance(target.getClass().getClassLoader(), new Class[]{HTTPConnection.class}, handler); } private HTTPSubjectInvoker(HTTPConnection target, Subject subject, AccessControlContext context) { super(target, subject, context); } protected boolean isPlainInvoke(Method method) { boolean plain = super.isPlainInvoke(method); if (plain) return plain; String methodName = method.getName(); // HTTPConnection methods that does not require the delegate subject if ("fetchNotifications".equals(methodName)) return true; if ("close".equals(methodName)) return true; return false; } } --- NEW FILE: HTTPConnectionHandler.java --- /* * Copyright (C) MX4J. * All rights reserved. * * This software is distributed under the terms of the MX4J License version 1.0. * See the terms of the MX4J License in the documentation provided with this software. */ package mx4j.tools.remote.http; import java.io.IOException; import javax.management.InstanceNotFoundException; import javax.management.ListenerNotFoundException; import javax.management.ObjectName; import javax.management.remote.NotificationResult; import javax.security.auth.Subject; import mx4j.tools.remote.ConnectionManager; import mx4j.tools.remote.JMXConnection; import mx4j.tools.remote.JMXConnectionHandler; /** * @author <a href="mailto:[email protected]">Simone Bordet</a> * @version $ */ public class HTTPConnectionHandler extends JMXConnectionHandler implements HTTPConnection { public HTTPConnectionHandler(JMXConnection connection, ConnectionManager manager, String connectionId) { super(connection, manager, connectionId); } public String connect(Object credentials) throws IOException, SecurityException { throw new Error("Method connect() must not be forwarded to the invocation chain"); } public Integer addNotificationListener(ObjectName name, Object filter, Subject delegate) throws InstanceNotFoundException, IOException { if (isClosed()) throw new IOException("Connection has been closed"); return ((HTTPConnection)getConnection()).addNotificationListener(name, filter, delegate); } public void removeNotificationListeners(ObjectName name, Integer[] listenerIDs, Subject delegate) throws InstanceNotFoundException, ListenerNotFoundException, IOException { if (isClosed()) throw new IOException("Connection has been closed"); ((HTTPConnection)getConnection()).removeNotificationListeners(name, listenerIDs, delegate); } public NotificationResult fetchNotifications(long clientSequenceNumber, int maxNotifications, long timeout) throws IOException { if (isClosed()) throw new IOException("Connection has been closed"); return ((HTTPConnection)getConnection()).fetchNotifications(clientSequenceNumber, maxNotifications, timeout); } } --- NEW FILE: HTTPConnectionMBeanServerConnection.java --- /* * Copyright (C) MX4J. * All rights reserved. * * This software is distributed under the terms of the MX4J License version 1.0. * See the terms of the MX4J License in the documentation provided with this software. */ package mx4j.tools.remote.http; import java.io.IOException; import javax.management.InstanceNotFoundException; import javax.management.ListenerNotFoundException; import javax.management.NotificationFilter; import javax.management.NotificationListener; import javax.management.ObjectName; import javax.security.auth.Subject; import mx4j.remote.NotificationTuple; import mx4j.remote.RemoteNotificationClientHandler; import mx4j.tools.remote.JMXConnection; import mx4j.tools.remote.JMXConnectionMBeanServerConnection; /** * Implementation of an adapter that converts MBeanServerConnection calls * to HTTPConnection calls. * It handles remote notifications, but it does not handle unmarshalling of * arguments (and all related classloading problems). * NotificationFilters are always invoked on client side. * * @author <a href="mailto:[email protected]">Simone Bordet</a> * @version $Revision: 1.1 $ */ public class HTTPConnectionMBeanServerConnection extends JMXConnectionMBeanServerConnection { private final RemoteNotificationClientHandler notificationHandler; public HTTPConnectionMBeanServerConnection(JMXConnection connection, Subject delegate, RemoteNotificationClientHandler notificationHandler) { super(connection, delegate); this.notificationHandler = notificationHandler; } public void addNotificationListener(ObjectName observed, NotificationListener listener, NotificationFilter filter, Object handback) throws InstanceNotFoundException, IOException { NotificationTuple tuple = new NotificationTuple(observed, listener, filter, handback); // Filters are always invoked on client side, for now tuple.setInvokeFilter(true); if (notificationHandler.contains(tuple)) return; Integer id = ((HTTPConnection)getConnection()).addNotificationListener(observed, null, getDelegateSubject()); notificationHandler.addNotificationListener(id, tuple); } public void removeNotificationListener(ObjectName observed, NotificationListener listener) throws InstanceNotFoundException, ListenerNotFoundException, IOException { Integer[] ids = notificationHandler.getNotificationListeners(new NotificationTuple(observed, listener)); if (ids == null) throw new ListenerNotFoundException("Could not find listener " + listener); ((HTTPConnection)getConnection()).removeNotificationListeners(observed, ids, getDelegateSubject()); notificationHandler.removeNotificationListeners(ids); } public void removeNotificationListener(ObjectName observed, NotificationListener listener, NotificationFilter filter, Object handback) throws InstanceNotFoundException, ListenerNotFoundException, IOException { Integer id = notificationHandler.getNotificationListener(new NotificationTuple(observed, listener, filter, handback)); if (id == null) throw new ListenerNotFoundException("Could not find listener " + listener + " with filter " + filter + " and handback " + handback); Integer[] ids = new Integer[]{id}; ((HTTPConnection)getConnection()).removeNotificationListeners(observed, ids, getDelegateSubject()); notificationHandler.removeNotificationListeners(ids); } } --- NEW FILE: HTTPService.java --- /* * Copyright (C) MX4J. * All rights reserved. * * This software is distributed under the terms of the MX4J License version 1.0. * See the terms of the MX4J License in the documentation provided with this software. */ package mx4j.tools.remote.http; import java.io.IOException; import java.net.MalformedURLException; import java.util.HashMap; import java.util.Map; import java.util.Set; import javax.management.AttributeList; import javax.management.AttributeNotFoundException; import javax.management.InstanceAlreadyExistsException; import javax.management.InstanceNotFoundException; import javax.management.IntrospectionException; import javax.management.InvalidAttributeValueException; import javax.management.ListenerNotFoundException; import javax.management.MBeanException; import javax.management.MBeanInfo; import javax.management.MBeanRegistrationException; import javax.management.NotCompliantMBeanException; import javax.management.ObjectInstance; import javax.management.ObjectName; import javax.management.ReflectionException; import javax.management.remote.JMXServiceURL; import javax.management.remote.NotificationResult; import javax.security.auth.Subject; import mx4j.log.Log; import mx4j.log.Logger; import mx4j.tools.remote.Connection; import mx4j.tools.remote.ConnectionManager; /** * @author <a href="mailto:[email protected]">Simone Bordet</a> * @version $Revision: 1.1 $ */ public abstract class HTTPService implements HTTPConnection { private final Map connections = new HashMap(); protected Logger getLogger() { return Log.getLogger(getClass().getName()); } public String connect(Object credentials) throws IOException, SecurityException { JMXServiceURL address = findJMXServiceURL(); // Lookup the ConnectionManager ConnectionManager connectionManager = HTTPConnectorServer.find(address); if (connectionManager == null) throw new IOException("Could not find ConnectionManager. Make sure a SOAPConnectorServer is in classloader scope and bound at this address " + address); Connection connection = connectionManager.connect(credentials); addConnection(connection); return connection.getConnectionId(); } protected JMXServiceURL findJMXServiceURL() throws MalformedURLException { String url = findRequestURL(); JMXServiceURL temp = new JMXServiceURL("service:jmx:" + url); int port = temp.getPort(); if ("http".equals(temp.getProtocol()) && port == 0) { // Default HTTP port, set it to 80 port = 80; } else if ("https".equals(temp.getProtocol()) && port == 0) { // Default HTTPS port, set it to 443 port = 443; } return new JMXServiceURL(getProtocol(), temp.getHost(), port, temp.getURLPath()); } protected abstract String findRequestURL(); protected abstract String getProtocol(); protected void addConnection(Connection connection) throws IOException { String connectionId = connection.getConnectionId(); synchronized (this) { if (connections.containsKey(connectionId)) throw new IOException("Connection '" + connection + "' already connected"); connections.put(connectionId, connection); Logger logger = getLogger(); if (logger.isEnabledFor(Logger.DEBUG)) logger.debug("Added connection '" + connectionId + "', known connections are " + connections.keySet()); } } protected void removeConnection(Connection connection) throws IOException { String connectionId = connection.getConnectionId(); synchronized (this) { if (!connections.containsKey(connectionId)) throw new IOException("Connection '" + connection + "' unknown"); connections.remove(connectionId); Logger logger = getLogger(); if (logger.isEnabledFor(Logger.DEBUG)) logger.debug("Removed connection '" + connectionId + "', known connections are " + connections.keySet()); } } protected Connection findConnection() throws IOException { String connectionId = findConnectionId(); synchronized (this) { Connection connection = (Connection)connections.get(connectionId); if (connection != null) return connection; Logger logger = getLogger(); if (logger.isEnabledFor(Logger.DEBUG)) logger.debug("Unknown connection '" + connectionId + "', known connections are " + connections.keySet()); throw new IOException("Connection ID '" + connectionId + "' unknown"); } } protected abstract String findConnectionId(); public void close() throws IOException { Connection connection = findConnection(); removeConnection(connection); connection.close(); } public String getConnectionId() throws IOException { Connection connection = findConnection(); return connection.getConnectionId(); } public ObjectInstance createMBean(String className, ObjectName name, Object params, String[] signature, Subject delegate) throws ReflectionException, InstanceAlreadyExistsException, MBeanRegistrationException, MBeanException, NotCompliantMBeanException, IOException { HTTPConnection connection = (HTTPConnection)findConnection(); return connection.createMBean(className, name, params, signature, delegate); } public ObjectInstance createMBean(String className, ObjectName name, ObjectName loaderName, Object params, String[] signature, Subject delegate) throws ReflectionException, InstanceAlreadyExistsException, MBeanRegistrationException, MBeanException, NotCompliantMBeanException, InstanceNotFoundException, IOException { HTTPConnection connection = (HTTPConnection)findConnection(); return connection.createMBean(className, name, loaderName, params, signature, delegate); } public void unregisterMBean(ObjectName name, Subject delegate) throws InstanceNotFoundException, MBeanRegistrationException, IOException { HTTPConnection connection = (HTTPConnection)findConnection(); connection.unregisterMBean(name, delegate); } public ObjectInstance getObjectInstance(ObjectName name, Subject delegate) throws InstanceNotFoundException, IOException { HTTPConnection connection = (HTTPConnection)findConnection(); return connection.getObjectInstance(name, delegate); } public Set queryMBeans(ObjectName name, Object query, Subject delegate) throws IOException { HTTPConnection connection = (HTTPConnection)findConnection(); return connection.queryMBeans(name, query, delegate); } public Set queryNames(ObjectName name, Object query, Subject delegate) throws IOException { HTTPConnection connection = (HTTPConnection)findConnection(); return connection.queryNames(name, query, delegate); } public boolean isRegistered(ObjectName name, Subject delegate) throws IOException { HTTPConnection connection = (HTTPConnection)findConnection(); return connection.isRegistered(name, delegate); } public Integer getMBeanCount(Subject delegate) throws IOException { HTTPConnection connection = (HTTPConnection)findConnection(); return connection.getMBeanCount(delegate); } public Object getAttribute(ObjectName name, String attribute, Subject delegate) throws MBeanException, AttributeNotFoundException, InstanceNotFoundException, ReflectionException, IOException { HTTPConnection connection = (HTTPConnection)findConnection(); return connection.getAttribute(name, attribute, delegate); } public AttributeList getAttributes(ObjectName name, String[] attributes, Subject delegate) throws InstanceNotFoundException, ReflectionException, IOException { HTTPConnection connection = (HTTPConnection)findConnection(); return connection.getAttributes(name, attributes, delegate); } public void setAttribute(ObjectName name, Object attribute, Subject delegate) throws InstanceNotFoundException, AttributeNotFoundException, InvalidAttributeValueException, MBeanException, ReflectionException, IOException { HTTPConnection connection = (HTTPConnection)findConnection(); connection.setAttribute(name, attribute, delegate); } public AttributeList setAttributes(ObjectName name, Object attributes, Subject delegate) throws InstanceNotFoundException, ReflectionException, IOException { HTTPConnection connection = (HTTPConnection)findConnection(); return connection.setAttributes(name, attributes, delegate); } public Object invoke(ObjectName name, String operationName, Object params, String[] signature, Subject delegate) throws InstanceNotFoundException, MBeanException, ReflectionException, IOException { HTTPConnection connection = (HTTPConnection)findConnection(); return connection.invoke(name, operationName, params, signature, delegate); } public String getDefaultDomain(Subject delegate) throws IOException { HTTPConnection connection = (HTTPConnection)findConnection(); return connection.getDefaultDomain(delegate); } public String[] getDomains(Subject delegate) throws IOException { HTTPConnection connection = (HTTPConnection)findConnection(); return connection.getDomains(delegate); } public MBeanInfo getMBeanInfo(ObjectName name, Subject delegate) throws InstanceNotFoundException, IntrospectionException, ReflectionException, IOException { HTTPConnection connection = (HTTPConnection)findConnection(); return connection.getMBeanInfo(name, delegate); } public boolean isInstanceOf(ObjectName name, String className, Subject delegate) throws InstanceNotFoundException, IOException { HTTPConnection connection = (HTTPConnection)findConnection(); return connection.isInstanceOf(name, className, delegate); } public void addNotificationListener(ObjectName name, ObjectName listener, Object filter, Object handback, Subject delegate) throws InstanceNotFoundException, IOException { HTTPConnection connection = (HTTPConnection)findConnection(); connection.addNotificationListener(name, listener, filter, handback, delegate); } public void removeNotificationListener(ObjectName name, ObjectName listener, Subject delegate) throws InstanceNotFoundException, ListenerNotFoundException, IOException { HTTPConnection connection = (HTTPConnection)findConnection(); connection.removeNotificationListener(name, listener, delegate); } public void removeNotificationListener(ObjectName name, ObjectName listener, Object filter, Object handback, Subject delegate) throws InstanceNotFoundException, ListenerNotFoundException, IOException { HTTPConnection connection = (HTTPConnection)findConnection(); connection.removeNotificationListener(name, listener, filter, handback, delegate); } public Integer addNotificationListener(ObjectName name, Object filter, Subject delegate) throws InstanceNotFoundException, IOException { HTTPConnection connection = (HTTPConnection)findConnection(); return connection.addNotificationListener(name, filter, delegate); } public void removeNotificationListeners(ObjectName name, Integer[] listenerIDs, Subject delegate) throws InstanceNotFoundException, ListenerNotFoundException, IOException { HTTPConnection connection = (HTTPConnection)findConnection(); connection.removeNotificationListeners(name, listenerIDs, delegate); } public NotificationResult fetchNotifications(long clientSequenceNumber, int maxNotifications, long timeout) throws IOException { HTTPConnection connection = (HTTPConnection)findConnection(); return connection.fetchNotifications(clientSequenceNumber, maxNotifications, timeout); } } ------------------------------------------------------- SF.Net email is sponsored by Shop4tech.com-Lowest price on Blank Media 100pk Sonic DVD-R 4x for only $29 -100pk Sonic DVD+R for only $33 Save 50% off Retail on Ink & Toner - Free Shipping and Free Gift. http://www.shop4tech.com/z/Inkjet_Cartridges/9_108_r285