1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * 15 * See the License for the specific language governing permissions and 16 * limitations under the License. 17 */ 18 19 /** 20 * @author Vitaly A. Provodin 21 */ 22 23 /** 24 * Created on 29.01.2005 25 */ 26 package org.apache.harmony.jpda.tests.share; 27 28 import java.io.DataInputStream; 29 import java.io.DataOutputStream; 30 import java.io.EOFException; 31 import java.io.IOException; 32 import java.net.Socket; 33 import java.net.ServerSocket; 34 35 import org.apache.harmony.jpda.tests.framework.DebuggeeSynchronizer; 36 import org.apache.harmony.jpda.tests.framework.LogWriter; 37 import org.apache.harmony.jpda.tests.framework.TestErrorException; 38 import org.apache.harmony.jpda.tests.framework.TestOptions; 39 40 /** 41 * This class implements <code>DebuggeeSynchronizer</code> interface using 42 * TCP/IP sockets. All operations can be timed out according to default timeout. 43 */ 44 public class JPDADebuggeeSynchronizer implements DebuggeeSynchronizer { 45 46 public final static String SGNL_READY = "ready"; 47 48 public final static String SGNL_CONTINUE = "continue"; 49 50 protected Socket clientSocket = null; 51 52 protected ServerSocket serverSocket = null; 53 54 protected DataOutputStream out; 55 56 protected DataInputStream in; 57 58 protected TestOptions settings; 59 60 protected LogWriter logWriter; 61 62 /** 63 * A constructor that initializes an instance of the class with specified 64 * <code>LogWriter</code> and <code>TestOptions</code>. 65 * 66 * @param logWriter 67 * The instance of implementation of LogWriter. 68 * @param settings 69 * Instance of test options. 70 */ 71 public JPDADebuggeeSynchronizer(LogWriter logWriter, TestOptions settings) { 72 super(); 73 this.logWriter = logWriter; 74 this.settings = settings; 75 } 76 77 /** 78 * Sends specified message to synchronization channel. 79 * 80 * @param message 81 * a message to be sent. 82 */ 83 public synchronized void sendMessage(String message) { 84 try { 85 out.writeUTF(message); 86 out.flush(); 87 logWriter.println("[SYNC] Message sent: " + message); 88 } catch (IOException e) { 89 throw new TestErrorException(e); 90 } 91 } 92 93 /** 94 * Receives message from synchronization channel and compares it with the 95 * expected <code>message</code>. 96 * 97 * @param message 98 * expected message. 99 * @return <code>true</code> if received string is equals to 100 * <code>message</code> otherwise - <code>false</code>. 101 * 102 */ 103 public synchronized boolean receiveMessage(String message) { 104 String msg; 105 try { 106 logWriter.println("[SYNC] Waiting for message: " + message); 107 msg = in.readUTF(); 108 logWriter.println("[SYNC] Received message: " + msg); 109 } catch (EOFException e) { 110 return false; 111 } catch (IOException e) { 112 logWriter.printError(e); 113 return false; 114 } 115 return message.equalsIgnoreCase(msg); 116 } 117 118 /** 119 * Receives message from synchronization channel. 120 * 121 * @return received string or null if connection was closed. 122 */ 123 public synchronized String receiveMessage() { 124 String msg; 125 try { 126 logWriter.println("[SYNC] Waiting for any messsage"); 127 msg = in.readUTF(); 128 logWriter.println("[SYNC] Received message: " + msg); 129 } catch (EOFException e) { 130 return null; 131 } catch (IOException e) { 132 throw new TestErrorException(e); 133 } 134 return msg; 135 } 136 137 /** 138 * Receives message from synchronization channel without Exception. 139 * 140 * @return received string 141 */ 142 public synchronized String receiveMessageWithoutException(String invoker) { 143 String msg; 144 try { 145 logWriter.println("[SYNC] Waiting for any message"); 146 msg = in.readUTF(); 147 logWriter.println("[SYNC] Received message: " + msg); 148 } catch (Throwable thrown) { 149 if (invoker != null) { 150 logWriter.println("#### receiveMessageWithoutException: Exception occurred:"); 151 logWriter.println("#### " + thrown); 152 logWriter.println("#### Invoker = " + invoker); 153 } 154 msg = "" + thrown; 155 } 156 return msg; 157 } 158 159 /** 160 * Returns socket port to be used for connection. 161 * 162 * @return port number 163 */ 164 public int getSyncPortNumber() { 165 return settings.getSyncPortNumber(); 166 } 167 168 /** 169 * Binds server to listen socket port. 170 * 171 * @return port number 172 */ 173 public synchronized int bindServer() { 174 int port = getSyncPortNumber(); 175 try { 176 logWriter.println("[SYNC] Binding socket on port: " + port); 177 serverSocket = new ServerSocket(port); 178 port = serverSocket.getLocalPort(); 179 logWriter.println("[SYNC] Bound socket on port: " + port); 180 return port; 181 } catch (IOException e) { 182 throw new TestErrorException( 183 "[SYNC] Exception in binding for socket sync connection", e); 184 } 185 } 186 187 /** 188 * Accepts sync connection form server side. 189 */ 190 public synchronized void startServer() { 191 long timeout = settings.getTimeout(); 192 try { 193 serverSocket.setSoTimeout((int) timeout); 194 logWriter.println("[SYNC] Accepting socket connection"); 195 clientSocket = serverSocket.accept(); 196 logWriter.println("[SYNC] Accepted socket connection"); 197 198 clientSocket.setSoTimeout((int) timeout); 199 out = new DataOutputStream(clientSocket.getOutputStream()); 200 in = new DataInputStream(clientSocket.getInputStream()); 201 } catch (IOException e) { 202 throw new TestErrorException( 203 "[SYNC] Exception in accepting socket sync connection", e); 204 } 205 } 206 207 /** 208 * Attaches for sync connection from client side.. 209 */ 210 public synchronized void startClient() { 211 long timeout = settings.getTimeout(); 212 String host = "localhost"; 213 int port = getSyncPortNumber(); 214 try { 215 logWriter.println("[SYNC] Attaching socket to: " + host + ":" + port); 216 clientSocket = new Socket(host, port); 217 logWriter.println("[SYNC] Attached socket"); 218 219 clientSocket.setSoTimeout((int) timeout); 220 out = new DataOutputStream(clientSocket.getOutputStream()); 221 in = new DataInputStream(clientSocket.getInputStream()); 222 } catch (IOException e) { 223 throw new TestErrorException( 224 "[SYNC] Exception in attaching for socket sync connection", e); 225 } 226 } 227 228 /** 229 * Stops synchronization work. It ignores <code>IOException</code> but 230 * prints a message. 231 */ 232 public void stop() { 233 try { 234 if (out != null) 235 out.close(); 236 if (in != null) 237 in.close(); 238 if (clientSocket != null) 239 clientSocket.close(); 240 if (serverSocket != null) 241 serverSocket.close(); 242 } catch (IOException e) { 243 logWriter.println 244 ("[SYNC] Ignoring exception in closing socket sync connection: " + e); 245 } 246 logWriter.println("[SYNC] Closed socket"); 247 } 248 } 249