/* * 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. */ package org.apache.karaf.main; import java.io.IOException; import java.io.InputStream; import java.net.ServerSocket; import java.net.Socket; import java.net.SocketTimeoutException; import java.security.AccessControlException; import java.util.Random; import java.util.logging.Level; import java.util.logging.Logger; import org.osgi.framework.launch.Framework; class ShutdownSocketThread extends Thread { Logger LOG = Logger.getLogger(this.getClass().getName()); private final String shutdown; private Random random = null; private ServerSocket shutdownSocket; private Framework framework; public ShutdownSocketThread(String shutdown, ServerSocket shutdownSocket, Framework framework) { super("Karaf Shutdown Socket Thread"); this.shutdown = shutdown; this.shutdownSocket = shutdownSocket; this.framework = framework; } public void run() { try { while (true) { // Wait for the next connection Socket socket = null; InputStream stream = null; long acceptStartTime = System.currentTimeMillis(); try { socket = shutdownSocket.accept(); socket.setSoTimeout(10 * 1000); // Ten seconds stream = socket.getInputStream(); } catch (SocketTimeoutException ste) { // This should never happen but bug 3325 suggests that it does LOG.log(Level.WARNING, "Karaf shutdown socket: " + "The socket listening for the shutdown command experienced " + "an unexpected timeout " + "[" + (System.currentTimeMillis() - acceptStartTime) + "] milliseconds " + "after the call to accept(). Is this an instance of bug 3325?", ste); continue; } catch (AccessControlException ace) { LOG.log(Level.WARNING, "Karaf shutdown socket: security exception: " + ace.getMessage(), ace); continue; } catch (IOException e) { LOG.log(Level.SEVERE, "Karaf shutdown socket: accept: ", e); System.exit(1); } // Read a set of characters from the socket StringBuilder command = new StringBuilder(); int expected = 1024; // Cut off to avoid DoS attack while (expected < shutdown.length()) { if (random == null) { random = new Random(); } expected += (random.nextInt() % 1024); } while (expected > 0) { int ch; try { ch = stream.read(); } catch (IOException e) { LOG.log(Level.WARNING, "Karaf shutdown socket: read: ", e); ch = -1; } if (ch < 32) { // Control character or EOF terminates loop break; } command.append((char) ch); expected--; } // Close the socket now that we are done with it try { socket.close(); } catch (IOException e) { // Ignore } // Match against our command string boolean match = command.toString().equals(shutdown); if (match) { LOG.log(Level.INFO, "Karaf shutdown socket: received shutdown command. Stopping framework..."); framework.stop(); break; } else { if (!command.toString().isEmpty()) { LOG.log(Level.WARNING, "Karaf shutdown socket: Invalid command '" + command.toString() + "' received"); } } } } catch (Exception e) { e.printStackTrace(); } finally { try { shutdownSocket.close(); } catch (IOException e) { // Ignore } } } }