Java tutorial
/*! ****************************************************************************** * * Pentaho Data Integration * * Copyright (C) 2002-2013 by Pentaho : http://www.pentaho.com * ******************************************************************************* * * 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.pentaho.di.trans.steps.checksum; import java.security.MessageDigest; import java.util.zip.Adler32; import java.util.zip.CRC32; import org.apache.commons.codec.binary.Hex; import org.pentaho.di.core.Const; import org.pentaho.di.core.exception.KettleException; import org.pentaho.di.core.row.RowDataUtil; import org.pentaho.di.i18n.BaseMessages; import org.pentaho.di.trans.Trans; import org.pentaho.di.trans.TransMeta; import org.pentaho.di.trans.step.BaseStep; import org.pentaho.di.trans.step.StepDataInterface; import org.pentaho.di.trans.step.StepInterface; import org.pentaho.di.trans.step.StepMeta; import org.pentaho.di.trans.step.StepMetaInterface; /** * Caculate a checksum for each row. * * @author Samatar Hassan * @since 30-06-2008 */ public class CheckSum extends BaseStep implements StepInterface { private static Class<?> PKG = CheckSumMeta.class; // for i18n purposes, needed by Translator2!! private CheckSumMeta meta; private CheckSumData data; public CheckSum(StepMeta stepMeta, StepDataInterface stepDataInterface, int copyNr, TransMeta transMeta, Trans trans) { super(stepMeta, stepDataInterface, copyNr, transMeta, trans); } public boolean processRow(StepMetaInterface smi, StepDataInterface sdi) throws KettleException { meta = (CheckSumMeta) smi; data = (CheckSumData) sdi; Object[] r = getRow(); // get row, set busy! if (r == null) { // no more input to be expected... setOutputDone(); return false; } if (first) { first = false; data.outputRowMeta = getInputRowMeta().clone(); data.nrInfields = data.outputRowMeta.size(); meta.getFields(data.outputRowMeta, getStepname(), null, null, this, repository, metaStore); if (meta.getFieldName() == null || meta.getFieldName().length > 0) { data.fieldnrs = new int[meta.getFieldName().length]; for (int i = 0; i < meta.getFieldName().length; i++) { data.fieldnrs[i] = getInputRowMeta().indexOfValue(meta.getFieldName()[i]); if (data.fieldnrs[i] < 0) { logError(BaseMessages.getString(PKG, "CheckSum.Log.CanNotFindField", meta.getFieldName()[i])); throw new KettleException(BaseMessages.getString(PKG, "CheckSum.Log.CanNotFindField", meta.getFieldName()[i])); } } } else { data.fieldnrs = new int[r.length]; for (int i = 0; i < r.length; i++) { data.fieldnrs[i] = i; } } data.fieldnr = data.fieldnrs.length; try { if (meta.getCheckSumType().equals(CheckSumMeta.TYPE_MD5) || meta.getCheckSumType().equals(CheckSumMeta.TYPE_SHA1)) { data.digest = MessageDigest.getInstance(meta.getCheckSumType()); } } catch (Exception e) { throw new KettleException(BaseMessages.getString(PKG, "CheckSum.Error.Digest"), e); } } // end if first Object[] outputRowData = null; try { if (meta.getCheckSumType().equals(CheckSumMeta.TYPE_ADLER32) || meta.getCheckSumType().equals(CheckSumMeta.TYPE_CRC32)) { // get checksum Long checksum = calculCheckSum(r); outputRowData = RowDataUtil.addValueData(r, data.nrInfields, checksum); } else { // get checksum byte[] o = createCheckSum(r); switch (meta.getResultType()) { case CheckSumMeta.result_TYPE_BINARY: outputRowData = RowDataUtil.addValueData(r, data.nrInfields, o); break; case CheckSumMeta.result_TYPE_HEXADECIMAL: String hex = meta.isCompatibilityMode() ? byteToHexEncode_compatible(o) : new String(Hex.encodeHex(o)); outputRowData = RowDataUtil.addValueData(r, data.nrInfields, hex); break; default: outputRowData = RowDataUtil.addValueData(r, data.nrInfields, getStringFromBytes(o)); break; } } if (checkFeedback(getLinesRead())) { if (log.isDetailed()) { logDetailed(BaseMessages.getString(PKG, "CheckSum.Log.LineNumber", "" + getLinesRead())); } } // add new values to the row. putRow(data.outputRowMeta, outputRowData); // copy row to output // rowset(s); } catch (Exception e) { boolean sendToErrorRow = false; String errorMessage = null; if (getStepMeta().isDoingErrorHandling()) { sendToErrorRow = true; errorMessage = e.toString(); } else { logError(BaseMessages.getString(PKG, "CheckSum.ErrorInStepRunning") + e.getMessage()); setErrors(1); stopAll(); setOutputDone(); // signal end to receiver(s) return false; } if (sendToErrorRow) { // Simply add this row to the error row putError(getInputRowMeta(), r, 1, errorMessage, meta.getResultFieldName(), "CheckSum001"); } } return true; } private byte[] createCheckSum(Object[] r) throws Exception { StringBuffer Buff = new StringBuffer(); // Loop through fields for (int i = 0; i < data.fieldnr; i++) { String fieldvalue = getInputRowMeta().getString(r, data.fieldnrs[i]); Buff.append(fieldvalue); } // Updates the digest using the specified array of bytes data.digest.update(Buff.toString().getBytes()); // Completes the hash computation by performing final operations such as padding byte[] hash = data.digest.digest(); // After digest has been called, the MessageDigest object is reset to its initialized state return hash; } private static String getStringFromBytes(byte[] bytes) { StringBuffer sb = new StringBuffer(); for (int i = 0; i < bytes.length; i++) { byte b = bytes[i]; sb.append(0x00FF & b); if (i + 1 < bytes.length) { sb.append("-"); } } return sb.toString(); } public String byteToHexEncode_compatible(byte[] in) { if (in == null) { return null; } final char[] hexDigits = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; String hex = new String(in); char[] s = hex.toCharArray(); StringBuffer hexString = new StringBuffer(2 * s.length); for (int i = 0; i < s.length; i++) { hexString.append(hexDigits[(s[i] & 0x00F0) >> 4]); // hi nibble hexString.append(hexDigits[s[i] & 0x000F]); // lo nibble } return hexString.toString(); } private Long calculCheckSum(Object[] r) throws Exception { Long retval; StringBuffer Buff = new StringBuffer(); // Loop through fields for (int i = 0; i < data.fieldnr; i++) { String fieldvalue = getInputRowMeta().getString(r, data.fieldnrs[i]); Buff.append(fieldvalue); } if (meta.getCheckSumType().equals(CheckSumMeta.TYPE_CRC32)) { CRC32 crc32 = new CRC32(); crc32.update(Buff.toString().getBytes()); retval = new Long(crc32.getValue()); } else { Adler32 adler32 = new Adler32(); adler32.update(Buff.toString().getBytes()); retval = new Long(adler32.getValue()); } return retval; } public boolean init(StepMetaInterface smi, StepDataInterface sdi) { meta = (CheckSumMeta) smi; data = (CheckSumData) sdi; if (super.init(smi, sdi)) { if (Const.isEmpty(meta.getResultFieldName())) { logError(BaseMessages.getString(PKG, "CheckSum.Error.ResultFieldMissing")); return false; } return true; } return false; } }