package com.microsoft.sqlserver.jdbc;
import java.util.logging.Level;
import java.util.logging.Logger;
final class TDSParser {
private static Logger logger = Logger.getLogger("com.microsoft.sqlserver.jdbc.internals.TDS.TOKEN");
static void parse(TDSReader tdsReader, String logContext) throws SQLServerException {
parse(tdsReader, new TDSTokenHandler(logContext));
}
static void parse(TDSReader tdsReader, TDSTokenHandler tdsTokenHandler) throws SQLServerException {
parse(tdsReader, tdsTokenHandler, false);
}
static void parse(TDSReader tdsReader, TDSTokenHandler tdsTokenHandler,
boolean readOnlyWarningsFlag) throws SQLServerException {
final boolean isLogging = logger.isLoggable(Level.FINEST);
boolean parsing = true;
boolean isLoginAck = false;
boolean isFeatureExtAck = false;
while (parsing) {
int tdsTokenType = tdsReader.peekTokenType();
if (isLogging) {
logger.finest(tdsReader.toString() + ": " + tdsTokenHandler.logContext + ": Processing "
+ ((-1 == tdsTokenType) ? "EOF" : TDS.getTokenName(tdsTokenType)));
}
if (readOnlyWarningsFlag && TDS.TDS_MSG != tdsTokenType) {
parsing = false;
return;
}
switch (tdsTokenType) {
case TDS.TDS_SSPI:
parsing = tdsTokenHandler.onSSPI(tdsReader);
break;
case TDS.TDS_LOGIN_ACK:
isLoginAck = true;
parsing = tdsTokenHandler.onLoginAck(tdsReader);
break;
case TDS.TDS_FEATURE_EXTENSION_ACK:
isFeatureExtAck = true;
tdsReader.getConnection().processFeatureExtAck(tdsReader);
parsing = true;
break;
case TDS.TDS_ENV_CHG:
parsing = tdsTokenHandler.onEnvChange(tdsReader);
break;
case TDS.TDS_RET_STAT:
parsing = tdsTokenHandler.onRetStatus(tdsReader);
break;
case TDS.TDS_RETURN_VALUE:
parsing = tdsTokenHandler.onRetValue(tdsReader);
break;
case TDS.TDS_DONEINPROC:
case TDS.TDS_DONEPROC:
case TDS.TDS_DONE:
tdsReader.getCommand().checkForInterrupt();
parsing = tdsTokenHandler.onDone(tdsReader);
break;
case TDS.TDS_ERR:
parsing = tdsTokenHandler.onError(tdsReader);
break;
case TDS.TDS_MSG:
parsing = tdsTokenHandler.onInfo(tdsReader);
break;
case TDS.TDS_ORDER:
parsing = tdsTokenHandler.onOrder(tdsReader);
break;
case TDS.TDS_COLMETADATA:
parsing = tdsTokenHandler.onColMetaData(tdsReader);
break;
case TDS.TDS_ROW:
parsing = tdsTokenHandler.onRow(tdsReader);
break;
case TDS.TDS_NBCROW:
parsing = tdsTokenHandler.onNBCRow(tdsReader);
break;
case TDS.TDS_COLINFO:
parsing = tdsTokenHandler.onColInfo(tdsReader);
break;
case TDS.TDS_TABNAME:
parsing = tdsTokenHandler.onTabName(tdsReader);
break;
case TDS.TDS_FEDAUTHINFO:
parsing = tdsTokenHandler.onFedAuthInfo(tdsReader);
break;
case -1:
tdsReader.getCommand().onTokenEOF();
tdsTokenHandler.onEOF(tdsReader);
parsing = false;
break;
default:
throwUnexpectedTokenException(tdsReader, tdsTokenHandler.logContext);
break;
}
}
if (isLoginAck && !isFeatureExtAck)
tdsReader.tryProcessFeatureExtAck(isFeatureExtAck);
}
static void throwUnexpectedTokenException(TDSReader tdsReader, String logContext) throws SQLServerException {
if (logger.isLoggable(Level.SEVERE))
logger.severe(tdsReader.toString() + ": " + logContext + ": Encountered unexpected "
+ TDS.getTokenName(tdsReader.peekTokenType()));
tdsReader.throwInvalidTDSToken(TDS.getTokenName(tdsReader.peekTokenType()));
}
static void ignoreLengthPrefixedToken(TDSReader tdsReader) throws SQLServerException {
tdsReader.readUnsignedByte();
int envValueLength = tdsReader.readUnsignedShort();
byte[] envValueData = new byte[envValueLength];
tdsReader.readBytes(envValueData, 0, envValueLength);
}
}
class TDSTokenHandler {
final String logContext;
private SQLServerError databaseError;
private static Logger logger = Logger.getLogger("com.microsoft.sqlserver.jdbc.internals.TDS.TOKEN");
final SQLServerError getDatabaseError() {
return databaseError;
}
TDSTokenHandler(String logContext) {
this.logContext = logContext;
}
boolean onSSPI(TDSReader tdsReader) throws SQLServerException {
TDSParser.throwUnexpectedTokenException(tdsReader, logContext);
return false;
}
boolean onLoginAck(TDSReader tdsReader) throws SQLServerException {
TDSParser.throwUnexpectedTokenException(tdsReader, logContext);
return false;
}
boolean onFeatureExtensionAck(TDSReader tdsReader) throws SQLServerException {
TDSParser.throwUnexpectedTokenException(tdsReader, logContext);
return false;
}
boolean onEnvChange(TDSReader tdsReader) throws SQLServerException {
tdsReader.getConnection().processEnvChange(tdsReader);
return true;
}
boolean onRetStatus(TDSReader tdsReader) throws SQLServerException {
(new StreamRetStatus()).setFromTDS(tdsReader);
return true;
}
boolean onRetValue(TDSReader tdsReader) throws SQLServerException {
TDSParser.throwUnexpectedTokenException(tdsReader, logContext);
return false;
}
boolean onDone(TDSReader tdsReader) throws SQLServerException {
StreamDone doneToken = new StreamDone();
doneToken.setFromTDS(tdsReader);
return true;
}
boolean onError(TDSReader tdsReader) throws SQLServerException {
if (null == databaseError) {
databaseError = new SQLServerError();
databaseError.setFromTDS(tdsReader);
} else {
(new SQLServerError()).setFromTDS(tdsReader);
}
return true;
}
boolean onInfo(TDSReader tdsReader) throws SQLServerException {
TDSParser.ignoreLengthPrefixedToken(tdsReader);
return true;
}
boolean onOrder(TDSReader tdsReader) throws SQLServerException {
TDSParser.ignoreLengthPrefixedToken(tdsReader);
return true;
}
boolean onColMetaData(TDSReader tdsReader) throws SQLServerException {
if (logger.isLoggable(Level.SEVERE))
logger.severe(tdsReader.toString() + ": " + logContext + ": Encountered "
+ TDS.getTokenName(tdsReader.peekTokenType()) + ". SHOWPLAN is ON, ignoring.");
return false;
}
boolean onRow(TDSReader tdsReader) throws SQLServerException {
TDSParser.throwUnexpectedTokenException(tdsReader, logContext);
return false;
}
boolean onNBCRow(TDSReader tdsReader) throws SQLServerException {
TDSParser.throwUnexpectedTokenException(tdsReader, logContext);
return false;
}
boolean onColInfo(TDSReader tdsReader) throws SQLServerException {
TDSParser.ignoreLengthPrefixedToken(tdsReader);
return true;
}
boolean onTabName(TDSReader tdsReader) throws SQLServerException {
TDSParser.ignoreLengthPrefixedToken(tdsReader);
return true;
}
void onEOF(TDSReader tdsReader) throws SQLServerException {
if (null != getDatabaseError()) {
SQLServerException.makeFromDatabaseError(tdsReader.getConnection(), null,
getDatabaseError().getErrorMessage(), getDatabaseError(), false);
}
}
boolean onFedAuthInfo(TDSReader tdsReader) throws SQLServerException {
tdsReader.getConnection().processFedAuthInfo(tdsReader, this);
return true;
}
}