| /* |
| * 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; |
| } |
| } |