001    // Copyright 2006, 2007, 2008, 2009 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    
015    package org.apache.tapestry5.corelib.pages;
016    
017    import org.apache.tapestry5.SymbolConstants;
018    import org.apache.tapestry5.annotations.ContentType;
019    import org.apache.tapestry5.annotations.Property;
020    import org.apache.tapestry5.ioc.annotations.Inject;
021    import org.apache.tapestry5.ioc.annotations.Symbol;
022    import org.apache.tapestry5.ioc.internal.util.InternalUtils;
023    import org.apache.tapestry5.services.ExceptionReporter;
024    import org.apache.tapestry5.services.Request;
025    import org.apache.tapestry5.services.Session;
026    
027    import java.util.List;
028    import java.util.regex.Pattern;
029    
030    /**
031     * Responsible for reporting runtime exceptions. This page is quite verbose and is usually overridden in a production
032     * application. When {@link org.apache.tapestry5.SymbolConstants#PRODUCTION_MODE} is "true", it is very abbreviated.
033     *
034     * @see org.apache.tapestry5.corelib.components.ExceptionDisplay
035     */
036    @ContentType("text/html")
037    public class ExceptionReport implements ExceptionReporter
038    {
039        private static final String PATH_SEPARATOR_PROPERTY = "path.separator";
040    
041        // Match anything ending in .(something?)path.
042    
043        private static final Pattern PATH_RECOGNIZER = Pattern.compile("\\..*path$");
044    
045        @Property
046        private String attributeName;
047    
048        @Inject
049        @Property
050        private Request request;
051    
052        @Inject
053        @Symbol(SymbolConstants.PRODUCTION_MODE)
054        @Property(write = false)
055        private boolean productionMode;
056    
057        @Inject
058        @Symbol(SymbolConstants.TAPESTRY_VERSION)
059        @Property(write = false)
060        private String tapestryVersion;
061    
062        @Inject
063        @Symbol(SymbolConstants.APPLICATION_VERSION)
064        @Property(write = false)
065        private String applicationVersion;
066    
067        @Property(write = false)
068        private Throwable rootException;
069    
070        @Property
071        private String propertyName;
072    
073        private final String pathSeparator = System.getProperty(PATH_SEPARATOR_PROPERTY);
074    
075        public void reportException(Throwable exception)
076        {
077            rootException = exception;
078        }
079    
080        public boolean getHasSession()
081        {
082            return request.getSession(false) != null;
083        }
084    
085        public Session getSession()
086        {
087            return request.getSession(false);
088        }
089    
090        public Object getAttributeValue()
091        {
092            return getSession().getAttribute(attributeName);
093        }
094    
095        /**
096         * Returns a <em>sorted</em> list of system property names.
097         */
098        public List<String> getSystemProperties()
099        {
100            return InternalUtils.sortedKeys(System.getProperties());
101        }
102    
103        public String getPropertyValue()
104        {
105            return System.getProperty(propertyName);
106        }
107    
108        public boolean isComplexProperty()
109        {
110            return PATH_RECOGNIZER.matcher(propertyName).find() && getPropertyValue().contains(pathSeparator);
111        }
112    
113        public String[] getComplexPropertyValue()
114        {
115            // Neither : nor ; is a regexp character.
116    
117            return getPropertyValue().split(pathSeparator);
118        }
119    }