org.ros.internal.node.server.XmlRpcServer.java Source code

Java tutorial

Introduction

Here is the source code for org.ros.internal.node.server.XmlRpcServer.java

Source

/*
 * 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;
    }
}