org.bytesoft.bytejta.logging.SampleTransactionLogger.java Source code

Java tutorial

Introduction

Here is the source code for org.bytesoft.bytejta.logging.SampleTransactionLogger.java

Source

/**
 * Copyright 2014-2016 yangming.liu<bytefox@126.com>.
 *
 * This copyrighted material is made available to anyone wishing to use, modify,
 * copy, or redistribute it subject to the terms and conditions of the GNU
 * Lesser General Public License, as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
 * for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this distribution; if not, see <http://www.gnu.org/licenses/>.
 */
package org.bytesoft.bytejta.logging;

import java.io.File;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.transaction.xa.Xid;

import org.apache.commons.lang3.StringUtils;
import org.bytesoft.bytejta.logging.store.VirtualLoggingSystemImpl;
import org.bytesoft.transaction.TransactionBeanFactory;
import org.bytesoft.transaction.archive.TransactionArchive;
import org.bytesoft.transaction.archive.XAResourceArchive;
import org.bytesoft.transaction.aware.TransactionBeanFactoryAware;
import org.bytesoft.transaction.aware.TransactionEndpointAware;
import org.bytesoft.transaction.logging.ArchiveDeserializer;
import org.bytesoft.transaction.logging.LoggingFlushable;
import org.bytesoft.transaction.logging.TransactionLogger;
import org.bytesoft.transaction.logging.store.VirtualLoggingListener;
import org.bytesoft.transaction.logging.store.VirtualLoggingRecord;
import org.bytesoft.transaction.logging.store.VirtualLoggingSystem;
import org.bytesoft.transaction.recovery.TransactionRecoveryCallback;
import org.bytesoft.transaction.xa.TransactionXid;
import org.bytesoft.transaction.xa.XidFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class SampleTransactionLogger extends VirtualLoggingSystemImpl
        implements TransactionLogger, LoggingFlushable, TransactionBeanFactoryAware, TransactionEndpointAware {
    static final Logger logger = LoggerFactory.getLogger(SampleTransactionLogger.class);

    private TransactionBeanFactory beanFactory;
    private String endpoint;

    public void createTransaction(TransactionArchive archive) {
        ArchiveDeserializer deserializer = this.beanFactory.getArchiveDeserializer();

        try {
            byte[] byteArray = deserializer.serialize((TransactionXid) archive.getXid(), archive);
            this.create(archive.getXid(), byteArray);
        } catch (RuntimeException rex) {
            logger.error("Error occurred while creating transaction-archive.", rex);
        }
    }

    public void updateTransaction(TransactionArchive archive) {
        ArchiveDeserializer deserializer = this.beanFactory.getArchiveDeserializer();

        try {
            byte[] byteArray = deserializer.serialize((TransactionXid) archive.getXid(), archive);
            this.modify(archive.getXid(), byteArray);
        } catch (RuntimeException rex) {
            logger.error("Error occurred while modifying transaction-archive.", rex);
        }
    }

    public void deleteTransaction(TransactionArchive archive) {
        try {
            this.delete(archive.getXid());
        } catch (RuntimeException rex) {
            logger.error("Error occurred while deleting transaction-archive.", rex);
        }
    }

    public void updateResource(XAResourceArchive archive) {
        ArchiveDeserializer deserializer = this.beanFactory.getArchiveDeserializer();

        try {
            byte[] byteArray = deserializer.serialize((TransactionXid) archive.getXid(), archive);
            this.modify(archive.getXid(), byteArray);
        } catch (RuntimeException rex) {
            logger.error("Error occurred while modifying resource-archive.", rex);
        }
    }

    public void recover(TransactionRecoveryCallback callback) {

        final Map<Xid, TransactionArchive> xidMap = new HashMap<Xid, TransactionArchive>();
        final ArchiveDeserializer deserializer = this.beanFactory.getArchiveDeserializer();
        final XidFactory xidFactory = this.beanFactory.getXidFactory();

        this.traversal(new VirtualLoggingListener() {
            public void recvOperation(VirtualLoggingRecord action) {
                Xid xid = action.getIdentifier();
                int operator = action.getOperator();
                if (VirtualLoggingSystem.OPERATOR_DELETE == operator) {
                    xidMap.remove(xid);
                } else if (xidMap.containsKey(xid) == false) {
                    xidMap.put(xid, null);
                }
            }
        });

        this.traversal(new VirtualLoggingListener() {
            public void recvOperation(VirtualLoggingRecord action) {
                Xid xid = action.getIdentifier();
                if (xidMap.containsKey(xid)) {
                    this.execOperation(action);
                }
            }

            public void execOperation(VirtualLoggingRecord action) {
                Xid identifier = action.getIdentifier();

                TransactionXid xid = xidFactory.createGlobalXid(identifier.getGlobalTransactionId());

                Object obj = deserializer.deserialize(xid, action.getValue());
                if (TransactionArchive.class.isInstance(obj)) {
                    TransactionArchive archive = (TransactionArchive) obj;
                    xidMap.put(identifier, archive);
                } else if (XAResourceArchive.class.isInstance(obj)) {
                    TransactionArchive archive = xidMap.get(identifier);
                    if (archive == null) {
                        logger.error("Error occurred while recovering resource archive: {}", obj);
                        return;
                    }

                    XAResourceArchive resourceArchive = (XAResourceArchive) obj;
                    boolean matched = false;

                    List<XAResourceArchive> nativeResources = archive.getNativeResources();
                    for (int i = 0; matched == false && nativeResources != null
                            && i < nativeResources.size(); i++) {
                        XAResourceArchive element = nativeResources.get(i);
                        if (resourceArchive.getXid().equals(element.getXid())) {
                            matched = true;
                            nativeResources.set(i, resourceArchive);
                        }
                    }

                    XAResourceArchive optimizedResource = archive.getOptimizedResource();
                    if (matched == false && optimizedResource != null) {
                        if (resourceArchive.getXid().equals(optimizedResource.getXid())) {
                            matched = true;
                            archive.setOptimizedResource(resourceArchive);
                        }
                    }

                    List<XAResourceArchive> remoteResources = archive.getRemoteResources();
                    for (int i = 0; matched == false && remoteResources != null
                            && i < remoteResources.size(); i++) {
                        XAResourceArchive element = remoteResources.get(i);
                        if (resourceArchive.getXid().equals(element.getXid())) {
                            matched = true;
                            remoteResources.set(i, resourceArchive);
                        }
                    }

                    if (matched == false) {
                        logger.error("Error occurred while recovering resource archive: {}, invalid resoure!", obj);
                    }

                }

            }
        });

        for (Iterator<Map.Entry<Xid, TransactionArchive>> itr = xidMap.entrySet().iterator(); itr.hasNext();) {
            Map.Entry<Xid, TransactionArchive> entry = itr.next();
            TransactionArchive archive = entry.getValue();
            if (archive == null) {
                continue;
            } else {
                try {
                    callback.recover(archive);
                } catch (RuntimeException rex) {
                    logger.error("Error occurred while recovering transaction(xid= {}).", archive.getXid(), rex);
                }
            }
        }

    }

    public File getDefaultDirectory() {
        String address = StringUtils.trimToEmpty(this.endpoint);
        File directory = new File(String.format("bytejta/%s", address.replaceAll("[^a-zA-Z0-9]", "_")));
        if (directory.exists() == false) {
            try {
                directory.mkdirs();
            } catch (SecurityException ex) {
                logger.error("Error occurred while creating directory {}!", directory.getAbsolutePath(), ex);
            }
        }
        return directory;
    }

    public String getLoggingFilePrefix() {
        return "bytejta-";
    }

    public String getLoggingIdentifier() {
        return "org.bytesoft.bytejta.logging.sample";
    }

    public void setEndpoint(String identifier) {
        this.endpoint = identifier;
    }

    public TransactionBeanFactory getBeanFactory() {
        return beanFactory;
    }

    public void setBeanFactory(TransactionBeanFactory beanFactory) {
        this.beanFactory = beanFactory;
    }

}