1 /* -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 package com
.sun
.star
.comp
.connections
;
23 import com
.sun
.star
.comp
.loader
.FactoryHelper
;
24 import com
.sun
.star
.connection
.XConnection
;
25 import com
.sun
.star
.lang
.XMultiServiceFactory
;
26 import com
.sun
.star
.lang
.XSingleServiceFactory
;
27 import com
.sun
.star
.registry
.XRegistryKey
;
30 * The <code>PipedConnection</code> is a component that implements the
31 * <code>XConnection</code> Interface.
32 * <p>It is useful for <code>Thread</code> communication in one Process.</p>
34 * @see com.sun.star.connection.XConnection
35 * @see com.sun.star.comp.loader.JavaLoader
38 public class PipedConnection
implements XConnection
{
40 * When set to true, enables various debugging output.
42 public static final boolean DEBUG
= false;
45 * The name of the service, the <code>JavaLoader</code> accesses this through
48 private static final String __serviceName
= "com.sun.star.connection.PipedConnection";
51 * Gives a factory for creating the service.
52 * <p>This method is called by the <code>JavaLoader</code>.</p>
54 * @param implName the name of the implementation for which a service is desired.
55 * @param multiFactory the service manager to be uses if needed.
56 * @param regKey the registryKey.
57 * @return returns a <code>XSingleServiceFactory</code> for creating the component.
59 * @see com.sun.star.comp.loader.JavaLoader
61 public static XSingleServiceFactory
__getServiceFactory(String implName
,
62 XMultiServiceFactory multiFactory
,
65 XSingleServiceFactory xSingleServiceFactory
= null;
67 if (implName
.equals(PipedConnection
.class.getName()) )
68 xSingleServiceFactory
= FactoryHelper
.getServiceFactory(PipedConnection
.class,
73 return xSingleServiceFactory
;
77 * The amount of time in milliseconds, to wait to see check the buffers.
79 protected static final int __waitTime
= 10000;
81 protected byte _buffer
[] = new byte[4096];
84 protected boolean _closed
;
85 protected PipedConnection _otherSide
;
88 * Constructs a new <code>PipedConnection</code>, sees if there is another
89 * side, which it should be connected to.
91 * @param args Another side could be in index 0.
93 public PipedConnection(Object args
[]) throws com
.sun
.star
.uno
.RuntimeException
{
94 if (DEBUG
) System
.err
.println("##### " + getClass().getName() + " - instantiated");
96 _otherSide
= (args
.length
== 1) ?
(PipedConnection
)args
[0] : null;
97 if(_otherSide
!= null) {
98 if(_otherSide
== this)
99 throw new RuntimeException("can not connect to myself");
101 _otherSide
._otherSide
= this;
106 * This is a private method, used to communicate internal in the pipe.
108 private synchronized void receive(byte aData
[]) throws com
.sun
.star
.io
.IOException
{
109 int bytesWritten
= 0;
111 if(DEBUG
) System
.err
.println("##### PipedConnection.receive - bytes:" + aData
.length
+ " at:" + _out
);
113 while(bytesWritten
< aData
.length
) {
114 // wait until it is not full anymore
115 while(_out
== (_in
- 1) || (_in
== 0 && _out
== _buffer
.length
- 1)) {
117 notify(); // the buffer is full, signal it
121 catch(InterruptedException interruptedException
) {
122 throw new com
.sun
.star
.io
.IOException(interruptedException
);
126 if(_closed
) throw new com
.sun
.star
.io
.IOException("connection has been closed");
131 bytes
= Math
.min(aData
.length
- bytesWritten
, _in
- _out
- 1);
133 System
.arraycopy(aData
, bytesWritten
, _buffer
, _out
, bytes
);
137 bytes
= Math
.min(aData
.length
- bytesWritten
, _buffer
.length
- _out
);
140 bytes
= Math
.min(aData
.length
- bytesWritten
, _buffer
.length
- _out
- 1);
143 System
.arraycopy(aData
, bytesWritten
, _buffer
, _out
, bytes
);
146 bytesWritten
+= bytes
;
148 if(_out
>= _buffer
.length
)
154 * Read the required number of bytes.
156 * @param aReadBytes the out parameter, where the bytes have to be placed.
157 * @param nBytesToRead the number of bytes to read.
158 * @return the number of bytes read.
160 * @see com.sun.star.connection.XConnection#read
162 public synchronized int read(/*OUT*/byte[][] aReadBytes
, int nBytesToRead
) throws com
.sun
.star
.io
.IOException
, com
.sun
.star
.uno
.RuntimeException
{
163 aReadBytes
[0] = new byte[nBytesToRead
];
165 if(DEBUG
) System
.err
.println("##### PipedConnection.read - bytes:" + nBytesToRead
+ " at:" + _in
);
167 // loop while not all bytes read or when closed but there is still data
168 while(nBytesToRead
> 0 && (_in
!= _out
|| !_closed
)) {
169 while(_in
== _out
&& !_closed
) {
171 notify(); // the buffer is empty, signal it
173 wait(__waitTime
); // we wait for data or for the pipe to be closed
175 catch(InterruptedException interruptedException
) {
176 throw new com
.sun
.star
.io
.IOException(interruptedException
);
181 int bytes
= Math
.min(nBytesToRead
, _out
- _in
);
183 System
.arraycopy(_buffer
, _in
, aReadBytes
[0], aReadBytes
[0].length
- nBytesToRead
, bytes
);
185 nBytesToRead
-= bytes
;
188 else if(_in
> _out
) {
189 int bytes
= Math
.min(nBytesToRead
, _buffer
.length
- _in
);
191 System
.arraycopy(_buffer
, _in
, aReadBytes
[0], aReadBytes
[0].length
- nBytesToRead
, bytes
);
193 nBytesToRead
-= bytes
;
195 if(_in
>= _buffer
.length
)
200 if(nBytesToRead
> 0) { // not all bytes read
201 byte tmp
[] = new byte[aReadBytes
[0].length
- nBytesToRead
];
202 System
.arraycopy(aReadBytes
[0], 0, tmp
, 0, tmp
.length
);
207 return aReadBytes
[0].length
;
213 * @param aData the bytes to write.
214 * @see com.sun.star.connection.XConnection#write
216 public void write(byte aData
[]) throws com
.sun
.star
.io
.IOException
, com
.sun
.star
.uno
.RuntimeException
{
217 _otherSide
.receive(aData
);
221 * Flushes the buffer, notifies if necessary the other side that new data has
224 * @see com.sun.star.connection.XConnection#flush
226 public void flush() throws com
.sun
.star
.io
.IOException
, com
.sun
.star
.uno
.RuntimeException
{
227 synchronized(_otherSide
) {
235 * @see com.sun.star.connection.XConnection#close()
237 public synchronized void close() throws com
.sun
.star
.io
.IOException
, com
.sun
.star
.uno
.RuntimeException
{
248 * Gives a description of this pipe.
250 * @return the description.
251 * @see com.sun.star.connection.XConnection#getDescription
253 public String
getDescription() throws com
.sun
.star
.uno
.RuntimeException
{
254 return getClass().getName();
259 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */