| package org.apache.commons.jcs3.auxiliary.remote; |
| |
| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| |
| import java.io.File; |
| import java.io.FileInputStream; |
| import java.io.IOException; |
| import java.io.InputStream; |
| import java.net.InetSocketAddress; |
| import java.net.ServerSocket; |
| import java.net.Socket; |
| import java.net.URL; |
| import java.rmi.RemoteException; |
| import java.rmi.registry.LocateRegistry; |
| import java.rmi.registry.Registry; |
| import java.rmi.server.RMISocketFactory; |
| import java.util.Properties; |
| |
| import org.apache.commons.jcs3.log.Log; |
| import org.apache.commons.jcs3.log.LogManager; |
| |
| /** |
| * This class provides some basic utilities for doing things such as starting |
| * the registry properly. |
| */ |
| public class RemoteUtils |
| { |
| /** The logger. */ |
| private static final Log log = LogManager.getLog(RemoteUtils.class); |
| |
| /** No instances please. */ |
| private RemoteUtils() |
| { |
| } |
| |
| /** |
| * Creates and exports a registry on the specified port of the local host. |
| * <p> |
| * |
| * @param port |
| * @return the registry |
| */ |
| public static Registry createRegistry(int port) |
| { |
| Registry registry = null; |
| |
| // if ( log.isInfoEnabled() ) |
| // { |
| // log.info( "createRegistry> Setting security manager" ); |
| // } |
| // |
| // System.setSecurityManager( new RMISecurityManager() ); |
| |
| if (port < 1024) |
| { |
| log.warn("createRegistry> Port chosen was less than 1024, will use default [{0}] instead.", |
| Registry.REGISTRY_PORT); |
| port = Registry.REGISTRY_PORT; |
| } |
| |
| try |
| { |
| registry = LocateRegistry.createRegistry(port); |
| log.info("createRegistry> Created the registry on port {0}", port); |
| } |
| catch (RemoteException e) |
| { |
| log.warn("createRegistry> Problem creating registry. It may already be started.", |
| e); |
| } |
| catch (Throwable t) |
| { |
| log.error("createRegistry> Problem creating registry.", t); |
| } |
| |
| if (registry == null) |
| { |
| try |
| { |
| registry = LocateRegistry.getRegistry(port); |
| } |
| catch (RemoteException e) |
| { |
| log.error("createRegistry> Problem getting a registry reference.", e); |
| } |
| } |
| |
| return registry; |
| } |
| |
| /** |
| * Loads properties for the named props file. |
| * First tries class path, then file, then URL |
| * <p> |
| * |
| * @param propFile |
| * @return The properties object for the file |
| * @throws IOException |
| */ |
| public static Properties loadProps(String propFile) |
| throws IOException |
| { |
| InputStream is = RemoteUtils.class.getResourceAsStream(propFile); |
| |
| if (null == is) // not found in class path |
| { |
| // Try root of class path |
| if (propFile != null && !propFile.startsWith("/")) |
| { |
| is = RemoteUtils.class.getResourceAsStream("/" + propFile); |
| } |
| } |
| |
| if (null == is) // not found in class path |
| { |
| if (new File(propFile).exists()) |
| { |
| // file found |
| is = new FileInputStream(propFile); |
| } |
| else |
| { |
| // try URL |
| is = new URL(propFile).openStream(); |
| } |
| } |
| |
| Properties props = new Properties(); |
| try |
| { |
| props.load(is); |
| log.debug("props.size={0}", () -> props.size()); |
| |
| if (log.isTraceEnabled()) |
| { |
| StringBuilder buf = new StringBuilder(); |
| props.forEach((key, value) |
| -> buf.append('\n').append(key).append(" = ").append(value)); |
| log.trace(buf.toString()); |
| } |
| |
| } |
| catch (IOException ex) |
| { |
| log.error("Error loading remote properties, for file name " |
| + "[{0}]", propFile, ex); |
| } |
| finally |
| { |
| if (is != null) |
| { |
| is.close(); |
| } |
| } |
| return props; |
| } |
| |
| /** |
| * Configure a custom socket factory to set the timeout value. This sets the |
| * global socket factory. It's used only if a custom factory is not |
| * configured for the specific object. |
| * <p> |
| * |
| * @param timeoutMillis |
| */ |
| public static void configureGlobalCustomSocketFactory(final int timeoutMillis) |
| { |
| try |
| { |
| // Don't set a socket factory if the setting is -1 |
| if (timeoutMillis > 0) |
| { |
| log.info("RmiSocketFactoryTimeoutMillis [{0}]. " |
| + " Configuring a custom socket factory.", timeoutMillis); |
| |
| // use this socket factory to add a timeout. |
| RMISocketFactory.setSocketFactory(new RMISocketFactory() |
| { |
| @Override |
| public Socket createSocket(String host, int port) |
| throws IOException |
| { |
| Socket socket = new Socket(); |
| socket.setSoTimeout(timeoutMillis); |
| socket.setSoLinger(false, 0); |
| socket.connect(new InetSocketAddress(host, port), timeoutMillis); |
| return socket; |
| } |
| |
| @Override |
| public ServerSocket createServerSocket(int port) |
| throws IOException |
| { |
| return new ServerSocket(port); |
| } |
| }); |
| } |
| } |
| catch (IOException e) |
| { |
| // Only try to do it once. Otherwise we |
| // Generate errors for each region on construction. |
| RMISocketFactory factoryInUse = RMISocketFactory.getSocketFactory(); |
| if (factoryInUse != null && !factoryInUse.getClass().getName().startsWith("org.apache.commons.jcs3")) |
| { |
| log.info("Could not create new custom socket factory. {0} Factory in use = {1}", |
| () -> e.getMessage(), RMISocketFactory::getSocketFactory); |
| } |
| } |
| } |
| |
| /** |
| * Get the naming url used for RMI registration |
| * |
| * @param location |
| * the remote location |
| * @param serviceName |
| * the remote service name |
| * @return the URL for RMI lookup |
| */ |
| public static String getNamingURL(final RemoteLocation location, final String serviceName) |
| { |
| return getNamingURL(location.getHost(), location.getPort(), serviceName); |
| } |
| |
| /** |
| * Get the naming url used for RMI registration |
| * |
| * @param registryHost |
| * the remote host |
| * @param registryPort |
| * the remote port |
| * @param serviceName |
| * the remote service name |
| * @return the URL for RMI lookup |
| */ |
| public static String getNamingURL(final String registryHost, final int registryPort, final String serviceName) |
| { |
| if (registryHost.contains(":")) |
| { // TODO improve this check? See also JCS-133 |
| return "//[" + registryHost.replaceFirst("%", "%25") + "]:" + registryPort + "/" + serviceName; |
| } |
| final String registryURL = "//" + registryHost + ":" + registryPort + "/" + serviceName; |
| return registryURL; |
| } |
| } |