io.cloudslang.lang.logging.LoggingServiceImpl.java Source code

Java tutorial

Introduction

Here is the source code for io.cloudslang.lang.logging.LoggingServiceImpl.java

Source

/*******************************************************************************
 * (c) Copyright 2016 Hewlett-Packard Development Company, L.P.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Apache License v2.0 which accompany this distribution.
 *
 * The Apache License is available at
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 *******************************************************************************/
package io.cloudslang.lang.logging;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.DisposableBean;

import javax.annotation.PostConstruct;
import java.util.concurrent.Future;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

import static java.util.concurrent.Executors.newFixedThreadPool;
import static org.apache.log4j.Level.DEBUG;
import static org.apache.log4j.Level.ERROR;
import static org.apache.log4j.Level.FATAL;
import static org.apache.log4j.Level.INFO;
import static org.apache.log4j.Level.TRACE;
import static org.apache.log4j.Level.WARN;

/**
 * Implements a logging service that is asynchronous with respect to the caller
 */
public class LoggingServiceImpl implements LoggingService, DisposableBean {
    private static final Logger logger = Logger.getLogger(LoggingServiceImpl.class);

    private ThreadPoolExecutor singleThreadExecutor;

    @PostConstruct
    public void initialize() {
        singleThreadExecutor = (ThreadPoolExecutor) newFixedThreadPool(1); // one thread only
    }

    @Override
    public Future<?> logEvent(Level level, String message) {
        return doLogEvent(level, message, null);
    }

    @Override
    public Future<?> logEvent(Level level, String message, Throwable throwable) {
        return doLogEvent(level, message, throwable);
    }

    @Override
    public void destroy() throws Exception {
        singleThreadExecutor.shutdown();
        singleThreadExecutor = null;
    }

    private Future<?> doLogEvent(Level level, String message, Throwable throwable) {
        try {
            return doSubmit(level, message, throwable);
        } catch (RejectedExecutionException rejectedExecutionException) {
            try {
                return doSubmit(level, message, throwable);
            } catch (RejectedExecutionException rejectedExecutionException2) {
                // try twice and fail
            }
        }
        return null;
    }

    private Future<?> doSubmit(Level level, String message, Throwable throwable) {
        return singleThreadExecutor
                .submit((throwable != null) ? new LoggingDetailsRunnable(level, message, throwable)
                        : new LoggingDetailsRunnable(level, message));
    }

    @Override
    public void waitForAllLogTasksToFinish() {
        try {
            singleThreadExecutor.shutdown();
            singleThreadExecutor.awaitTermination(1, TimeUnit.MINUTES);
        } catch (InterruptedException ignore) {
        }
    }

    static class LoggingDetailsRunnable implements Runnable {
        private final Level level;
        private final String message;
        private final Throwable exception;

        LoggingDetailsRunnable(Level level, String message, Throwable t) {
            this.level = level;
            this.message = message;
            this.exception = t;
        }

        LoggingDetailsRunnable(Level level, String message) {
            this(level, message, null);
        }

        @Override
        public void run() {
            try {
                String localMessage = StringUtils.isEmpty(message) ? "" : message;
                final Throwable throwable = exception;
                if (exception == null) {
                    if (level == TRACE) {
                        if (logger.isTraceEnabled()) {
                            logger.trace(localMessage);
                        }
                    } else if (level == DEBUG) {
                        if (logger.isDebugEnabled()) {
                            logger.debug(localMessage);
                        }
                    } else if (level == INFO) {
                        logger.info(localMessage);
                    } else if (level == WARN) {
                        logger.warn(localMessage);
                    } else if (level == ERROR) {
                        logger.error(localMessage);
                    } else if (level == FATAL) {
                        logger.fatal(localMessage);
                    }
                } else {
                    if (level == TRACE) {
                        if (logger.isTraceEnabled()) {
                            logger.trace(localMessage, throwable);
                        }
                    } else if (level == DEBUG) {
                        if (logger.isDebugEnabled()) {
                            logger.debug(localMessage, throwable);
                        }
                    } else if (level == INFO) {
                        logger.info(localMessage, throwable);
                    } else if (level == WARN) {
                        logger.warn(localMessage, throwable);
                    } else if (level == ERROR) {
                        logger.error(localMessage, throwable);
                    } else if (level == FATAL) {
                        logger.fatal(localMessage, throwable);
                    }
                }
            } catch (Exception ignore) {
                // so that this thread does not die
            }
        }

        @Override
        public boolean equals(Object obj) {
            if (obj == null) {
                return false;
            }
            if (obj == this) {
                return true;
            }
            if (obj.getClass() != getClass()) {
                return false;
            }
            LoggingDetailsRunnable rhs = (LoggingDetailsRunnable) obj;
            return new EqualsBuilder().append(this.level, rhs.level).append(this.message, rhs.message)
                    .append(this.exception, rhs.exception).isEquals();
        }

        @Override
        public int hashCode() {
            return new HashCodeBuilder().append(level).append(message).append(exception).toHashCode();
        }
    }

}