/* * 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.File; import java.io.FileOutputStream; import java.io.OutputStreamWriter; import java.io.RandomAccessFile; import java.io.Writer; import java.lang.management.ManagementFactory; import java.lang.management.RuntimeMXBean; import java.net.InetAddress; import java.net.ServerSocket; import java.nio.channels.FileLock; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.apache.felix.utils.properties.TypedProperties; import org.apache.karaf.util.locks.FileLockUtils; import org.osgi.framework.launch.Framework; public class InstanceHelper { static void updateInstancePid(final File karafHome, final File karafBase, final boolean isStartingInstance) { try { final String instanceName = System.getProperty("karaf.name"); final String pid = isStartingInstance ? getPid() : "0"; if (instanceName != null) { String storage = System.getProperty("karaf.instances"); if (storage == null) { throw new Exception("System property 'karaf.instances' is not set. \n" + "This property needs to be set to the full path of the instance.properties file."); } File storageFile = new File(storage); final File propertiesFile = new File(storageFile, "instance.properties"); if (!propertiesFile.getParentFile().exists()) { try { if (!propertiesFile.getParentFile().mkdirs()) { throw new Exception("Unable to create directory " + propertiesFile.getParentFile()); } } catch (SecurityException se) { throw new Exception(se.getMessage()); } } // don't instance.properties if we're stopping and can't acquire lock if (!isStartingInstance) { boolean proceed = true; try (RandomAccessFile raf = new RandomAccessFile(propertiesFile, "rw")) { FileLock lock = raf.getChannel().tryLock(); if (lock == null) { proceed = false; } else { lock.release(); } } // if proceed is true than we got the lock or OverlappingFileLockException // but we may proceed in either case if (!proceed) { // we didn't acquire lock, it may mean that root container is holding the lock when // stopping the child return; } } FileLockUtils.execute(propertiesFile, (TypedProperties props) -> { if (props.isEmpty()) { // it's the first instance running, so we consider as root props.put("count", "1"); props.put("item.0.name", instanceName); props.put("item.0.loc", karafBase.getAbsolutePath()); props.put("item.0.pid", pid); props.put("item.0.root", "true"); } else { int count = Integer.parseInt(props.get("count").toString()); for (int i = 0; i < count; i++) { String name = props.get("item." + i + ".name").toString(); if (name.equals(instanceName)) { props.put("item." + i + ".pid", pid); return; } } // it's not found, let assume it's the root instance, so 0 props.put("item.0.name", instanceName); props.put("item.0.pid", pid); } }, true); } } catch (Exception e) { System.err.println("Unable to update instance pid: " + e.getMessage()); } } private static String getPid() { String pid = ManagementFactory.getRuntimeMXBean().getName(); if (pid.indexOf('@') > 0) { pid = pid.substring(0, pid.indexOf('@')); } return pid; } private static void writePid(String pidFile) { try { if (pidFile != null) { RuntimeMXBean rtb = ManagementFactory.getRuntimeMXBean(); String processName = rtb.getName(); Pattern pattern = Pattern.compile("^([0-9]+)@.+$", Pattern.CASE_INSENSITIVE); Matcher matcher = pattern.matcher(processName); if (matcher.matches()) { int pid = Integer.parseInt(matcher.group(1)); Writer w = new OutputStreamWriter(new FileOutputStream(pidFile)); w.write(Integer.toString(pid)); w.close(); } } } catch (Exception e) { e.printStackTrace(); } } static void setupShutdown(ConfigProperties config, Framework framework) { writePid(config.pidFile); try { int port = config.shutdownPort; String host = config.shutdownHost; String portFile = config.portFile; final String shutdown = config.shutdownCommand; if (port >= 0) { ServerSocket shutdownSocket = new ServerSocket(port, 1, InetAddress.getByName(host)); if (port == 0) { port = shutdownSocket.getLocalPort(); } if (portFile != null) { File portF = new File(portFile); portF.getParentFile().mkdirs(); Writer w = new OutputStreamWriter(new FileOutputStream(portF)); w.write(Integer.toString(port)); w.close(); } Thread thread = new ShutdownSocketThread(shutdown, shutdownSocket, framework); thread.setDaemon(true); thread.start(); } } catch (Exception e) { e.printStackTrace(); } } }