001// Copyright 2006-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.pages; 016 017import org.apache.tapestry5.EventContext; 018import org.apache.tapestry5.SymbolConstants; 019import org.apache.tapestry5.alerts.AlertManager; 020import org.apache.tapestry5.annotations.ContentType; 021import org.apache.tapestry5.annotations.Import; 022import org.apache.tapestry5.annotations.Property; 023import org.apache.tapestry5.annotations.UnknownActivationContextCheck; 024import org.apache.tapestry5.internal.InternalConstants; 025import org.apache.tapestry5.internal.services.PageActivationContextCollector; 026import org.apache.tapestry5.internal.services.ReloadHelper; 027import org.apache.tapestry5.ioc.annotations.Inject; 028import org.apache.tapestry5.ioc.annotations.Symbol; 029import org.apache.tapestry5.ioc.internal.util.InternalUtils; 030import org.apache.tapestry5.services.*; 031 032import java.net.MalformedURLException; 033import java.net.URL; 034import java.util.List; 035import java.util.regex.Pattern; 036 037/** 038 * Responsible for reporting runtime exceptions. This page is quite verbose and is usually overridden in a production 039 * application. When {@link org.apache.tapestry5.SymbolConstants#PRODUCTION_MODE} is "true", it is very abbreviated. 040 * 041 * @see org.apache.tapestry5.corelib.components.ExceptionDisplay 042 */ 043@UnknownActivationContextCheck(false) 044@ContentType("text/html") 045@Import(stack = "core", stylesheet = "ExceptionReport.css") 046public class ExceptionReport implements ExceptionReporter 047{ 048 private static final String PATH_SEPARATOR_PROPERTY = "path.separator"; 049 050 // Match anything ending in .(something?)path. 051 052 private static final Pattern PATH_RECOGNIZER = Pattern.compile("\\..*path$"); 053 054 @Property 055 private String attributeName; 056 057 @Inject 058 @Property 059 private Request request; 060 061 @Inject 062 @Symbol(SymbolConstants.PRODUCTION_MODE) 063 @Property(write = false) 064 private boolean productionMode; 065 066 @Inject 067 @Symbol(SymbolConstants.TAPESTRY_VERSION) 068 @Property(write = false) 069 private String tapestryVersion; 070 071 @Inject 072 @Symbol(SymbolConstants.APPLICATION_VERSION) 073 @Property(write = false) 074 private String applicationVersion; 075 076 @Property(write = false) 077 private Throwable rootException; 078 079 @Property 080 private String propertyName; 081 082 @Property 083 private String failurePage; 084 085 @Inject 086 private RequestGlobals requestGlobals; 087 088 @Inject 089 private AlertManager alertManager; 090 091 @Inject 092 private PageActivationContextCollector pageActivationContextCollector; 093 094 @Inject 095 private PageRenderLinkSource linkSource; 096 097 @Inject 098 private BaseURLSource baseURLSource; 099 100 @Inject 101 private ReloadHelper reloadHelper; 102 103 @Inject 104 private URLEncoder urlEncoder; 105 106 @Property 107 private String rootURL; 108 109 private final String pathSeparator = System.getProperty(PATH_SEPARATOR_PROPERTY); 110 111 public boolean isShowActions() { 112 return failurePage != null && ! request.isXHR(); 113 } 114 115 public void reportException(Throwable exception) 116 { 117 rootException = exception; 118 119 failurePage = (request.getAttribute(InternalConstants.ACTIVE_PAGE_LOADED) == null) 120 ? null 121 : requestGlobals.getActivePageName(); 122 123 rootURL = baseURLSource.getBaseURL(request.isSecure()); 124 } 125 126 public Object[] getReloadContext() 127 { 128 return pageActivationContextCollector.collectPageActivationContext(failurePage); 129 } 130 131 Object onActionFromReloadFirst(EventContext reloadContext) 132 { 133 reloadHelper.forceReload(); 134 135 return linkSource.createPageRenderLinkWithContext(urlEncoder.decode(request.getParameter("loadPage")), reloadContext); 136 } 137 138 Object onActionFromReloadRoot() throws MalformedURLException 139 { 140 reloadHelper.forceReload(); 141 142 return new URL(baseURLSource.getBaseURL(request.isSecure())); 143 } 144 145 146 public boolean getHasSession() 147 { 148 return request.getSession(false) != null; 149 } 150 151 public Session getSession() 152 { 153 return request.getSession(false); 154 } 155 156 public Object getAttributeValue() 157 { 158 return getSession().getAttribute(attributeName); 159 } 160 161 /** 162 * Returns a <em>sorted</em> list of system property names. 163 */ 164 public List<String> getSystemProperties() 165 { 166 return InternalUtils.sortedKeys(System.getProperties()); 167 } 168 169 public String getPropertyValue() 170 { 171 return System.getProperty(propertyName); 172 } 173 174 public boolean isComplexProperty() 175 { 176 return PATH_RECOGNIZER.matcher(propertyName).find() && getPropertyValue().contains(pathSeparator); 177 } 178 179 public String[] getComplexPropertyValue() 180 { 181 // Neither : nor ; is a regexp character. 182 183 return getPropertyValue().split(pathSeparator); 184 } 185}