org.jasig.ssp.util.liquibase.UpdateMessageTemplateAndChecksum.java Source code

Java tutorial

Introduction

Here is the source code for org.jasig.ssp.util.liquibase.UpdateMessageTemplateAndChecksum.java

Source

/**
 * Licensed to Apereo under one or more contributor license
 * agreements. See the NOTICE file distributed with this work
 * for additional information regarding copyright ownership.
 * Apereo 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 the following location:
 *
 *   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.jasig.ssp.util.liquibase;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.apache.commons.lang.StringUtils;

import liquibase.change.custom.CustomSqlChange;
import liquibase.database.Database;
import liquibase.database.jvm.JdbcConnection;
import liquibase.exception.CustomChangeException;
import liquibase.exception.CustomPreconditionErrorException;
import liquibase.exception.SetupException;
import liquibase.exception.ValidationErrors;
import liquibase.resource.ResourceAccessor;
import liquibase.statement.SqlStatement;
import liquibase.statement.core.RawSqlStatement;

/**
 * Use this after a message template has been updated to update the checksum
 * WARNING DO NOT USE UPDATE MESSAGE TEMPLATES WITHOUT VALIDATING CHECKSUMS
 * with {@link MessageTemplateCheckSumPrecondition} or you may override user changes.
 *
 * <p>
 * Example:
 * </p>
 *
 * <pre>
 * {@code <customChange class="org.jasig.ssp.util.liquibase.UpdateMessageTemplateAndChecksum">
 *     <param name="messageTemplateId" value="0b7e484d-44e4-4f0d-8db5-3518d015b495"/>
 *     <param name="columnName" value="body"/>
 *     <param name="columnValue"><![CDATA[ <p>Template Update<p>
 *                             <p>"Please See your advisor" </p>]]>]]</param>
 *   </customChange>
 * }
 * </pre>
 *
 * <p>FULL SAMPLE CHANGE SET:</p>
 *
 * <pre>
 * {@code <changeSet id="sample change set" author="jim.stanley">
 *      <preConditions onFail="MARK_RAN" onFailMessage="Skipping update to message template ">
 *           <customPrecondition className="org.jasig.ssp.util.liquibase.MessageTemplateCheckSumPrecondition">
 *                 <param name="messageTemplateId" value="d6d1f68a-0533-426f-bd0b-d129a92edf81"/>
 *                <param name="columnName" value="subject"/>
 *          </customPrecondition>
 *      </preConditions>
 *       <customChange class="org.jasig.ssp.util.liquibase.UpdateMessageTemplateAndChecksum">
 *               <param name="messageTemplateId" value="d6d1f68a-0533-426f-bd0b-d129a92edf81"/>
 *              <param name="columnName" value="subject"/>
 *              <param name="columnValue"><![CDATA[ <p>Template Update<p>
 *                              <p>"Please See your advisor" </p>]]></param>
 *       </customChange>
 *  </changeSet>
 * }
 * </pre>
 *
 */
public class UpdateMessageTemplateAndChecksum implements CustomSqlChange {

    public static final String DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm:ss.SSS";

    String messageTemplateId;

    String columnName;

    String columnValue;

    Boolean resetChecksum = false;

    private ResourceAccessor resourceAccessor;

    public UpdateMessageTemplateAndChecksum() {
        // TODO Auto-generated constructor stub
    }

    public String getMessageTemplateId() {
        return messageTemplateId;
    }

    public void setMessageTemplateId(String messageTemplateId) {
        this.messageTemplateId = messageTemplateId;
    }

    public String getColumnName() {
        return columnName;
    }

    public void setColumnName(String columnName) {
        this.columnName = columnName;
    }

    public String getColumnValue() {
        return columnValue;
    }

    public void setColumnValue(String columnValue) {
        this.columnValue = columnValue;
    }

    @Override
    public String getConfirmationMessage() {
        return "Checksum updated for " + columnName + " and message template: " + messageTemplateId;

    }

    @Override
    public void setUp() throws SetupException {
        ValidationErrors errors = new ValidationErrors();

        if (StringUtils.isBlank(messageTemplateId))
            errors.addError("MessageTemplateId can not be blank.");
        if (resetChecksum == false && StringUtils.isBlank(columnName))
            errors.addError("columnName can not be blank.");

        if (errors.hasErrors()) {
            throw new SetupException(errors.getErrorMessages().toString());
        }
    }

    @Override
    public void setFileOpener(ResourceAccessor resourceAccessor) {
        this.resourceAccessor = resourceAccessor;
    }

    @Override
    public ValidationErrors validate(Database database) {
        return new ValidationErrors();
    }

    @Override
    public SqlStatement[] generateStatements(Database database) throws CustomChangeException {
        List<SqlStatement> statements = new ArrayList<SqlStatement>();
        if (resetChecksum) {
            final String query = "select " + columnName + " from message_template where id = '" + messageTemplateId
                    + "'";
            columnValue = processQuery(database, query);
        } else {
            //UPDATE COLUMN
            statements.add(new RawSqlStatement("update message_template set " + columnName + " = '" + columnValue
                    + "' where id = '" + messageTemplateId + "'"));
        }
        try {
            String newColumnCheckSum = getCheckSum(StringUtils.deleteWhitespace(columnValue));

            //UPDATE CHECKSUM
            statements.add(new RawSqlStatement("update message_template set " + columnName + "_checksum = '"
                    + newColumnCheckSum + "' where id = '" + messageTemplateId + "'"));
            final SimpleDateFormat df = new SimpleDateFormat(DATE_TIME_FORMAT);
            String newFormattedDate = df.format(new Date());
            statements.add(new RawSqlStatement("update message_template set modified_date = '" + newFormattedDate
                    + "' where id = '" + messageTemplateId + "'"));

        } catch (NoSuchAlgorithmException exp) {
            throw new CustomChangeException("Jave version does not support Message Digest type SHA1", exp);
        }

        return statements.toArray(new SqlStatement[statements.size()]);
    }

    private String processQuery(Database database, String query) throws CustomChangeException {
        PreparedStatement preparedQuery = null;
        ResultSet rs = null;
        CustomPreconditionErrorException error = null;
        try {
            JdbcConnection conn = (JdbcConnection) database.getConnection();
            preparedQuery = conn.prepareStatement(query);
            rs = preparedQuery.executeQuery();
            rs.next();
            return rs.getString(1);
        } catch (Exception e) {
            throw new CustomChangeException("Query [" + query + "] failed", e);
        } finally {
            if (rs != null) {
                try {
                    rs.close();
                } catch (Exception ee) {
                    if (error == null) {
                        throw new CustomChangeException("Failed to cleanup result set after query [" + query + "]",
                                ee);
                    }
                }
            }
            if (preparedQuery != null) {
                try {
                    preparedQuery.close();
                } catch (Exception ee) {
                    if (error == null) {
                        throw new CustomChangeException("Failed to cleanup statement after query [" + query + "]",
                                ee);
                    }
                }
            }
        }
    }

    private String getCheckSum(String value) throws NoSuchAlgorithmException {
        MessageDigest md = MessageDigest.getInstance("SHA1");

        byte[] mdbytes = md.digest(value.getBytes());
        StringBuffer sb = new StringBuffer("");
        for (int i = 0; i < mdbytes.length; i++) {
            sb.append(Integer.toString((mdbytes[i] & 0xff) + 0x100, 16).substring(1));
        }
        return sb.toString();
    }

    public Boolean getResetChecksum() {
        return resetChecksum;
    }

    public void setResetChecksum(Boolean resetChecksum) {
        this.resetChecksum = resetChecksum;
    }

}