1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 24 package com.sun.star.comp.connections; 25 26 27 import com.sun.star.comp.loader.FactoryHelper; 28 29 import com.sun.star.connection.XConnection; 30 31 import com.sun.star.lang.XMultiServiceFactory; 32 import com.sun.star.lang.XSingleServiceFactory; 33 34 import com.sun.star.registry.XRegistryKey; 35 36 /** 37 * The PipedConnection is a component that implements the 38 * <code>XConnection</code> Interface. 39 * It is useful for <code>Thread</code> communication 40 * in one Process. 41 * <p> 42 * @version $Revision: 1.3 $ $ $Date: 2008-04-11 11:09:30 $ 43 * @author Kay Ramme 44 * @see com.sun.star.connections.XConnection 45 * @see com.sun.star.loader.JavaLoader 46 * @since UDK1.0 47 */ 48 public class PipedConnection implements XConnection { 49 /** 50 * When set to true, enables various debugging output. 51 */ 52 public static final boolean DEBUG = false; 53 54 /** 55 * The name of the service, the <code>JavaLoader</code> acceses this through reflection. 56 */ 57 static private final String __serviceName = "com.sun.star.connection.PipedConnection"; 58 59 /** 60 * Gives a factory for creating the service. 61 * This method is called by the <code>JavaLoader</code> 62 * <p> 63 * @return returns a <code>XSingleServiceFactory</code> for creating the component 64 * @param implName the name of the implementation for which a service is desired 65 * @param multiFactory the service manager to be uses if needed 66 * @param regKey the registryKey 67 * @see com.sun.star.comp.loader.JavaLoader 68 */ __getServiceFactory(String implName, XMultiServiceFactory multiFactory, XRegistryKey regKey)69 public static XSingleServiceFactory __getServiceFactory(String implName, 70 XMultiServiceFactory multiFactory, 71 XRegistryKey regKey) 72 { 73 XSingleServiceFactory xSingleServiceFactory = null; 74 75 if (implName.equals(PipedConnection.class.getName()) ) 76 xSingleServiceFactory = FactoryHelper.getServiceFactory(PipedConnection.class, 77 __serviceName, 78 multiFactory, 79 regKey); 80 81 return xSingleServiceFactory; 82 } 83 84 /** 85 * The amount of time in milliseconds, to wait to 86 * see check the buffers. 87 */ 88 protected static final int __waitTime = 10000; 89 90 protected byte _buffer[] = new byte[4096]; 91 protected int _in, 92 _out; 93 protected boolean _closed; 94 protected PipedConnection _otherSide; 95 96 /** 97 * Constructs a new <code>PipedConnection</code>, sees if there 98 * is an other side, which it should be connected to. 99 * <p> 100 * @param args Another side could be in index 0. 101 */ PipedConnection(Object args[])102 public PipedConnection(Object args[]) throws com.sun.star.uno.RuntimeException { 103 if (DEBUG) System.err.println("##### " + getClass().getName() + " - instantiated"); 104 105 _otherSide = (args.length == 1) ? (PipedConnection)args[0] : null; 106 if(_otherSide != null) { 107 if(_otherSide == this) 108 throw new RuntimeException("can not connect to myself"); 109 110 _otherSide._otherSide = this; 111 } 112 } 113 114 /** 115 * This is a private method, used to cummunicate 116 * internal in the pipe. 117 */ receive(byte aData[])118 private synchronized void receive(byte aData[]) throws com.sun.star.io.IOException { 119 int bytesWritten = 0; 120 121 if(DEBUG) System.err.println("##### PipedConnection.receive - bytes:" + aData.length + " at:" + _out); 122 123 while(bytesWritten < aData.length) { 124 // wait until it is not full anymore 125 while(_out == (_in - 1) || (_in == 0 && _out == _buffer.length - 1)) { 126 try { 127 notify(); // the buffer is full, signal it 128 129 wait(__waitTime); 130 } 131 catch(InterruptedException interruptedException) { 132 throw new com.sun.star.io.IOException(interruptedException.toString()); 133 } 134 } 135 136 if(_closed) throw new com.sun.star.io.IOException("connection has been closed"); 137 138 int bytes ; 139 140 if(_out < _in) { 141 bytes = Math.min(aData.length - bytesWritten, _in - _out - 1); 142 143 System.arraycopy(aData, bytesWritten, _buffer, _out, bytes); 144 } 145 else { 146 if(_in > 0){ 147 bytes = Math.min(aData.length - bytesWritten, _buffer.length - _out); 148 } 149 else { 150 bytes = Math.min(aData.length - bytesWritten, _buffer.length - _out - 1); 151 } 152 153 System.arraycopy(aData, bytesWritten, _buffer, _out, bytes); 154 } 155 156 bytesWritten += bytes; 157 _out += bytes; 158 if(_out >= _buffer.length) 159 _out = 0; 160 } 161 } 162 163 /** 164 * Read the required number of bytes. 165 * <p> 166 * @return the number of bytes read 167 * @param aReadBytes the outparameter, where the bytes have to be placed 168 * @param nBytesToRead the number of bytes to read 169 * @see com.sun.star.connections.XConnection#read 170 */ read( byte[][] aReadBytes, int nBytesToRead)171 public synchronized int read(/*OUT*/byte[][] aReadBytes, int nBytesToRead) throws com.sun.star.io.IOException, com.sun.star.uno.RuntimeException { 172 aReadBytes[0] = new byte[nBytesToRead]; 173 174 if(DEBUG) System.err.println("##### PipedConnection.read - bytes:" + nBytesToRead + " at:" + _in); 175 176 // loop while not all bytes read or when closed but there is still data 177 while(nBytesToRead > 0 && (_in != _out || !_closed)) { 178 while(_in == _out && !_closed) { 179 try { 180 notify(); // the buffer is empty, signal it 181 182 wait(__waitTime); // we wait for data or for the pipe to be closed 183 } 184 catch(InterruptedException interruptedException) { 185 throw new com.sun.star.io.IOException(interruptedException.toString()); 186 } 187 } 188 189 if(_in < _out) { 190 int bytes = Math.min(nBytesToRead, _out - _in); 191 192 System.arraycopy(_buffer, _in, aReadBytes[0], aReadBytes[0].length - nBytesToRead, bytes); 193 194 nBytesToRead -= bytes; 195 _in += bytes; 196 } 197 else if(_in > _out) { 198 int bytes = Math.min(nBytesToRead, _buffer.length - _in); 199 200 System.arraycopy(_buffer, _in, aReadBytes[0], aReadBytes[0].length - nBytesToRead, bytes); 201 202 nBytesToRead -= bytes; 203 _in += bytes; 204 if(_in >= _buffer.length) 205 _in = 0; 206 } 207 } 208 209 if(nBytesToRead > 0) { // not all bytes read 210 byte tmp[] = new byte[aReadBytes[0].length - nBytesToRead]; 211 System.arraycopy(aReadBytes[0], 0, tmp, 0, tmp.length); 212 213 aReadBytes[0] = tmp; 214 } 215 216 return aReadBytes[0].length; 217 } 218 219 /** 220 * Write bytes. 221 * <p> 222 * @param aData the bytes to write 223 * @see com.sun.star.connections.XConnection#write 224 */ write(byte aData[])225 public void write(byte aData[]) throws com.sun.star.io.IOException, com.sun.star.uno.RuntimeException { 226 _otherSide.receive(aData); 227 } 228 229 /** 230 * Flushes the buffer, notifies if necessary the other side that new data has arrived. 231 * <p> 232 * @see com.sun.star.connections.XConnection#flush 233 */ flush()234 public void flush() throws com.sun.star.io.IOException, com.sun.star.uno.RuntimeException { 235 synchronized(_otherSide) { 236 _otherSide.notify(); 237 } 238 } 239 240 /** 241 * Closes the pipe. 242 * <p> 243 * @see com.sun.star.connections.XConnection#closed 244 */ close()245 public synchronized void close() throws com.sun.star.io.IOException, com.sun.star.uno.RuntimeException { 246 if(!_closed) { 247 _closed = true; 248 249 _otherSide.close(); 250 251 notify(); 252 } 253 } 254 255 /** 256 * Gives a description of this pipe. 257 * <p> 258 * @return the description 259 * @see com.sun.star.connections.XConnection#getDescription 260 */ getDescription()261 public String getDescription() throws com.sun.star.uno.RuntimeException { 262 return getClass().getName(); 263 } 264 265 } 266 267