001/* 002 * This file is part of McIDAS-V 003 * 004 * Copyright 2007-2016 005 * Space Science and Engineering Center (SSEC) 006 * University of Wisconsin - Madison 007 * 1225 W. Dayton Street, Madison, WI 53706, USA 008 * https://www.ssec.wisc.edu/mcidas 009 * 010 * All Rights Reserved 011 * 012 * McIDAS-V is built on Unidata's IDV and SSEC's VisAD libraries, and 013 * some McIDAS-V source code is based on IDV and VisAD source code. 014 * 015 * McIDAS-V is free software; you can redistribute it and/or modify 016 * it under the terms of the GNU Lesser Public License as published by 017 * the Free Software Foundation; either version 3 of the License, or 018 * (at your option) any later version. 019 * 020 * McIDAS-V is distributed in the hope that it will be useful, 021 * but WITHOUT ANY WARRANTY; without even the implied warranty of 022 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 023 * GNU Lesser Public License for more details. 024 * 025 * You should have received a copy of the GNU Lesser Public License 026 * along with this program. If not, see http://www.gnu.org/licenses. 027 */ 028package edu.wisc.ssec.mcidasv.servermanager; 029 030import java.io.InputStream; 031import java.io.InputStreamReader; 032 033import org.bushe.swing.event.EventBus; 034 035import edu.wisc.ssec.mcidasv.Constants; 036import edu.wisc.ssec.mcidasv.McIDASV; 037 038import org.slf4j.Logger; 039import org.slf4j.LoggerFactory; 040 041/** 042 * Thread that actually execs the {@literal "mcservl"} process. 043 */ 044public class AddeThread extends Thread { 045 046 private static final Logger logger = LoggerFactory.getLogger(AddeThread.class); 047 048 /** Mcserv events. */ 049 public enum McservEvent { 050 /** Mcservl is actively listening. */ 051 ACTIVE("Local servers are running."), 052 /** Mcservl has died unexpectedly. */ 053 DIED("Local servers quit unexpectedly."), 054 /** Mcservl started listening. */ 055 STARTED("Local servers started listening on port %s."), 056 /** Mcservl has stopped listening. */ 057 STOPPED("Local servers have been stopped."); 058 059 /** */ 060 private final String message; 061 062 /** 063 * Creates an object that represents the status of a mcservl process. 064 * 065 * @param message Should not be {@code null}. 066 */ 067 McservEvent(final String message) { 068 this.message = message; 069 } 070 071 /** 072 * 073 * 074 * @return Format string associated with an event. 075 */ 076 public String getMessage() { 077 return message; 078 } 079 } 080 081 /** */ 082 Process proc; 083 084 /** Server manager. */ 085 private final EntryStore entryStore; 086 087 /** 088 * Creates a thread that controls a mcservl process. 089 * 090 * @param entryStore Server manager. 091 */ 092 public AddeThread(final EntryStore entryStore) { 093 this.entryStore = entryStore; 094 } 095 096 public void run() { 097 StringBuilder err = new StringBuilder(); 098 String[] cmds = entryStore.getAddeCommands(); 099 String[] env = (McIDASV.isWindows()) ? entryStore.getWindowsAddeEnv() : entryStore.getUnixAddeEnv(); 100 101 StringBuilder temp = new StringBuilder(512); 102 for (String cmd : cmds) { 103 temp.append(cmd).append(' '); 104 } 105 logger.info("Starting mcservl: {}", temp.toString()); 106 temp = new StringBuilder(1024).append("{ "); 107 for (String e : env) { 108 temp.append(e).append(", "); 109 } 110 temp.append('}'); 111 logger.debug("env={}", temp.toString()); 112// temp = null; 113 114 try { 115 //start ADDE binary with "-p PORT" and set environment appropriately 116 proc = Runtime.getRuntime().exec(cmds, env); 117 118 //create thread for reading inputStream (process' stdout) 119 StreamReaderThread outThread = new StreamReaderThread(proc.getInputStream(), new StringBuilder()); 120 121 //create thread for reading errorStream (process' stderr) 122 StreamReaderThread errThread = new StreamReaderThread(proc.getErrorStream(), err); 123 124 //start both threads 125 outThread.start(); 126 errThread.start(); 127 128 //wait for process to end 129 int result = proc.waitFor(); 130 131 //finish reading whatever's left in the buffers 132 outThread.join(); 133 errThread.join(); 134 135 if (result != 0) { 136// entryStore.stopLocalServer(entryStore.getRestarting()); 137 entryStore.stopLocalServer(); 138 String errString = err.toString(); 139 140 // If the server couldn't start for a known reason, try again on another port 141 // Retry up to 10 times 142 if (((result == 35584) || (errString.contains("Error binding to port"))) && 143 (Integer.parseInt(EntryStore.getLocalPort()) < (Integer.parseInt(Constants.LOCAL_ADDE_PORT) + 30))) 144 { 145 EntryStore.setLocalPort(EntryStore.nextLocalPort()); 146// entryStore.startLocalServer(entryStore.getRestarting()); 147 entryStore.startLocalServer(); 148 } 149 } 150 } catch (InterruptedException e) { 151// McservEvent type = McservEvent.DIED; 152//// if (entryStore.getRestarting()) { 153// type = McservEvent.STARTED; 154//// } 155// EventBus.publish(type); 156 EventBus.publish(McservEvent.STARTED); 157 } catch (Exception e) { 158 EventBus.publish(McservEvent.DIED); 159 } 160 } 161 162 /** 163 * 164 */ 165 public void stopProcess() { 166 proc.destroy(); 167 } 168 169// /** 170// * 171// */ 172// public String toString() { 173// return String.format("[AddeThread@%x: ADDE_ENV=%s, ADDE_COMMANDS=%s]", hashCode(), ADDE_ENV, ADDE_COMMANDS); 174// } 175 176 /** 177 * Thread to read the stderr and stdout of mcservl. 178 */ 179 private static class StreamReaderThread extends Thread { 180 181 /** stderr */ 182 private final StringBuilder mOut; 183 184 /** stdin */ 185 private final InputStreamReader mIn; 186 187 /** 188 * Create a thread for reading mcservl output. 189 * 190 * @param in Input {@literal "stream"}. 191 * @param out Output {@literal "stream"}. 192 */ 193 public StreamReaderThread(final InputStream in, final StringBuilder out) { 194 mOut = out; 195 mIn = new InputStreamReader(in); 196 } 197 198 /** 199 * Reads {@link #mIn} and appends to {@link #mOut}. 200 */ 201 public void run() { 202 int ch; 203 try { 204 while (-1 != (ch = mIn.read())) { 205 mOut.append((char)ch); 206 } 207 } catch (Exception e) { 208 mOut.append("\nRead error: ").append(e.getMessage()); 209 } 210 } 211 } 212}