1// BEGIN LICENSE BLOCK 2// Version: CMPL 1.1 3// 4// The contents of this file are subject to the Cisco-style Mozilla Public 5// License Version 1.1 (the "License"); you may not use this file except 6// in compliance with the License. You may obtain a copy of the License 7// at www.eclipse-clp.org/license. 8// 9// Software distributed under the License is distributed on an "AS IS" 10// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See 11// the License for the specific language governing rights and limitations 12// under the License. 13// 14// The Original Code is The ECLiPSe Constraint Logic Programming System. 15// The Initial Developer of the Original Code is Cisco Systems, Inc. 16// Portions created by the Initial Developer are 17// Copyright (C) 2000 - 2006 Cisco Systems, Inc. All Rights Reserved. 18// 19// Contributor(s): Stefano Novello / Josh Singer, Parc Technologies 20// 21// END LICENSE BLOCK 22 23//Title: Java/ECLiPSe interface 24//Version: $Id: FromEclipseQueue.java,v 1.1 2006/09/23 01:54:10 snovello Exp $ 25//Author: Stefano Novello / Josh Singer 26//Company: Parc Technologies 27//Description: Queue for sending ECLiPSe data to Java. 28package com.parctechnologies.eclipse; 29import java.io.*; 30import java.util.*; 31 32/** 33 * A queue for 34 * sending data from ECLiPSe to Java. This class performs no processing of the 35 * data and cannot for example, deal with EXDR format (see {@link EXDRInputStream} 36 * for a class which can handle this). <p> 37 * 38 * In addition to the standard methods inherited from its superclass, this class 39 * also provides the ability to attach a {@link QueueListener} object to the 40 * FromEclipseQueue, as a handler for incoming data. 41 * <p> 42 * There is no public constructor; to access an <i>FromEclipseQueue</i> use the 43 * <code>createFromEclipseQueue()</code> of an object implementing the {@link 44 * EclipseConnection} interface or the <code>getEclipseStderr()</code> or 45 * <code>getEclipseStdout()</code> method of an object implementing the 46 * {@link EclipseEngine} interface. 47 * 48 */ 49public class FromEclipseQueue extends InputStream { 50 /** 51 * This is the eclipse numeric id for the queue 52 * it is used to uniquely identify the stream 53 */ 54 private int id; 55 /** 56 * Handler for new data on queue 57 */ 58 private QueueListener listener = null; 59 /** 60 * Name of the queue 61 */ 62 private String name; 63 64 /** 65 * The eclipse which this is a queue from 66 */ 67 private EclipseConnectionImpl eclipse; 68 69 /** 70 * Flag to indicate whether or not the queue has been closed. 71 */ 72 private boolean isClosed = false; 73 74 /** 75 * Flag indicating whether this is a system or user queue. The eclipse side of 76 * a System queue does not get closed when the EclipseConnectionImpl's 77 * closeAllQueues method is called. Examples of system queues are ec_rpc_in 78 * ec_rpc_out, and standard stream queues. 79 */ 80 private boolean systemQueue = false; 81 82 83 /** 84 * make new queue 85 */ 86 FromEclipseQueue(int id,String name, EclipseConnectionImpl eclipse) 87 { 88 this.eclipse = eclipse; 89 this.id = id; 90 this.name = name; 91 } 92 93 int getID() 94 { 95 return id; 96 } 97 98 /** 99 * Returns true if this queue is a system queue, such as ec_rpc_in. 100 */ 101 boolean isSystemQueue() 102 { 103 return(systemQueue); 104 } 105 106 /** 107 * sets flag indicating wether this is a system queue 108 */ 109 void setSystemQueue(boolean newValue) 110 { 111 systemQueue = newValue; 112 } 113 114 115 116 // overrides superclass method. Return the number of bytes which 117 // can be read from the FromEclipseQueue stream without blocking. 118 public int available() throws IOException 119 { 120 testClosed(); 121 return(eclipse.availableOnStream(id)); 122 } 123 124 /** 125 * Read bytes from the FromEclipseQueue into a byte array. 126 * <code>len</code> bytes are read from the queue and stored in byte 127 * array <code>b</code> at offset <code>off</code>. 128 * 129 * @return the number of bytes read. 130 * 131 */ 132 public int read(byte[] b, int off, int len) throws IOException 133 { 134 testClosed(); 135 // read len bytes from the Eclipse stream and copy them into b at 136 // offset off. Set read to the number of bytes read. 137 int read = eclipse.readFromStream(id,off,len,b); 138 // If nothing was read 139/* if(read == 0) 140 { 141 try 142 { 143 // pass control to eclipse to allow events to be 144 // handled somehow here. 145 146 // try the read operation again 147 read = eclipse.readFromStream(id,off,len,b); 148 } 149 catch(EclipseException e) 150 { 151 throw(new IOException("Problem handling events on ECLiPSe side.")); 152 } 153 } 154*/ 155 // Return the number of bytes read 156 return read; 157 158 } 159 160 public int read() throws IOException 161 { 162 testClosed(); 163 return(eclipse.readByteFromStream(id)); 164 } 165 166 /** 167 * Called to notify a listener, if there is one, that data is available 168 */ 169 void notifyAvailable() 170 { 171 if (listener != null) 172 { 173 listener.dataAvailable(this); 174 } 175 } 176 177 /** 178 * Attach a <i>QueueListener</i> to this <i>FromEclipseQueue</i> for handling 179 * incoming data. When ECLiPSe 180 * flushes the 181 * queue, the <code>dataAvailable()</code> method of the 182 * <i>QueueListener</i> is invoked. 183 */ 184 public void setListener(QueueListener l) throws IOException 185 { 186 testClosed(); 187 listener = l; 188 } 189 190 /** 191 * Detach any <i>QueueListener</i> from this <i>FromEclipseQueue</i>. 192 */ 193 public void removeListener() throws IOException 194 { 195 testClosed(); 196 listener = null; 197 } 198 199 /** 200 * Closes the queue (both eclipse and Java sides), removing any listener. 201 */ 202 public void close() throws IOException 203 { 204 testClosed(); 205 close_cleanup(); 206 eclipse.closeFromEclipseStreamEclipseSide(id); 207 eclipse.closeFromEclipseStreamJavaSide(id); 208 } 209 210 // method to clean up locally 211 void close_cleanup() 212 { 213 try 214 { 215 this.removeListener(); 216 } 217 catch(IOException ioe) 218 { 219 // only thrown if the queue has already been closed, which it hasn't 220 System.err.println("Error: removal of listener threw an IOException."); 221 System.err.flush(); 222 } 223 isClosed = true; 224 } 225 226 /** 227 * Test whether the queue has been closed; if so, throw an IOException 228 * "Operation not possible: stream closed." 229 */ 230 private void testClosed() throws IOException 231 { 232 if(isClosed) 233 { 234 throw new IOException("Operation not possible: stream closed."); 235 } 236 } 237 238} 239