001// Licensed under the Apache License, Version 2.0 (the "License");
002// you may not use this file except in compliance with the License.
003// You may obtain a copy of the License at
004//
005// http://www.apache.org/licenses/LICENSE-2.0
006//
007// Unless required by applicable law or agreed to in writing, software
008// distributed under the License is distributed on an "AS IS" BASIS,
009// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
010// See the License for the specific language governing permissions and
011// limitations under the License.
012
013package org.apache.tapestry5.internal.services.exceptions;
014
015import org.apache.tapestry5.SymbolConstants;
016import org.apache.tapestry5.ioc.annotations.Inject;
017import org.apache.tapestry5.ioc.annotations.Symbol;
018import org.apache.tapestry5.ioc.internal.util.InternalUtils;
019import org.apache.tapestry5.ioc.util.ExceptionUtils;
020import org.apache.tapestry5.services.ExceptionReportWriter;
021import org.apache.tapestry5.services.ExceptionReporter;
022import org.slf4j.Logger;
023
024import java.io.File;
025import java.io.IOException;
026import java.io.PrintWriter;
027import java.util.Date;
028import java.util.concurrent.atomic.AtomicInteger;
029
030@SuppressWarnings("ResultOfMethodCallIgnored")
031public class ExceptionReporterImpl implements ExceptionReporter
032{
033
034    @Inject
035    @Symbol(SymbolConstants.EXCEPTION_REPORTS_DIR)
036    private File logDir;
037
038    @Inject
039    @Symbol(SymbolConstants.RESTRICTIVE_ENVIRONMENT)
040    private boolean restrictive;
041
042    private final AtomicInteger uid = new AtomicInteger();
043
044    @Inject
045    private Logger logger;
046
047
048    @Inject
049    private ExceptionReportWriter exceptionReportWriter;
050
051    @Override
052    public void reportException(Throwable exception)
053    {
054        Date date = new Date();
055        String fileName = String.format(
056                "exception-%tY%<tm%<td-%<tH%<tM%<tS-%<tL.%d.txt", date,
057                uid.getAndIncrement());
058
059        File folder;
060
061        try
062        {
063            if (restrictive)
064            {
065                // Good luck with this; all exceptions written to a single folder.
066                folder = logDir;
067            } else
068            {
069                String folderName = String.format("%tY-%<tm-%<td/%<tH/%<tM", date);
070                folder = new File(logDir, folderName);
071
072                folder.mkdirs();
073            }
074
075            File log = new File(folder, fileName);
076
077            writeExceptionToFile(exception, log);
078
079            logger.warn(String.format("Wrote exception report to %s", toURI(log)));
080        } catch (Exception ex)
081        {
082            logger.error(String.format("Unable to write exception report %s: %s",
083                    fileName, ExceptionUtils.toMessage(ex)));
084
085            logger.error("Original exception:", exception);
086        }
087    }
088
089    private String toURI(File file)
090    {
091        try
092        {
093            return file.toURI().toString();
094        } catch (Exception e)
095        {
096            return file.toString();
097        }
098    }
099
100    private void writeExceptionToFile(Throwable exception, File log) throws IOException
101    {
102        log.createNewFile();
103
104        PrintWriter writer = null;
105
106        try
107        {
108            writer = new PrintWriter(log);
109            exceptionReportWriter.writeReport(writer, exception);
110        } finally
111        {
112            InternalUtils.close(writer);
113        }
114    }
115
116
117}