/* 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.pig.backend.hadoop.accumulo; import java.io.ByteArrayInputStream; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.math.BigDecimal; import java.math.BigInteger; import java.util.Map; import org.apache.accumulo.core.Constants; import org.apache.pig.LoadStoreCaster; import org.apache.pig.ResourceSchema.ResourceFieldSchema; import org.apache.pig.backend.executionengine.ExecException; import org.apache.pig.data.DataBag; import org.apache.pig.data.DataByteArray; import org.apache.pig.data.Tuple; import org.joda.time.DateTime; import com.google.common.base.Preconditions; /** * A LoadStoreCaster implementation which stores most type implementations as * bytes generated from the toString representation with a UTF8 Charset. Pulled * some implementations from the Accumulo Lexicoder implementations in 1.6.0. */ public class AccumuloBinaryConverter implements LoadStoreCaster { private static final int SIZE_OF_INT = Integer.SIZE / Byte.SIZE; private static final int SIZE_OF_LONG = Long.SIZE / Byte.SIZE; /** * NOT IMPLEMENTED */ @Override public DataBag bytesToBag(byte[] b, ResourceFieldSchema fieldSchema) throws IOException { throw new ExecException("Can't generate DataBags from byte[]"); } @Override public BigDecimal bytesToBigDecimal(byte[] b) throws IOException { throw new ExecException("Can't generate a BigInteger from byte[]"); } @Override public BigInteger bytesToBigInteger(byte[] b) throws IOException { // Taken from Accumulo's BigIntegerLexicoder in 1.6.0 DataInputStream dis = new DataInputStream(new ByteArrayInputStream(b)); int len = dis.readInt(); len = len ^ 0x80000000; len = Math.abs(len); byte[] bytes = new byte[len]; dis.readFully(bytes); bytes[0] = (byte) (0x80 ^ bytes[0]); return new BigInteger(bytes); } @Override public Boolean bytesToBoolean(byte[] b) throws IOException { Preconditions.checkArgument(1 == b.length); return b[0] == (byte) 1; } @Override public String bytesToCharArray(byte[] b) throws IOException { return new String(b, Constants.UTF8); } /** * NOT IMPLEMENTED */ @Override public DateTime bytesToDateTime(byte[] b) throws IOException { String s = new String(b, Constants.UTF8); return DateTime.parse(s); } @Override public Double bytesToDouble(byte[] b) throws IOException { return Double.longBitsToDouble(bytesToLong(b)); } @Override public Float bytesToFloat(byte[] b) throws IOException { return Float.intBitsToFloat(bytesToInteger(b)); } @Override public Integer bytesToInteger(byte[] b) throws IOException { Preconditions.checkArgument(b.length == SIZE_OF_INT); int n = 0; for (int i = 0; i < b.length; i++) { n <<= 8; n ^= b[i] & 0xFF; } return n; } @Override public Long bytesToLong(byte[] b) throws IOException { Preconditions.checkArgument(b.length == SIZE_OF_LONG); long l = 0; for (int i = 0; i < b.length; i++) { l <<= 8; l ^= b[i] & 0xFF; } return l; } /** * NOT IMPLEMENTED */ @Override public Map<String, Object> bytesToMap(byte[] b, ResourceFieldSchema fieldSchema) throws IOException { throw new ExecException("Can't generate Map from byte[]"); } /** * NOT IMPLEMENTED */ @Override public Tuple bytesToTuple(byte[] b, ResourceFieldSchema fieldSchema) throws IOException { throw new ExecException("Can't generate a Tuple from byte[]"); } /** * Not implemented! */ @Override public byte[] toBytes(BigDecimal bd) throws IOException { throw new IOException("Can't generate bytes from BigDecimal"); } @Override public byte[] toBytes(BigInteger bi) throws IOException { // Taken from Accumulo's BigIntegerLexicoder in 1.6.0 byte[] bytes = bi.toByteArray(); byte[] ret = new byte[4 + bytes.length]; DataOutputStream dos = new DataOutputStream( new FixedByteArrayOutputStream(ret)); // flip the sign bit bytes[0] = (byte) (0x80 ^ bytes[0]); int len = bytes.length; if (bi.signum() < 0) len = -len; len = len ^ 0x80000000; try { dos.writeInt(len); dos.write(bytes); } finally { dos.close(); } return ret; } @Override public byte[] toBytes(Boolean b) throws IOException { return new byte[] { b ? (byte) 1 : (byte) 0 }; } /** * NOT IMPLEMENTED */ @Override public byte[] toBytes(DataBag bag) throws IOException { throw new ExecException("Cant' generate bytes from DataBag"); } @Override public byte[] toBytes(DataByteArray a) throws IOException { return a.get(); } @Override public byte[] toBytes(DateTime dt) throws IOException { return dt.toString().getBytes(Constants.UTF8); } @Override public byte[] toBytes(Double d) throws IOException { return toBytes(Double.doubleToRawLongBits(d)); } @Override public byte[] toBytes(Float f) throws IOException { return toBytes(Float.floatToRawIntBits(f)); } @Override public byte[] toBytes(Integer val) throws IOException { int intVal = val.intValue(); byte[] b = new byte[4]; for (int i = 3; i > 0; i--) { b[i] = (byte) intVal; intVal >>>= 8; } b[0] = (byte) intVal; return b; } @Override public byte[] toBytes(Long val) throws IOException { long longVal = val.longValue(); byte[] b = new byte[8]; for (int i = 7; i > 0; i--) { b[i] = (byte) longVal; longVal >>>= 8; } b[0] = (byte) longVal; return b; } /** * NOT IMPLEMENTED */ @Override public byte[] toBytes(Map<String, Object> m) throws IOException { throw new IOException("Can't generate bytes from Map"); } @Override public byte[] toBytes(String s) throws IOException { return s.getBytes(Constants.UTF8); } /** * NOT IMPLEMENTED */ @Override public byte[] toBytes(Tuple t) throws IOException { throw new IOException("Can't generate bytes from Tuple"); } }