package voldemort.rest;
import java.io.IOException;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import org.apache.commons.codec.binary.Base64;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.type.TypeReference;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.input.SAXBuilder;
import org.jdom.output.Format;
import org.jdom.output.XMLOutputter;
import voldemort.serialization.SerializerDefinition;
import voldemort.store.StoreDefinition;
import voldemort.utils.ByteArray;
import voldemort.utils.ByteUtils;
import voldemort.versioning.VectorClock;
import voldemort.versioning.Version;
import voldemort.xml.MappingException;
import voldemort.xml.StoreDefinitionsMapper;
public class RestUtils {
protected final static ObjectMapper mapper = new ObjectMapper();
/**
* Function to serialize the given Vector clock into a string. If something
* goes wrong, it returns an empty string.
*
* @param vc The Vector clock to serialize
* @return The string (JSON) version of the specified Vector clock
*/
public static String getSerializedVectorClock(VectorClock vc) {
VectorClockWrapper vcWrapper = new VectorClockWrapper(vc);
String serializedVC = "";
try {
serializedVC = mapper.writeValueAsString(vcWrapper);
} catch(Exception e) {
e.printStackTrace();
}
return serializedVC;
}
public static VectorClock deserializeVectorClock(String serializedVC) {
VectorClock vc = null;
if(serializedVC == null) {
return null;
}
try {
VectorClockWrapper vcWrapper = mapper.readValue(serializedVC, VectorClockWrapper.class);
vc = new VectorClock(vcWrapper.getVersions(), vcWrapper.getTimestamp());
} catch(Exception e) {
e.printStackTrace();
}
return vc;
}
/**
* Function to serialize the given list of Vector clocks into a string. If
* something goes wrong, it returns an empty string.
*
* @param vectorClocks The Vector clock list to serialize
* @return The string (JSON) version of the specified Vector clock
*/
public static String getSerializedVectorClocks(List<VectorClock> vectorClocks) {
List<VectorClockWrapper> vectorClockWrappers = new ArrayList<VectorClockWrapper>();
for(VectorClock vc: vectorClocks) {
vectorClockWrappers.add(new VectorClockWrapper(vc));
}
String serializedVC = "";
try {
serializedVC = mapper.writeValueAsString(vectorClockWrappers);
} catch(Exception e) {
e.printStackTrace();
}
return serializedVC;
}
public static List<Version> deserializeVectorClocks(String serializedVC) {
Set<VectorClockWrapper> vectorClockWrappers = null;
List<Version> vectorClocks = null;
if(serializedVC == null) {
return null;
}
try {
vectorClockWrappers = mapper.readValue(serializedVC,
new TypeReference<Set<VectorClockWrapper>>() {});
if(vectorClockWrappers.size() > 0) {
vectorClocks = new ArrayList<Version>();
}
for(VectorClockWrapper vectorClockWrapper: vectorClockWrappers) {
vectorClocks.add(new VectorClock(vectorClockWrapper.getVersions(),
vectorClockWrapper.getTimestamp()));
}
} catch(Exception e) {
e.printStackTrace();
}
return vectorClocks;
}
/**
* Given a storedefinition, constructs the xml string to be sent out in
* response to a "schemata" fetch request
*
* @param storeDefinition
* @return serialized store definition
*/
public static String constructSerializerInfoXml(StoreDefinition storeDefinition) {
Element store = new Element(StoreDefinitionsMapper.STORE_ELMT);
store.addContent(new Element(StoreDefinitionsMapper.STORE_NAME_ELMT).setText(storeDefinition.getName()));
Element keySerializer = new Element(StoreDefinitionsMapper.STORE_KEY_SERIALIZER_ELMT);
StoreDefinitionsMapper.addSerializer(keySerializer, storeDefinition.getKeySerializer());
store.addContent(keySerializer);
Element valueSerializer = new Element(StoreDefinitionsMapper.STORE_VALUE_SERIALIZER_ELMT);
StoreDefinitionsMapper.addSerializer(valueSerializer, storeDefinition.getValueSerializer());
store.addContent(valueSerializer);
XMLOutputter serializer = new XMLOutputter(Format.getPrettyFormat());
return serializer.outputString(store);
}
/**
* Given an xml string containing the store's serialization information,
* obtains the key serializer definition
*
* @param serializerInfoXml
* @return key serializer definition
*/
public static SerializerDefinition parseKeySerializerDefinition(String serializerInfoXml) {
return parseSerializerDefinition(serializerInfoXml,
StoreDefinitionsMapper.STORE_KEY_SERIALIZER_ELMT);
}
/**
* Given an xml string containing the store's serialization information,
* obtains the value serializer definition
*
* @param serializerInfoXml
* @return serializer definition
*/
public static SerializerDefinition parseValueSerializerDefinition(String serializerInfoXml) {
return parseSerializerDefinition(serializerInfoXml,
StoreDefinitionsMapper.STORE_VALUE_SERIALIZER_ELMT);
}
private static SerializerDefinition parseSerializerDefinition(String serializerInfoXml,
String elementName) {
SAXBuilder builder = new SAXBuilder();
try {
Document doc = builder.build(new StringReader(serializerInfoXml));
Element root = doc.getRootElement();
Element serializerElement = root.getChild(elementName);
return StoreDefinitionsMapper.readSerializer(serializerElement);
} catch(JDOMException e) {
throw new MappingException(e);
} catch(IOException e) {
throw new MappingException(e);
}
}
public static String encodeVoldemortKey(byte[] keyBytes) {
String base64Key = Base64.encodeBase64URLSafeString(keyBytes);
return base64Key;
}
public static byte[] decodeVoldemortKey(String base64Key) {
byte[] keyBytes = Base64.decodeBase64(base64Key);
return keyBytes;
}
public static String getKeyHexString(ByteArray key) {
String keyStr = "< " + ByteUtils.toHexString(key.get()) + " >";
return keyStr;
}
public static String getKeysHexString(Iterator<ByteArray> keys) {
StringBuilder keysStr = new StringBuilder();
keysStr.append("< ");
if(keys != null) {
ByteArray key = null;
while(keys.hasNext()) {
key = keys.next();
keysStr.append(ByteUtils.toHexString(key.get()) + " ");
}
}
keysStr.append(" >");
return keysStr.toString();
}
}