1 package org.apache.jcs.auxiliary.remote.server;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import java.io.IOException;
23 import java.net.MalformedURLException;
24 import java.net.ServerSocket;
25 import java.net.Socket;
26 import java.rmi.Naming;
27 import java.rmi.NotBoundException;
28 import java.rmi.registry.Registry;
29 import java.rmi.server.RMISocketFactory;
30 import java.util.Properties;
31
32 import org.apache.commons.logging.Log;
33 import org.apache.commons.logging.LogFactory;
34 import org.apache.jcs.auxiliary.remote.RemoteUtils;
35 import org.apache.jcs.auxiliary.remote.behavior.IRemoteCacheConstants;
36 import org.apache.jcs.auxiliary.remote.behavior.IRemoteCacheServiceAdmin;
37
38 /***
39 * Provides remote cache services. This creates remote cache servers and can proxy command line
40 * requests to a running server.
41 */
42 public class RemoteCacheServerFactory
43 implements IRemoteCacheConstants
44 {
45 private final static Log log = LogFactory.getLog( RemoteCacheServerFactory.class );
46
47 /*** The single instance of the RemoteCacheServer object. */
48 private static RemoteCacheServer remoteCacheServer;
49
50 private static String serviceName;
51
52 private static int DEFAULT_RMI_SOCKET_FACTORY_TIMEOUT_MS = 10000;
53
54 /*** Constructor for the RemoteCacheServerFactory object. */
55 private RemoteCacheServerFactory()
56 {
57 super();
58 }
59
60 /***
61 * This will allow you to get stats from the server, etc. Perhaps we should provide methods on
62 * the factory to do this instead.
63 * A remote cache is either a local cache or a cluster cache
64 * @return Returns the remoteCacheServer.
65 */
66 public static RemoteCacheServer getRemoteCacheServer()
67 {
68 return remoteCacheServer;
69 }
70
71
72 /***
73 * Starts up the remote cache server on this JVM, and binds it to the registry on the given host
74 * and port.
75 * A remote cache is either a local cache or a cluster cache
76 * @param host
77 * @param port
78 * @param propFile
79 * @throws IOException
80 */
81 public static void startup( String host, int port, String propFile )
82 throws IOException
83 {
84 if ( remoteCacheServer != null )
85 {
86 throw new IllegalArgumentException( "Server already started." );
87 }
88
89 synchronized ( RemoteCacheServer.class )
90 {
91 if ( remoteCacheServer != null )
92 {
93 return;
94 }
95
96 if ( log.isInfoEnabled() )
97 {
98 log.info( "ConfigFileName = [" + propFile + "]" );
99 }
100
101 try
102 {
103
104
105 RMISocketFactory.setSocketFactory( new RMISocketFactory()
106 {
107 public Socket createSocket( String host, int port )
108 throws IOException
109 {
110 Socket socket = new Socket( host, port );
111 socket.setSoTimeout( DEFAULT_RMI_SOCKET_FACTORY_TIMEOUT_MS );
112 socket.setSoLinger( false, 0 );
113 return socket;
114 }
115
116 public ServerSocket createServerSocket( int port )
117 throws IOException
118 {
119 return new ServerSocket( port );
120 }
121 } );
122 }
123 catch ( Exception e )
124 {
125 log.error( "Problem setting custom RMI Socket Factory.", e );
126 }
127
128
129 RemoteCacheServerAttributes rcsa = new RemoteCacheServerAttributes();
130 rcsa.setConfigFileName( propFile );
131
132 Properties prop = RemoteUtils.loadProps( propFile );
133
134
135 String servicePortStr = prop.getProperty( REMOTE_CACHE_SERVICE_PORT );
136 int servicePort = -1;
137 try
138 {
139 servicePort = Integer.parseInt( servicePortStr );
140
141 rcsa.setServicePort( servicePort );
142 log.debug( "Remote cache service uses port number " + servicePort + "." );
143 }
144 catch ( NumberFormatException ignore )
145 {
146 log.debug( "Remote cache service port property " + REMOTE_CACHE_SERVICE_PORT
147 + " not specified. An anonymous port will be used." );
148 }
149
150 String lccStr = prop.getProperty( REMOTE_LOCAL_CLUSTER_CONSISTENCY );
151 if ( lccStr == null )
152 {
153 lccStr = "true";
154 }
155 boolean lcc = Boolean.valueOf( lccStr ).booleanValue();
156 rcsa.setLocalClusterConsistency( lcc );
157
158 String acgStr = prop.getProperty( REMOTE_ALLOW_CLUSTER_GET );
159 if ( acgStr == null )
160 {
161 acgStr = "true";
162 }
163 boolean acg = Boolean.valueOf( acgStr ).booleanValue();
164 rcsa.setAllowClusterGet( acg );
165
166 if ( log.isInfoEnabled() )
167 {
168 log.info( "Creating server with these attributes " + rcsa );
169 }
170
171
172 remoteCacheServer = new RemoteCacheServer( rcsa );
173
174 if ( host == null )
175 {
176 host = "";
177 }
178
179 serviceName = prop.getProperty( REMOTE_CACHE_SERVICE_NAME, REMOTE_CACHE_SERVICE_VAL ).trim();
180
181 if ( log.isInfoEnabled() )
182 {
183 log.info( "Binding server to " + host + ":" + port + " with the name " + serviceName );
184 }
185 try
186 {
187 Naming.rebind( "//" + host + ":" + port + "/" + serviceName, remoteCacheServer );
188 }
189 catch ( MalformedURLException ex )
190 {
191
192 throw new IllegalArgumentException( ex.getMessage() + "; host=" + host + ", port=" + port );
193 }
194 }
195 }
196
197 /***
198 * Unbinds the remote server.
199 * <p>
200 * @param host
201 * @param port
202 * @exception IOException
203 */
204 static void shutdownImpl( String host, int port )
205 throws IOException
206 {
207 if ( remoteCacheServer == null )
208 {
209 return;
210 }
211 synchronized ( RemoteCacheServer.class )
212 {
213 if ( remoteCacheServer == null )
214 {
215 return;
216 }
217 log.info( "Unbinding host=" + host + ", port=" + port + ", serviceName=" + serviceName );
218 try
219 {
220 Naming.unbind( "//" + host + ":" + port + "/" + serviceName );
221 }
222 catch ( MalformedURLException ex )
223 {
224
225 throw new IllegalArgumentException( ex.getMessage() + "; host=" + host + ", port=" + port
226 + ", serviceName=" + serviceName );
227 }
228 catch ( NotBoundException ex )
229 {
230
231 }
232 remoteCacheServer.release();
233 remoteCacheServer = null;
234
235 try
236 {
237 Thread.sleep( 2000 );
238 }
239 catch ( InterruptedException ex )
240 {
241
242 }
243 System.exit( 0 );
244 }
245 }
246
247 /***
248 * Creates an local RMI registry on the default port, starts up the remote cache server, and
249 * binds it to the registry.
250 * A remote cache is either a local cache or a cluster cache
251 * @param args The command line arguments
252 * @throws Exception
253 */
254 public static void main( String[] args )
255 throws Exception
256 {
257 Properties prop = args.length > 0 ? RemoteUtils.loadProps( args[args.length - 1] ) : new Properties();
258
259 int port;
260 try
261 {
262 port = Integer.parseInt( prop.getProperty( "registry.port" ) );
263 }
264 catch ( NumberFormatException ex )
265 {
266 port = Registry.REGISTRY_PORT;
267 }
268
269
270 if ( args.length > 0 && args[0].toLowerCase().indexOf( "-shutdown" ) != -1 )
271 {
272 String serviceName = prop.getProperty( REMOTE_CACHE_SERVICE_NAME, REMOTE_CACHE_SERVICE_VAL ).trim();
273 String registry = "//:" + port + "/" + serviceName;
274
275 if ( log.isDebugEnabled() )
276 {
277 log.debug( "looking up server " + registry );
278 }
279 Object obj = Naming.lookup( registry );
280 if ( log.isDebugEnabled() )
281 {
282 log.debug( "server found" );
283 }
284 IRemoteCacheServiceAdmin admin = (IRemoteCacheServiceAdmin) obj;
285 try
286 {
287 admin.shutdown();
288 }
289 catch ( Exception ex )
290 {
291 log.error( "Problem calling shutdown.", ex );
292 }
293 log.debug( "done." );
294 System.exit( 0 );
295 }
296
297
298 if ( args.length > 0 && args[0].toLowerCase().indexOf( "-stats" ) != -1 )
299 {
300
301 log.debug( "getting cache stats" );
302
303 try
304 {
305 String serviceName = prop.getProperty( REMOTE_CACHE_SERVICE_NAME, REMOTE_CACHE_SERVICE_VAL ).trim();
306 String registry = "//:" + port + "/" + serviceName;
307 log.debug( "looking up server " + registry );
308 Object obj = Naming.lookup( registry );
309 log.debug( "server found" );
310
311 log.debug( "obj = " + obj );
312 IRemoteCacheServiceAdmin admin = (IRemoteCacheServiceAdmin) obj;
313
314 try
315 {
316 System.out.println( admin.getStats().toString() );
317 log.debug( admin.getStats() );
318 }
319 catch ( Exception es )
320 {
321 log.error( es );
322 }
323
324 }
325 catch ( Exception ex )
326 {
327 log.error( "Problem getting stats.", ex );
328 }
329 log.debug( "done." );
330 System.exit( 0 );
331 }
332
333
334 String host = prop.getProperty( "registry.host" );
335
336 if ( host == null || host.trim().equals( "" ) || host.trim().equals( "localhost" ) )
337 {
338 log.debug( "main> creating registry on the localhost" );
339 port = RemoteUtils.createRegistry( port );
340 }
341 log.debug( "main> starting up RemoteCacheServer" );
342 RemoteCacheServerFactory.startup( host, port, args.length > 0 ? args[0] : null );
343 log.debug( "main> done" );
344 }
345 }