blob: 4e3c3232a1c9670e74a74a593b1b7745f96f5057 [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.oozie.util;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Objects;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.curator.x.discovery.ServiceInstance;
import org.apache.curator.x.discovery.ServiceInstanceBuilder;
import org.apache.curator.x.discovery.ServiceType;
import org.apache.curator.x.discovery.UriSpec;
import org.apache.curator.x.discovery.details.InstanceSerializer;
// TODO: Workaround for CURATOR-5 (https://issues.apache.org/jira/browse/CURATOR-5)
// Remove this class (code from pull request listed on JIRA) and use regular JsonInstanceSerializer once fixed
// (Otherwise we can't properly serialize objects for the ZK Service Discovery)
public class FixedJsonInstanceSerializer<T> implements InstanceSerializer<T>
{
private final ObjectMapper mMapper;
private final Class<T> mPayloadClass;
/**
* @param payloadClass
* used to validate payloads when deserializing
*/
public FixedJsonInstanceSerializer(final Class<T> payloadClass) {
this(payloadClass, new ObjectMapper());
}
public FixedJsonInstanceSerializer(final Class<T> pPayloadClass, final ObjectMapper pMapper) {
mPayloadClass = pPayloadClass;
mMapper = pMapper;
mMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
}
@Override
public byte[] serialize(final ServiceInstance<T> pInstance) throws Exception {
final ByteArrayOutputStream out = new ByteArrayOutputStream();
mMapper.writeValue(out, pInstance);
return out.toByteArray();
}
private String getTextField(final JsonNode pNode, final String pFieldName) {
Objects.requireNonNull(pNode, "pNode cannot be null");
Objects.requireNonNull(pFieldName, "pFieldName cannot be null");
return pNode.get(pFieldName) != null ? pNode.get(pFieldName).textValue() : null;
}
private Integer getIntegerField(final JsonNode pNode, final String pFieldName) {
Objects.requireNonNull(pNode, "pNode cannot be null");
Objects.requireNonNull(pFieldName, "pFieldName cannot be null");
return (pNode.get(pFieldName) != null && pNode.get(pFieldName).isNumber()) ? pNode.get(pFieldName)
.intValue() : null;
}
private Long getLongField(final JsonNode pNode, final String pFieldName) {
Objects.requireNonNull(pNode, "pNode cannot be null");
Objects.requireNonNull(pFieldName, "pFieldName cannot be null");
return (pNode.get(pFieldName) != null && pNode.get(pFieldName).isLong()) ? pNode.get(pFieldName).longValue()
: null;
}
private <O> O getObject(final JsonNode pNode, final String pFieldName, final Class<O> pObjectClass)
throws JsonParseException, JsonMappingException, IOException {
Objects.requireNonNull(pNode, "pNode cannot be null");
Objects.requireNonNull(pFieldName, "pFieldName cannot be null");
Objects.requireNonNull(pObjectClass, "pObjectClass cannot be null");
if (pNode.get(pFieldName) != null && pNode.get(pFieldName).isObject()) {
return mMapper.readValue(pNode.get(pFieldName).toString(), pObjectClass);
} else {
return null;
}
}
@Override
public ServiceInstance<T> deserialize(final byte[] pBytes) throws Exception {
final ByteArrayInputStream bais = new ByteArrayInputStream(pBytes);
final JsonNode rootNode = mMapper.readTree(bais);
final ServiceInstanceBuilder<T> builder = ServiceInstance.builder();
{
final String address = getTextField(rootNode, "address");
if (address != null) {
builder.address(address);
}
}
{
final String id = getTextField(rootNode, "id");
if (id != null) {
builder.id(id);
}
}
{
final String name = getTextField(rootNode, "name");
if (name != null) {
builder.name(name);
}
}
{
final Integer port = getIntegerField(rootNode, "port");
if (port != null) {
builder.port(port);
}
}
{
final Integer sslPort = getIntegerField(rootNode, "sslPort");
if (sslPort != null) {
builder.sslPort(sslPort);
}
}
{
final Long registrationTimeUTC = getLongField(rootNode, "registrationTimeUTC");
if (registrationTimeUTC != null) {
builder.registrationTimeUTC(registrationTimeUTC);
}
}
{
final T payload = getObject(rootNode, "payload", mPayloadClass);
if (payload != null) {
builder.payload(payload);
}
}
{
final ServiceType serviceType = getObject(rootNode, "serviceType", ServiceType.class);
if (serviceType != null) {
builder.serviceType(serviceType);
}
}
{
final UriSpec uriSpec = getObject(rootNode, "uriSpec", UriSpec.class);
if (uriSpec != null) {
builder.uriSpec(uriSpec);
}
}
return builder.build();
}
}