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