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 package com.sun.star.lib.connections.socket;
28 
29 
30 import java.io.BufferedInputStream;
31 import java.io.BufferedOutputStream;
32 import java.io.InputStream;
33 import java.io.IOException;
34 import java.io.OutputStream;
35 
36 import java.net.Socket;
37 
38 import java.util.Enumeration;
39 import java.util.Vector;
40 
41 
42 import com.sun.star.io.XStreamListener;
43 
44 import com.sun.star.connection.XConnection;
45 import com.sun.star.connection.XConnectionBroadcaster;
46 
47 /**
48  * The SocketConnection implements the <code>XConnection</code> interface
49  * and is uses by the <code>SocketConnector</code> and the <code>SocketAcceptor</code>.
50  * This class is not part of the provided <code>api</code>.
51  * <p>
52  * @version 	$Revision: 1.6 $ $ $Date: 2008-04-11 11:14:31 $
53  * @author 	    Kay Ramme
54  * @see         com.sun.star.comp.connections.SocketAcceptor
55  * @see         com.sun.star.comp.connections.SocketConnector
56  * @see         com.sun.star.connections.XConnection
57  * @since       UDK1.0
58  */
59 public class SocketConnection implements XConnection, XConnectionBroadcaster {
60 	/**
61 	 * When set to true, enables various debugging output.
62 	 */
63 	static public final boolean DEBUG = false;
64 
65 	protected String       _description;
66 	protected Socket       _socket;
67 	protected InputStream  _inputStream;
68 	protected OutputStream _outputStream;
69 	protected Vector       _listeners;
70 	protected boolean      _firstRead;
71 
72 	/**
73 	 * Constructs a new <code>SocketConnection</code>.
74 	 * <p>
75 	 * @param  description   the description of the connection
76 	 * @param  socket        the socket of the connection
77 	 */
78 	public SocketConnection(String description, Socket socket) throws IOException {
79 		if (DEBUG) System.err.println("##### " + getClass().getName() + " - instantiated " + description + " " + socket);
80 
81 		_description = description
82 			+ ",localHost=" + socket.getLocalAddress().getHostName()
83 			+ ",localPort=" + socket.getLocalPort()
84 			+ ",peerHost=" + socket.getInetAddress().getHostName()
85 			+ ",peerPort=" + socket.getPort();
86 
87 		_socket = socket;
88 		_inputStream = new BufferedInputStream(socket.getInputStream());
89 		_outputStream = new BufferedOutputStream(socket.getOutputStream());
90 
91 		_listeners = new Vector();
92 		_firstRead = true;
93 	}
94 
95 
96 
97 
98     public void addStreamListener(XStreamListener aListener ) throws com.sun.star.uno.RuntimeException {
99 		_listeners.addElement(aListener);
100 	}
101 
102     public void removeStreamListener(XStreamListener aListener ) throws com.sun.star.uno.RuntimeException {
103 		_listeners.removeElement(aListener);
104 	}
105 
106 	private void notifyListeners_open() {
107 		Enumeration elements = _listeners.elements();
108 		while(elements.hasMoreElements()) {
109 			XStreamListener xStreamListener = (XStreamListener)elements.nextElement();
110 			xStreamListener.started();
111 		}
112 	}
113 
114 	private void notifyListeners_close() {
115 		Enumeration elements = _listeners.elements();
116 		while(elements.hasMoreElements()) {
117 			XStreamListener xStreamListener = (XStreamListener)elements.nextElement();
118 			xStreamListener.closed();
119 		}
120 	}
121 
122 	private void notifyListeners_error(com.sun.star.uno.Exception exception) {
123 		Enumeration elements = _listeners.elements();
124 		while(elements.hasMoreElements()) {
125 			XStreamListener xStreamListener = (XStreamListener)elements.nextElement();
126 			xStreamListener.error(exception);
127 		}
128 	}
129 
130 
131 	/**
132 	 * Read the required number of bytes.
133 	 * <p>
134 	 * @return   the number of bytes read
135 	 * @param    aReadBytes   the outparameter, where the bytes have to be placed
136 	 * @param    nBytesToRead the number of bytes to read
137      * @see       com.sun.star.connections.XConnection#read
138 	 */
139     public int read(/*OUT*/byte[][] bytes, int nBytesToRead) throws com.sun.star.io.IOException, com.sun.star.uno.RuntimeException {
140 		if(_firstRead) {
141 			_firstRead = false;
142 
143 			notifyListeners_open();
144 		}
145 
146 		String errMessage = null;
147 
148 		int read_bytes = 0;
149 		bytes[0] = new byte[nBytesToRead];
150 
151 		try {
152 			int count  ;
153 
154 			do {
155 				count = _inputStream.read(bytes[0], read_bytes, nBytesToRead - read_bytes);
156 				if(count == -1)
157 					errMessage = "EOF reached - " + getDescription();
158 
159 				read_bytes += count;
160 			}
161 			while(read_bytes >= 0 && read_bytes < nBytesToRead && count >= 0);
162 		}
163 		catch(IOException ioException) {
164 			if(DEBUG) {
165 				System.err.println("##### " + getClass().getName() + ".read - exception occurred:" + ioException);
166 				ioException.printStackTrace();
167 			}
168 
169 			errMessage = ioException.toString();
170 		}
171 
172 		if(errMessage != null) {
173 			com.sun.star.io.IOException unoIOException = new com.sun.star.io.IOException(errMessage);
174 			notifyListeners_error(unoIOException);
175 
176 			throw unoIOException;
177 		}
178 
179 		if (DEBUG) System.err.println("##### " + getClass().getName() + " - read byte:" + read_bytes + " " + bytes[0]);
180 
181 		return read_bytes;
182 	}
183 
184 	/**
185 	 * Write bytes.
186 	 * <p>
187 	 * @param    aData the bytes to write
188      * @see       com.sun.star.connections.XConnection#write
189 	 */
190     public void write(byte aData[]) throws com.sun.star.io.IOException, com.sun.star.uno.RuntimeException {
191 		try {
192 			_outputStream.write(aData);
193 		}
194 		catch(IOException ioException) {
195 			com.sun.star.io.IOException unoIOException = new com.sun.star.io.IOException(ioException.toString());
196 			notifyListeners_error(unoIOException);
197 
198 			throw unoIOException;
199 		}
200 
201 		if (DEBUG) System.err.println("##### " + getClass().getName() + " - written bytes:" + aData + " " + aData.length);
202 	}
203 
204 	/**
205 	 * Flushes the buffer.
206 	 * <p>
207      * @see       com.sun.star.connections.XConnection#flush
208 	 */
209     public void flush() throws com.sun.star.io.IOException, com.sun.star.uno.RuntimeException {
210 		try {
211 			_outputStream.flush();
212 		}
213 		catch(IOException ioException) {
214 			com.sun.star.io.IOException unoIOException = new com.sun.star.io.IOException(ioException.toString());
215 			notifyListeners_error(unoIOException);
216 
217 			throw unoIOException;
218 		}
219 	}
220 
221 	/**
222 	 * Closes the connection.
223 	 * <p>
224      * @see       com.sun.star.connections.XConnection#close
225 	 */
226     public void close() throws com.sun.star.io.IOException, com.sun.star.uno.RuntimeException {
227 		try {
228 			_socket.close();
229 		}
230 		catch(IOException ioException) {
231 			com.sun.star.io.IOException unoIOException = new com.sun.star.io.IOException(ioException.toString());
232 			notifyListeners_error(unoIOException);
233 
234 			throw unoIOException;
235 		}
236 		if (DEBUG) System.err.println("##### " + getClass().getName() + " - socket closed");
237 
238 		notifyListeners_close();
239 	}
240 
241 	/**
242 	 * Gives a description of the connection.
243 	 * <p>
244 	 * @return  the description
245      * @see       com.sun.star.connections.XConnection#getDescription
246 	 */
247 	public String getDescription() throws com.sun.star.uno.RuntimeException {
248 		return _description;
249 	}
250 
251 }
252 
253