Skip to content

Commit

Permalink
Merge pull request #6 from tanersener/development
Browse files Browse the repository at this point in the history
Merge v0.1.1
  • Loading branch information
tanersener authored Nov 29, 2021
2 parents ab67a92 + 4f0734a commit 7ac79ea
Show file tree
Hide file tree
Showing 23 changed files with 1,111 additions and 67 deletions.
201 changes: 177 additions & 24 deletions README.md

Large diffs are not rendered by default.

8 changes: 5 additions & 3 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ subprojects {
apply plugin: 'java-library'

group = 'com.arthenica'
version = '0.1.0'
version = '0.1.1'

task sourcesJar(type: Jar) {
archiveClassifier.set('sources')
Expand All @@ -20,7 +20,8 @@ subprojects {
'Built-By': System.getProperty('user.name'),
'Build-Timestamp': new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSSZ").format(new Date()),
'Created-By': "Gradle ${gradle.gradleVersion}",
'Build-Jdk': System.getProperty('java.version')
'Build-Jdk': System.getProperty('java.version'),
'Implementation-Version': version
)
}
}
Expand All @@ -32,7 +33,8 @@ subprojects {
'Built-By': System.getProperty('user.name'),
'Build-Timestamp': new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSSZ").format(new Date()),
'Created-By': "Gradle ${gradle.gradleVersion}",
'Build-Jdk': System.getProperty('java.version')
'Build-Jdk': System.getProperty('java.version'),
'Implementation-Version': version
)
}
}
Expand Down

Large diffs are not rendered by default.

39 changes: 39 additions & 0 deletions common/src/main/java/com/arthenica/smartexception/ClassLoader.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/*
* BSD 3-Clause License
*
* Copyright (c) 2021, Taner Sener
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

package com.arthenica.smartexception;

public interface ClassLoader {

Class<?> loadClass(final String className);

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/*
* BSD 3-Clause License
*
* Copyright (c) 2021, Taner Sener
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

package com.arthenica.smartexception;

public interface PackageLoader {

Package getPackage(final java.lang.ClassLoader classLoader, final String className);

}
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,20 @@ public interface StackTraceElementSerializer {
/**
* <p>Converts the given <code>stackTraceElement</code> into a string.
*
* @param stackTraceElement stack trace element to convert
* @param stackTraceElement stack trace element to convert
* @param printPackageInformation print package information
* @return string representing the given <code>stackTraceElement</code>
*/
String toString(final StackTraceElement stackTraceElement);
String toString(final StackTraceElement stackTraceElement, final boolean printPackageInformation);

/**
* <p>Returns package information for the given <code>stackTraceElement</code>.
*
* @param stackTraceElement stack trace element to use
* @return package information of the given <code>stackTraceElement</code> or an empty string if implementation
* does not support getting package information
*/
String getPackageInformation(final StackTraceElement stackTraceElement);

/**
* <p>Returns module name for the given <code>stackTraceElement</code>.
Expand Down
Binary file added docs/assets/smart-exception-logo-v5.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 2 additions & 1 deletion java/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ task javadocJar(type: Jar, dependsOn: javadoc) {
'Built-By': System.getProperty('user.name'),
'Build-Timestamp': new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSSZ").format(new Date()),
'Created-By': "Gradle ${gradle.gradleVersion}",
'Build-Jdk': System.getProperty('java.version')
'Build-Jdk': System.getProperty('java.version'),
'Implementation-Version': version
)
}
}
Expand Down
100 changes: 96 additions & 4 deletions java/src/main/java/com/arthenica/smartexception/java/Exceptions.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
* BSD 3-Clause License
*
* Copyright (c) 2020, Taner Sener
* Copyright (c) 2020-2021, Taner Sener
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
Expand Down Expand Up @@ -33,6 +33,8 @@
package com.arthenica.smartexception.java;

import com.arthenica.smartexception.AbstractExceptions;
import com.arthenica.smartexception.ClassLoader;
import com.arthenica.smartexception.PackageLoader;
import com.arthenica.smartexception.StackTraceElementSerializer;

import java.util.Set;
Expand All @@ -47,18 +49,21 @@
public class Exceptions {

static {
packageLoader = new JavaPackageLoader();
classLoader = new JavaClassLoader();

AbstractExceptions.setStackTraceElementSerializer(new StackTraceElementSerializer() {

@Override
public String toString(StackTraceElement stackTraceElement) {
public String toString(final StackTraceElement stackTraceElement, final boolean printPackageInformation) {
final StringBuilder stringBuilder = new StringBuilder();

stringBuilder.append(stackTraceElement.getClassName());
stringBuilder.append(".");
stringBuilder.append(stackTraceElement.getMethodName());

if (stackTraceElement.isNativeMethod()) {
stringBuilder.append("(Native Method)");
stringBuilder.append(getNativeMethodDefinition());
} else if ((stackTraceElement.getFileName() != null) && (stackTraceElement.getFileName().length() > 0)) {
stringBuilder.append("(");
stringBuilder.append(stackTraceElement.getFileName());
Expand All @@ -68,7 +73,37 @@ public String toString(StackTraceElement stackTraceElement) {
}
stringBuilder.append(")");
} else {
stringBuilder.append("(Unknown Source)");
stringBuilder.append(getUnknownSourceDefinition());
}

if (printPackageInformation) {
stringBuilder.append(getPackageInformation(stackTraceElement));
}

return stringBuilder.toString();
}

@Override
public String getPackageInformation(final StackTraceElement stackTraceElement) {
final StringBuilder stringBuilder = new StringBuilder();

String className = stackTraceElement.getClassName();
Class<?> loadedClass = Exceptions.classLoader.loadClass(className);
if (loadedClass != null) {
final String libraryName = AbstractExceptions.libraryName(loadedClass);
final String version = AbstractExceptions.getVersion(Exceptions.packageLoader, loadedClass, AbstractExceptions.packageName(className));

if ((libraryName != null) || (version != null)) {
stringBuilder.append(" [");
stringBuilder.append(libraryName);
if ((libraryName != null) && (version != null)) {
if (!libraryName.contains(version)) {
stringBuilder.append(":");
stringBuilder.append(version);
}
}
stringBuilder.append("]");
}
}

return stringBuilder.toString();
Expand All @@ -91,6 +126,10 @@ public String getUnknownSourceDefinition() {
});
}

static PackageLoader packageLoader;

static ClassLoader classLoader;

/**
* <p>Registers a new root package.
*
Expand Down Expand Up @@ -182,6 +221,31 @@ public static void setIgnoreAllCauses(final boolean ignoreAllCauses) {
AbstractExceptions.setIgnoreAllCauses(ignoreAllCauses);
}

/**
* <p>Returns the value of print package information option.
*
* @return the value of global print package information option. When this option is true, stack trace elements
* printed or converted to string will include the name of the jar file that includes the printed class and the version
* of the jar. If it is false, none of this information is printed
*/
public static boolean isPrintPackageInformation() {
return AbstractExceptions.isPrintPackageInformation();
}

