ninja.diagnostics.DiagnosticErrorBuilder Maven / Gradle / Ivy
/**
* Copyright (C) the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ninja.diagnostics;
import java.io.File;
import java.io.IOException;
import ninja.Result;
/**
* Utility class for building DiagnosticError
instances.
*
* @author Joe Lauer (https://twitter.com/jjlauer)
* @author Fizzed, Inc. (http://fizzed.com)
*/
public class DiagnosticErrorBuilder {
// base dir will remain static throughout life of app
static String baseDirectory
= System.getProperty("user.dir")
+ File.separator
+ "src"
+ File.separator
+ "main"
+ File.separator
+ "java";
static public DiagnosticError build404NotFoundDiagnosticError(
boolean tryToReadLinesFromSourceCode) {
SourceSnippet snippet = null;
if (tryToReadLinesFromSourceCode) {
// try to read entire routes file
snippet = tryToReadSourceSnippetInPackage("conf", "Routes.java", 0, 200);
}
return buildDiagnosticError(
"Route not found",
null,
snippet,
-1,
null);
}
static public DiagnosticError build404NotFoundDiagnosticError(
Throwable cause,
boolean tryToReadLinesFromSourceCode) {
return buildDiagnosticError(
"Route not found",
cause,
tryToReadLinesFromSourceCode, null);
}
static public DiagnosticError build403ForbiddenDiagnosticError() {
return buildDiagnosticError(
"Forbidden",
null, false, null);
}
static public DiagnosticError build403ForbiddenDiagnosticError(
Throwable cause,
boolean tryToReadLinesFromSourceCode) {
return buildDiagnosticError(
"Forbidden",
cause,
tryToReadLinesFromSourceCode, null);
}
static public DiagnosticError build401UnauthorizedDiagnosticError() {
return buildDiagnosticError(
"Not authorized",
null, false, null);
}
static public DiagnosticError build500InternalServerErrorDiagnosticError(
Throwable cause,
boolean tryToReadLinesFromSourceCode,
Result underlyingResult) {
return buildDiagnosticError(
"Application exception",
cause,
tryToReadLinesFromSourceCode, underlyingResult);
}
static public DiagnosticError build400BadRequestDiagnosticError(
Throwable cause,
boolean tryToReadLinesFromSourceCode) {
return buildDiagnosticError(
"Bad request to application",
cause,
tryToReadLinesFromSourceCode, null);
}
static public DiagnosticError buildDiagnosticError(String title,
Throwable throwable,
boolean tryToReadLinesFromSourceCode,
Result underlyingResult) {
if (tryToReadLinesFromSourceCode) {
// see if we can find the source code for this error
StackTraceElement ste = findFirstStackTraceElementWithSourceCodeInProject(throwable);
if (ste != null) {
String relativeSourcePath = getSourceCodeRelativePathForStackTraceElement(ste);
int lineNumberOfError = ste.getLineNumber();
return buildDiagnosticError(title, throwable, relativeSourcePath, lineNumberOfError, underlyingResult);
}
}
// fallback to just displaying the error w/o any source
return new DiagnosticError(
title,
throwable,
underlyingResult);
}
static public DiagnosticError buildDiagnosticError(String title,
Throwable throwable,
String packageName,
String fileName,
int lineNumberOfError,
Result underlyingResult) {
String relativeSourcePath =
packageName.replace(".", File.separator)
+ fileName;
return buildDiagnosticError(title, throwable, relativeSourcePath, lineNumberOfError, underlyingResult);
}
static public DiagnosticError buildDiagnosticError(String title,
Throwable throwable,
String relativeSourcePath,
int lineNumberOfError,
Result underlyingResult) {
int lineNumberFrom = lineNumberOfError - 4;
int lineNumberTo = lineNumberOfError + 5;
SourceSnippet snippet = tryToReadSourceSnippet(relativeSourcePath, lineNumberFrom, lineNumberTo);
return buildDiagnosticError(title, throwable, snippet, lineNumberOfError, underlyingResult);
}
static public DiagnosticError buildDiagnosticError(String title,
Throwable throwable,
SourceSnippet snippet,
int lineNumberOfError,
Result underlyingResult) {
// if source snippet exists then include it with diagnostic error
if (snippet != null && snippet.getLines() != null && snippet.getLines().size() > 0) {
return new DiagnosticError(
title,
throwable,
snippet.getSourceLocation(),
snippet.getLines(),
snippet.getLineNumberFrom(),
lineNumberOfError,
underlyingResult);
}
// fallback to just displaying the error w/o any source
return new DiagnosticError(
title,
throwable,
underlyingResult);
}
static public StackTraceElement findFirstStackTraceElementWithSourceCodeInProject(Throwable throwable) {
if (throwable != null) {
StackTraceElement[] stackTrace = throwable.getStackTrace();
if (stackTrace != null) {
for (StackTraceElement stackTraceElement : stackTrace) {
String sourceRelativePath = getSourceCodeRelativePathForStackTraceElement(stackTraceElement);
if (sourceCodeExistsInProject(sourceRelativePath)) {
return stackTraceElement;
}
}
}
}
return null;
}
static public boolean sourceCodeExistsInProject(String sourceRelativePath) {
File sourceCodeFile = new File(baseDirectory, sourceRelativePath);
return sourceCodeFile.exists();
}
static public SourceSnippet tryToReadSourceSnippetInPackage(String packageName,
String fileName,
int lineFrom,
int lineTo) {
try {
return SourceSnippetHelper.readFromQualifiedSourceCodePath(
new File(baseDirectory),
packageName,
fileName,
lineFrom,
lineTo);
} catch (IOException e) {
return null;
}
}
static public SourceSnippet tryToReadSourceSnippet(String sourceRelativePath,
int lineFrom,
int lineTo) {
try {
return SourceSnippetHelper.readFromRelativeFilePath(
new File(baseDirectory),
sourceRelativePath,
lineFrom,
lineTo);
} catch (IOException e) {
return null;
}
}
/**
* Calculates the relative path of the source code file of a StackTrace
* element if its available. Uses the packageName of the class to create a relative path
* and appends the "filename" included with the stack trace element.
* @param ste The stack trace element
* @return The relative path of the source code file or null if the information
* wasn't available in the stack trace element.
*/
static public String getSourceCodeRelativePathForStackTraceElement(StackTraceElement ste) {
String packageName = ste.getClassName();
// e.g. com.fizzed.test.Application$1 for an internal class
int pos = packageName.lastIndexOf('.');
if (pos > 0) {
packageName = packageName.substring(0, pos);
return
packageName.replace(".", File.separator)
+ File.separator
+ ste.getFileName();
} else {
// must be in default package
return
ste.getFileName();
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy