001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache license, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the license for the specific language governing permissions and
015 * limitations under the license.
016 */
017package org.apache.logging.log4j.core.appender.rolling.action;
018
019import java.io.IOException;
020
021import org.apache.logging.log4j.Logger;
022import org.apache.logging.log4j.status.StatusLogger;
023
024
025/**
026 * Abstract base class for implementations of Action.
027 */
028public abstract class AbstractAction implements Action {
029
030    /**
031     * Allows subclasses access to the status logger without creating another instance.
032     */
033    protected static final Logger LOGGER = StatusLogger.getLogger();
034    /**
035     * Is action complete.
036     */
037    private boolean complete = false;
038
039    /**
040     * Is action interrupted.
041     */
042    private boolean interrupted = false;
043
044    /**
045     * Constructor.
046     */
047    protected AbstractAction() {
048    }
049
050    /**
051     * Performs action.
052     *
053     * @return true if successful.
054     * @throws IOException if IO error.
055     */
056    @Override
057    public abstract boolean execute() throws IOException;
058
059    /**
060     * {@inheritDoc}
061     */
062    @Override
063    public synchronized void run() {
064        if (!interrupted) {
065            try {
066                execute();
067            } catch (final RuntimeException | IOException ex) {
068                reportException(ex);
069            } catch (final Error e) {
070                // reportException takes Exception, widening to Throwable would break custom implementations
071                // so we wrap Errors in RuntimeException for handling.
072                reportException(new RuntimeException(e));
073            }
074
075            complete = true;
076            interrupted = true;
077        }
078    }
079
080    /**
081     * {@inheritDoc}
082     */
083    @Override
084    public synchronized void close() {
085        interrupted = true;
086    }
087
088    /**
089     * Tests if the action is complete.
090     *
091     * @return true if action is complete.
092     */
093    @Override
094    public boolean isComplete() {
095        return complete;
096    }
097
098    public boolean isInterrupted() {
099        return interrupted;
100    }
101
102    /**
103     * Captures exception.
104     *
105     * @param ex exception.
106     */
107    protected void reportException(final Exception ex) {
108        LOGGER.warn("Exception reported by action '{}'", getClass(), ex);
109    }
110
111}