/**
* <p>Sets the value of print package information option.
*
* <p>When this option is true, stack trace elements printed or converted to string will include the name of the
* jar file that includes the printed class and the version of the jar.
*
* <p>Note that for some libraries extracting the jar file and the version may not be possible.
*
* @param printPackageInformation new print package information option.
*/
public static void setPrintPackageInformation(final boolean printPackageInformation) {
AbstractExceptions.setPrintPackageInformation(printPackageInformation);
}

/**
* <p>Returns the smart stack trace for the given <code>throwable</code>.
*
Expand Down Expand Up @@ -238,6 +302,21 @@ public static String getStackTraceString(final Throwable throwable, final Set<St
return AbstractExceptions.getStackTraceString(throwable, rootPackageSet, groupPackageSet, ignorePackageSet, ignoreAllCauses);
}

/**
* <p>Returns the smart stack trace for the given <code>throwable</code> using packages provided.
*
* @param throwable parent throwable
* @param rootPackageSet root packages to use for building the stack trace
* @param groupPackageSet group packages to use for building the stack trace
* @param ignorePackageSet ignore packages to use for building the stack trace
* @param ignoreAllCauses ignore all causes in the exception chain
* @param printPackageInformation print package information
* @return a string containing the smart stack trace for the given <code>throwable</code>
*/
public static String getStackTraceString(final Throwable throwable, final Set<String> rootPackageSet, final Set<String> groupPackageSet, final Set<String> ignorePackageSet, final boolean ignoreAllCauses, final boolean printPackageInformation) {
return AbstractExceptions.getStackTraceString(throwable, rootPackageSet, groupPackageSet, ignorePackageSet, ignoreAllCauses, printPackageInformation);
}

/**
* <p>Returns the smart stack trace for the given <code>throwable</code> using root package provided.
*
Expand Down Expand Up @@ -284,6 +363,19 @@ public static String getStackTraceString(final Throwable throwable, final int ma
return AbstractExceptions.getStackTraceString(throwable, maxDepth, ignoreAllCauses);
}

/**
* <p>Returns the smart stack trace for the given <code>throwable</code> using elements found until the maxDepth.
*
* @param throwable parent throwable
* @param maxDepth max depth in exception chain that will be used
* @param ignoreAllCauses ignore all causes in the exception chain
* @param printPackageInformation print package information
* @return a string containing the smart stack trace for the given <code>throwable</code>
*/
public static String getStackTraceString(final Throwable throwable, final int maxDepth, final boolean ignoreAllCauses, final boolean printPackageInformation) {
return AbstractExceptions.getStackTraceString(throwable, maxDepth, ignoreAllCauses, printPackageInformation);
}

/**
* <p>Returns all messages found in the exception chain of the <code>throwable</code> as a single string.
*
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/*
* BSD 3-Clause License
*
* Copyright (c) 2021, Taner Sener
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

package com.arthenica.smartexception.java;

import com.arthenica.smartexception.ClassLoader;

public class JavaClassLoader implements ClassLoader {

@Override
public Class<?> loadClass(final String className) {
try {
java.lang.ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
if (contextClassLoader != null) {
return contextClassLoader.loadClass(className);
}
} catch (ClassNotFoundException | SecurityException ignored) {
}

try {
java.lang.ClassLoader systemClassLoader = java.lang.ClassLoader.getSystemClassLoader();
if (systemClassLoader != null) {
return systemClassLoader.loadClass(className);
}
} catch (ClassNotFoundException | SecurityException | IllegalStateException | Error ignored) {
}

try {
return Class.forName(className);
} catch (ClassNotFoundException | LinkageError ignored) {
return null;
}
}

}
Loading

0 comments on commit 7ac79ea

Please sign in to comment.