1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: PipedConnection.java,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 package com
.sun
.star
.comp
.connections
;
34 import com
.sun
.star
.comp
.loader
.FactoryHelper
;
36 import com
.sun
.star
.connection
.XConnection
;
38 import com
.sun
.star
.lang
.XMultiServiceFactory
;
39 import com
.sun
.star
.lang
.XSingleServiceFactory
;
41 import com
.sun
.star
.registry
.XRegistryKey
;
44 * The PipedConnection is a component that implements the
45 * <code>XConnection</code> Interface.
46 * It is useful for <code>Thread</code> communication
49 * @version $Revision: 1.3 $ $ $Date: 2008-04-11 11:09:30 $
51 * @see com.sun.star.connections.XConnection
52 * @see com.sun.star.loader.JavaLoader
55 public class PipedConnection
implements XConnection
{
57 * When set to true, enables various debugging output.
59 public static final boolean DEBUG
= false;
62 * The name of the service, the <code>JavaLoader</code> acceses this through reflection.
64 static private final String __serviceName
= "com.sun.star.connection.PipedConnection";
67 * Gives a factory for creating the service.
68 * This method is called by the <code>JavaLoader</code>
70 * @return returns a <code>XSingleServiceFactory</code> for creating the component
71 * @param implName the name of the implementation for which a service is desired
72 * @param multiFactory the service manager to be uses if needed
73 * @param regKey the registryKey
74 * @see com.sun.star.comp.loader.JavaLoader
76 public static XSingleServiceFactory
__getServiceFactory(String implName
,
77 XMultiServiceFactory multiFactory
,
80 XSingleServiceFactory xSingleServiceFactory
= null;
82 if (implName
.equals(PipedConnection
.class.getName()) )
83 xSingleServiceFactory
= FactoryHelper
.getServiceFactory(PipedConnection
.class,
88 return xSingleServiceFactory
;
92 * Writes the service information into the given registry key.
93 * This method is called by the <code>JavaLoader</code>
95 * @return returns true if the operation succeeded
96 * @param regKey the registryKey
97 * @see com.sun.star.comp.loader.JavaLoader
99 public static boolean __writeRegistryServiceInfo(XRegistryKey regKey
) {
100 return FactoryHelper
.writeRegistryServiceInfo(PipedConnection
.class.getName(), __serviceName
, regKey
);
105 * The amount of time in milliseconds, to wait to
106 * see check the buffers.
108 protected static final int __waitTime
= 10000;
110 protected byte _buffer
[] = new byte[4096];
113 protected boolean _closed
;
114 protected PipedConnection _otherSide
;
117 * Constructs a new <code>PipedConnection</code>, sees if there
118 * is an other side, which it should be connected to.
120 * @param args Another side could be in index 0.
122 public PipedConnection(Object args
[]) throws com
.sun
.star
.uno
.RuntimeException
{
123 if (DEBUG
) System
.err
.println("##### " + getClass().getName() + " - instantiated");
125 _otherSide
= (args
.length
== 1) ?
(PipedConnection
)args
[0] : null;
126 if(_otherSide
!= null) {
127 if(_otherSide
== this)
128 throw new RuntimeException("can not connect to myself");
130 _otherSide
._otherSide
= this;
135 * This is a private method, used to cummunicate
136 * internal in the pipe.
138 private synchronized void receive(byte aData
[]) throws com
.sun
.star
.io
.IOException
{
139 int bytesWritten
= 0;
141 if(DEBUG
) System
.err
.println("##### PipedConnection.receive - bytes:" + aData
.length
+ " at:" + _out
);
143 while(bytesWritten
< aData
.length
) {
144 // wait until it is not full anymore
145 while(_out
== (_in
- 1) || (_in
== 0 && _out
== _buffer
.length
- 1)) {
147 notify(); // the buffer is full, signal it
151 catch(InterruptedException interruptedException
) {
152 throw new com
.sun
.star
.io
.IOException(interruptedException
.toString());
156 if(_closed
) throw new com
.sun
.star
.io
.IOException("connection has been closed");
161 bytes
= Math
.min(aData
.length
- bytesWritten
, _in
- _out
- 1);
163 System
.arraycopy(aData
, bytesWritten
, _buffer
, _out
, bytes
);
167 bytes
= Math
.min(aData
.length
- bytesWritten
, _buffer
.length
- _out
);
170 bytes
= Math
.min(aData
.length
- bytesWritten
, _buffer
.length
- _out
- 1);
173 System
.arraycopy(aData
, bytesWritten
, _buffer
, _out
, bytes
);
176 bytesWritten
+= bytes
;
178 if(_out
>= _buffer
.length
)
184 * Read the required number of bytes.
186 * @return the number of bytes read
187 * @param aReadBytes the outparameter, where the bytes have to be placed
188 * @param nBytesToRead the number of bytes to read
189 * @see com.sun.star.connections.XConnection#read
191 public synchronized int read(/*OUT*/byte[][] aReadBytes
, int nBytesToRead
) throws com
.sun
.star
.io
.IOException
, com
.sun
.star
.uno
.RuntimeException
{
192 aReadBytes
[0] = new byte[nBytesToRead
];
194 if(DEBUG
) System
.err
.println("##### PipedConnection.read - bytes:" + nBytesToRead
+ " at:" + _in
);
196 // loop while not all bytes read or when closed but there is still data
197 while(nBytesToRead
> 0 && (_in
!= _out
|| !_closed
)) {
198 while(_in
== _out
&& !_closed
) {
200 notify(); // the buffer is empty, signal it
202 wait(__waitTime
); // we wait for data or for the pipe to be closed
204 catch(InterruptedException interruptedException
) {
205 throw new com
.sun
.star
.io
.IOException(interruptedException
.toString());
210 int bytes
= Math
.min(nBytesToRead
, _out
- _in
);
212 System
.arraycopy(_buffer
, _in
, aReadBytes
[0], aReadBytes
[0].length
- nBytesToRead
, bytes
);
214 nBytesToRead
-= bytes
;
217 else if(_in
> _out
) {
218 int bytes
= Math
.min(nBytesToRead
, _buffer
.length
- _in
);
220 System
.arraycopy(_buffer
, _in
, aReadBytes
[0], aReadBytes
[0].length
- nBytesToRead
, bytes
);
222 nBytesToRead
-= bytes
;
224 if(_in
>= _buffer
.length
)
229 if(nBytesToRead
> 0) { // not all bytes read
230 byte tmp
[] = new byte[aReadBytes
[0].length
- nBytesToRead
];
231 System
.arraycopy(aReadBytes
[0], 0, tmp
, 0, tmp
.length
);
236 return aReadBytes
[0].length
;
242 * @param aData the bytes to write
243 * @see com.sun.star.connections.XConnection#write
245 public void write(byte aData
[]) throws com
.sun
.star
.io
.IOException
, com
.sun
.star
.uno
.RuntimeException
{
246 _otherSide
.receive(aData
);
250 * Flushes the buffer, notifies if necessary the other side that new data has arrived.
252 * @see com.sun.star.connections.XConnection#flush
254 public void flush() throws com
.sun
.star
.io
.IOException
, com
.sun
.star
.uno
.RuntimeException
{
255 synchronized(_otherSide
) {
263 * @see com.sun.star.connections.XConnection#closed
265 public synchronized void close() throws com
.sun
.star
.io
.IOException
, com
.sun
.star
.uno
.RuntimeException
{
276 * Gives a description of this pipe.
278 * @return the description
279 * @see com.sun.star.connections.XConnection#getDescription
281 public String
getDescription() throws com
.sun
.star
.uno
.RuntimeException
{
282 return getClass().getName();