add some missing classes

This commit is contained in:
aliveoutside
2022-07-11 01:34:27 +03:00
parent cd389af2bd
commit b001517a63
4 changed files with 1232 additions and 7 deletions
@@ -0,0 +1,732 @@
/*
* BSD 3-Clause License
*
* Copyright (c) 2020, 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;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
/**
* <p>Abstract class that includes common variables and methods for different <code>Exceptions</code> implementations.
*
* @author Taner Sener
* @since 0.1.0
*/
public abstract class AbstractExceptions {
/**
* <p>Default max depth used in methods which do not have a maxDepth argument.
*/
public static final int DEFAULT_MAX_DEPTH = 10;
/**
* <p>Default value for ignoring all causes when stack trace elements are printed or converted to string.
*/
public static final boolean DEFAULT_IGNORE_ALL_CAUSES = false;
/**
* <p>Stores global root package names.
*/
public static final Set<String> rootPackageSet = Collections.synchronizedSet(new HashSet<String>());
/**
* <p>Stores global group package names.
*/
public static final Set<String> groupPackageSet = Collections.synchronizedSet(new HashSet<String>());
/**
* <p>Stores global ignore package names.
*/
public static final Set<String> ignorePackageSet = Collections.synchronizedSet(new HashSet<String>());
/**
* <p>Stores global ignore cause package names.
*/
public static final Set<String> ignoreCausePackageSet = Collections.synchronizedSet(new HashSet<String>());
/**
* <p>Stores the value of global ignore all causes option.
*/
public static boolean ignoreAllCauses = DEFAULT_IGNORE_ALL_CAUSES;
/**
* <p>Stores the global stack trace serializer implementation.
*/
public static StackTraceElementSerializer stackTraceElementSerializer;
/**
* <p>Registers a new root package.
*
* @param packageString root package name to register
*/
public static void registerRootPackage(final String packageString) {
rootPackageSet.add(packageString);
}
/**
* <p>Clears previously registered root packages.
*/
public static void clearRootPackages() {
rootPackageSet.clear();
}
/**
* <p>Registers a new group package.
*
* @param packageString group package name to register
*/
public static void registerGroupPackage(final String packageString) {
groupPackageSet.add(packageString);
}
/**
* <p>Clears previously registered group packages.
*/
public static void clearGroupPackages() {
groupPackageSet.clear();
}
/**
* <p>Returns the global stack trace serializer implementation which is used to serialize {@link StackTraceElement}
* objects in <code>getStackTraceString</code> methods.
*
* @return current stack trace serializer implementation
*/
public static StackTraceElementSerializer getStackTraceElementSerializer() {
return stackTraceElementSerializer;
}
/**
* <p>Sets the global stack trace serializer implementation which is used to serialize {@link StackTraceElement}
* objects in <code>getStackTraceString</code> methods.
*
* @param stackTraceElementSerializer new stack trace serializer implementation
*/
public static void setStackTraceElementSerializer(final StackTraceElementSerializer stackTraceElementSerializer) {
AbstractExceptions.stackTraceElementSerializer = stackTraceElementSerializer;
}
/**
* <p>Registers a new ignore package.
*
* @param packageString ignore package name to register
* @param ignoreCauseClasses ignore cause classes from this package too
*/
public static void registerIgnorePackage(final String packageString, final boolean ignoreCauseClasses) {
ignorePackageSet.add(packageString);
if (ignoreCauseClasses) {
ignoreCausePackageSet.add(packageString);
}
}
/**
* <p>Clears previously registered ignore packages.
*/
public static void clearIgnorePackages() {
ignorePackageSet.clear();
ignoreCausePackageSet.clear();
}
/**
* <p>Returns the value of ignore all causes option.
*
* @return the value of global ignore all causes option. If value is true then stack trace elements printed or
* converted to string will not include causes. If value is false causes will be appended to the stack trace of
* the main throwable.
*/
public static boolean getIgnoreAllCauses() {
return ignoreAllCauses;
}
/**
* <p>Sets the value of ignore all causes option.
*
* @param ignoreAllCauses new global ignore all causes option. If value is true then stack trace elements printed
* or converted to string will not include causes. If value is false causes will be appended to the stack trace of
* the main throwable.
*/
public static void setIgnoreAllCauses(final boolean ignoreAllCauses) {
AbstractExceptions.ignoreAllCauses = ignoreAllCauses;
}
/**
* <p>Returns the smart stack trace for the given <code>throwable</code>.
*
* <p>This method uses root packages registered by {@link #registerRootPackage(String)}, group packages registered
* by {@link #registerGroupPackage(String)} and ignore packages registered by
* {@link #registerIgnorePackage(String, boolean)} to build the smart stack trace.
*
* @param throwable parent throwable
* @return a string containing the smart stack trace for the given <code>throwable</code>
*/
public static String getStackTraceString(final Throwable throwable) {
return getStackTraceString(throwable, false, rootPackageSet, groupPackageSet, ignorePackageSet, 0, ignoreAllCauses);
}
/**
* <p>Returns the smart stack trace for the given <code>throwable</code>.
*
* <p>This method uses root packages registered by {@link #registerRootPackage(String)}, group packages registered
* by {@link #registerGroupPackage(String)} and ignore packages registered by
* {@link #registerIgnorePackage(String, boolean)} to build the smart stack trace.
*
* @param throwable parent throwable
* @param ignoreAllCauses ignore all causes in the exception chain
* @return a string containing the smart stack trace for the given <code>throwable</code>
*/
public static String getStackTraceString(final Throwable throwable, final boolean ignoreAllCauses) {
return getStackTraceString(throwable, false, rootPackageSet, groupPackageSet, ignorePackageSet, 0, 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
* @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) {
return getStackTraceString(throwable, false, rootPackageSet, groupPackageSet, ignorePackageSet, 0, 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
* @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) {
return getStackTraceString(throwable, false, rootPackageSet, groupPackageSet, ignorePackageSet, 0, ignoreAllCauses);
}
/**
* <p>Returns the smart stack trace for the given <code>throwable</code> using root package provided.
*
* @param throwable parent throwable
* @param rootPackage root package to use for building the stack trace
* @return a string containing the smart stack trace for the given <code>throwable</code>
*/
public static String getStackTraceString(final Throwable throwable, final String rootPackage) {
return getStackTraceString(throwable, false, Collections.singleton(rootPackage), new HashSet<String>(), new HashSet<String>(), 0, ignoreAllCauses);
}
/**
* <p>Returns the smart stack trace for the given <code>throwable</code> using root package provided.
*
* @param throwable parent throwable
* @param rootPackage root package to use for building the stack trace
* @param groupPackage group package to use for building the stack trace
* @return a string containing the smart stack trace for the given <code>throwable</code>
*/
public static String getStackTraceString(final Throwable throwable, final String rootPackage, final String groupPackage) {
return getStackTraceString(throwable, false, Collections.singleton(rootPackage), Collections.singleton(groupPackage), new HashSet<String>(), 0, 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
* @return a string containing the smart stack trace for the given <code>throwable</code>
*/
public static String getStackTraceString(final Throwable throwable, final int maxDepth) {
return getStackTraceString(throwable, false, new HashSet<String>(), new HashSet<String>(), new HashSet<String>(), 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
* @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) {
return getStackTraceString(throwable, false, new HashSet<String>(), new HashSet<String>(), new HashSet<String>(), maxDepth, ignoreAllCauses);
}
/**
* <p>Returns the smart stack trace for the given <code>throwable</code> using parameters provided.
*
* @param throwable parent throwable
* @param isCause throwable is a cause or not
* @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 maxDepth max depth in exception chain that will be used
* @param ignoreAllCauses ignore all causes in the exception chain
* @return a string containing the smart stack trace for the given <code>throwable</code>
*/
public static String getStackTraceString(final Throwable throwable, final boolean isCause, final Set<String> rootPackageSet, final Set<String> groupPackageSet, final Set<String> ignorePackageSet, final int maxDepth, final boolean ignoreAllCauses) {
final StringBuilder builder = new StringBuilder();
if (throwable == null) {
return "";
}
final String className = throwable.getClass().getName();
final StackTraceElement[] stackTraceElements;
if (maxDepth > 0) {
stackTraceElements = getStackTrace(throwable, maxDepth);
} else {
stackTraceElements = getStackTrace(throwable, rootPackageSet, ignorePackageSet);
}
String message = throwable.getLocalizedMessage();
if (isEmpty(message)) {
message = throwable.getMessage();
}
/* PRINT MESSAGE */
if (isCause) {
builder.append(System.lineSeparator());
builder.append("Caused by: ");
builder.append(className);
if (!isEmpty(message)) {
builder.append(": ");
builder.append(message);
}
} else {
builder.append(System.lineSeparator());
builder.append(className);
if (!isEmpty(message)) {
builder.append(": ");
builder.append(message);
}
}
/* PRINT SHORT STACK TRACE */
String currentGroupPackage = null;
StackTraceElement firstStackTraceElementInTheGroup = null;
int currentGroupCount = 0;
for (StackTraceElement traceElement : stackTraceElements) {
String traceElementClassName = traceElement.getClassName();
String groupPackageMatch = getContainingPackage(traceElementClassName, groupPackageSet);
if (groupPackageMatch != null) {
if (!groupPackageMatch.equals(currentGroupPackage)) {
appendStackTraceGroupElement(builder, currentGroupPackage, currentGroupCount, firstStackTraceElementInTheGroup);
builder.append(System.lineSeparator());
builder.append("\tat ");
currentGroupPackage = groupPackageMatch;
firstStackTraceElementInTheGroup = traceElement;
currentGroupCount = 1;
} else {
currentGroupCount++;
}
} else {
currentGroupCount = appendStackTraceGroupElement(builder, currentGroupPackage, currentGroupCount, firstStackTraceElementInTheGroup);
builder.append(System.lineSeparator());
builder.append("\tat ");
if (stackTraceElementSerializer == null) {
throw new IllegalArgumentException("Stack trace element serializer not initialized.");
} else {
builder.append(stackTraceElementSerializer.toString(traceElement));
}
currentGroupPackage = null;
}
}
appendStackTraceGroupElement(builder, currentGroupPackage, currentGroupCount, firstStackTraceElementInTheGroup);
final Throwable cause = throwable.getCause();
if (cause != null && !containsPackage(className, ignoreCausePackageSet) && !ignoreAllCauses) {
builder.append(getStackTraceString(cause, true, rootPackageSet, groupPackageSet, ignorePackageSet, maxDepth, ignoreAllCauses));
}
return builder.toString();
}
/**
* <p>Appends stack trace group information for the given parameters.
*
* @param stringBuilder string builder that group stack trace information will be appended
* @param currentGroupPackage package name of the current group
* @param numberOfElementsInTheCurrentGroup number of elements in the current group
* @param firstStackTraceElementInTheGroup first stack trace element of this group
* @return new value for the group element count
*/
public static int appendStackTraceGroupElement(final StringBuilder stringBuilder, final String currentGroupPackage, final int numberOfElementsInTheCurrentGroup, final StackTraceElement firstStackTraceElementInTheGroup) {
if (numberOfElementsInTheCurrentGroup > 0) {
if (stackTraceElementSerializer == null) {
throw new IllegalArgumentException("Stack trace element serializer not initialized.");
} else {
stringBuilder.append((numberOfElementsInTheCurrentGroup == 1) ? stackTraceElementSerializer.toString(firstStackTraceElementInTheGroup) : String.format("%s%s ... %d more", stackTraceElementSerializer.getModuleName(firstStackTraceElementInTheGroup), currentGroupPackage, (numberOfElementsInTheCurrentGroup - 1)));
}
}
return 0;
}
/**
* <p>Returns true if package of the given class name matches one of package names provided in
* <code>packageSet</code>.
*
* @param fullClassName fully qualified class name
* @param packageSet set containing package names
* @return true if package of the given class name matches one of package names provided in <code>packageSet</code>,
* false otherwise
*/
public static boolean containsPackage(final String fullClassName, final Set<String> packageSet) {
return getContainingPackage(fullClassName, packageSet) != null;
}
/**
* <p>Checks if one of the package names in the <code>packageSet</code> matches the package of the given class name
* and returns the matching package name.
*
* @param fullClassName fully qualified class name
* @param packageSet set containing package names
* @return one of the package names in the <code>packageSet</code> that matches the package of the given class name
* or null if no matching package name is found in the <code>packageSet</code>
*/
public static String getContainingPackage(final String fullClassName, final Set<String> packageSet) {
for (final String parentExceptionPackage : packageSet) {
if (fullClassName.startsWith(parentExceptionPackage)) {
return parentExceptionPackage;
}
}
return null;
}
/**
* <p>Returns all messages found in the exception chain of the <code>throwable</code> as a single string.
*
* @param throwable parent throwable
* @return a string containing all messages found in the exception chain
*/
public static String getAllMessages(final Throwable throwable) {
final StringBuilder messageBuilder = new StringBuilder();
getAllMessages(throwable, messageBuilder);
return messageBuilder.toString();
}
/**
* <p>Adds all messages found in the exception chain of the <code>throwable</code> into the given message builder.
*
* @param throwable parent throwable
* @param messageBuilder message builder
*/
public static void getAllMessages(final Throwable throwable, final StringBuilder messageBuilder) {
if (throwable != null) {
final String message = throwable.getMessage();
if (!isEmpty(message)) {
if (messageBuilder.length() != 0) {
messageBuilder.append(System.lineSeparator());
messageBuilder.append(" - Caused by: ");
}
messageBuilder.append(message);
}
getAllMessages(throwable.getCause(), messageBuilder);
}
}
/**
* <p>Builds a smart stack trace for the given <code>throwable</code> using elements found until the maxDepth and
* elements of it.
*
* @param throwable parent throwable
* @param maxDepth max depth in exception chain that will be returned
* @return an array containing stack trace elements
*/
public static StackTraceElement[] getStackTrace(final Throwable throwable, final int maxDepth) {
final ArrayList<StackTraceElement> list = new ArrayList<StackTraceElement>();
if (throwable != null) {
StackTraceElement[] stackTrace = throwable.getStackTrace();
for (int i = 0; (i < stackTrace.length) && (i < maxDepth); i++) {
list.add(stackTrace[i]);
}
}
return list.toArray(new StackTraceElement[0]);
}
/**
* <p>Builds a smart stack trace for the given <code>throwable</code> using packages provided and returns elements
* of it.
*
* @param throwable parent throwable
* @param rootPackageSet root packages to use for building the stack trace
* @param ignorePackageSet ignore packages to use for building the stack trace
* @return an array containing stack trace elements
*/
public static StackTraceElement[] getStackTrace(final Throwable throwable, final Set<String> rootPackageSet, final Set<String> ignorePackageSet) {
final ArrayList<StackTraceElement> list = new ArrayList<StackTraceElement>();
final ArrayList<StackTraceElement> partialList = new ArrayList<StackTraceElement>();
if (throwable != null) {
for (StackTraceElement stackTraceElement : throwable.getStackTrace()) {
final String className = stackTraceElement.getClassName();
if (!isEmpty(className)) {
if (containsPackage(className, rootPackageSet)) {
list.addAll(partialList);
list.add(stackTraceElement);
} else if (!containsPackage(className, ignorePackageSet)) {
partialList.add(stackTraceElement);
}
}
}
}
if (list.isEmpty()) {
list.addAll(partialList);
}
return list.toArray(new StackTraceElement[0]);
}
/**
* <p>Returns true if the given cause class is found in the exception chain of the <code>throwable</code>.
* <br>
* <br>
* <p>Search starts from the <code>throwable</code> itself and goes through the exception chain up until
* {@link #DEFAULT_MAX_DEPTH}.
*
* @param throwable parent throwable
* @param causeClass class to search for
* @return true if the given cause class is found in the exception chain of the <code>throwable</code>, false
* otherwise
*/
public static boolean containsCause(final Throwable throwable, final Class<?> causeClass) {
return containsCause(throwable, causeClass, null);
}
/**
* <p>Returns true if the given cause class and cause message is found in the exception chain of the
* <code>throwable</code>.
* <br>
* <br>
* <p>Search starts from the <code>throwable</code> itself and goes through the exception chain up until
* {@link #DEFAULT_MAX_DEPTH}.
*
* @param throwable parent throwable
* @param causeClass class to search for
* @param causeMessage message to search for
* @return true if the given cause class and cause message is found in the exception chain of the
* <code>throwable</code>, false otherwise
*/
public static boolean containsCause(final Throwable throwable, final Class<?> causeClass, final String causeMessage) {
return (searchCause(throwable, causeClass, causeMessage, DEFAULT_MAX_DEPTH) != null);
}
/**
* <p>Returns the cause of the <code>throwable</code> by walking through the exception chain.
*
* @param throwable parent throwable
* @return the cause of the <code>throwable</code> found or null if <code>throwable</code> does not have a cause
*/
public static Throwable getCause(final Throwable throwable) {
return getCause(throwable, DEFAULT_MAX_DEPTH);
}
/**
* <p>Returns the cause of the <code>throwable</code> by walking through the exception chain.
* <br>
* <br>
* <p>Note that this method walks through the exception chain up to given <code>maxDepth</code>. If exception chain
* includes more items than <code>maxDepth</code>, cause found at <code>maxDepth</code> level is returned.
*
* @param throwable parent throwable
* @param maxDepth max depth in exception chain that will be searched
* @return the cause of the <code>throwable</code> found until <code>maxDepth</code> is reached in the exception
* chain or null if <code>throwable</code> does not have a cause
*/
public static Throwable getCause(final Throwable throwable, final int maxDepth) {
if (throwable == null) {
return null;
}
if (maxDepth <= 0) {
return throwable;
}
final Throwable cause = throwable.getCause();
if (cause == null) {
return throwable;
} else {
return getCause(cause, maxDepth - 1);
}
}
/**
* <p>Searches for the given cause class in the exception chain of the <code>throwable</code>.
* <br>
* <br>
* <p>Search starts from the <code>throwable</code> itself and goes through the exception chain up until
* {@link #DEFAULT_MAX_DEPTH}.
*
* @param throwable parent throwable
* @param causeClass class to search for
* @return the <code>throwable</code> found or null if no class in exception chain matches the given cause class
*/
public static Throwable searchCause(final Throwable throwable, final Class<?> causeClass) {
return searchCause(throwable, causeClass, null, DEFAULT_MAX_DEPTH);
}
/**
* <p>Searches for the given cause class and cause message in the exception chain of the <code>throwable</code>.
* <br>
* <br>
* <p>Search starts from the <code>throwable</code> itself and goes through the exception chain up until
* {@link #DEFAULT_MAX_DEPTH}.
*
* @param throwable parent throwable
* @param causeClass class to search for
* @param causeMessage message to search for
* @return the <code>throwable</code> found or null if no class in exception chain matches the given cause class
* and cause message
*/
public static Throwable searchCause(final Throwable throwable, final Class<?> causeClass, final String causeMessage) {
return searchCause(throwable, causeClass, causeMessage, DEFAULT_MAX_DEPTH);
}
/**
* <p>Searches for the given cause class and cause message in the exception chain of the <code>throwable</code>.
* <br>
* <br>
* <p>Search starts from the <code>throwable</code> itself and goes through the exception chain up until the given
* <code>maxDepth</code>.
*
* @param throwable parent throwable
* @param causeClass class to search for
* @param causeMessage message to search for
* @param maxDepth max depth in exception chain that will be searched
* @return the <code>throwable</code> found or null if no class in exception chain matches the given cause class
* and cause message
*/
public static Throwable searchCause(final Throwable throwable, final Class<?> causeClass, final String causeMessage, final int maxDepth) {
if (throwable == null) {
return null;
}
if (isEmpty(causeMessage)) {
if (throwable.getClass().equals(causeClass)) {
return throwable;
}
} else {
if (throwable.getClass().equals(causeClass) && getAllMessages(throwable).toLowerCase().contains(causeMessage.toLowerCase())) {
return throwable;
}
}
if (maxDepth <= 0) {
return null;
}
final Throwable cause = throwable.getCause();
if (cause == null) {
return null;
} else {
return searchCause(cause, causeClass, causeMessage, maxDepth - 1);
}
}
/**
* <p>Searches for the given cause class in the exception chain of the <code>throwable</code>.
* <br>
* <br>
* <p>Search starts from the <code>throwable</code> itself and goes through the exception chain up until the given
* <code>maxDepth</code>.
*
* @param throwable parent throwable
* @param causeClass class to search for
* @param maxDepth max depth in exception chain that will be searched
* @return the <code>throwable</code> found or null if no class in exception chain matches the given cause class
*/
public static Throwable searchCause(final Throwable throwable, final Class<?> causeClass, final int maxDepth) {
if (throwable == null) {
return null;
}
if (throwable.getClass().equals(causeClass)) {
return throwable;
}
if (maxDepth <= 0) {
return null;
}
final Throwable cause = throwable.getCause();
if (cause == null) {
return null;
} else {
return searchCause(cause, causeClass, maxDepth - 1);
}
}
/**
* <p>Checks if given string is empty or not.
*
* @param value string to check
* @return true if given string is null or has zero length after trim(), false otherwise
*/
public static boolean isEmpty(final String value) {
if (value == null) {
return true;
}
return value.trim().length() == 0;
}
/**
* <p>Returns the package name of this class.
*
* @param className fully qualified class name
* @return name of the package
*/
public static String packageName(final String className) {
if (className == null) {
return "";
}
int index = className.lastIndexOf(".");
if (index >= 0) {
return className.substring(0, index);
} else {
return "";
}
}
}
@@ -0,0 +1,74 @@
/*
* BSD 3-Clause License
*
* Copyright (c) 2020, 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;
/**
* <p>Base interface for classes which can serialize {@link StackTraceElement} objects.
*
* @author Taner Sener
* @since 0.1.0
*/
public interface StackTraceElementSerializer {
/**
* <p>Converts the given <code>stackTraceElement</code> into a string.
*
* @param stackTraceElement stack trace element to convert
* @return string representing the given <code>stackTraceElement</code>
*/
String toString(final StackTraceElement stackTraceElement);
/**
* <p>Returns module name for the given <code>stackTraceElement</code>.
*
* @param stackTraceElement stack trace element to use
* @return module name of the given <code>stackTraceElement</code> or an empty string if implementation does not
* support printing module names
*/
String getModuleName(final StackTraceElement stackTraceElement);
/**
* <p>Returns string definition used to print native methods.
*
* @return string definition used to print native methods
*/
String getNativeMethodDefinition();
/**
* <p>Returns string definition used to print methods with unknown source.
*
* @return string definition used to print methods with unknown source
*/
String getUnknownSourceDefinition();
}
@@ -0,0 +1,423 @@
/*
* BSD 3-Clause License
*
* Copyright (c) 2020, 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.AbstractExceptions;
import com.arthenica.smartexception.StackTraceElementSerializer;
import java.util.Set;
/**
* <p>Utility class to handle Throwable objects and stack traces. This implementation is compatible with all Java and
* Android versions.
*
* @author Taner Sener
* @since 0.1.0
*/
public class Exceptions {
static {
AbstractExceptions.setStackTraceElementSerializer(new StackTraceElementSerializer() {
@Override
public String toString(StackTraceElement stackTraceElement) {
final StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append(stackTraceElement.getClassName());
stringBuilder.append(".");
stringBuilder.append(stackTraceElement.getMethodName());
if (stackTraceElement.isNativeMethod()) {
stringBuilder.append("(Native Method)");
} else if ((stackTraceElement.getFileName() != null) && (stackTraceElement.getFileName().length() > 0)) {
stringBuilder.append("(");
stringBuilder.append(stackTraceElement.getFileName());
if (stackTraceElement.getLineNumber() >= 0) {
stringBuilder.append(":");
stringBuilder.append(stackTraceElement.getLineNumber());
}
stringBuilder.append(")");
} else {
stringBuilder.append("(Unknown Source)");
}
return stringBuilder.toString();
}
@Override
public String getModuleName(StackTraceElement stackTraceElement) {
return "";
}
@Override
public String getNativeMethodDefinition() {
return "(Native Method)";
}
@Override
public String getUnknownSourceDefinition() {
return "(Unknown Source)";
}
});
}
/**
* <p>Registers a new root package.
*
* @param packageString root package name to register
*/
public static void registerRootPackage(final String packageString) {
AbstractExceptions.registerRootPackage(packageString);
}
/**
* <p>Clears previously registered root packages.
*/
public static void clearRootPackages() {
AbstractExceptions.clearRootPackages();
}
/**
* <p>Registers a new group package.
*
* @param packageString group package name to register
*/
public static void registerGroupPackage(final String packageString) {
AbstractExceptions.registerGroupPackage(packageString);
}
/**
* <p>Clears previously registered group packages.
*/
public static void clearGroupPackages() {
AbstractExceptions.clearGroupPackages();
}
/**
* <p>Returns the global stack trace serializer implementation which is used to serialize {@link StackTraceElement}
* objects in <code>getStackTraceString</code> methods.
*
* @return current stack trace serializer implementation
*/
public static StackTraceElementSerializer getStackTraceElementSerializer() {
return AbstractExceptions.getStackTraceElementSerializer();
}
/**
* <p>Sets the global stack trace serializer implementation which is used to serialize {@link StackTraceElement}
* objects in <code>getStackTraceString</code> methods.
*
* @param stackTraceElementSerializer new stack trace serializer implementation
*/
public static void setStackTraceElementSerializer(final StackTraceElementSerializer stackTraceElementSerializer) {
AbstractExceptions.setStackTraceElementSerializer(stackTraceElementSerializer);
}
/**
* <p>Registers a new ignore package.
*
* @param packageString ignore package name to register
* @param ignoreCauseClasses ignore cause classes from this package too
*/
public static void registerIgnorePackage(final String packageString, final boolean ignoreCauseClasses) {
AbstractExceptions.registerIgnorePackage(packageString, ignoreCauseClasses);
}
/**
* <p>Clears previously registered ignore packages.
*/
public static void clearIgnorePackages() {
AbstractExceptions.clearIgnorePackages();
}
/**
* <p>Returns the value of ignore all causes option.
*
* @return the value of global ignore all causes option. If value is true then stack trace elements printed or
* converted to string will not include causes. If value is false causes will be appended to the stack trace of
* the main throwable.
*/
public static boolean getIgnoreAllCauses() {
return AbstractExceptions.getIgnoreAllCauses();
}
/**
* <p>Sets the value of ignore all causes option.
*
* @param ignoreAllCauses new global ignore all causes option. If value is true then stack trace elements printed
* or converted to string will not include causes. If value is false causes will be appended to the stack trace of
* the main throwable.
*/
public static void setIgnoreAllCauses(final boolean ignoreAllCauses) {
AbstractExceptions.setIgnoreAllCauses(ignoreAllCauses);
}
/**
* <p>Returns the smart stack trace for the given <code>throwable</code>.
*
* <p>This method uses root packages registered by {@link #registerRootPackage(String)}, group packages registered
* by {@link #registerGroupPackage(String)} and ignore packages registered by
* {@link #registerIgnorePackage(String, boolean)} to build the smart stack trace.
*
* @param throwable parent throwable
* @return a string containing the smart stack trace for the given <code>throwable</code>
*/
public static String getStackTraceString(final Throwable throwable) {
return AbstractExceptions.getStackTraceString(throwable);
}
/**
* <p>Returns the smart stack trace for the given <code>throwable</code>.
*
* <p>This method uses root packages registered by {@link #registerRootPackage(String)}, group packages registered
* by {@link #registerGroupPackage(String)} and ignore packages registered by
* {@link #registerIgnorePackage(String, boolean)} to build the smart stack trace.
*
* @param throwable parent throwable
* @param ignoreAllCauses ignore all causes in the exception chain
* @return a string containing the smart stack trace for the given <code>throwable</code>
*/
public static String getStackTraceString(final Throwable throwable, final boolean ignoreAllCauses) {
return AbstractExceptions.getStackTraceString(throwable, 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
* @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) {
return AbstractExceptions.getStackTraceString(throwable, rootPackageSet, groupPackageSet, ignorePackageSet);
}
/**
* <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
* @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) {
return AbstractExceptions.getStackTraceString(throwable, rootPackageSet, groupPackageSet, ignorePackageSet, ignoreAllCauses);
}
/**
* <p>Returns the smart stack trace for the given <code>throwable</code> using root package provided.
*
* @param throwable parent throwable
* @param rootPackage root package to use for building the stack trace
* @return a string containing the smart stack trace for the given <code>throwable</code>
*/
public static String getStackTraceString(final Throwable throwable, final String rootPackage) {
return AbstractExceptions.getStackTraceString(throwable, rootPackage);
}
/**
* <p>Returns the smart stack trace for the given <code>throwable</code> using root package provided.
*
* @param throwable parent throwable
* @param rootPackage root package to use for building the stack trace
* @param groupPackage group package to use for building the stack trace
* @return a string containing the smart stack trace for the given <code>throwable</code>
*/
public static String getStackTraceString(final Throwable throwable, final String rootPackage, final String groupPackage) {
return AbstractExceptions.getStackTraceString(throwable, rootPackage, groupPackage);
}
/**
* <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
* @return a string containing the smart stack trace for the given <code>throwable</code>
*/
public static String getStackTraceString(final Throwable throwable, final int maxDepth) {
return AbstractExceptions.getStackTraceString(throwable, maxDepth);
}
/**
* <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
* @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) {
return AbstractExceptions.getStackTraceString(throwable, maxDepth, ignoreAllCauses);
}
/**
* <p>Returns all messages found in the exception chain of the <code>throwable</code> as a single string.
*
* @param throwable parent throwable
* @return a string containing all messages found in the exception chain
*/
public static String getAllMessages(final Throwable throwable) {
return AbstractExceptions.getAllMessages(throwable);
}
/**
* <p>Returns true if the given cause class is found in the exception chain of the <code>throwable</code>.
* <br>
* <br>
* <p>Search starts from the <code>throwable</code> itself and goes through the exception chain up until
* {@link AbstractExceptions#DEFAULT_MAX_DEPTH}.
*
* @param throwable parent throwable
* @param causeClass class to search for
* @return true if the given cause class is found in the exception chain of the <code>throwable</code>, false
* otherwise
*/
public static boolean containsCause(final Throwable throwable, final Class<?> causeClass) {
return AbstractExceptions.containsCause(throwable, causeClass);
}
/**
* <p>Returns true if the given cause class and cause message is found in the exception chain of the
* <code>throwable</code>.
* <br>
* <br>
* <p>Search starts from the <code>throwable</code> itself and goes through the exception chain up until
* {@link AbstractExceptions#DEFAULT_MAX_DEPTH}.
*
* @param throwable parent throwable
* @param causeClass class to search for
* @param causeMessage message to search for
* @return true if the given cause class and cause message is found in the exception chain of the
* <code>throwable</code>, false otherwise
*/
public static boolean containsCause(final Throwable throwable, final Class<?> causeClass, final String causeMessage) {
return AbstractExceptions.containsCause(throwable, causeClass, causeMessage);
}
/**
* <p>Returns the cause of the <code>throwable</code> by walking through the exception chain.
*
* @param throwable parent throwable
* @return the cause of the <code>throwable</code> found or null if <code>throwable</code> does not have a cause
*/
public static Throwable getCause(final Throwable throwable) {
return AbstractExceptions.getCause(throwable);
}
/**
* <p>Returns the cause of the <code>throwable</code> by walking through the exception chain.
* <br>
* <br>
* <p>Note that this method walks through the exception chain up to given <code>maxDepth</code>. If exception chain
* includes more items than <code>maxDepth</code>, cause found at <code>maxDepth</code> level is returned.
*
* @param throwable parent throwable
* @param maxDepth max depth in exception chain that will be searched
* @return the cause of the <code>throwable</code> found until <code>maxDepth</code> is reached in the exception
* chain or null if <code>throwable</code> does not have a cause
*/
public static Throwable getCause(final Throwable throwable, final int maxDepth) {
return AbstractExceptions.getCause(throwable, maxDepth);
}
/**
* <p>Searches for the given cause class in the exception chain of the <code>throwable</code>.
* <br>
* <br>
* <p>Search starts from the <code>throwable</code> itself and goes through the exception chain up until
* {@link AbstractExceptions#DEFAULT_MAX_DEPTH}.
*
* @param throwable parent throwable
* @param causeClass class to search for
* @return the <code>throwable</code> found or null if no class in exception chain matches the given cause class
*/
public static Throwable searchCause(final Throwable throwable, final Class<?> causeClass) {
return AbstractExceptions.searchCause(throwable, causeClass);
}
/**
* <p>Searches for the given cause class and cause message in the exception chain of the <code>throwable</code>.
* <br>
* <br>
* <p>Search starts from the <code>throwable</code> itself and goes through the exception chain up until
* {@link AbstractExceptions#DEFAULT_MAX_DEPTH}.
*
* @param throwable parent throwable
* @param causeClass class to search for
* @param causeMessage message to search for
* @return the <code>throwable</code> found or null if no class in exception chain matches the given cause class
* and cause message
*/
public static Throwable searchCause(final Throwable throwable, final Class<?> causeClass, final String causeMessage) {
return AbstractExceptions.searchCause(throwable, causeClass, causeMessage);
}
/**
* <p>Searches for the given cause class and cause message in the exception chain of the <code>throwable</code>.
* <br>
* <br>
* <p>Search starts from the <code>throwable</code> itself and goes through the exception chain up until the given
* <code>maxDepth</code>.
*
* @param throwable parent throwable
* @param causeClass class to search for
* @param causeMessage message to search for
* @param maxDepth max depth in exception chain that will be searched
* @return the <code>throwable</code> found or null if no class in exception chain matches the given cause class
* and cause message
*/
public static Throwable searchCause(final Throwable throwable, final Class<?> causeClass, final String causeMessage, final int maxDepth) {
return AbstractExceptions.searchCause(throwable, causeClass, causeMessage, maxDepth);
}
/**
* <p>Searches for the given cause class in the exception chain of the <code>throwable</code>.
* <br>
* <br>
* <p>Search starts from the <code>throwable</code> itself and goes through the exception chain up until the given
* <code>maxDepth</code>.
*
* @param throwable parent throwable
* @param causeClass class to search for
* @param maxDepth max depth in exception chain that will be searched
* @return the <code>throwable</code> found or null if no class in exception chain matches the given cause class
*/
public static Throwable searchCause(final Throwable throwable, final Class<?> causeClass, final int maxDepth) {
return AbstractExceptions.searchCause(throwable, causeClass, maxDepth);
}
}
@@ -1,6 +1,5 @@
package ru.vtosters.lite.music;
import android.os.Environment;
import android.util.Log;
import com.arthenica.ffmpegkit.FFmpegKit;
@@ -21,11 +20,11 @@ public class FFMpeg {
try {
String[] files = Globals.getContext().getAssets().list("ffmpeg");
// log all files
Log.d("INIT", "files: " + Arrays.toString(files));
Log.d("FFMpeg", "files: " + Arrays.toString(files));
for (String file : files) {
if (file.endsWith(".so")) {
InputStream in = Globals.getContext().getAssets().open("ffmpeg" + File.separator + file);
FileOutputStream out = new FileOutputStream(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS) + "/" + file);
FileOutputStream out = new FileOutputStream(Globals.getContext().getFilesDir() + File.separator + file);
byte[] buffer = new byte[BUFFER_SIZE];
int read;
while ((read = in.read(buffer)) != -1) {
@@ -41,7 +40,7 @@ public class FFMpeg {
}
private static void checkFFMpegLibs() {
var lib = new File(Globals.getContext().getCacheDir(), "libffmpegkit_abidetect.so");
var lib = new File(Globals.getContext().getFilesDir(), "libffmpegkit_abidetect.so");
if (!lib.exists()) {
ToastUtils.a("Копирование библиотеки ffmpegkit");
copyAssets();
@@ -60,7 +59,4 @@ public class FFMpeg {
return false;
}
}
}