001// License: GPL. For details, see LICENSE file.
002package org.openstreetmap.josm.io.remotecontrol;
003
004import java.io.File;
005import java.net.Inet4Address;
006import java.net.Inet6Address;
007import java.net.InetAddress;
008import java.net.UnknownHostException;
009
010import org.openstreetmap.josm.data.preferences.BooleanProperty;
011import org.openstreetmap.josm.io.remotecontrol.handler.RequestHandler;
012import org.openstreetmap.josm.spi.preferences.Config;
013import org.openstreetmap.josm.tools.Logging;
014
015/**
016 * Manager class for remote control operations.
017 *
018 * IMPORTANT! increment the minor version on compatible API extensions
019 * and increment the major version and set minor to 0 on incompatible changes.
020 */
021public class RemoteControl {
022
023    /**
024     * If the remote control feature is enabled or disabled. If disabled,
025     * it should not start the server.
026     */
027    public static final BooleanProperty PROP_REMOTECONTROL_ENABLED = new BooleanProperty("remotecontrol.enabled", false);
028
029    /**
030     * If the remote control feature is enabled or disabled for HTTPS. If disabled,
031     * only HTTP access will be available.
032     * @since 7335
033     */
034    public static final BooleanProperty PROP_REMOTECONTROL_HTTPS_ENABLED = new BooleanProperty(
035            "remotecontrol.https.enabled", false);
036
037    /**
038     * RemoteControl HTTP protocol version. Change minor number for compatible
039     * interface extensions. Change major number in case of incompatible
040     * changes.
041     */
042    static final int protocolMajorVersion = 1;
043    static final int protocolMinorVersion = 7;
044
045    /**
046     * Starts the remote control server
047     */
048    public static void start() {
049        RemoteControlHttpServer.restartRemoteControlHttpServer();
050        if (supportsHttps()) {
051            RemoteControlHttpsServer.restartRemoteControlHttpsServer();
052        }
053    }
054
055    /**
056     * Stops the remote control server
057     * @since 5861
058     */
059    public static void stop() {
060        RemoteControlHttpServer.stopRemoteControlHttpServer();
061        if (supportsHttps()) {
062            RemoteControlHttpsServer.stopRemoteControlHttpsServer();
063        }
064    }
065
066    /**
067     * Determines if the current JVM support HTTPS remote control.
068     * @return {@code true} if the JVM provides {@code sun.security.x509} classes
069     * @since 12703
070     */
071    public static boolean supportsHttps() {
072        try {
073            return Class.forName("sun.security.x509.GeneralName") != null;
074        } catch (ClassNotFoundException e) {
075            Logging.trace(e);
076            return false;
077        }
078    }
079
080    /**
081     * Adds external request handler.
082     * Can be used by plugins that want to use remote control.
083     *
084     * @param command The command name.
085     * @param handlerClass The additional request handler.
086     */
087    public void addRequestHandler(String command, Class<? extends RequestHandler> handlerClass) {
088        RequestProcessor.addRequestHandlerClass(command, handlerClass);
089    }
090
091    /**
092     * Returns the remote control directory.
093     * @return The remote control directory
094     * @since 7335
095     */
096    public static String getRemoteControlDir() {
097        return new File(Config.getDirs().getUserDataDirectory(true), "remotecontrol").getAbsolutePath();
098    }
099
100    /**
101     * Returns the IPv6 address used for remote control.
102     * @return the IPv6 address used for remote control
103     * @throws UnknownHostException if the local host name could not be resolved into an address.
104     * @since 8337
105     */
106    public static InetAddress getInet6Address() throws UnknownHostException {
107        for (InetAddress a : InetAddress.getAllByName(Config.getPref().get("remote.control.host.ipv6", "::1"))) {
108            if (a instanceof Inet6Address) {
109                return a;
110            }
111        }
112        throw new UnknownHostException();
113    }
114
115    /**
116     * Returns the IPv4 address used for remote control.
117     * @return the IPv4 address used for remote control
118     * @throws UnknownHostException if the local host name could not be resolved into an address.
119     * @since 8337
120     */
121    public static InetAddress getInet4Address() throws UnknownHostException {
122        // Return an address to the loopback interface by default
123        for (InetAddress a : InetAddress.getAllByName(Config.getPref().get("remote.control.host.ipv4", "127.0.0.1"))) {
124            if (a instanceof Inet4Address) {
125                return a;
126            }
127        }
128        throw new UnknownHostException();
129    }
130}