| /* |
| * 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.server.impl; |
| |
| import org.quickserver.net.server.*; |
| import org.quickserver.net.*; |
| import org.quickserver.util.*; |
| |
| import java.io.*; |
| import java.net.*; |
| import java.util.logging.*; |
| |
| import java.nio.channels.*; |
| |
| public class BlockingClientHandler extends BasicClientHandler { |
| private static final Logger logger = Logger.getLogger(BlockingClientHandler.class.getName()); |
| |
| public BlockingClientHandler(int instanceCount) { |
| super(instanceCount); |
| } |
| |
| public BlockingClientHandler() { |
| super(); |
| } |
| |
| public void clean() { |
| logger.log(Level.FINEST, "Starting clean - {0}", getName()); |
| super.clean(); |
| logger.log(Level.FINEST, "Finished clean - {0}", getName()); |
| } |
| |
| public void handleClient(TheClient theClient) throws Exception { |
| super.handleClient(theClient); |
| } |
| |
| protected void setInputStream(InputStream in) throws IOException { |
| this.in = in; |
| if(getDataMode(DataType.IN) == DataMode.STRING) { |
| b_in = null; |
| o_in = null; |
| bufferedReader = new BufferedReader(new InputStreamReader(this.in, charset)); |
| } else if(getDataMode(DataType.IN) == DataMode.OBJECT) { |
| b_in = null; |
| bufferedReader = null; |
| o_in = new ObjectInputStream(in); |
| } else if(getDataMode(DataType.IN) == DataMode.BYTE || |
| getDataMode(DataType.IN) == DataMode.BINARY) { |
| o_in = null; |
| bufferedReader = null; |
| b_in = new BufferedInputStream(in); |
| } |
| } |
| |
| public BufferedReader getBufferedReader() { |
| return bufferedReader; |
| } |
| |
| public synchronized void closeConnection() { |
| if(connection==false) return; |
| connection = false; |
| try { |
| if(hasEvent(ClientEvent.MAX_CON_BLOCKING)==false) { |
| notifyCloseOrLost(); |
| } |
| |
| if(out!=null) { |
| logger.finest("Closing output streams"); |
| try { |
| out.flush(); |
| } catch(IOException ioe) { |
| logger.log(Level.FINEST, "Flushing output streams failed: "+ioe, ioe); |
| } |
| |
| if(socket!=null && isSecure()==false) { |
| socket.shutdownOutput(); |
| } |
| if(dataModeOUT == DataMode.OBJECT) { |
| o_out.close(); |
| } else { |
| b_out.close(); |
| } |
| if(out!=null) out.close(); |
| } |
| |
| if(in!=null) { |
| logger.finest("Closing input streams"); |
| //if(socket!=null) socket.shutdownInput(); |
| |
| if(dataModeIN == DataMode.STRING) { |
| if(bufferedReader!=null) bufferedReader.close(); |
| } else if(dataModeIN == DataMode.OBJECT) { |
| o_in.close(); |
| } else { |
| b_in.close(); |
| } |
| if(in!=null) in.close(); |
| } |
| } catch(IOException e) { |
| logger.log(Level.WARNING, "Error in closeConnection: {0}", e); |
| if(logger.isLoggable(Level.FINE)) { |
| logger.log(Level.FINE, "StackTrace: "+e, e); |
| } |
| } catch(NullPointerException npe) { |
| logger.log(Level.FINE, "NullPointerException: "+npe, npe); |
| } |
| } |
| |
| public void run() { |
| if(unprocessedClientEvents.isEmpty()) { |
| logger.finest("No unprocessed ClientEvents!"); |
| return; |
| } |
| |
| ClientEvent currentEvent = (ClientEvent) unprocessedClientEvents.poll(); |
| if(currentEvent==null) { |
| threadEvent.set(null); |
| logger.finest("No unprocessed ClientEvents! pool was null"); |
| return; |
| } |
| |
| if(logger.isLoggable(Level.FINEST)) { |
| StringBuilder sb = new StringBuilder(); |
| sb.append("Running ").append(getName()); |
| sb.append(" using "); |
| sb.append(Thread.currentThread().getName()); |
| sb.append(" for "); |
| |
| synchronized(clientEvents) { |
| if(clientEvents.size()>1) { |
| sb.append(currentEvent).append(", Current Events - ").append(clientEvents); |
| } else { |
| sb.append(currentEvent); |
| } |
| } |
| logger.finest(sb.toString()); |
| } |
| |
| threadEvent.set(currentEvent); |
| |
| try { |
| if(socket==null) |
| throw new SocketException("Socket was null!"); |
| |
| prepareForRun(); |
| |
| if(getThreadEvent()==ClientEvent.MAX_CON_BLOCKING) { |
| processMaxConnection(currentEvent); |
| } |
| |
| try { |
| if(getThreadEvent()==ClientEvent.RUN_BLOCKING) { |
| clientEventHandler.gotConnected(this); |
| |
| if(authorised == false) { |
| if(clientAuthenticationHandler==null && authenticator == null) { |
| authorised = true; |
| } else { |
| if(clientAuthenticationHandler!=null) { |
| AuthStatus authStatus = null; |
| do { |
| authStatus = processAuthorisation(); |
| } while(authStatus==AuthStatus.FAILURE); |
| |
| if(authStatus==AuthStatus.SUCCESS) |
| authorised = true; |
| } else { |
| processAuthorisation(); |
| } |
| } |
| }//end of authorised |
| |
| processRead(); |
| } |
| } catch(SocketException e) { |
| appLogger.log(Level.FINEST, "SocketException - Client [{0}]: {1}", |
| new Object[]{getHostAddress(), e}); |
| lost = true; |
| } catch(AppException e) { |
| appLogger.log(Level.FINEST, "AppException {0}: {1}", new Object[]{ |
| Thread.currentThread().getName(), e}); |
| } catch(javax.net.ssl.SSLException e) { |
| lost = true; |
| if(Assertion.isEnabled()) { |
| appLogger.log(Level.INFO, "SSLException - Client [{0}] {1}: {2}", |
| new Object[]{getHostAddress(), Thread.currentThread().getName(), e}); |
| } else { |
| appLogger.log(Level.WARNING, "SSLException - Client [{0}]: {1}", |
| new Object[]{getHostAddress(), e}); |
| } |
| } catch(ConnectionLostException e) { |
| lost = true; |
| if(e.getMessage()!=null) |
| appLogger.log(Level.FINEST, "Connection lost {0}: {1}", |
| new Object[]{Thread.currentThread().getName(), e}); |
| else |
| appLogger.log(Level.FINEST, "Connection lost {0}", Thread.currentThread().getName()); |
| } catch(IOException e) { |
| lost = true; |
| appLogger.log(Level.FINE, "IOError {0}: {1}", new Object[]{Thread.currentThread().getName(), e}); |
| } catch(AssertionError er) { |
| logger.log(Level.WARNING, "[AssertionError] {0} {1}", new Object[]{getName(), er}); |
| if(logger.isLoggable(Level.FINEST)) { |
| logger.log(Level.FINEST, "StackTrace {0}: {1}", new Object[]{ |
| Thread.currentThread().getName(), MyString.getStackTrace(er)}); |
| } |
| assertionSystemExit(); |
| } catch(RuntimeException re) { |
| logger.log(Level.WARNING, "[RuntimeException] {0}", MyString.getStackTrace(re)); |
| if(Assertion.isEnabled()) { |
| assertionSystemExit(); |
| } |
| lost = true; |
| } catch(Throwable er) { |
| logger.log(Level.WARNING, "[Error] {0}", er); |
| if(logger.isLoggable(Level.FINEST)) { |
| logger.log(Level.FINEST, "StackTrace {0}: {1}", |
| new Object[]{Thread.currentThread().getName(), MyString.getStackTrace(er)}); |
| } |
| if(Assertion.isEnabled()) { |
| assertionSystemExit(); |
| } |
| lost = true; |
| } |
| |
| if(getThreadEvent()!=ClientEvent.MAX_CON_BLOCKING) { |
| notifyCloseOrLost(); |
| } |
| |
| if(connection) { |
| logger.log(Level.FINEST, "{0} calling closeConnection()", Thread.currentThread().getName()); |
| closeConnection(); |
| } |
| } catch(javax.net.ssl.SSLException se) { |
| logger.log(Level.WARNING, "SSLException {0}", se); |
| } catch(IOException ie) { |
| logger.log(Level.WARNING, "IOError - Closing Client: {0}", ie); |
| } catch(RuntimeException re) { |
| logger.log(Level.WARNING, "[RuntimeException] {0} {1}", new Object[]{ |
| getName(), MyString.getStackTrace(re)}); |
| if(Assertion.isEnabled()) { |
| assertionSystemExit(); |
| } |
| } catch(Exception e) { |
| logger.log(Level.WARNING, "Error on Event:{0} - Socket:{1} : {2}", new Object[]{getThreadEvent(), socket, e}); |
| logger.log(Level.FINE, "StackTrace: {0}\n{1}", new Object[]{getName(), MyString.getStackTrace(e)}); |
| if(Assertion.isEnabled()) { |
| assertionSystemExit(); |
| } |
| } catch(Throwable e) { |
| logger.log(Level.WARNING, "Error on - Event:{0} - Socket:{1} : {2}", new Object[]{getThreadEvent(), socket, e}); |
| logger.log(Level.FINE, "StackTrace: {0}\n{1}", new Object[]{getName(), MyString.getStackTrace(e)}); |
| if(Assertion.isEnabled()) { |
| assertionSystemExit(); |
| } |
| } |
| |
| try { |
| if(socket!=null && socket.isClosed()==false) { |
| logger.finest("Closing Socket"); |
| socket.close(); |
| } |
| } catch(Exception re) { |
| logger.log(Level.WARNING, "Error closing Socket/Channel: {0}", re); |
| } |
| |
| willClean = true; |
| returnClientData(); |
| |
| boolean returnClientHandler = false; |
| synchronized(lockObj) { |
| returnClientHandler = checkReturnClientHandler(); |
| } |
| |
| if(returnClientHandler) { |
| returnClientHandler(); //return to pool |
| } |
| } |
| |
| protected boolean checkReturnClientHandler() { |
| return true; |
| } |
| |
| private void processRead() throws IOException, ClassNotFoundException, AppException { |
| AuthStatus authStatus = null; |
| |
| String rec = null; |
| Object recObject = null; //v1.2 |
| byte[] recByte = null; //1.4 |
| |
| while(connection) { |
| try { |
| if(dataModeIN == DataMode.STRING) { |
| rec = bufferedReader.readLine(); |
| if(rec==null) { |
| lost = true; |
| break; |
| } |
| if(getCommunicationLogging() && authorised == true) { |
| appLogger.log(Level.FINE, "Got STRING [{0}] : {1}", |
| new Object[]{getHostAddress(), rec}); |
| } |
| totalReadBytes = totalReadBytes + rec.length() + 2; |
| |
| if(authorised == false) |
| authStatus = clientAuthenticationHandler.handleAuthentication(this, rec); |
| else |
| clientCommandHandler.handleCommand(this, rec); |
| } else if(dataModeIN == DataMode.OBJECT) { |
| recObject = o_in.readObject(); |
| if(recObject==null) { |
| lost = true; |
| break; |
| } |
| |
| if(getCommunicationLogging() && authorised == true) { |
| appLogger.log(Level.FINE, "Got OBJECT [{0}] : {1}", |
| new Object[]{getHostAddress(), recObject.toString()}); |
| } |
| totalReadBytes = totalReadBytes + 1; |
| if(authorised == false) |
| authStatus = clientAuthenticationHandler.handleAuthentication(this, recObject); |
| else |
| clientObjectHandler.handleObject(this, recObject); |
| } else if(dataModeIN == DataMode.BYTE) { |
| rec = readBytes(); |
| if(rec==null) { |
| lost = true; |
| break; |
| } |
| if(getCommunicationLogging() && authorised == true) { |
| appLogger.log(Level.FINE, "Got BYTE [{0}] : {1}", new Object[]{getHostAddress(), rec}); |
| } |
| totalReadBytes = totalReadBytes + rec.length(); |
| if(authorised == false) |
| authStatus = clientAuthenticationHandler.handleAuthentication(this, rec); |
| else |
| clientCommandHandler.handleCommand(this, rec); |
| } else if(dataModeIN == DataMode.BINARY) { |
| recByte = readBinary(); |
| if(recByte==null) { |
| lost = true; |
| break; |
| } |
| if(getCommunicationLogging() && authorised == true) { |
| if(getServer().isRawCommunicationLogging()) { |
| if(getServer().getRawCommunicationMaxLength()>0 && |
| recByte.length>getServer().getRawCommunicationMaxLength()) { |
| appLogger.log(Level.FINE, |
| "Got BINARY [{0}] : {1}; RAW: {2}{3}", new Object[]{ |
| getHostAddress(), MyString.getMemInfo(recByte.length), |
| new String(recByte,0,getServer().getRawCommunicationMaxLength(),charset),"..."}); |
| } else { |
| appLogger.log(Level.FINE, |
| "Got BINARY [{0}] : {1}; RAW: {2}", new Object[]{ |
| getHostAddress(), MyString.getMemInfo(recByte.length), |
| new String(recByte,charset)}); |
| } |
| } else { |
| appLogger.log(Level.FINE, |
| "Got BINARY [{0}] : {1}", new Object[]{getHostAddress(), |
| MyString.getMemInfo(recByte.length)}); |
| } |
| } else if (getCommunicationLogging()) { |
| appLogger.log(Level.FINE, |
| "Got BINARY [{0}] : {1}", new Object[]{getHostAddress(), |
| MyString.getMemInfo(recByte.length)}); |
| } |
| totalReadBytes = totalReadBytes + recByte.length; |
| if(authorised == false) |
| authStatus = clientAuthenticationHandler.handleAuthentication(this, recByte); |
| else |
| clientBinaryHandler.handleBinary(this, recByte); |
| } else { |
| throw new IllegalStateException("Incoming DataMode is not supported: "+dataModeIN); |
| } |
| updateLastCommunicationTime(); |
| |
| while(authStatus==AuthStatus.FAILURE) |
| authStatus = processAuthorisation(); |
| |
| if(authStatus==AuthStatus.SUCCESS) |
| authorised = true; |
| } catch(SocketTimeoutException e) { |
| handleTimeout(e); |
| } |
| }//end of while |
| } |
| |
| protected void returnClientHandler() { |
| logger.finest(getName()); |
| super.returnClientHandler(); |
| } |
| |
| public void setDataMode(DataMode dataMode, DataType dataType) |
| throws IOException { |
| if(getDataMode(dataType)==dataMode) return; |
| |
| appLogger.log(Level.FINE, "Setting Type:{0}, Mode:{1}", new Object[]{dataType, dataMode}); |
| super.checkDataModeSet(dataMode, dataType); |
| |
| setDataModeBlocking(dataMode, dataType); |
| } |
| |
| private void setDataModeBlocking(DataMode dataMode, DataType dataType) |
| throws IOException { |
| logger.finest("ENTER"); |
| if(dataMode == DataMode.STRING) { |
| if(dataType == DataType.OUT) { |
| if(dataModeOUT == DataMode.BYTE || dataModeOUT == DataMode.BINARY) { |
| dataModeOUT = dataMode; |
| } else if(dataModeOUT == DataMode.OBJECT) { |
| dataModeOUT = dataMode; |
| o_out.flush(); o_out = null; |
| b_out = new BufferedOutputStream(out); |
| } else { |
| Assertion.affirm(false, "Unknown DataType.OUT DataMode - "+dataModeOUT); |
| } |
| Assertion.affirm(b_out!=null, "BufferedOutputStream is still null!"); |
| } else if(dataType == DataType.IN) { |
| dataModeIN = dataMode; |
| |
| if(o_in!=null) { |
| if(o_in.available()!=0) |
| logger.warning("Data looks to be present in ObjectInputStream"); |
| o_in = null; |
| } |
| if(b_in!=null) { |
| if(b_in.available()!=0) |
| logger.warning("Data looks to be present in BufferedInputStream"); |
| b_in = null; |
| } |
| bufferedReader = new BufferedReader(new InputStreamReader(in, charset)); |
| Assertion.affirm(bufferedReader!=null, "BufferedReader is still null!"); |
| } |
| } else if(dataMode == DataMode.OBJECT) { |
| if(dataType == DataType.OUT) { |
| dataModeOUT = dataMode; |
| if(b_out!=null) { |
| b_out.flush(); |
| b_out = null; |
| } |
| o_out = new ObjectOutputStream(out); |
| Assertion.affirm(o_out!=null, "ObjectOutputStream is still null!"); |
| } else if(dataType == DataType.IN) { |
| dataModeIN = dataMode; |
| if(b_in!=null) { |
| if(b_in.available()!=0) |
| logger.warning("Data looks to be present in BufferedInputStream"); |
| b_in = null; |
| } |
| bufferedReader = null; |
| o_in = new ObjectInputStream(in); //will block |
| Assertion.affirm(o_in!=null, "ObjectInputStream is still null!"); |
| } |
| } else if(dataMode == DataMode.BYTE || dataMode == DataMode.BINARY) { |
| if(dataType == DataType.OUT) { |
| if(dataModeOUT == DataMode.STRING || dataModeOUT == DataMode.BYTE || |
| dataModeOUT == DataMode.BINARY) { |
| dataModeOUT = dataMode; |
| } else if(dataModeOUT == DataMode.OBJECT) { |
| dataModeOUT = dataMode; |
| if(o_out!=null) { |
| o_out.flush(); |
| o_out = null; |
| } |
| b_out = new BufferedOutputStream(out); |
| } else { |
| Assertion.affirm(false, "Unknown DataType.OUT - DataMode: "+dataModeOUT); |
| } |
| Assertion.affirm(b_out!=null, "BufferedOutputStream is still null!"); |
| } else if(dataType == DataType.IN) { |
| dataModeIN = dataMode; |
| if(o_in!=null) { |
| if(o_in.available()!=0) |
| logger.warning("Data looks to be present in ObjectInputStream"); |
| o_in = null; |
| } |
| bufferedReader = null; |
| b_in = new BufferedInputStream(in); |
| Assertion.affirm(b_in!=null, "BufferedInputStream is still null!"); |
| } else { |
| throw new IllegalArgumentException("Unknown DataType : "+dataType); |
| } |
| } else { |
| throw new IllegalArgumentException("Unknown DataMode : "+dataMode); |
| } |
| } |
| |
| protected byte[] readInputStream() throws IOException { |
| return readInputStream(b_in); |
| } |
| |
| public void updateInputOutputStreams() throws IOException { |
| setInputStream(getSocket().getInputStream()); |
| setOutputStream(getSocket().getOutputStream()); |
| } |
| |
| public boolean getBlockingMode() { |
| return true; |
| } |
| |
| public void setSocketChannel(SocketChannel socketChannel) { |
| if(true) throw new IllegalStateException("Can't set in blocking mode!"); |
| } |
| public SocketChannel getSocketChannel() { |
| if(true) throw new IllegalStateException("Can't get in blocking mode!"); |
| return null; |
| } |
| |
| public void setSelectionKey(SelectionKey selectionKey) { |
| if(true) throw new IllegalStateException("Can't set in blocking mode!"); |
| } |
| public SelectionKey getSelectionKey() { |
| if(true) throw new IllegalStateException("Can't get in blocking mode!"); |
| return null; |
| } |
| |
| public void registerForRead() throws IOException, ClosedChannelException { |
| if(true) throw new IllegalStateException("Can't register in blocking mode!"); |
| } |
| |
| public void registerForWrite() throws IOException, ClosedChannelException { |
| if(true) throw new IllegalStateException("Can't register in blocking mode!"); |
| } |
| |
| protected void setClientWriteHandler(ClientWriteHandler handler) { |
| if(true) throw new IllegalStateException("Can't register in blocking mode!"); |
| } |
| } |