001 /**
002 *
003 * Copyright 2004 The Apache Software Foundation
004 *
005 * Licensed under the Apache License, Version 2.0 (the "License");
006 * you may not use this file except in compliance with the License.
007 * 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
018 package org.apache.geronimo.security.remoting.jmx;
019
020 import java.io.IOException;
021 import java.net.InetSocketAddress;
022 import java.net.URI;
023 import java.net.URISyntaxException;
024 import javax.management.ObjectName;
025 import org.activeio.AcceptListener;
026 import org.activeio.AsyncChannelServer;
027 import org.activeio.Channel;
028 import org.activeio.Packet;
029 import org.activeio.RequestChannel;
030 import org.activeio.SyncChannel;
031 import org.activeio.SyncChannelServer;
032 import org.activeio.adapter.AsyncChannelToServerRequestChannel;
033 import org.activeio.adapter.AsyncToSyncChannel;
034 import org.activeio.adapter.SyncToAsyncChannel;
035 import org.activeio.adapter.SyncToAsyncChannelServer;
036 import org.activeio.filter.PacketAggregatingAsyncChannel;
037 import org.activeio.net.SocketMetadata;
038 import org.activeio.net.SocketSyncChannelFactory;
039 import org.apache.commons.logging.Log;
040 import org.apache.commons.logging.LogFactory;
041 import org.apache.geronimo.gbean.GBeanInfo;
042 import org.apache.geronimo.gbean.GBeanInfoBuilder;
043 import org.apache.geronimo.gbean.GBeanLifecycle;
044 import org.apache.geronimo.kernel.ObjectNameUtil;
045 import org.apache.geronimo.management.geronimo.NetworkConnector;
046 import org.apache.geronimo.security.jaas.server.JaasLoginServiceMBean;
047
048
049 /**
050 * A server-side utility that exposes a JaasLoginService to remote clients.
051 * It prevents clients from connecting to arbitrary server-side MBeans through
052 * this listener -- only the JaasLoginService is exposed.
053 *
054 * @version $Rev: 417891 $ $Date: 2006-06-28 15:45:07 -0700 (Wed, 28 Jun 2006) $
055 */
056 public class JaasLoginServiceRemotingServer implements GBeanLifecycle, NetworkConnector {
057
058 public static final ObjectName REQUIRED_OBJECT_NAME = ObjectNameUtil.getObjectName("geronimo.remoting:target=JaasLoginServiceRemotingServer");
059
060 private static final Log log = LogFactory.getLog(JaasLoginServiceRemotingServer.class);
061 private AsyncChannelServer server;
062 private JaasLoginServiceMBean loginService;
063 private String protocol;
064 private String host;
065 private int port;
066
067 public JaasLoginServiceRemotingServer(String protocol, String host, int port, JaasLoginServiceMBean loginService) {
068 this.protocol = protocol;
069 this.host = host;
070 this.port = port;
071 this.loginService = loginService;
072 }
073
074 public String getProtocol() {
075 return protocol;
076 }
077
078 public void setProtocol(String protocol) {
079 this.protocol = protocol;
080 }
081
082 public String getHost() {
083 return host;
084 }
085
086 public void setHost(String host) {
087 this.host = host;
088 }
089
090 public int getPort() {
091 return port;
092 }
093
094 public void setPort(int port) {
095 this.port = port;
096 }
097
098 public URI getClientConnectURI() {
099 return server.getConnectURI();
100 }
101
102 public InetSocketAddress getListenAddress() {
103 if (server != null) {
104 URI uri = server.getBindURI();
105 return new InetSocketAddress(uri.getHost(), uri.getPort());
106 } else {
107 return new InetSocketAddress(host, port);
108 }
109 }
110
111 public void doStart() throws Exception {
112 final ReflexiveInterceptor loginServiceInterceptor = new ReflexiveInterceptor(loginService);
113
114 server = createAsyncChannelServer();
115 server.setAcceptListener(new AcceptListener() {
116 public void onAccept(Channel channel) {
117 RequestChannel requestChannel = null;
118 try {
119 SyncChannel syncChannel = AsyncToSyncChannel.adapt(channel);
120 SocketMetadata socket = (SocketMetadata) syncChannel.narrow(SocketMetadata.class);
121 socket.setTcpNoDelay(true);
122
123 requestChannel = createRequestChannel(syncChannel);
124
125 RequestChannelInterceptorInvoker invoker = new RequestChannelInterceptorInvoker(loginServiceInterceptor, loginService.getClass().getClassLoader());
126 requestChannel.setRequestListener(invoker);
127 requestChannel.start();
128 } catch (IOException e) {
129 log.warn("Failed to accept connection.", e);
130 if (requestChannel != null)
131 requestChannel.dispose();
132 else
133 channel.dispose();
134 }
135 }
136
137 public void onAcceptError(IOException error) {
138 log.warn("Accept Failed: " + error);
139 }
140 });
141
142 server.start();
143 log.debug("Remote login service started on: " + server.getConnectURI() + " clients can connect to: " + server.getConnectURI());
144 }
145
146 private AsyncChannelServer createAsyncChannelServer() throws IOException, URISyntaxException {
147 SocketSyncChannelFactory factory = new SocketSyncChannelFactory();
148 SyncChannelServer server = factory.bindSyncChannel(new URI(protocol, null, host, port, null, null, null));
149 return new SyncToAsyncChannelServer(server);
150 }
151
152 private RequestChannel createRequestChannel(SyncChannel channel) throws IOException {
153
154 return new AsyncChannelToServerRequestChannel(new PacketAggregatingAsyncChannel(SyncToAsyncChannel.adapt(channel))) {
155 /**
156 * close out the channel once one request has been serviced.
157 */
158 public void onPacket(Packet packet) {
159 super.onPacket(packet);
160 dispose();
161 }
162 };
163 }
164
165 public void doStop() {
166 server.dispose();
167 server = null;
168 log.debug("Stopped remote login service.");
169 }
170
171 public void doFail() {
172 if (server != null) {
173 server.dispose();
174 server = null;
175 }
176 log.warn("Failed remote login service.");
177 }
178
179 public static final GBeanInfo GBEAN_INFO;
180
181 static {
182 GBeanInfoBuilder infoFactory = GBeanInfoBuilder.createStatic("Remote Login Listener", JaasLoginServiceRemotingServer.class); //has fixed name, j2eeType is irrelevant
183 infoFactory.addAttribute("clientConnectURI", URI.class, false);
184 infoFactory.addReference("LoginService", JaasLoginServiceMBean.class, "JaasLoginService");
185 infoFactory.addInterface(NetworkConnector.class, new String[]{"host", "port", "protocol"}, new String[]{"host", "port"});
186 infoFactory.setConstructor(new String[]{"protocol", "host", "port", "LoginService"});
187 GBEAN_INFO = infoFactory.getBeanInfo();
188 }
189
190 public static GBeanInfo getGBeanInfo() {
191 return GBEAN_INFO;
192 }
193 }