Java tutorial
/* * 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.kittests; import org.apache.commons.compress.archivers.ArchiveEntry; import org.apache.commons.compress.archivers.ArchiveInputStream; import org.apache.commons.compress.archivers.tar.TarArchiveInputStream; import org.apache.commons.compress.archivers.zip.ZipArchiveInputStream; import org.apache.commons.compress.compressors.gzip.GzipCompressorInputStream; import org.apache.commons.io.FileUtils; import org.apache.commons.io.IOUtils; import org.apache.felix.utils.properties.InterpolationHelper; import org.apache.karaf.util.process.PumpStreamHandler; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.net.Socket; import java.net.URL; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Properties; public final class Helper { private Helper() { } public static class Instance { public static final String STOPPED = "Stopped"; public static final String STARTING = "Starting"; public static final String STARTED = "Started"; public static final String ERROR = "Error"; private static final String CONFIG_PROPERTIES_FILE_NAME = "config.properties"; private static final String KARAF_SHUTDOWN_PORT = "karaf.shutdown.port"; private static final String KARAF_SHUTDOWN_HOST = "karaf.shutdown.host"; private static final String KARAF_SHUTDOWN_PORT_FILE = "karaf.shutdown.port.file"; private static final String KARAF_SHUTDOWN_COMMAND = "karaf.shutdown.command"; private static final String KARAF_SHUTDOWN_PID_FILE = "karaf.shutdown.pid.file"; private static final String DEFAULT_SHUTDOWN_COMMAND = "SHUTDOWN"; private String location; private Process process; public Instance(String location, Process process) { this.location = location; this.process = process; } public boolean exists() { return new File(location).isDirectory(); } public int getSshPort() { InputStream is = null; try { File f = new File(location, "etc/org.apache.karaf.shell.cfg"); is = new FileInputStream(f); Properties props = new Properties(); props.load(is); String loc = props.getProperty("sshPort"); return Integer.parseInt(loc); } catch (Exception e) { return 0; } finally { if (is != null) { try { is.close(); } catch (IOException e) { // Ignore } } } } public synchronized String getState() { int port = getSshPort(); if (!exists() || port <= 0) { return ERROR; } checkProcess(); if (this.process == null) { return STOPPED; } else { try { Socket s = new Socket("localhost", port); s.close(); return STARTED; } catch (Exception e) { // ignore } return STARTING; } } protected void checkProcess() { if (this.process != null) { try { this.process.exitValue(); this.process = null; } catch (IllegalThreadStateException e) { } } } private static String getProperty(Map<String, String> props, String key, String deflt) { String res = props.get(key); if (res == null) { res = deflt; } return res; } public void stop() throws Exception { checkProcess(); if (this.process != null) { // Try a clean shutdown cleanShutdown(); if (this.process != null) { this.process.destroy(); } } } protected void cleanShutdown() { try { File file = new File(new File(location, "etc"), CONFIG_PROPERTIES_FILE_NAME); URL configPropURL = file.toURI().toURL(); Map<String, String> props = loadPropertiesFile(configPropURL); props.put("karaf.base", new File(location).getCanonicalPath()); props.put("karaf.home", new File(location).getCanonicalPath()); props.put("karaf.data", new File(new File(location), "data").getCanonicalPath()); InterpolationHelper.performSubstitution(props); int port = Integer.parseInt(getProperty(props, KARAF_SHUTDOWN_PORT, "0")); String host = getProperty(props, KARAF_SHUTDOWN_HOST, "localhost"); String portFile = props.get(KARAF_SHUTDOWN_PORT_FILE); String shutdown = getProperty(props, KARAF_SHUTDOWN_COMMAND, DEFAULT_SHUTDOWN_COMMAND); if (port == 0 && portFile != null) { BufferedReader r = new BufferedReader(new InputStreamReader(new FileInputStream(portFile))); String portStr = r.readLine(); port = Integer.parseInt(portStr); r.close(); } // We found the port, try to send the command if (port > 0) { Socket s = new Socket(host, port); s.getOutputStream().write(shutdown.getBytes()); s.close(); long t = System.currentTimeMillis() + 5000; do { Thread.sleep(100); checkProcess(); } while (System.currentTimeMillis() < t && process != null); } } catch (Exception e) { e.printStackTrace(); } } protected static Map<String, String> loadPropertiesFile(URL configPropURL) throws Exception { // Read the properties file. Properties configProps = new Properties(); InputStream is = null; try { is = configPropURL.openConnection().getInputStream(); configProps.load(is); is.close(); } catch (Exception ex) { System.err.println("Error loading config properties from " + configPropURL); System.err.println("Main: " + ex); try { if (is != null) is.close(); } catch (IOException ex2) { // Nothing we can do. } return null; } return (Map) configProps; } } protected static final boolean IS_WINDOWS_OS = System.getProperty("os.name").toLowerCase().contains("windows"); public static void extractKit(File targetDir) throws Exception { if (isWindowsOs()) { extractWindowsKit(targetDir); } else { extractUnixKit(targetDir); } } public static boolean isWindowsOs() { return IS_WINDOWS_OS; } protected static void extractWindowsKit(File targetDir) throws Exception { InputStream is = Helper.class.getResourceAsStream("/karaf.zip"); extract(new ZipArchiveInputStream(is), targetDir); } protected static void extractUnixKit(File targetDir) throws Exception { InputStream is = Helper.class.getResourceAsStream("/karaf.tar.gz"); extract(new TarArchiveInputStream(new GzipCompressorInputStream(is)), targetDir); File bin = new File(targetDir, "bin"); String[] files = bin.list(); List<String> args = new ArrayList(); Collections.addAll(args, "chmod", "+x"); Collections.addAll(args, files); Process chmod = new ProcessBuilder().directory(new File(targetDir, "bin")).command(args).start(); PumpStreamHandler pump = new PumpStreamHandler(System.in, System.out, System.err); pump.attach(chmod); pump.start(); waitForProcessEnd(chmod, 5000); } protected static void extract(ArchiveInputStream is, File targetDir) throws IOException { try { if (targetDir.exists()) { FileUtils.forceDelete(targetDir); } targetDir.mkdirs(); ArchiveEntry entry = is.getNextEntry(); while (entry != null) { String name = entry.getName(); name = name.substring(name.indexOf("/") + 1); File file = new File(targetDir, name); if (entry.isDirectory()) { file.mkdirs(); } else { file.getParentFile().mkdirs(); OutputStream os = new FileOutputStream(file); try { IOUtils.copy(is, os); } finally { IOUtils.closeQuietly(os); } } entry = is.getNextEntry(); } } finally { is.close(); } } public static Process launchScript(File homeDir, String script, String args) throws IOException { ProcessBuilder builder = new ProcessBuilder(); builder.directory(homeDir); if (isWindowsOs()) { builder.command("cmd.exe", "/c", new File(homeDir, "bin\\" + script + ".bat").getAbsolutePath(), args); } else { builder.command("/bin/sh", new File(homeDir, "bin/" + script).getAbsolutePath(), args); } builder.redirectErrorStream(true); Process process = builder.start(); PumpStreamHandler pump = new PumpStreamHandler(System.in, System.out, System.err); pump.attach(process); pump.start(); return process; } public static Instance startKaraf(File home) throws Exception { Process karaf = launchScript(home, "karaf", "server"); return new Instance(home.getAbsolutePath(), karaf); // InstanceImpl instance = new InstanceImpl(null, "root", home.getAbsolutePath(), null, true); // instance.attach(karaf.getPid()); // return instance; } public static void waitForKarafStarted(Instance karaf, long timeout) throws Exception { for (int i = 0; i < timeout / 100; i++) { if (Instance.STARTING.equals(karaf.getState())) { Thread.sleep(100); } else { break; } } if (!Instance.STARTED.equals(karaf.getState())) { throw new Exception("Karaf did not start correctly: state " + karaf.getState()); } } public static void waitForKarafStopped(Instance karaf, long timeout) throws Exception { waitForProcessEnd(karaf.process, timeout); } public static void waitForProcessEnd(Process process, long timeout) throws Exception { for (int i = 0; i < timeout / 100; i++) { try { process.exitValue(); return; } catch (IllegalThreadStateException e) { } Thread.sleep(100); } throw new Exception("Process is still running"); } public static void kill(Process process) { try { process.destroy(); } catch (Throwable e) { } } public static void kill(Instance instance) { try { instance.stop(); } catch (Throwable e) { } } }