package com.linkedin.databus2.core.container.request;
/*
*
* Copyright 2013 LinkedIn Corp. All rights reserved
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*/
import java.nio.charset.Charset;
import java.util.List;
import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.buffer.ChannelBuffers;
import com.linkedin.databus.core.data_model.PhysicalPartition;
import com.linkedin.databus.core.data_model.UnknownPartitionException;
import com.linkedin.databus2.core.DatabusException;
public class ErrorResponse extends SimpleDatabusResponse
{
private final byte _errorCode;
private final Throwable _cause;
private final String _causeClassName;
private final String _causeMessage;
// A boolean to indicate whether this response is expected. If so, we don't want to log exception stack.
private boolean _isExpected = false;
public ErrorResponse(byte errorCode, Throwable cause)
{
super((byte)1);
_errorCode = errorCode;
_cause = cause;
_causeClassName = _cause.getClass().getName();
_causeMessage = _cause.getMessage();
}
public ErrorResponse(byte errorCode, String causeClassName, String causeMessage)
{
super((byte)1);
_errorCode = errorCode;
_cause = null;
_causeClassName = causeClassName;
_causeMessage = causeMessage;
}
public boolean isExpected()
{
return _isExpected;
}
public void setExpected(boolean expected)
{
_isExpected = expected;
}
public static ErrorResponse decodeFromChannelBuffer(ChannelBuffer buffer)
{
if (buffer.readableBytes() < 1 + 4 + 2 + 2) return null;
byte opcode = buffer.readByte();
int responseLen = buffer.readInt();
if (responseLen <= 0) throw new IllegalArgumentException("responseLen=" + responseLen);
if (buffer.readableBytes() < responseLen) return null;
short errorClassLen = buffer.readShort();
if (errorClassLen <= 0) throw new IllegalArgumentException("errorClassLen=" + errorClassLen);
byte[] classNameBytes = new byte[errorClassLen];
buffer.readBytes(classNameBytes);
short errorMessageLen = buffer.readShort();
if (errorMessageLen < 0) throw new IllegalArgumentException("errorMessageLen=" + errorMessageLen);
byte[] errorMessageBytes = (errorMessageLen > 0) ? new byte[errorMessageLen] : null;
if (errorMessageLen > 0) buffer.readBytes(errorMessageBytes);
ErrorResponse result = new ErrorResponse(opcode, new String(classNameBytes),
null != errorMessageBytes ? new String(errorMessageBytes)
: null);
return result;
}
public byte getErrorCode()
{
return _errorCode;
}
public Throwable getCause()
{
return _cause;
}
public String getCauseClassName()
{
return _causeClassName;
}
public String getCauseMessage()
{
return _causeMessage;
}
public static ErrorResponse createUnknownCommandResponse(int opcode)
{
return new ErrorResponse(BinaryProtocol.RESULT_ERR_UNKNOWN_COMMAND,
new UnknownCommandException(Integer.toHexString(opcode & 0xFF)));
}
public static ErrorResponse createMismatchingMetadata(String cmd, String param, String value)
{
return new ErrorResponse(BinaryProtocol.RESULT_ERR_INVALID_METADATA,
new InvalidRequestParamValueException(cmd, param, value));
}
public static ErrorResponse createUnexpectedControlEventErrorResponse(String msg)
{
return new ErrorResponse(BinaryProtocol.RESULT_ERR_UNEXPECTED_CONTROL_EVENT,
new DatabusException(msg));
}
public static ErrorResponse createInternalServerErrorResponse(Throwable cause)
{
return new ErrorResponse(BinaryProtocol.RESULT_ERR_INTERNAL_SERVER_ERROR, cause);
}
public static ErrorResponse createUnsupportedProtocolVersionResponse(byte version)
{
return new ErrorResponse(BinaryProtocol.RESULT_ERR_UNSUPPORTED_PROTOCOL_VERSION,
new UnsupportedProtocolVersionException(version));
}
public static ErrorResponse createSourcesTooOldResponse(List<Short> srcIds)
{
return new ErrorResponse(BinaryProtocol.RESULT_ERR_SOURCES_TOO_OLD,
new SourcesTooOldException(srcIds));
}
public static ErrorResponse createSourcesTooOldResponse(int serverId)
{
return new ErrorResponse(BinaryProtocol.RESULT_ERR_SOURCES_TOO_OLD,
new SourcesTooOldException(serverId));
}
public static ErrorResponse createUnexpectedCommandResponse(String commandName)
{
return new ErrorResponse(BinaryProtocol.RESULT_ERR_UNEXPECTED_COMMAND,
new UnexpectedCommand(commandName));
}
public static ErrorResponse createUnexpectedCommandResponse(byte opcode)
{
return new ErrorResponse(BinaryProtocol.RESULT_ERR_UNEXPECTED_COMMAND,
new UnexpectedCommand(opcode));
}
public static ErrorResponse createInvalidRequestParam(String cmdName, String paramName,
String paramValue)
{
return new ErrorResponse(BinaryProtocol.RESULT_ERR_INVALID_REQ_PARAM,
new InvalidRequestParamValueException(cmdName, paramName, paramValue));
}
public static ErrorResponse createUnknownPartition(PhysicalPartition ppart)
{
return new ErrorResponse(BinaryProtocol.RESULT_ERR_UNKNOWN_PARTITION,
new UnknownPartitionException(ppart));
}
public static ErrorResponse createInvalidEvent(String errMsg)
{
return new ErrorResponse(BinaryProtocol.RESULT_ERR_INVALID_EVENT,
new DatabusException(errMsg));
}
public static ErrorResponse createUnsupportedDbusEventVersion(String errMsg)
{
return new ErrorResponse(BinaryProtocol.RESULT_ERR_UNSUPPORTED_DBUS_EVENT_VERSION,
new DatabusException(errMsg));
}
/**
* See MyBus protocol wiki
* @return the binary serialization
*/
@Override
public ChannelBuffer serializeToBinary()
{
int resultSize = 1 + 4 + 2 + 2;
int classLen = 0;
byte[] causeClass = null;
int messageLen = 0;
byte[] causeMessage = null;
if (null != _cause)
{
causeClass = _causeClassName.getBytes(Charset.defaultCharset());
classLen = Math.min(causeClass.length, BinaryProtocol.MAX_ERROR_CLASS_LEN);
resultSize += classLen;
if (null != _causeMessage)
{
causeMessage = _causeMessage.getBytes(Charset.defaultCharset());
messageLen = Math.min(causeMessage.length, BinaryProtocol.MAX_ERROR_MESSAGE_LEN);
resultSize += causeMessage.length;
}
}
ChannelBuffer result = ChannelBuffers.buffer(BinaryProtocol.BYTE_ORDER, resultSize);
result.writeByte(_errorCode);
result.writeInt(resultSize - 1 - 4);
result.writeShort(classLen);
result.writeBytes(causeClass, 0, classLen);
result.writeShort(messageLen);
if (messageLen > 0)
{
result.writeBytes(causeMessage, 0, messageLen);
}
return result;
}
}