| /* |
| * Copyright 2016-present Open Networking Laboratory |
| * |
| * 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 org.onosproject.checkstyle; |
| |
| import com.puppycrawl.tools.checkstyle.api.CheckstyleException; |
| |
| import java.io.IOException; |
| import java.net.ServerSocket; |
| import java.nio.ByteBuffer; |
| import java.nio.channels.FileChannel; |
| import java.nio.channels.FileLock; |
| import java.nio.file.Files; |
| import java.nio.file.Path; |
| import java.nio.file.Paths; |
| import java.util.Timer; |
| import java.util.TimerTask; |
| import java.util.concurrent.ExecutorService; |
| import java.util.concurrent.Executors; |
| |
| import static java.nio.file.StandardOpenOption.*; |
| |
| /** |
| * Main program for executing scenario test warden. |
| */ |
| public final class Main { |
| |
| private static long POLLING_INTERVAL = 1000; //ms |
| |
| // Public construction forbidden |
| private Main(String[] args) { |
| } |
| |
| /** |
| * Main entry point for the cell warden. |
| * |
| * @param args command-line arguments |
| */ |
| public static void main(String[] args) |
| throws CheckstyleException, IOException { |
| startServer(args); |
| } |
| |
| // Monitors another PID and exit when that process exits |
| private static void watchProcess(String pid) { |
| if (pid == null || pid.equals("0")) { |
| return; |
| } |
| Timer timer = new Timer(true); // start as a daemon, so we don't hang shutdown |
| timer.scheduleAtFixedRate(new TimerTask() { |
| private String cmd = "kill -s 0 " + pid; |
| @Override |
| public void run() { |
| try { |
| Process p = Runtime.getRuntime().exec(cmd); |
| p.waitFor(); |
| if (p.exitValue() != 0) { |
| System.err.println("shutting down..."); |
| System.exit(0); |
| } |
| } catch (IOException | InterruptedException e) { |
| //no-op |
| e.printStackTrace(); |
| } |
| } |
| }, POLLING_INTERVAL, POLLING_INTERVAL); |
| } |
| |
| // Initiates a server. |
| private static void startServer(String[] args) throws IOException, CheckstyleException { |
| String portLock = args[0]; |
| String buckPid = args[1]; |
| String checkstyleFile = args[2]; |
| String suppressionsFile = args[3]; |
| |
| // Use a file lock to ensure only one copy of the daemon runs |
| Path portLockPath = Paths.get(portLock); |
| FileChannel channel = FileChannel.open(portLockPath, WRITE, CREATE); |
| FileLock lock = channel.tryLock(); |
| if (lock == null) { |
| System.out.println("Server is already running"); |
| System.exit(1); |
| } //else, hold the lock until the JVM exits |
| |
| // Start the server and bind it to a random port |
| ServerSocket server = new ServerSocket(0); |
| |
| // Monitor the parent buck process |
| watchProcess(buckPid); |
| |
| // Set up hook to clean up after ourselves |
| Runtime.getRuntime().addShutdownHook(new Thread(() -> { |
| try { |
| if (channel != null) { |
| channel.truncate(0); |
| channel.close(); |
| } |
| System.err.println("tear down..."); |
| Files.delete(portLockPath); |
| } catch (IOException e) { |
| //no-op: shutting down |
| e.printStackTrace(); |
| } |
| })); |
| |
| // Write the bound port to the port file |
| int port = server.getLocalPort(); |
| channel.truncate(0); |
| channel.write(ByteBuffer.wrap(Integer.toString(port).getBytes())); |
| |
| // Instantiate a Checkstyle runner and executor; serve until exit... |
| CheckstyleRunner runner = new CheckstyleRunner(checkstyleFile, suppressionsFile); |
| ExecutorService executor = Executors.newCachedThreadPool(); |
| while (true) { |
| try { |
| executor.submit(runner.checkClass(server.accept())); |
| } catch (Exception e) { |
| e.printStackTrace(); |
| //no-op |
| } |
| } |
| } |
| } |