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