Java tutorial
/* * Copyright (C) 2011 Google Inc. * * Licensed 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. */ package org.ros.internal.node.server; import org.apache.commons.logging.Log; import org.apache.xmlrpc.XmlRpcException; import org.apache.xmlrpc.server.PropertyHandlerMapping; import org.apache.xmlrpc.server.XmlRpcServerConfigImpl; import org.ros.address.AdvertiseAddress; import org.ros.address.BindAddress; import org.ros.exception.RosRuntimeException; import org.ros.internal.system.Process; import org.ros.internal.xmlrpc.webserver.NettyXmlRpcWebServer; import org.ros.log.RosLogFactory; import java.net.InetSocketAddress; import java.net.URI; import java.util.concurrent.Callable; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; /** * Base class for an XML-RPC server. * * @author damonkohler@google.com (Damon Kohler) */ public class XmlRpcServer { /** * The logger for the server. */ private static final Log LOG = RosLogFactory.getLog(XmlRpcServer.class); /** * The RPC web server. */ private final NettyXmlRpcWebServer server; /** * The advertising address for the server. */ private final AdvertiseAddress advertiseAddress; /** * The countdown latch for detecting when the server has fully started up. */ private final CountDownLatch startLatch; /** * The executor service for the server. */ private final ScheduledExecutorService executorService; /** * Construct a new server. * * @param bindAddress * the address to bind the server to * @param advertiseAddress * the address to be used for advertising the server * @param executorService * the threadpool for the server */ public XmlRpcServer(BindAddress bindAddress, AdvertiseAddress advertiseAddress, ScheduledExecutorService executorService) { InetSocketAddress address = bindAddress.toInetSocketAddress(); server = new NettyXmlRpcWebServer(address.getPort(), address.getAddress(), executorService, LOG); this.executorService = executorService; this.advertiseAddress = advertiseAddress; this.advertiseAddress.setPortCallable(new Callable<Integer>() { @Override public Integer call() throws Exception { return server.getPort(); } }); startLatch = new CountDownLatch(1); } /** * Start up the remote calling server. * * @param instanceClass * the class of the remoting server * @param instance * an instance of the remoting server class * @param <T> * the type of the RPC endpoint */ public <T extends org.ros.internal.node.xmlrpc.XmlRpcEndpoint> void start(Class<T> instanceClass, T instance) { org.apache.xmlrpc.server.XmlRpcServer xmlRpcServer = server.getXmlRpcServer(); PropertyHandlerMapping phm = new PropertyHandlerMapping(); phm.setRequestProcessorFactoryFactory(new NodeRequestProcessorFactoryFactory<T>(instance)); try { phm.addHandler("", instanceClass); } catch (XmlRpcException e) { throw new RosRuntimeException(e); } xmlRpcServer.setHandlerMapping(phm); XmlRpcServerConfigImpl serverConfig = (XmlRpcServerConfigImpl) xmlRpcServer.getConfig(); serverConfig.setEnabledForExtensions(false); serverConfig.setContentLengthOptional(false); server.start(); if (LOG.isDebugEnabled()) { LOG.debug("XmlRPCServer Bound to: " + getUri()); } startLatch.countDown(); } /** * Shut the remote call server down. */ public void shutdown() { server.shutdown(); } /** * Get the URI of the server. * * @return the {@link URI} of the server */ public URI getUri() { return advertiseAddress.toUri("http"); } /** * Get the socket address of the advertising address. * * @return the socket address */ public InetSocketAddress getAddress() { return advertiseAddress.toInetSocketAddress(); } /** * Get the advertising address for the server. * * @return the advertising address */ public AdvertiseAddress getAdvertiseAddress() { return advertiseAddress; } /** * Wait for the start of the server. * * <p> * There is no time limit on this wait. * * @throws InterruptedException * the thread got interrupted */ public void awaitStart() throws InterruptedException { startLatch.await(); } /** * Wait for the startup of the server. * * @param timeout * the amount of time to wait for the server to start * @param unit * the time units for the wait time * * @return {@code true} if the startup happened within the wait time * * @throws InterruptedException * the thread got interrupted */ public boolean awaitStart(long timeout, TimeUnit unit) throws InterruptedException { return startLatch.await(timeout, unit); } /** * get the PID of the RPC server process. * * @return PID of node process if available, throws {@link UnsupportedOperationException} otherwise */ public int getPid() { return Process.getPid(); } /** * Get the executor service for the server. * * @return the executor service */ public ScheduledExecutorService getExecutorService() { return executorService; } }