xref: /AOO41X/main/jurt/com/sun/star/comp/connections/PipedConnection.java (revision 2be432768a66cc90838f6a32e76ec156f587e741)
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