blob: fcbb3b570c7dea8d4e7c5809a184dcba987937c4 [file] [log] [blame]
/*
* This file is part of the QuickServer library
* Copyright (C) QuickServer.org
*
* Use, modification, copying and distribution of this software is subject to
* the terms and conditions of the GNU Lesser General Public License.
* You should have received a copy of the GNU LGP License along with this
* library; if not, you can download a copy from <http://www.quickserver.org/>.
*
* For questions, suggestions, bug-reports, enhancement-requests etc.
* visit http://www.quickserver.org
*
*/
package org.quickserver.net.client;
import java.io.*;
import java.net.*;
import java.security.KeyStore;
import java.security.SecureRandom;
import java.util.logging.*;
import javax.net.ssl.KeyManager;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
/**
* Blocking Client socket.
* @author Akshathkumar Shetty
* @since 1.4.7
*/
public class BlockingClient implements ClientService {
private static final Logger logger = Logger.getLogger(BlockingClient.class.getName());
private static String charset = "ISO-8859-1";
private static boolean debug = false;
private static final int _CR = 13;
private static final int _LF = 10;
private static String providerForSSLContext;
public static boolean isDebug() {
return debug;
}
public static void setDebug(boolean aDebug) {
debug = aDebug;
}
/**
* @return the providerForSSLContext
*/
public static String getProviderForSSLContext() {
return providerForSSLContext;
}
/**
* @param aProviderForSSLContext the providerForSSLContext to set
*/
public static void setProviderForSSLContext(String aProviderForSSLContext) {
providerForSSLContext = aProviderForSSLContext;
}
private String host = "localhost";
private int port = 0;
private Socket socket;
private boolean secure;
private boolean useDummyTrustManager;
private TrustManager[] trustManager;
private SSLContext sslContext;
private SSLSocketFactory sslSocketFactory;
private InputStream clientAuthKeystoreInputStream;
private char[] clientAuthKeystorePassword;
private char[] clientAuthKeyPassword;
private OutputStream out;
private BufferedOutputStream b_out;
private ObjectOutputStream o_out;
private InputStream in;
private BufferedInputStream b_in;
private BufferedReader br;
private ObjectInputStream o_in;
public void setCharset(String c) {
charset = c;
}
public String getCharset() {
return charset;
}
public int getMode() {
return ClientService.BLOCKING;
}
public void connect(String host, int port) throws Exception {
this.host = host;
this.port = port;
if(isDebug()) logger.finest("Connecting to "+host+":"+port);
if(isSecure()) {
makeSSLSocketFactory();
socket = getSslSocketFactory().createSocket(host, port);
} else {
socket = new Socket(host, port);
}
in = socket.getInputStream();
out = socket.getOutputStream();
if(isDebug()) logger.fine("Connected");
}
public boolean isConnected() {
if(socket==null) return false;
return socket.isConnected();
}
public void close() throws IOException {
if(isDebug()) logger.fine("Closing");
if(out!=null) {
if(isDebug()) logger.finest("Closing output streams");
try {
out.flush();
} catch(IOException ioe) {
logger.log(Level.FINEST, "Flushing output streams failed: {0}", ioe);
}
/*
if(socket!=null && isSecure()==false) {
socket.shutdownOutput();
}
*/
try {
if(o_out != null) {
o_out.close();
}
} catch(IOException ioe) {
logger.log(Level.FINEST, "o_out stream close failed: {0}", ioe);
}
try {
if(b_out != null) {
b_out.close();
}
} catch(IOException ioe) {
logger.log(Level.FINEST, "b_out stream close failed: {0}", ioe);
}
try {
out.close();
} catch(IOException ioe) {
logger.log(Level.FINEST, "out stream close failed: {0}", ioe);
}
}
if(in!=null) {
if(isDebug()) logger.finest("Closing input streams");
/*
if(socket!=null && isSecure()==false) {
socket.shutdownInput();
}
*/
if(o_in != null) {
try {
o_in.close();
} catch(IOException ioe) {
logger.log(Level.FINEST, "o_in stream close failed: {0}", ioe);
}
}
if(b_in != null) {
try {
b_in.close();
} catch(IOException ioe) {
logger.log(Level.FINEST, "b_in stream close failed: {0}", ioe);
}
}
if(br != null) {
try {
br.close();
} catch(IOException ioe) {
logger.log(Level.FINEST, "b_in stream close failed: {0}", ioe);
}
}
try {
in.close();
} catch(IOException ioe) {
logger.log(Level.FINEST, "in stream close failed: {0}", ioe);
}
}
if(socket!=null) {
socket.close();
socket = null;
}
}
public void sendByte(int data) throws IOException {
if(isDebug()) logger.fine("Sending byte");
checkBufferedOutputStream();
b_out.write(data);
b_out.flush();
}
public void sendBytes(byte[] data) throws IOException {
if(isDebug()) logger.log(Level.FINE, "Sending bytes: {0}", data.length);
checkBufferedOutputStream();
b_out.write(data);
b_out.flush();
}
public void sendBytes(String data, String _charset) throws IOException {
if(isDebug()) logger.log(Level.FINE, "Sending: {0}", data);
checkBufferedOutputStream();
if(_charset==null) _charset = charset;
byte d[] = data.getBytes(_charset);
b_out.write(d, 0 , d.length);
b_out.flush();
}
public void sendLine(String data, String _charset) throws IOException {
if(isDebug()) logger.log(Level.FINE, "Sending: {0}", data);
checkBufferedOutputStream();
if(_charset==null) _charset = charset;
byte d[] = data.getBytes(_charset);
b_out.write(d, 0 , d.length);
d = "\r\n".getBytes(_charset);
b_out.write(d, 0 , d.length);
b_out.flush();
}
public void sendObject(Object data) throws IOException {
checkObjectOutputStream();
o_out.writeObject(data);
o_out.flush();
}
public int readByte() throws IOException {
checkBufferedInputStream();
return b_in.read();
}
public byte[] readBytes() throws IOException {
checkBufferedInputStream();
return readInputStream(b_in);
}
public byte[] readBytes(int countToRead) throws IOException {
checkBufferedInputStream();
return readInputStream(b_in, countToRead);
}
public String readBytes(String _charset) throws IOException {
byte data[] = readBytes();
if(data==null) return null;
if(_charset==null) _charset = charset;
return new String(data, _charset);
}
public String readBytes(String _charset, int countToRead) throws IOException {
byte data[] = readInputStream(b_in, countToRead);
if(data==null) return null;
if(_charset==null) _charset = charset;
return new String(data, _charset);
}
public String readLine() throws IOException {
checkBufferedReader();
return br.readLine();
}
public String readCRLFLine() throws IOException {
checkBufferedInputStream();
StringBuilder sb = new StringBuilder();
int _ch = -1;
do {
_ch = b_in.read();
if(_ch==-1) {
return null;
}
if(_ch==_CR) {
_ch = b_in.read();
if(_ch==_LF) {
break;
} else {
sb.append((char) _CR);
sb.append((char) _ch);
}
} else {
sb.append((char) _ch);
}
} while(true);
return(new String(sb));
}
public Object readObject() throws IOException, ClassNotFoundException {
checkObjectInputStream();
return o_in.readObject();
}
public Socket getSocket() {
return socket;
}
private void checkObjectOutputStream() throws IOException {
if(o_out==null) {
b_out = null;
o_out = new ObjectOutputStream(out);
o_out.flush();
}
}
private void checkBufferedOutputStream() throws IOException {
if(b_out==null) {
o_out = null;
b_out = new BufferedOutputStream(out);
}
}
private void checkBufferedInputStream() throws IOException {
if(b_in==null) {
br = null;
o_in = null;
b_in = new BufferedInputStream(in);
}
}
private void checkBufferedReader() throws IOException {
if(br==null) {
b_in = null;
o_in = null;
br = new BufferedReader(new InputStreamReader(in, charset));
}
}
private void checkObjectInputStream() throws IOException {
if(o_in==null) {
b_in = null;
br = null;
o_in = new ObjectInputStream(in);
}
}
public static byte[] readInputStream(InputStream _in, int countToRead)
throws IOException {
byte data[] = new byte[countToRead];
if(_in==null) {
throw new IOException("InputStream can't be null!");
}
int count = 0;
int dataRead = 0;
int dataLeftToRead = countToRead - dataRead;
while(true) {
count = _in.read(data, dataRead, dataLeftToRead);
if(count==-1) {
if(dataRead==countToRead) {
break;
} else {
throw new IOException("we have eof!");
}
} else {
dataRead = dataRead + count;
dataLeftToRead = countToRead - dataRead;
}
if(dataRead>=countToRead) {
break;
}
}//while
return data;
}
public static byte[] readInputStream(InputStream _in) throws IOException {
byte data[] = null;
if(_in==null)
throw new IOException("InputStream can't be null!");
int s = _in.read();
if(s==-1) {
return null; //Connection lost
}
int alength = _in.available();
if(alength > 0) {
data = new byte[alength+1];
data[0] = (byte) s;
int len = _in.read(data, 1, alength);
if(len < alength) {
data = copyOf(data, len+1);
}
} else {
data = new byte[1];
data[0] = (byte) s;
}
return data;
}
private static byte[] copyOf(byte data[], int len) {
byte newdate[] = new byte[len];
System.arraycopy(data, 0, newdate, 0, len);
return newdate;
}
public boolean isSecure() {
return secure;
}
public void setSecure(boolean secure) {
this.secure = secure;
}
public boolean isUseDummyTrustManager() {
return useDummyTrustManager;
}
public void setUseDummyTrustManager(boolean useDummyTrustManager) {
this.useDummyTrustManager = useDummyTrustManager;
}
public TrustManager[] getTrustManager() {
return trustManager;
}
public void setTrustManager(TrustManager[] trustManager) {
this.trustManager = trustManager;
}
public SSLContext getSslContext() {
return sslContext;
}
public void setSslContext(SSLContext sslContext) {
this.sslContext = sslContext;
}
public SSLSocketFactory getSslSocketFactory() {
return sslSocketFactory;
}
public void setSslSocketFactory(SSLSocketFactory sslSocketFactory) {
this.sslSocketFactory = sslSocketFactory;
}
public void makeSSLSocketFactory() throws Exception {
if(getSslContext()==null && getSslSocketFactory()==null) {
SSLContext context = null;
if(getProviderForSSLContext()!=null) {
context = SSLContext.getInstance("TLS", getProviderForSSLContext());
} else {
context = SSLContext.getInstance("TLS");
}
if(getTrustManager()==null && isUseDummyTrustManager()) {
setTrustManager(new TrustManager[]{DummyTrustManager.getInstance()});
}
KeyManager km[] = null;
if(getClientAuthKeystoreInputStream()!=null) {
KeyStore keyStore = KeyStore.getInstance("JKS");
keyStore.load(getClientAuthKeystoreInputStream(), getClientAuthKeystorePassword());
KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
kmf.init(keyStore, getClientAuthKeyPassword());
km = kmf.getKeyManagers();
} else {
km = new KeyManager[0];
}
context.init(km, getTrustManager(), new SecureRandom());
setSslContext(context);
}
if(getSslSocketFactory()==null) {
SSLSocketFactory factory = getSslContext().getSocketFactory();
setSslSocketFactory(factory);
}
}
public InputStream getClientAuthKeystoreInputStream() {
return clientAuthKeystoreInputStream;
}
public void setClientAuthKeystoreInputStream(InputStream clientAuthKeystoreInputStream) {
this.clientAuthKeystoreInputStream = clientAuthKeystoreInputStream;
}
public char[] getClientAuthKeystorePassword() {
return clientAuthKeystorePassword;
}
public void setClientAuthKeystorePassword(char clientAuthKeystorePassword[]) {
this.clientAuthKeystorePassword = clientAuthKeystorePassword;
}
public char[] getClientAuthKeyPassword() {
return clientAuthKeyPassword;
}
public void setClientAuthKeyPassword(char[] clientAuthKeyPassword) {
this.clientAuthKeyPassword = clientAuthKeyPassword;
}
}