diff options
Diffstat (limited to 'ridljar/com/sun/star/lib/connections')
7 files changed, 1167 insertions, 0 deletions
diff --git a/ridljar/com/sun/star/lib/connections/pipe/PipeConnection.java b/ridljar/com/sun/star/lib/connections/pipe/PipeConnection.java new file mode 100644 index 000000000..b3a686f17 --- /dev/null +++ b/ridljar/com/sun/star/lib/connections/pipe/PipeConnection.java @@ -0,0 +1,213 @@ +/* -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +package com.sun.star.lib.connections.pipe; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.StringTokenizer; + +import com.sun.star.connection.XConnection; +import com.sun.star.connection.XConnectionBroadcaster; +import com.sun.star.io.XStreamListener; +import com.sun.star.lib.util.NativeLibraryLoader; + +/** + * The PipeConnection implements the <code>XConnection</code> interface + * and is uses by the <code>PipeConnector</code> and the <code>PipeAcceptor</code>. + * This class is not part of the provided <code>api</code>. + * + * The native implementation is in jurt/source/pipe/com_sun_star_lib_connections_pipe_PipeConnection.c + * + * @see com.sun.star.lib.connections.pipe.pipeAcceptor + * @see com.sun.star.lib.connections.pipe.pipeConnector + * @see com.sun.star.connection.XConnection + * @since UDK1.0 + */ +public class PipeConnection implements XConnection, XConnectionBroadcaster { + /** + * When set to true, enables various debugging output. + */ + public static final boolean DEBUG = false; + + static { + // load shared library for JNI code + NativeLibraryLoader.loadLibrary(PipeConnection.class.getClassLoader(), "jpipe"); + } + + protected String _aDescription; + protected long _nPipeHandle; + protected ArrayList<XStreamListener> _aListeners; + protected boolean _bFirstRead; + + /** + * Constructs a new <code>PipeConnection</code>. + * + * @param description the description of the connection. + */ + public PipeConnection(String description) + throws IOException + { + if (DEBUG) System.err.println("##### " + getClass().getName() + " - instantiated " + description ); + + _aListeners = new ArrayList<XStreamListener>(); + _bFirstRead = true; + + // get pipe name from pipe descriptor + String aPipeName ; + StringTokenizer aTokenizer = new StringTokenizer( description, "," ); + if ( aTokenizer.hasMoreTokens() ) { + String aConnType = aTokenizer.nextToken(); + if ( !aConnType.equals( "pipe" ) ) + throw new RuntimeException( "invalid pipe descriptor: does not start with 'pipe,'" ); + + String aPipeNameParam = aTokenizer.nextToken(); + if ( !aPipeNameParam.substring( 0, 5 ).equals( "name=" ) ) + throw new RuntimeException( "invalid pipe descriptor: no 'name=' parameter found" ); + aPipeName = aPipeNameParam.substring( 5 ); + } + else + throw new RuntimeException( "invalid or empty pipe descriptor" ); + + // create the pipe + try { + createJNI( aPipeName ); + } catch ( java.lang.Exception ex1 ) { + IOException ex2 = new IOException(); + ex2.initCause(ex1); + throw ex2; + } + } + + public void addStreamListener(XStreamListener aListener ) throws com.sun.star.uno.RuntimeException { + _aListeners.add(aListener); + } + + public void removeStreamListener(XStreamListener aListener ) throws com.sun.star.uno.RuntimeException { + _aListeners.remove(aListener); + } + + private void notifyListeners_open() { + for (XStreamListener xStreamListener : _aListeners) { + xStreamListener.started(); + } + } + + private void notifyListeners_close() { + for (XStreamListener xStreamListener : _aListeners) { + xStreamListener.closed(); + } + } + + private void notifyListeners_error(com.sun.star.uno.Exception exception) { + for (XStreamListener xStreamListener : _aListeners) { + xStreamListener.error(exception); + } + } + + // JNI implementation to create the pipe + private native int createJNI( String name ) + throws com.sun.star.io.IOException, com.sun.star.uno.RuntimeException; + + // JNI implementation to read from the pipe + private native int readJNI(/*OUT*/byte[][] bytes, int nBytesToRead) + throws com.sun.star.io.IOException, com.sun.star.uno.RuntimeException; + + // JNI implementation to write to the pipe + private native void writeJNI(byte aData[]) + throws com.sun.star.io.IOException, com.sun.star.uno.RuntimeException; + + // JNI implementation to flush the pipe + private native void flushJNI() + throws com.sun.star.io.IOException, com.sun.star.uno.RuntimeException; + + // JNI implementation to close the pipe + private native void closeJNI() + throws com.sun.star.io.IOException, com.sun.star.uno.RuntimeException; + + /** + * Read the required number of bytes. + * + * @param bytes the outparameter, where the bytes have to be placed. + * @param nBytesToRead the number of bytes to read. + * @return the number of bytes read. + * + * @see com.sun.star.connection.XConnection#read + */ + public int read(/*OUT*/byte[][] bytes, int nBytesToRead) + throws com.sun.star.io.IOException, com.sun.star.uno.RuntimeException + { + if(_bFirstRead) { + _bFirstRead = false; + + notifyListeners_open(); + } + + return readJNI( bytes, nBytesToRead ); + } + + /** + * Write bytes. + * + * @param aData the bytes to write. + * @see com.sun.star.connection.XConnection#write + */ + public void write(byte aData[]) + throws com.sun.star.io.IOException, com.sun.star.uno.RuntimeException + { + writeJNI( aData ); + } + + /** + * Flushes the buffer. + * + * @see com.sun.star.connection.XConnection#flush + */ + public void flush() + throws com.sun.star.io.IOException, com.sun.star.uno.RuntimeException + { + flushJNI(); + } + + /** + * Closes the connection. + * + * @see com.sun.star.connection.XConnection#close + */ + public void close() + throws com.sun.star.io.IOException, com.sun.star.uno.RuntimeException + { + if (DEBUG) System.out.print( "PipeConnection::close() " ); + closeJNI(); + notifyListeners_close(); + if (DEBUG) System.out.println( "done" ); + } + + /** + * Gives a description of the connection. + * + * @return the description. + * @see com.sun.star.connection.XConnection#getDescription + */ + public String getDescription() throws com.sun.star.uno.RuntimeException { + return _aDescription; + } + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/ridljar/com/sun/star/lib/connections/pipe/pipeAcceptor.java b/ridljar/com/sun/star/lib/connections/pipe/pipeAcceptor.java new file mode 100644 index 000000000..983eb3265 --- /dev/null +++ b/ridljar/com/sun/star/lib/connections/pipe/pipeAcceptor.java @@ -0,0 +1,123 @@ +/* -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +package com.sun.star.lib.connections.pipe; + +import com.sun.star.comp.loader.FactoryHelper; +import com.sun.star.connection.AlreadyAcceptingException; +import com.sun.star.connection.ConnectionSetupException; +import com.sun.star.connection.XAcceptor; +import com.sun.star.connection.XConnection; +import com.sun.star.lang.XMultiServiceFactory; +import com.sun.star.lang.XSingleServiceFactory; +import com.sun.star.registry.XRegistryKey; + +/** + * A component that implements the <code>XAcceptor</code> interface. + * + * <p>The <code>pipeAcceptor</code> is a specialized component that uses TCP + * pipes for communication. The <code>pipeAcceptor</code> is generally used + * by the <code>com.sun.star.connection.Acceptor</code> service.</p> + * + * @see com.sun.star.connection.XAcceptor + * @see com.sun.star.connection.XConnection + * @see com.sun.star.connection.XConnector + * @see com.sun.star.comp.loader.JavaLoader + * + * @since UDK 1.0 + */ +public final class pipeAcceptor implements XAcceptor { + /** + * The name of the service. + * + * <p>The <code>JavaLoader</code> accesses this through reflection.</p> + * + * @see com.sun.star.comp.loader.JavaLoader + */ + public static final String __serviceName + = "com.sun.star.connection.pipeAcceptor"; + + /** + * Returns a factory for creating the service. + * + * <p>This method is called by the <code>JavaLoader</code>.</p> + * + * @param implName the name of the implementation for which a service is + * requested. + * @param multiFactory the service manager to be used (if needed). + * @param regKey the registry key. + * @return an <code>XSingleServiceFactory</code> for creating the component. + * + * @see com.sun.star.comp.loader.JavaLoader + */ + public static XSingleServiceFactory __getServiceFactory( + String implName, XMultiServiceFactory multiFactory, XRegistryKey regKey) + { + return implName.equals(pipeAcceptor.class.getName()) + ? FactoryHelper.getServiceFactory( + pipeAcceptor.class, __serviceName, multiFactory, regKey) + : null; + } + + /** + * Accepts a connection request via the described pipe. + * + * <p>This call blocks until a connection has been established.</p> + * + * <p>The connection description has the following format: + * <code><var>type</var></code><!-- + * -->*(<code><var>key</var>=<var>value</var></code>), + * where <code><var>type</var></code> should be <code>pipe</code> + * (ignoring case). Supported keys (ignoring case) currently are</p> + * <dl> + * <dt><code>host</code> + * <dd>The name or address of the accepting interface (defaults to + * <code>0</code>, meaning any interface). + * <dt><code>port</code> + * <dd>The TCP port number to accept on (defaults to <code>6001</code>). + * <dt><code>backlog</code> + * <dd>The maximum length of the acceptor's queue (defaults to + * <code>50</code>). + * <dt><code>tcpnodelay</code> + * <dd>A flag (<code>0</code>/<code>1</code>) enabling or disabling Nagle's + * algorithm on the resulting connection. + * </dl> + * + * @param connectionDescription the description of the connection. + * @return an <code>XConnection</code> to the client. + * + * @see com.sun.star.connection.XConnection + * @see com.sun.star.connection.XConnector + */ + public XConnection accept(String connectionDescription) throws + AlreadyAcceptingException, ConnectionSetupException, + com.sun.star.lang.IllegalArgumentException + { + throw new java.lang.NoSuchMethodError( "pipeAcceptor not fully implemented yet" ); + } + + /** + * + * @see com.sun.star.connection.XAcceptor#stopAccepting + */ + public void stopAccepting() { + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/ridljar/com/sun/star/lib/connections/pipe/pipeConnector.java b/ridljar/com/sun/star/lib/connections/pipe/pipeConnector.java new file mode 100644 index 000000000..192d35007 --- /dev/null +++ b/ridljar/com/sun/star/lib/connections/pipe/pipeConnector.java @@ -0,0 +1,120 @@ +/* -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +package com.sun.star.lib.connections.pipe; + +import com.sun.star.comp.loader.FactoryHelper; +import com.sun.star.connection.ConnectionSetupException; +import com.sun.star.connection.NoConnectException; +import com.sun.star.connection.XConnection; +import com.sun.star.connection.XConnector; +import com.sun.star.lang.XMultiServiceFactory; +import com.sun.star.lang.XSingleServiceFactory; +import com.sun.star.registry.XRegistryKey; + +/** + * A component that implements the <code>XConnector</code> interface. + * + * <p>The <code>pipeConnector</code> is a specialized component that uses TCP + * pipes for communication. The <code>pipeConnector</code> is generally + * used by the <code>com.sun.star.connection.Connector</code> service.</p> + * + * @see com.sun.star.connection.XAcceptor + * @see com.sun.star.connection.XConnection + * @see com.sun.star.connection.XConnector + * @see com.sun.star.comp.loader.JavaLoader + * + * @since UDK 1.0 + */ +public final class pipeConnector implements XConnector { + /** + * The name of the service. + * + * <p>The <code>JavaLoader</code> accesses this through reflection.</p> + * + * @see com.sun.star.comp.loader.JavaLoader + */ + public static final String __serviceName = "com.sun.star.connection.pipeConnector"; + + /** + * Returns a factory for creating the service. + * + * <p>This method is called by the <code>JavaLoader</code>.</p> + * + * @param implName the name of the implementation for which a service is + * requested. + * @param multiFactory the service manager to be used (if needed). + * @param regKey the registry key. + * @return an <code>XSingleServiceFactory</code> for creating the component. + * + * @see com.sun.star.comp.loader.JavaLoader + */ + public static XSingleServiceFactory __getServiceFactory( + String implName, XMultiServiceFactory multiFactory, XRegistryKey regKey) + { + return implName.equals(pipeConnector.class.getName()) + ? FactoryHelper.getServiceFactory(pipeConnector.class, + __serviceName, multiFactory, + regKey) + : null; + } + + /** + * Connects via the described pipe to a waiting server. + * + * <p>The connection description has the following format: + * <code><var>type</var></code><!-- + * -->*(<code><var>key</var>=<var>value</var></code>), + * where <code><var>type</var></code> should be <code>pipe</code> + * (ignoring case). Supported keys (ignoring case) currently are</p> + * <dl> + * <dt><code>host</code> + * <dd>The name or address of the server. Must be present. + * <dt><code>port</code> + * <dd>The TCP port number of the server (defaults to <code>6001</code>). + * <dt><code>tcpnodelay</code> + * <dd>A flag (<code>0</code>/<code>1</code>) enabling or disabling Nagle's + * algorithm on the resulting connection. + * </dl> + * + * @param connectionDescription the description of the connection. + * @return an <code>XConnection</code> to the server. + * + * @see com.sun.star.connection.XAcceptor + * @see com.sun.star.connection.XConnection + */ + public synchronized XConnection connect(String connectionDescription) + throws NoConnectException, ConnectionSetupException + { + if (bConnected) + throw new ConnectionSetupException("already connected"); + + try { + XConnection xConn = new PipeConnection( connectionDescription ); + bConnected = true; + return xConn; + } catch ( java.io.IOException e ) { + throw new NoConnectException(e); + } + } + + private boolean bConnected = false; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/ridljar/com/sun/star/lib/connections/socket/ConnectionDescriptor.java b/ridljar/com/sun/star/lib/connections/socket/ConnectionDescriptor.java new file mode 100644 index 000000000..5a88d41ba --- /dev/null +++ b/ridljar/com/sun/star/lib/connections/socket/ConnectionDescriptor.java @@ -0,0 +1,98 @@ +/* -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +package com.sun.star.lib.connections.socket; + +/** + * Helper class for <code>socketAcceptor</code> and <code>socketConnector</code>. + * + * <p>FIXME: Once those classes have been moved from <code>jurt</code> to + * <code>javaunohelper</code>, they should use + * <code>com.sun.star.lib.uno.helper.UnoUrl</code> either instead of this class + * or underneath this class.</p> + */ +final class ConnectionDescriptor { + public ConnectionDescriptor(String description) + throws com.sun.star.lang.IllegalArgumentException { + for (int i = description.indexOf(','); i >= 0;) { + int j = description.indexOf(',', i + 1); + int k = j < 0 ? description.length() : j; + int l = description.indexOf('=', i + 1); + if (l < 0 || l >= k) { + throw new com.sun.star.lang.IllegalArgumentException( + "parameter lacks '='"); + } + String key = description.substring(i + 1, l); + String value = description.substring(l + 1, k); + if (key.equalsIgnoreCase("host")) { + host = value; + } else if (key.equalsIgnoreCase("port")) { + try { + port = Integer.parseInt(value); + } catch (NumberFormatException e) { + throw new com.sun.star.lang.IllegalArgumentException(e); + } + if (port < 0 || port > 65535) { + throw new com.sun.star.lang.IllegalArgumentException( + "port parameter must have value between 0 and 65535," + + " inclusive"); + } + } else if (key.equalsIgnoreCase("backlog")) { + try { + backlog = Integer.parseInt(value); + } catch (NumberFormatException e) { + throw new com.sun.star.lang.IllegalArgumentException(e); + } + } else if (key.equalsIgnoreCase("tcpnodelay")) { + if (value.equals("0")) { + tcpNoDelay = Boolean.FALSE; + } else if (value.equals("1")) { + tcpNoDelay = Boolean.TRUE; + } else { + throw new com.sun.star.lang.IllegalArgumentException( + "tcpnodelay parameter must have 0/1 value"); + } + } + i = j; + } + } + + public String getHost() { + return host; + } + + public int getPort() { + return port; + } + + public int getBacklog() { + return backlog; + } + + public Boolean getTcpNoDelay() { + return tcpNoDelay; + } + + private String host = null; + private int port = 6001; + private int backlog = 50; + private Boolean tcpNoDelay = null; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/ridljar/com/sun/star/lib/connections/socket/SocketConnection.java b/ridljar/com/sun/star/lib/connections/socket/SocketConnection.java new file mode 100644 index 000000000..a906496f2 --- /dev/null +++ b/ridljar/com/sun/star/lib/connections/socket/SocketConnection.java @@ -0,0 +1,235 @@ +/* -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +package com.sun.star.lib.connections.socket; + + +import java.io.BufferedInputStream; +import java.io.BufferedOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + +import java.net.Socket; + +import java.util.ArrayList; +import java.util.Arrays; + +import com.sun.star.connection.XConnection; +import com.sun.star.connection.XConnectionBroadcaster; +import com.sun.star.io.XStreamListener; + +/** + * The SocketConnection implements the <code>XConnection</code> interface + * and is uses by the <code>SocketConnector</code> and the <code>SocketAcceptor</code>. + * + * <p>This class is not part of the provided <code>api</code>.</p> + * + * @see com.sun.star.lib.connections.socket.socketAcceptor + * @see com.sun.star.lib.connections.socket.socketConnector + * @see com.sun.star.connection.XConnection + * @since UDK1.0 + */ +public class SocketConnection implements XConnection, XConnectionBroadcaster { + /** + * When set to true, enables various debugging output. + */ + public static final boolean DEBUG = false; + + protected String _description; + protected Socket _socket; + protected InputStream _inputStream; + protected OutputStream _outputStream; + protected ArrayList<XStreamListener> _listeners; + protected boolean _firstRead; + + /** + * Constructs a new <code>SocketConnection</code>. + * + * @param description the description of the connection. + * @param socket the socket of the connection. + */ + public SocketConnection(String description, Socket socket) throws IOException { + if (DEBUG) System.err.println("##### " + getClass().getName() + " - instantiated " + description + " " + socket); + + _description = description + + ",localHost=" + socket.getLocalAddress().getHostName() + + ",localPort=" + socket.getLocalPort() + + ",peerHost=" + socket.getInetAddress().getHostName() + + ",peerPort=" + socket.getPort(); + + _socket = socket; + _inputStream = new BufferedInputStream(socket.getInputStream()); + _outputStream = new BufferedOutputStream(socket.getOutputStream()); + + _listeners = new ArrayList<XStreamListener>(); + _firstRead = true; + } + + public void addStreamListener(XStreamListener aListener ) + throws com.sun.star.uno.RuntimeException { + _listeners.add(aListener); + } + + public void removeStreamListener(XStreamListener aListener ) + throws com.sun.star.uno.RuntimeException { + _listeners.remove(aListener); + } + + private void notifyListeners_open() { + for (XStreamListener xStreamListener : _listeners) { + xStreamListener.started(); + } + } + + private void notifyListeners_close() { + for (XStreamListener xStreamListener : _listeners) { + xStreamListener.closed(); + } + } + + private void notifyListeners_error(com.sun.star.uno.Exception exception) { + for (XStreamListener xStreamListener : _listeners) { + xStreamListener.error(exception); + } + } + + /** + * Read the required number of bytes. + * + * @param bytes the outparameter, where the bytes have to be placed. + * @param nBytesToRead the number of bytes to read. + * @return the number of bytes read. + * + * @see com.sun.star.connection.XConnection#read + */ + public int read(/*OUT*/byte[][] bytes, int nBytesToRead) + throws com.sun.star.io.IOException, com.sun.star.uno.RuntimeException { + if(_firstRead) { + _firstRead = false; + + notifyListeners_open(); + } + + String errMessage = null; + + int read_bytes = 0; + bytes[0] = new byte[nBytesToRead]; + + try { + int count ; + + do { + count = _inputStream.read(bytes[0], read_bytes, nBytesToRead - read_bytes); + if(count == -1) + errMessage = "EOF reached - " + getDescription(); + + read_bytes += count; + } + while(read_bytes >= 0 && read_bytes < nBytesToRead && count >= 0); + } catch(IOException ioException) { + if(DEBUG) { + System.err.println("##### " + getClass().getName() + ".read - exception occurred:" + ioException); + ioException.printStackTrace(); + } + + errMessage = ioException.toString(); + } + + if(errMessage != null) { + com.sun.star.io.IOException unoIOException = new com.sun.star.io.IOException(errMessage); + notifyListeners_error(unoIOException); + + throw unoIOException; + } + + if (DEBUG) System.err.println("##### " + getClass().getName() + " - read byte:" + read_bytes + " " + Arrays.toString(bytes[0])); + + return read_bytes; + } + + /** + * Write bytes. + * + * @param aData the bytes to write. + * @see com.sun.star.connection.XConnection#write + */ + public void write(byte aData[]) throws com.sun.star.io.IOException, + com.sun.star.uno.RuntimeException { + try { + _outputStream.write(aData); + } catch(IOException ioException) { + com.sun.star.io.IOException unoIOException = new com.sun.star.io.IOException(ioException); + notifyListeners_error(unoIOException); + + throw unoIOException; + } + + if (DEBUG) System.err.println("##### " + getClass().getName() + " - written bytes:" + Arrays.toString(aData) + " " + aData.length); + } + + /** + * Flushes the buffer. + * + * @see com.sun.star.connection.XConnection#flush + */ + public void flush() throws com.sun.star.io.IOException, + com.sun.star.uno.RuntimeException { + try { + _outputStream.flush(); + } catch(IOException ioException) { + com.sun.star.io.IOException unoIOException = new com.sun.star.io.IOException(ioException); + notifyListeners_error(unoIOException); + + throw unoIOException; + } + } + + /** + * Closes the connection. + * + * @see com.sun.star.connection.XConnection#close + */ + public void close() throws com.sun.star.io.IOException, + com.sun.star.uno.RuntimeException { + try { + _socket.close(); + } catch(IOException ioException) { + com.sun.star.io.IOException unoIOException = new com.sun.star.io.IOException(ioException); + notifyListeners_error(unoIOException); + + throw unoIOException; + } + if (DEBUG) System.err.println("##### " + getClass().getName() + " - socket closed"); + + notifyListeners_close(); + } + + /** + * Gives a description of the connection. + * + * @return the description. + * @see com.sun.star.connection.XConnection#getDescription + */ + public String getDescription() throws com.sun.star.uno.RuntimeException { + return _description; + } + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/ridljar/com/sun/star/lib/connections/socket/socketAcceptor.java b/ridljar/com/sun/star/lib/connections/socket/socketAcceptor.java new file mode 100644 index 000000000..4000a1d0a --- /dev/null +++ b/ridljar/com/sun/star/lib/connections/socket/socketAcceptor.java @@ -0,0 +1,202 @@ +/* -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +package com.sun.star.lib.connections.socket; + +import com.sun.star.comp.loader.FactoryHelper; +import com.sun.star.connection.AlreadyAcceptingException; +import com.sun.star.connection.ConnectionSetupException; +import com.sun.star.connection.XAcceptor; +import com.sun.star.connection.XConnection; +import com.sun.star.lang.XMultiServiceFactory; +import com.sun.star.lang.XSingleServiceFactory; +import com.sun.star.registry.XRegistryKey; + +import java.io.IOException; +import java.net.*; + +/** + * A component that implements the <code>XAcceptor</code> interface. + * + * <p>The <code>socketAcceptor</code> is a specialized component that uses TCP + * sockets for communication. The <code>socketAcceptor</code> is generally used + * by the <code>com.sun.star.connection.Acceptor</code> service.</p> + * + * @see com.sun.star.connection.XAcceptor + * @see com.sun.star.connection.XConnection2 + * @see com.sun.star.connection.XConnector + * @see com.sun.star.comp.loader.JavaLoader + * + * @since UDK 1.0 + */ +public final class socketAcceptor implements XAcceptor { + /** + * The name of the service. + * + * <p>The <code>JavaLoader</code> accesses this through reflection.</p> + * + * @see com.sun.star.comp.loader.JavaLoader + */ + public static final String __serviceName + = "com.sun.star.connection.socketAcceptor"; + + /** + * Returns a factory for creating the service. + * + * <p>This method is called by the <code>JavaLoader</code>.</p> + * + * @param implName the name of the implementation for which a service is + * requested. + * @param multiFactory the service manager to be used (if needed). + * @param regKey the registry key. + * @return an <code>XSingleServiceFactory</code> for creating the component. + * + * @see com.sun.star.comp.loader.JavaLoader + */ + public static XSingleServiceFactory __getServiceFactory( + String implName, XMultiServiceFactory multiFactory, XRegistryKey regKey) + { + return implName.equals(socketAcceptor.class.getName()) + ? FactoryHelper.getServiceFactory(socketAcceptor.class, + __serviceName, multiFactory, + regKey) + : null; + } + + /** + * Accepts a connection request via the described socket. + * + * <p>This call blocks until a connection has been established.</p> + * + * <p>The connection description has the following format: + * <code><var>type</var></code><!-- + * -->*(<code><var>key</var>=<var>value</var></code>), + * where <code><var>type</var></code> should be <code>socket</code> + * (ignoring case). Supported keys (ignoring case) currently are</p> + * <dl> + * <dt><code>host</code> + * <dd>The name or address of the accepting interface (defaults to + * <code>0</code>, meaning any interface). + * <dt><code>port</code> + * <dd>The TCP port number to accept on (defaults to <code>6001</code>). + * <dt><code>backlog</code> + * <dd>The maximum length of the acceptor's queue (defaults to + * <code>50</code>). + * <dt><code>tcpnodelay</code> + * <dd>A flag (<code>0</code>/<code>1</code>) enabling or disabling Nagle's + * algorithm on the resulting connection. + * </dl> + * + * @param connectionDescription the description of the connection. + * @return an <code>XConnection</code> to the client. + * + * @see com.sun.star.connection.XConnection + * @see com.sun.star.connection.XConnector + */ + public XConnection accept(String connectionDescription) throws + AlreadyAcceptingException, ConnectionSetupException, + com.sun.star.lang.IllegalArgumentException + { + ServerSocket serv; + synchronized (this) { + if (server == null) { + ConnectionDescriptor desc + = new ConnectionDescriptor(connectionDescription); + String host = desc.getHost(); + if (host.equals("0")) { + host = null; + } + if (DEBUG) { + System.err.println("##### " + getClass().getName() + + ".accept: creating ServerSocket " + + desc.getPort() + ", " + + desc.getBacklog() + ", " + host); + } + try { + server = new ServerSocket(desc.getPort(), desc.getBacklog(), + host == null ? null + : InetAddress.getByName(host)); + } catch (IOException e) { + throw new ConnectionSetupException(e); + } + acceptingDescription = connectionDescription; + tcpNoDelay = desc.getTcpNoDelay(); + } else if (!connectionDescription.equals(acceptingDescription)) { + throw new AlreadyAcceptingException(acceptingDescription + + " vs. " + + connectionDescription); + } + serv = server; + } + Socket socket = null; + try { + socket = serv.accept(); + if (DEBUG) { + System.err.println("##### " + getClass().getName() + + ".accept: accepted " + socket); + } + // we enable tcpNoDelay for loopback connections because + // it can make a significant speed difference on linux boxes. + if (tcpNoDelay != null) { + socket.setTcpNoDelay(tcpNoDelay.booleanValue()); + } + else { + InetSocketAddress address = (InetSocketAddress)socket.getRemoteSocketAddress(); + if (address != null && address.getAddress().isLoopbackAddress()) { + socket.setTcpNoDelay(true); + } + } + return new SocketConnection(acceptingDescription, socket); + } + catch(IOException e) { + if (socket != null) { + try { + socket.close(); + } catch(IOException ioException) { + } + } + throw new ConnectionSetupException(e); + } + } + + /** + * + * @see com.sun.star.connection.XAcceptor#stopAccepting + */ + public void stopAccepting() { + ServerSocket serv; + synchronized (this) { + serv = server; + } + try { + serv.close(); + } + catch (IOException e) { + throw new com.sun.star.uno.RuntimeException(e); + } + } + + private static final boolean DEBUG = false; + + private ServerSocket server = null; + private String acceptingDescription; + private Boolean tcpNoDelay; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/ridljar/com/sun/star/lib/connections/socket/socketConnector.java b/ridljar/com/sun/star/lib/connections/socket/socketConnector.java new file mode 100644 index 000000000..484ffd135 --- /dev/null +++ b/ridljar/com/sun/star/lib/connections/socket/socketConnector.java @@ -0,0 +1,176 @@ +/* -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +package com.sun.star.lib.connections.socket; + +import com.sun.star.comp.loader.FactoryHelper; +import com.sun.star.connection.ConnectionSetupException; +import com.sun.star.connection.NoConnectException; +import com.sun.star.connection.XConnection; +import com.sun.star.connection.XConnector; +import com.sun.star.lang.XMultiServiceFactory; +import com.sun.star.lang.XSingleServiceFactory; +import com.sun.star.registry.XRegistryKey; + +import java.io.IOException; +import java.net.InetAddress; +import java.net.Socket; +import java.net.UnknownHostException; + +/** + * A component that implements the <code>XConnector</code> interface. + * + * <p>The <code>socketConnector</code> is a specialized component that uses TCP + * sockets for communication. The <code>socketConnector</code> is generally + * used by the <code>com.sun.star.connection.Connector</code> service.</p> + * + * @see com.sun.star.connection.XAcceptor + * @see com.sun.star.connection.XConnection + * @see com.sun.star.connection.XConnector + * @see com.sun.star.comp.loader.JavaLoader + * + * @since UDK 1.0 + */ +public final class socketConnector implements XConnector { + /** + * The name of the service. + * + * <p>The <code>JavaLoader</code> accesses this through reflection.</p> + * + * @see com.sun.star.comp.loader.JavaLoader + */ + public static final String __serviceName + = "com.sun.star.connection.socketConnector"; + + /** + * Returns a factory for creating the service. + * + * <p>This method is called by the <code>JavaLoader</code>.</p> + * + * @param implName the name of the implementation for which a service is + * requested. + * @param multiFactory the service manager to be used (if needed). + * @param regKey the registry key. + * @return an <code>XSingleServiceFactory</code> for creating the component. + * + * @see com.sun.star.comp.loader.JavaLoader + */ + public static XSingleServiceFactory __getServiceFactory( + String implName, XMultiServiceFactory multiFactory, XRegistryKey regKey) + { + return implName.equals(socketConnector.class.getName()) + ? FactoryHelper.getServiceFactory(socketConnector.class, + __serviceName, multiFactory, + regKey) + : null; + } + + /** + * Connects via the described socket to a waiting server. + * + * <p>The connection description has the following format: + * <code><var>type</var></code><!-- + * -->*(<code><var>key</var>=<var>value</var></code>), + * where <code><var>type</var></code> should be <code>socket</code> + * (ignoring case). Supported keys (ignoring case) currently are</p> + * <dl> + * <dt><code>host</code> + * <dd>The name or address of the server. Must be present. + * <dt><code>port</code> + * <dd>The TCP port number of the server (defaults to <code>6001</code>). + * <dt><code>tcpnodelay</code> + * <dd>A flag (<code>0</code>/<code>1</code>) enabling or disabling Nagle's + * algorithm on the resulting connection. + * </dl> + * + * @param connectionDescription the description of the connection. + * @return an <code>XConnection</code> to the server. + * + * @see com.sun.star.connection.XAcceptor + * @see com.sun.star.connection.XConnection + */ + public synchronized XConnection connect(String connectionDescription) + throws NoConnectException, ConnectionSetupException + { + if (connected) + throw new ConnectionSetupException("already connected"); + + ConnectionDescriptor desc; + try { + desc = new ConnectionDescriptor(connectionDescription); + } catch (com.sun.star.lang.IllegalArgumentException e) { + throw new ConnectionSetupException(e); + } + + if (desc.getHost() == null) + throw new ConnectionSetupException("host parameter missing"); + // Try all (IPv4 and IPv6) addresses, in case this client is on a + // dual-stack host and the server process is an IPv4-only process, also + // on a dual-stack host (see Stevens, Fenner, Rudoff: "Unix Network + // Programming, Volume 1: The Sockets Networking API, 3rd Edition", + // p. 359): + InetAddress[] adr; + try { + adr = InetAddress.getAllByName(desc.getHost()); + } catch (UnknownHostException e) { + throw new ConnectionSetupException(e); + } + Socket socket = null; + boolean isLoopbackAddress = false; + for (int i = 0; i < adr.length; ++i) { + try { + isLoopbackAddress = adr[i].isLoopbackAddress(); + socket = new Socket(adr[i], desc.getPort()); + break; + } catch (IOException e) { + if (i == adr.length - 1) + throw new NoConnectException(e); + } + } + + if (socket == null) + throw new ConnectionSetupException("no socket"); + + XConnection con; + try { + // we enable tcpNoDelay for loopback connections because + // it can make a significant speed difference on linux boxes. + if (desc.getTcpNoDelay() != null) + socket.setTcpNoDelay(desc.getTcpNoDelay().booleanValue()); + else if (isLoopbackAddress) + socket.setTcpNoDelay(true); + + con = new SocketConnection(connectionDescription, socket); + } catch (IOException e) { + if (socket != null) { + try { + socket.close(); + } catch(IOException ioException) { + } + } + throw new NoConnectException(e); + } + connected = true; + return con; + } + + private boolean connected = false; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |