001 /* 002 * This file is part of McIDAS-V 003 * 004 * Copyright 2007-2013 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 */ 028 package edu.wisc.ssec.mcidasv.servermanager; 029 030 import java.io.InputStream; 031 import java.io.InputStreamReader; 032 033 import org.bushe.swing.event.EventBus; 034 035 import edu.wisc.ssec.mcidasv.Constants; 036 import edu.wisc.ssec.mcidasv.McIDASV; 037 038 /** 039 * Thread that actually execs mcservl 040 */ 041 public class AddeThread extends Thread { 042 043 /** Mcserv events. */ 044 public enum McservEvent { 045 /** Mcservl is actively listening. */ 046 ACTIVE("Local servers are running."), 047 /** Mcservl has died unexpectedly. */ 048 DIED("Local servers quit unexpectedly."), 049 /** Mcservl started listening. */ 050 STARTED("Local servers started listening on port %s."), 051 /** Mcservl has stopped listening. */ 052 STOPPED("Local servers have been stopped."); 053 054 /** */ 055 private final String message; 056 057 /** 058 * Creates an object that represents the status of a mcservl process. 059 * 060 * @param message Should not be {@code null}. 061 */ 062 private McservEvent(final String message) { 063 this.message = message; 064 } 065 066 /** 067 * 068 * 069 * @return Format string associated with an event. 070 */ 071 public String getMessage() { 072 return message; 073 } 074 }; 075 076 /** */ 077 Process proc; 078 079 /** Server manager. */ 080 private final EntryStore entryStore; 081 082 /** 083 * Creates a thread that controls a mcservl process. 084 * 085 * @param entryStore Server manager. 086 */ 087 public AddeThread(final EntryStore entryStore) { 088 this.entryStore = entryStore; 089 } 090 091 public void run() { 092 StringBuilder err = new StringBuilder(); 093 String[] cmds = entryStore.getAddeCommands(); 094 String[] env = (McIDASV.isWindows()) ? entryStore.getWindowsAddeEnv() : entryStore.getUnixAddeEnv(); 095 try { 096 //start ADDE binary with "-p PORT" and set environment appropriately 097 proc = Runtime.getRuntime().exec(cmds, env); 098 099 //create thread for reading inputStream (process' stdout) 100 StreamReaderThread outThread = new StreamReaderThread(proc.getInputStream(), new StringBuilder()); 101 102 //create thread for reading errorStream (process' stderr) 103 StreamReaderThread errThread = new StreamReaderThread(proc.getErrorStream(), err); 104 105 //start both threads 106 outThread.start(); 107 errThread.start(); 108 109 //wait for process to end 110 int result = proc.waitFor(); 111 112 //finish reading whatever's left in the buffers 113 outThread.join(); 114 errThread.join(); 115 116 if (result != 0) { 117 // entryStore.stopLocalServer(entryStore.getRestarting()); 118 entryStore.stopLocalServer(); 119 String errString = err.toString(); 120 121 // If the server couldn't start for a known reason, try again on another port 122 // Retry up to 10 times 123 if ((result==35584 || errString.indexOf("Error binding to port") >= 0) && 124 Integer.parseInt(EntryStore.getLocalPort()) < Integer.parseInt(Constants.LOCAL_ADDE_PORT) + 30) { 125 EntryStore.setLocalPort(EntryStore.nextLocalPort()); 126 // entryStore.startLocalServer(entryStore.getRestarting()); 127 entryStore.startLocalServer(); 128 } 129 } 130 } catch (InterruptedException e) { 131 McservEvent type = McservEvent.DIED; 132 // if (entryStore.getRestarting()) { 133 type = McservEvent.STARTED; 134 // } 135 EventBus.publish(type); 136 } catch (Exception e) { 137 EventBus.publish(McservEvent.DIED); 138 } 139 } 140 141 /** 142 * 143 */ 144 public void stopProcess() { 145 proc.destroy(); 146 } 147 148 // /** 149 // * 150 // */ 151 // public String toString() { 152 // return String.format("[AddeThread@%x: ADDE_ENV=%s, ADDE_COMMANDS=%s]", hashCode(), ADDE_ENV, ADDE_COMMANDS); 153 // } 154 155 /** 156 * Thread to read the stderr and stdout of mcservl 157 */ 158 private static class StreamReaderThread extends Thread { 159 /** */ 160 private final StringBuilder mOut; 161 162 /** */ 163 private final InputStreamReader mIn; 164 165 /** */ 166 public StreamReaderThread(final InputStream in, final StringBuilder out) { 167 mOut = out; 168 mIn = new InputStreamReader(in); 169 } 170 171 /** */ 172 public void run() { 173 int ch; 174 try { 175 while (-1 != (ch = mIn.read())) { 176 mOut.append((char)ch); 177 } 178 } catch (Exception e) { 179 mOut.append("\nRead error: "+e.getMessage()); 180 } 181 } 182 } 183 }