/*
* Copyright 2014-2016 CyberVision, Inc.
*
* 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.
*/
package org.kaaproject.kaa.server.transport;
import org.apache.avro.specific.SpecificRecordBase;
import org.kaaproject.kaa.common.avro.AvroByteArrayConverter;
import org.kaaproject.kaa.server.transport.message.MessageHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.nio.charset.Charset;
import java.text.MessageFormat;
import java.util.Arrays;
import java.util.List;
/**
* Abstract implementation of {@link Transport} that handles deserialization of
* binary configuration.
*
* @param <T> specific configuration record type
* @author Andrew Shvayka
*/
public abstract class AbstractKaaTransport<T extends SpecificRecordBase> implements Transport {
protected static final int SIZE_OF_INT = 4;
protected static final String BIND_INTERFACE_PROP_NAME = "transport_bind_interface";
protected static final String PUBLIC_INTERFACE_PROP_NAME = "transport_public_interface";
protected static final String LOCALHOST = "localhost";
private static final Logger LOG = LoggerFactory.getLogger(AbstractKaaTransport.class);
private static final Charset UTF8 = Charset.forName("UTF-8");
protected MessageHandler handler;
protected SpecificTransportContext<T> context;
/*
* (non-Javadoc)
*
* @see org.kaaproject.kaa.server.transport.Transport#init(byte[])
*/
@Override
public void init(GenericTransportContext context) throws TransportLifecycleException {
this.handler = context.getHandler();
AvroByteArrayConverter<T> converter = new AvroByteArrayConverter<>(getConfigurationClass());
try {
T config = converter.fromByteArray(context.getConfiguration());
LOG.info("Initializing transport {} with {}", getClassName(), config);
this.context = new SpecificTransportContext<T>(context, config);
init(this.context);
LOG.info("Transport {} initialized with {}", getClassName(), this.context.getConfiguration());
} catch (IOException ex) {
LOG.error(MessageFormat.format("Failed to initialize transport {0}", getClassName()), ex);
throw new TransportLifecycleException(ex);
}
}
/**
* Initializes the transport with specified context.
*
* @param context the initialization context
*/
protected abstract void init(SpecificTransportContext<T> context)
throws TransportLifecycleException;
@Override
public TransportMetaData getConnectionInfo() {
LOG.info("Serializing connection info");
List<byte[]> buffs = getSerializedConnectionInfoList();
for (byte[] buf : buffs) {
LOG.trace("Serialized connection info is {}", Arrays.toString(buf));
}
return new TransportMetaData(getMinSupportedVersion(), getMaxSupportedVersion(), buffs);
}
/**
* Gets the configuration class.
*
* @return the configuration class
*/
public abstract Class<T> getConfigurationClass();
protected abstract List<byte[]> getSerializedConnectionInfoList();
protected abstract int getMinSupportedVersion();
protected abstract int getMaxSupportedVersion();
private String getClassName() {
return this.getClass().getName();
}
protected String replaceProperty(String source, String propertyName, String propertyValue) {
return source.replace("${" + propertyName + "}", propertyValue);
}
protected byte[] toUtf8Bytes(String str) {
return str.getBytes(UTF8);
}
}