View Javadoc

1   /*
2    * Copyright 2013 smartics, Kronseder & Reiner GmbH
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *     http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package de.smartics.properties.admin.resources.representation.html.share;
17  
18  import java.io.OutputStream;
19  import java.io.PrintWriter;
20  import java.io.StringWriter;
21  import java.util.List;
22  
23  import javax.ws.rs.core.MultivaluedMap;
24  import javax.ws.rs.core.UriInfo;
25  
26  import org.apache.commons.lang3.StringUtils;
27  
28  import de.smartics.exceptions.i18n.CauseTrailMessages;
29  import de.smartics.exceptions.i18n.LocalizedException;
30  import de.smartics.exceptions.i18n.message.MessageType;
31  import de.smartics.exceptions.i18n.message.Messages;
32  import de.smartics.html5.jatl.HtmlResourceContext;
33  import de.smartics.properties.admin.domain.model.CannotInitializeManagedApplicationException;
34  import de.smartics.properties.admin.domain.model.Paths;
35  import de.smartics.properties.admin.resources.controller.ApiResource;
36  import de.smartics.properties.admin.resources.representation.share.BreadcrumbHelper;
37  import de.smartics.properties.admin.resources.representation.share.LinkDescriptorFactory;
38  import de.smartics.resteasy.hypermedia.renderer.LinkDescriptor;
39  import de.smartics.resteasy.hypermedia.renderer.LocalizationProvider;
40  import de.smartics.resteasy.hypermedia.renderer.ResourceContext;
41  
42  /**
43   * HTML view to render exception information.
44   */
45  public class ExceptionHtmlRepresentationRenderer extends
46      AbstractHtmlRepresentationRenderer<Throwable>
47  {
48    // ********************************* Fields *********************************
49  
50    // --- constants ------------------------------------------------------------
51  
52    // --- members --------------------------------------------------------------
53  
54    /**
55     * The domain object to render.
56     */
57    private final Throwable domainObject;
58  
59    // ****************************** Initializer *******************************
60  
61    // ****************************** Constructors ******************************
62  
63    /**
64     * Default constructor.
65     *
66     * @param htmlContext the context information to render the representation.
67     * @param domainObject the domain object to render.
68     * @param entityStream the stream to write to.
69     */
70    public ExceptionHtmlRepresentationRenderer(
71        final HtmlResourceContext htmlContext, final Throwable domainObject,
72        final OutputStream entityStream)
73    {
74      super(htmlContext, entityStream);
75      this.domainObject = domainObject;
76    }
77  
78    // ****************************** Inner Classes *****************************
79  
80    // ********************************* Methods ********************************
81  
82    // --- init -----------------------------------------------------------------
83  
84    // --- get&set --------------------------------------------------------------
85  
86    @Override
87    protected String getTitle()
88    {
89      return "Exception raised";
90    }
91  
92    // --- business -------------------------------------------------------------
93  
94    @Override
95    protected void bodyContents()
96    {
97      if (domainObject instanceof LocalizedException)
98      {
99        renderSmartException();
100     }
101     else if (domainObject instanceof CannotInitializeManagedApplicationException)
102     {
103       renderCannotInitializeManagedApplicationException();
104     }
105     else
106     {
107       renderThrowable();
108     }
109   }
110 
111   private void renderSmartException()
112   {
113     final LocalizedException localizedException =
114         (LocalizedException) domainObject;
115 
116     final Messages messages = localizedException.createMessages();
117     renderPageTitle(messages.getMessage(MessageType.TITLE));
118     html.p().text("An exception has been raised!").end();
119 
120     html.h2().text("Raised Exception").end();
121     renderException(localizedException, messages);
122 
123     final CauseTrailMessages causeTrail = localizedException.getCauseTrail();
124     for (final Messages causeMessages : causeTrail.getTrail())
125     {
126       html.h2().text(messages.getMessage(MessageType.SUMMARY)).end();
127       renderException(null, causeMessages);
128     }
129     html.h2().text("Stack Trace").end();
130     html.p().text("This is the stack trace to the exception:").end();
131     final StringBuilder buffer = new StringBuilder();
132     for (final StackTraceElement element : localizedException.getStackTrace())
133     {
134       buffer.append("  at ").append(element.getClassName()).append(".")
135           .append(element.getMethodName()).append(":")
136           .append(element.getLineNumber()).append('\n');
137     }
138     final String text = buffer.toString();
139     html.pre().text(text).end();
140   }
141 
142   private void renderCannotInitializeManagedApplicationException()
143   {
144     renderPageTitle("!?!");
145     html.p().text("An exception has been raised!").end();
146 
147     html.div().classAttr("alert alert-info");
148     html.button().type("button").classAttr("close")
149         .attr("data-dismiss", "alert").raw("&times;").end();
150     html.h4().text("Managed Application Problem").end();
151     html.text("The application to be managed cannot be initialized."
152               + " Maybe you want to provide the required boot properties via JNDI?");
153     html.p();
154     final LinkDescriptor link =
155         linkDescriptorFactory.createDescriptor(ApiResource.JNDI, "getAsHtml");
156     html.link(link);
157     html.end();
158 
159     html.end();
160 
161     renderMessageAndStackTrace();
162   }
163 
164   private void renderThrowable()
165   {
166     renderPageTitle("!?!");
167     html.p().text("An exception has been raised!").end();
168 
169     renderMessageAndStackTrace();
170   }
171 
172   private void renderMessageAndStackTrace()
173   {
174     final String message = domainObject.getLocalizedMessage();
175     html.pre().text(message).end();
176 
177     html.h2().text("Stack Trace").end();
178     html.p().text("This is the stack trace to the exception:").end();
179     final StringWriter writer = new StringWriter();
180     final PrintWriter print = new PrintWriter(writer);
181     domainObject.printStackTrace(print);
182     final String stacktrace = writer.toString();
183     html.pre().text(stacktrace).end();
184   }
185 
186   private void renderException(final LocalizedException e,
187       final Messages messages)
188   {
189     if (e != null)
190     {
191       html.h3().text("Metadata").end();
192       html.table().classAttr("table table-striped");
193       renderMetadataRow("Code", e.getCode());
194       renderMetadataRow("ID", e.getId());
195       renderMetadataRow("Timestamp", e.getTime());
196       html.end();
197     }
198 
199     renderSection(messages, "Summary", MessageType.SUMMARY);
200     renderSection(messages, "Details", MessageType.DETAILS);
201     renderSection(messages, "Implications",
202         MessageType.IMPLICATIONS_ON_CURRENT_TASK);
203     renderSection(messages, "Todo", MessageType.WHAT_TO_DO_NOW);
204     renderSection(messages, "URL", MessageType.URL);
205   }
206 
207   private void renderMetadataRow(final String label, final Object value)
208   {
209     html.tr().th().text(label).end().td().text(String.valueOf(value)).end()
210         .end();
211   }
212 
213   private void renderSection(final Messages messages, final String label,
214       final MessageType type)
215   {
216     final String message = messages.getMessage(type);
217     if (StringUtils.isNotBlank(message))
218     {
219       html.h3().text(label).end();
220       html.p().text(message).end();
221     }
222   }
223 
224   @Override
225   protected List<LinkDescriptor> breadcrumbLinks()
226   {
227     final ResourceContext context = this.htmlContext.getContext();
228     final LocalizationProvider provider = context.getL7nProvider();
229     final UriInfo uriInfo = context.getUriInfo();
230     final LinkDescriptorFactory factory =
231         new LinkDescriptorFactory(uriInfo, provider);
232     final BreadcrumbHelper breadcrumb =
233         new BreadcrumbHelper(factory, "getAsHtml");
234 
235     final String path = uriInfo.getPath();
236     if (path.startsWith(Paths.PATH_SECURITY))
237     {
238       return breadcrumb.security();
239     }
240     if (path.startsWith(Paths.PATH_JNDI))
241     {
242       return breadcrumb.jndi();
243     }
244     else if (path.startsWith(Paths.PATH_PROPERTY_DESCRIPTORS))
245     {
246       return breadcrumbDescriptors(uriInfo, breadcrumb);
247     }
248     else if (path.startsWith(Paths.PATH_CONFIGURATIONS))
249     {
250       return breadcrumbConfigurations(uriInfo, breadcrumb);
251     }
252     else
253     {
254       return breadcrumb.home();
255     }
256   }
257 
258   private List<LinkDescriptor> breadcrumbDescriptors(final UriInfo uriInfo,
259       final BreadcrumbHelper breadcrumb)
260   {
261     final MultivaluedMap<String, String> params = uriInfo.getPathParameters();
262     final String propertyKey = params.getFirst(Paths.PARAM_PROPERTY_KEY);
263 
264     final List<LinkDescriptor> descriptors;
265     if (StringUtils.isBlank(propertyKey))
266     {
267       descriptors = breadcrumb.descriptors();
268     }
269     else
270     {
271       descriptors = breadcrumb.descriptor(propertyKey);
272     }
273     return descriptors;
274   }
275 
276   private List<LinkDescriptor> breadcrumbConfigurations(final UriInfo uriInfo,
277       final BreadcrumbHelper breadcrumb)
278   {
279     final MultivaluedMap<String, String> params = uriInfo.getPathParameters();
280     final String configurationKey =
281         params.getFirst(Paths.PARAM_CONFIGURATION_KEY);
282     final String propertyKey = params.getFirst(Paths.PARAM_PROPERTY_KEY);
283 
284     final List<LinkDescriptor> descriptors;
285     if (StringUtils.isBlank(configurationKey))
286     {
287       descriptors = breadcrumb.configurations();
288     }
289     else if (StringUtils.isBlank(propertyKey))
290     {
291       descriptors = breadcrumb.configuration(configurationKey);
292     }
293     else
294     {
295       descriptors = breadcrumb.property(configurationKey, propertyKey);
296     }
297     return descriptors;
298   }
299 
300   // --- object basics --------------------------------------------------------
301 
302 }