All Downloads are FREE. Search and download functionalities are using the official Maven repository.

ninja.diagnostics.DiagnosticErrorBuilder Maven / Gradle / Ivy

There is a newer version: 7.0.0
Show newest version
/**
 * 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