001// Copyright 2008-2013 The Apache Software Foundation
002//
003// Licensed under the Apache License, Version 2.0 (the "License");
004// you may not use this file except in compliance with the License.
005// You may obtain a copy of the License at
006//
007// http://www.apache.org/licenses/LICENSE-2.0
008//
009// Unless required by applicable law or agreed to in writing, software
010// distributed under the License is distributed on an "AS IS" BASIS,
011// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
012// See the License for the specific language governing permissions and
013// limitations under the License.
014
015package org.apache.tapestry5.corelib.components;
016
017import org.apache.tapestry5.annotations.Import;
018import org.apache.tapestry5.annotations.Parameter;
019import org.apache.tapestry5.annotations.Property;
020import org.apache.tapestry5.ioc.annotations.Inject;
021import org.apache.tapestry5.ioc.annotations.Primary;
022import org.apache.tapestry5.ioc.services.ExceptionAnalysis;
023import org.apache.tapestry5.ioc.services.ExceptionAnalyzer;
024import org.apache.tapestry5.ioc.services.ExceptionInfo;
025import org.apache.tapestry5.services.StackTraceElementAnalyzer;
026import org.apache.tapestry5.services.StackTraceElementClassConstants;
027
028import java.util.List;
029
030/**
031 * Integral part of the default {@link org.apache.tapestry5.corelib.pages.ExceptionReport} page used to break apart and
032 * display the properties of the exception.
033 *
034 * @tapestrydoc
035 * @see org.apache.tapestry5.ioc.services.ExceptionAnalyzer
036 */
037@Import(stylesheet = "ExceptionDisplay.css", module = "t5/core/exception-display")
038public class ExceptionDisplay
039{
040    /**
041     * Exception to report.
042     */
043    @Parameter(required = true, allowNull = false)
044    private Throwable exception;
045
046    @Inject
047    private ExceptionAnalyzer analyzer;
048
049    @Property
050    private ExceptionInfo info;
051
052    @Property
053    private String propertyName;
054
055    @Property
056    private StackTraceElement frame;
057
058    @Property
059    private List<ExceptionInfo> stack;
060
061    private boolean sawDoFilter;
062
063    @Inject
064    @Primary
065    private StackTraceElementAnalyzer frameAnalyzer;
066
067    void setupRender()
068    {
069        ExceptionAnalysis analysis = analyzer.analyze(exception);
070
071        stack = analysis.getExceptionInfos();
072    }
073
074    public Object getPropertyValue()
075    {
076        return info.getProperty(propertyName);
077    }
078
079    public String getFrameClass()
080    {
081        if (sawDoFilter)
082        {
083            return StackTraceElementClassConstants.OMITTED;
084        }
085
086        String result = frameAnalyzer.classForFrame(frame);
087
088        sawDoFilter |= frame.getMethodName().equals("doFilter");
089
090        return result;
091    }
092
093    public Object getLineNumberForFrame()
094    {
095        if (frame.getLineNumber() < 1)
096        {
097            return "";
098        }
099
100        return frame.getLineNumber();
101    }
102
103    public String getFramePackageName()
104    {
105        return splitClass()[0];
106    }
107
108    public String getFrameClassName()
109    {
110        return splitClass()[1];
111    }
112
113    private String[] splitClass()
114    {
115        String name = frame.getClassName();
116
117        int dotx = name.lastIndexOf('.');
118
119        // For generated classes in root package:
120        if (dotx < 0)
121        {
122            return new String[]{"", name};
123        }
124
125        // For normal classes:
126
127        return new String[]{
128                name.substring(0, dotx),
129                name.substring(dotx)
130        };
131    }
132}
133