blob: cc2099e7aa4817330e6592e8c44f51f2339bd20d [file] [log] [blame]
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.
*/
package org.apache.atlas.notification;
import com.google.gson.Gson;
import org.slf4j.Logger;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
/**
* Deserializer that works with versioned messages. The version of each deserialized message is checked against an
* expected version.
*/
public abstract class VersionedMessageDeserializer<T> implements MessageDeserializer<T> {
public static final String VERSION_MISMATCH_MSG =
"Notification message version mismatch. Expected %s but recieved %s. Message %s";
private final Type versionedMessageType;
private final MessageVersion expectedVersion;
private final Logger notificationLogger;
private final Gson gson;
// ----- Constructors ----------------------------------------------------
/**
* Create a versioned message deserializer.
*
* @param versionedMessageType the type of the versioned message
* @param expectedVersion the expected message version
* @param gson JSON serialization/deserialization
* @param notificationLogger logger for message version mismatch
*/
public VersionedMessageDeserializer(Type versionedMessageType, MessageVersion expectedVersion,
Gson gson, Logger notificationLogger) {
this.versionedMessageType = versionedMessageType;
this.expectedVersion = expectedVersion;
this.gson = gson;
this.notificationLogger = notificationLogger;
}
// ----- MessageDeserializer ---------------------------------------------
@Override
public T deserialize(String messageJson) {
VersionedMessage<T> versionedMessage = gson.fromJson(messageJson, versionedMessageType);
// older style messages not wrapped with VersionedMessage
if (versionedMessage.getVersion() == null) {
Type t = ((ParameterizedType) versionedMessageType).getActualTypeArguments()[0];
versionedMessage = new VersionedMessage<>(MessageVersion.NO_VERSION, gson.<T>fromJson(messageJson, t));
}
checkVersion(versionedMessage, messageJson);
return versionedMessage.getMessage();
}
// ----- helper methods --------------------------------------------------
/**
* Check the message version against the expected version.
*
* @param versionedMessage the versioned message
* @param messageJson the notification message json
*
* @throws IncompatibleVersionException if the message version is incompatable with the expected version
*/
protected void checkVersion(VersionedMessage<T> versionedMessage, String messageJson) {
int comp = versionedMessage.compareVersion(expectedVersion);
// message has newer version
if (comp > 0) {
String msg =
String.format(VERSION_MISMATCH_MSG, expectedVersion, versionedMessage.getVersion(), messageJson);
notificationLogger.error(msg);
throw new IncompatibleVersionException(msg);
}
// message has older version
if (comp < 0) {
notificationLogger.info(String.format(VERSION_MISMATCH_MSG, expectedVersion, versionedMessage.getVersion(),
messageJson));
}
}
}