org.asteriskjava.util.internal.SocketConnectionFacadeImpl Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of asterisk-java Show documentation
Show all versions of asterisk-java Show documentation
The free Java library for Asterisk PBX integration.
/*
* Copyright 2004-2006 Stefan Reuter
*
* Licensed 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
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package org.asteriskjava.util.internal;
import org.asteriskjava.util.SocketConnectionFacade;
import org.asteriskjava.util.internal.streamreader.FastScanner;
import org.asteriskjava.util.internal.streamreader.FastScannerFactory;
import javax.net.SocketFactory;
import javax.net.ssl.SSLSocketFactory;
import java.io.*;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.NoSuchElementException;
import java.util.regex.Pattern;
/**
* Default implementation of the SocketConnectionFacade interface using java.io.
*
* @author srt
* @version $Id$
*/
public class SocketConnectionFacadeImpl implements SocketConnectionFacade {
public static final Pattern CRNL_PATTERN = Pattern.compile("\r\n");
public static final Pattern NL_PATTERN = Pattern.compile("\n");
private Socket socket;
private FastScanner scanner;
private BufferedWriter writer;
private Trace trace;
/**
* Creates a new instance for use with the Manager API that uses UTF-8
* as the encoding and CRLF ("\r\n") as line delimiter.
*
* @param host the foreign host to connect to.
* @param port the foreign port to connect to.
* @param ssl true
to use SSL, false
otherwise.
* @param timeout 0 incidcates default
* @param readTimeout see {@link Socket#setSoTimeout(int)}
* @throws IOException if the connection cannot be established.
*/
public SocketConnectionFacadeImpl(String host, int port, boolean ssl, int timeout, int readTimeout) throws IOException {
this(host, port, ssl, timeout, readTimeout, StandardCharsets.UTF_8, CRNL_PATTERN);
}
/**
* Creates a new instance for use with the Manager API that uses the given
* encoding and CRLF ("\r\n") as line delimiter.
*
* @param host the foreign host to connect to.
* @param port the foreign port to connect to.
* @param ssl true
to use SSL, false
otherwise.
* @param timeout 0 incidcates default
* @param readTimeout see {@link Socket#setSoTimeout(int)}
* @param encoding the encoding used for transmission of strings (all
* connections should use the same encoding)
* @throws IOException if the connection cannot be established.
*/
public SocketConnectionFacadeImpl(String host, int port, boolean ssl, int timeout, int readTimeout, Charset encoding)
throws IOException {
this(host, port, ssl, timeout, readTimeout, encoding, CRNL_PATTERN);
}
/**
* Creates a new instance for use with the Manager API that uses UTF-8 as
* encoding and the given line delimiter.
*
* @param host the foreign host to connect to.
* @param port the foreign port to connect to.
* @param ssl true
to use SSL, false
otherwise.
* @param timeout 0 incidcates default
* @param readTimeout see {@link Socket#setSoTimeout(int)}
* @param lineDelimiter a {@link Pattern} for matching the line delimiter
* for the socket
* @throws IOException if the connection cannot be established.
*/
public SocketConnectionFacadeImpl(String host, int port, boolean ssl, int timeout, int readTimeout,
Pattern lineDelimiter) throws IOException {
this(host, port, ssl, timeout, readTimeout, StandardCharsets.UTF_8, lineDelimiter);
}
/**
* Creates a new instance for use with the Manager API that uses the given
* encoding and line delimiter.
*
* @param host the foreign host to connect to.
* @param port the foreign port to connect to.
* @param ssl true
to use SSL, false
otherwise.
* @param timeout 0 incidcates default
* @param readTimeout see {@link Socket#setSoTimeout(int)}
* @param encoding the encoding used for transmission of strings (all
* connections should use the same encoding)
* @param lineDelimiter a {@link Pattern} for matching the line delimiter
* for the socket
* @throws IOException if the connection cannot be established.
*/
public SocketConnectionFacadeImpl(String host, int port, boolean ssl, int timeout, int readTimeout, Charset encoding,
Pattern lineDelimiter) throws IOException {
Socket socket;
if (ssl) {
socket = SSLSocketFactory.getDefault().createSocket();
} else {
socket = SocketFactory.getDefault().createSocket();
}
socket.setSoTimeout(readTimeout);
socket.connect(new InetSocketAddress(host, port), timeout);
initialize(socket, encoding, lineDelimiter);
if (System.getProperty(Trace.TRACE_PROPERTY, "false").equalsIgnoreCase("true")) {
trace = new FileTrace(socket);
}
}
/**
* Creates a new instance for use with FastAGI that uses NL ("\n") as line
* delimiter.
*
* @param socket the underlying socket.
* @throws IOException if the connection cannot be initialized.
*/
SocketConnectionFacadeImpl(Socket socket) throws IOException {
this(socket, MAX_SOCKET_READ_TIMEOUT_MILLIS);
}
/**
* Creates a new instance for use with FastAGI that uses NL ("\n") as line delimiter.
*
* @param socket the underlying socket.
* @param timeout 0 indicates default, -1 indicates infinite timeout (not recommended)
* @throws IOException if the connection cannot be initialized.
*/
SocketConnectionFacadeImpl(Socket socket, int timeout) throws IOException {
if (timeout == -1) {
timeout = 0;
} else if (timeout == 0) {
timeout = MAX_SOCKET_READ_TIMEOUT_MILLIS;
}
socket.setSoTimeout(timeout);
initialize(socket, StandardCharsets.UTF_8, NL_PATTERN);
}
/**
* 3 hrs = 3 * 3660 * 1000
*/
public static final int MAX_SOCKET_READ_TIMEOUT_MILLIS = 10800000;
private void initialize(Socket socket, Charset encoding, Pattern pattern) throws IOException {
this.socket = socket;
InputStream inputStream = socket.getInputStream();
OutputStream outputStream = socket.getOutputStream();
InputStreamReader reader = new InputStreamReader(inputStream, encoding);
this.scanner = FastScannerFactory.getReader(reader, pattern);
// this.scanner.useDelimiter(pattern);
this.writer = new BufferedWriter(new OutputStreamWriter(outputStream, encoding));
}
@Override
public String readLine() throws IOException {
String line = null;
try {
line = scanner.next();
} catch (IllegalStateException e) {
// throw new IOException("No more lines available", e); // JDK6
throw new IOException("No more lines available: " + e.getMessage());
} catch (NoSuchElementException e) {
// throw new IOException("No more lines available", e); // JDK6
throw new IOException("No more lines available: " + e.getMessage());
}
if (trace != null) {
trace.received(line);
}
return line;
}
public void write(String s) throws IOException {
writer.write(s);
if (trace != null) {
trace.sent(s);
}
}
public void flush() throws IOException {
writer.flush();
}
public void close() throws IOException {
socket.close();
scanner.close();
// close the trace only if it was activated (the object is not null)
if (trace != null) {
trace.close();
}
}
public boolean isConnected() {
return socket.isConnected();
}
public InetAddress getLocalAddress() {
return socket.getLocalAddress();
}
public int getLocalPort() {
return socket.getLocalPort();
}
public InetAddress getRemoteAddress() {
return socket.getInetAddress();
}
public int getRemotePort() {
return socket.getPort();
}
}