/** * AnalyzerBeans * Copyright (C) 2014 Neopost - Customer Information Management * * 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, write to: * Free Software Foundation, Inc. * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ package org.eobjects.analyzer.job.runner; import java.sql.SQLException; import java.util.ArrayList; import java.util.LinkedList; import java.util.List; import java.util.concurrent.atomic.AtomicBoolean; import org.eobjects.analyzer.data.InputRow; import org.eobjects.analyzer.job.AnalysisJob; import org.eobjects.analyzer.job.AnalyzerJob; import org.eobjects.analyzer.job.FilterJob; import org.eobjects.analyzer.job.TransformerJob; import org.eobjects.analyzer.job.concurrent.PreviousErrorsExistException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * AnalysisListener that will register errors * * */ final class ErrorAwareAnalysisListener extends AnalysisListenerAdaptor implements ErrorAware { private static final Logger logger = LoggerFactory.getLogger(ErrorAwareAnalysisListener.class); private final List<Throwable> _errors = new LinkedList<Throwable>(); private final AtomicBoolean _cancelled = new AtomicBoolean(false); protected void handleError(AnalysisJob job, Throwable throwable) { if (throwable instanceof AnalysisJobCancellation) { _cancelled.set(true); } if (!(throwable instanceof PreviousErrorsExistException)) { logger.warn("Exception stack trace:", throwable); } synchronized (_errors) { if (!_errors.contains(throwable)) { _errors.add(throwable); } } // check for SQLException.getNextException() which is particularly // important and unfortunately NOT included by default in stack traces. Throwable t = throwable; while (t != null) { if (t instanceof SQLException) { SQLException nextException = ((SQLException) t).getNextException(); if (nextException != null) { logger.warn("SQLException.getNextException() stack trace:", nextException); } } t = t.getCause(); } } @Override public List<Throwable> getErrors() { // create a copy to avoid mutations or concurrent modifications final List<Throwable> result; synchronized (_errors) { result = new ArrayList<Throwable>(_errors); } return result; } @Override public boolean isErrornous() { synchronized (_errors) { return !_errors.isEmpty(); } } @Override public void errorInFilter(AnalysisJob job, FilterJob filterJob, InputRow row, Throwable throwable) { logger.warn("errorInFilter({},{},{},{})", new Object[] { job, filterJob, row, throwable }); handleError(job, throwable); } @Override public void errorInTransformer(AnalysisJob job, TransformerJob transformerJob, InputRow row, Throwable throwable) { logger.warn("errorInTransformer({},{},{},{})", new Object[] { job, transformerJob, row, throwable }); handleError(job, throwable); } @Override public void errorInAnalyzer(AnalysisJob job, AnalyzerJob analyzerJob, InputRow row, Throwable throwable) { logger.warn("errorInAnalyzer({},{},{},{})", new Object[] { job, analyzerJob, row, throwable }); handleError(job, throwable); } @Override public void errorUknown(AnalysisJob job, Throwable throwable) { logger.warn("errorUnknown({},{})", new Object[] { job, throwable }); handleError(job, throwable); } @Override public boolean isCancelled() { return _cancelled.get(); } }