public void addListener(Object id, Object l, int validOps) {
		//cannot do instanceof here as clients may use one object as two instances and it
		//could be set wrong or twice.....ie. we can't tell.  instead use validOps
		switch(validOps) {
		case SelectionKey.OP_ACCEPT:
			if(acceptCallback != null)
				throw new RuntimeException(channel+"ConnectionListener is already set, cannot be set again");
			acceptCallback = (ConnectionListener)l;
			break;
		case SelectionKey.OP_CONNECT:
			if(connectCallback != null)
				throw new RuntimeException(channel+"ConnectionListener is already set, cannot be set again");
			connectCallback = (ConnectionListener)l;
			break;
		case SelectionKey.OP_READ:
			if(dataHandler != null) {
				//A VERY BAD hack for now.  When SSL layer fires connected, the client calls registerForRead which calls this addListener
				//method BUT then when we return down the stack, the SSL layer calls DataChunk.setProcessed() which is required to notify
				//bottom basic layer to start reading again EXCEPT that results in two calls to this method which I don't like.
				return;
//				if(!dataHandler.equals(l)) //we only throw if it is NOT the exact same listener
//					throw new RuntimeException(channel+"DataListener is already set, cannot be set again");
			}
			dataHandler = (DataListener)l;
			break;
		case SelectionKey.OP_WRITE:
		    //okay to ignore and do nothing...not used later
			break;
		default:
			throw new IllegalArgumentException("type="+l.getClass().getName()+" is not allowed");
		}
	}