diff options
Diffstat (limited to 'remote/server/src/com/android/layoutlib/bridge/remote/server/ServerMain.java')
-rw-r--r-- | remote/server/src/com/android/layoutlib/bridge/remote/server/ServerMain.java | 213 |
1 files changed, 0 insertions, 213 deletions
diff --git a/remote/server/src/com/android/layoutlib/bridge/remote/server/ServerMain.java b/remote/server/src/com/android/layoutlib/bridge/remote/server/ServerMain.java deleted file mode 100644 index 4c23afc209..0000000000 --- a/remote/server/src/com/android/layoutlib/bridge/remote/server/ServerMain.java +++ /dev/null @@ -1,213 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * 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 com.android.layoutlib.bridge.remote.server; - -import com.android.layout.remote.api.RemoteBridge; -import com.android.tools.layoutlib.annotations.NotNull; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.lang.management.ManagementFactory; -import java.lang.management.RuntimeMXBean; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.rmi.NoSuchObjectException; -import java.rmi.RemoteException; -import java.rmi.registry.LocateRegistry; -import java.rmi.registry.Registry; -import java.rmi.server.UnicastRemoteObject; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.ArrayBlockingQueue; -import java.util.concurrent.BlockingQueue; -import java.util.concurrent.TimeUnit; -import java.util.function.Consumer; -import java.util.stream.Collectors; - -/** - * Main server class. The main method will start an RMI server for the {@link RemoteBridgeImpl} - * class. - */ -public class ServerMain { - private static final String RUNNING_SERVER_STR = "Server is running on port "; - public static int REGISTRY_BASE_PORT = 9000; - - private final int mPort; - private final Registry mRegistry; - - private ServerMain(int port, @NotNull Registry registry) { - mPort = port; - mRegistry = registry; - } - - public int getPort() { - return mPort; - } - - public void stop() { - try { - UnicastRemoteObject.unexportObject(mRegistry, true); - } catch (NoSuchObjectException ignored) { - } - } - - private static Thread createOutputProcessor(String outputProcessorName, - InputStream inputStream, - Consumer<String> consumer) { - BufferedReader inputReader = new BufferedReader(new InputStreamReader(inputStream)); - Thread thread = new Thread(() -> inputReader.lines().forEach(consumer)); - thread.setName(outputProcessorName); - thread.start(); - return thread; - } - - /** - * This will start a new JVM and connect to the new JVM RMI registry. - * <p/> - * The server will start looking for ports available for the {@link Registry} until a free one - * is found. The port number will be returned. - * If no ports are available, a {@link RemoteException} will be thrown. - * @param basePort port number to start looking for available ports - * @param limit number of ports to check. The last port to be checked will be (basePort + limit) - */ - public static ServerMain forkAndStartServer(int basePort, int limit) - throws IOException, InterruptedException { - // We start a new VM by copying all the parameter that we received in the current VM. - // We only remove the agentlib parameter since that could cause a port collision and avoid - // the new VM from starting. - RuntimeMXBean runtimeMxBean = ManagementFactory.getRuntimeMXBean(); - List<String> arguments = runtimeMxBean.getInputArguments().stream() - .filter(arg -> !arg.contains("-agentlib")) // Filter agentlib to avoid conflicts - .collect(Collectors.toList()); - - Path javaPath = Paths.get(System.getProperty("java.home"), "bin", "java"); - String thisClassName = ServerMain.class.getName() - .replace('.','/'); - - List<String> cmd = new ArrayList<>(); - cmd.add(javaPath.toString()); - - // Inherited arguments - cmd.addAll(arguments); - - // Classpath - cmd.add("-cp"); - cmd.add(System.getProperty("java.class.path")); - - // Class name and path - cmd.add(thisClassName); - - // ServerMain parameters [basePort. limit] - cmd.add(Integer.toString(basePort)); - cmd.add(Integer.toString(limit)); - - Process process = new ProcessBuilder() - .command(cmd) - .start(); - - BlockingQueue<String> outputQueue = new ArrayBlockingQueue<>(10); - Thread outputThread = createOutputProcessor("output", process.getInputStream(), - outputQueue::offer); - Thread errorThread = createOutputProcessor("error", process.getErrorStream(), - System.err::println); - - Runnable killServer = () -> { - process.destroyForcibly(); - outputThread.interrupt(); - errorThread.interrupt(); - try { - outputThread.join(); - } catch (InterruptedException ignore) { - } - - try { - errorThread.join(); - } catch (InterruptedException ignore) { - } - }; - - // Try to read the "Running on port" line in 10 lines. If it's not there just fail. - for (int i = 0; i < 10; i++) { - String line = outputQueue.poll(5, TimeUnit.SECONDS); - - if (line != null && line.startsWith(RUNNING_SERVER_STR)) { - int runningPort = Integer.parseInt(line.substring(RUNNING_SERVER_STR.length())); - System.out.println("Running on port " + runningPort); - - // We already know where the server is running so we just need to get the registry - // and return our own instance of ServerMain - Registry registry = LocateRegistry.getRegistry(runningPort); - return new ServerMain(runningPort, registry) { - @Override - public void stop() { - killServer.run(); - } - }; - } - } - - killServer.run(); - throw new IOException("Unable to find start string"); - } - - /** - * The server will start looking for ports available for the {@link Registry} until a free one - * is found. The port number will be returned. - * If no ports are available, a {@link RemoteException} will be thrown. - * @param basePort port number to start looking for available ports - * @param limit number of ports to check. The last port to be checked will be (basePort + limit) - */ - private static ServerMain startServer(int basePort, int limit) throws RemoteException { - RemoteBridgeImpl remoteBridge = new RemoteBridgeImpl(); - RemoteBridge stub = (RemoteBridge) UnicastRemoteObject.exportObject(remoteBridge, 0); - - RemoteException lastException = null; - for (int port = basePort; port <= basePort + limit; port++) { - try { - Registry registry = LocateRegistry.createRegistry(port); - registry.rebind(RemoteBridge.class.getName(), stub); - return new ServerMain(port, registry); - } catch (RemoteException e) { - lastException = e; - } - } - - if (lastException == null) { - lastException = new RemoteException("Unable to start server"); - } - - throw lastException; - } - - /** - * Starts an RMI server that runs in the current JVM. Only for debugging. - */ - public static ServerMain startLocalJvmServer() throws RemoteException { - System.err.println("Starting server in the local JVM"); - return startServer(REGISTRY_BASE_PORT, 10); - } - - public static void main(String[] args) throws RemoteException { - int basePort = args.length > 0 ? Integer.parseInt(args[0]) : REGISTRY_BASE_PORT; - int limit = args.length > 1 ? Integer.parseInt(args[1]) : 10; - - ServerMain server = startServer(basePort, limit); - System.out.println(RUNNING_SERVER_STR + server.getPort()); - } -} |