Better exception handling for DataExtension gathering:

- Any method that causes an exception is temporarily disabled until
  next Plan reload
  - Gathering is attempted again for the rest of the methods of that
    extension
- Exceptions are properly logged instead of just names of the exceptions
This commit is contained in:
Rsl1122 2019-05-02 17:00:30 +03:00
parent 41720baf78
commit 6e78e9e7ad
11 changed files with 170 additions and 87 deletions

View File

@ -0,0 +1,44 @@
/*
* This file is part of Player Analytics (Plan).
*
* Plan is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License v3 as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Plan is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Plan. If not, see <https://www.gnu.org/licenses/>.
*/
package com.djrapitops.plan.api.exceptions;
import com.djrapitops.plan.extension.implementation.providers.MethodWrapper;
/**
* Exception that is thrown when a call to a DataExtension method throws an exception.
*
* @author Rsl1122
*/
public class DataExtensionMethodCallException extends IllegalStateException {
private final String pluginName;
private final MethodWrapper method;
public DataExtensionMethodCallException(Throwable cause, String pluginName, MethodWrapper method) {
super(cause);
this.pluginName = pluginName;
this.method = method;
}
public String getPluginName() {
return pluginName;
}
public MethodWrapper getMethod() {
return method;
}
}

View File

@ -16,6 +16,7 @@
*/ */
package com.djrapitops.plan.extension; package com.djrapitops.plan.extension;
import com.djrapitops.plan.api.exceptions.DataExtensionMethodCallException;
import com.djrapitops.plan.data.plugin.PluginsConfigSection; import com.djrapitops.plan.data.plugin.PluginsConfigSection;
import com.djrapitops.plan.extension.implementation.CallerImplementation; import com.djrapitops.plan.extension.implementation.CallerImplementation;
import com.djrapitops.plan.extension.implementation.DataProviderExtractor; import com.djrapitops.plan.extension.implementation.DataProviderExtractor;
@ -111,7 +112,6 @@ public class ExtensionServiceImplementation implements ExtensionService {
if (extensionGatherers.remove(pluginName) != null) { if (extensionGatherers.remove(pluginName) != null) {
logger.getDebugLogger().logOn(DebugChannels.DATA_EXTENSIONS, pluginName + " extension unregistered."); logger.getDebugLogger().logOn(DebugChannels.DATA_EXTENSIONS, pluginName + " extension unregistered.");
} }
} }
private boolean shouldNotAllowRegistration(String pluginName) { private boolean shouldNotAllowRegistration(String pluginName) {
@ -150,16 +150,29 @@ public class ExtensionServiceImplementation implements ExtensionService {
gatherer.updateValues(playerUUID, playerName); gatherer.updateValues(playerUUID, playerName);
logger.getDebugLogger().logOn(DebugChannels.DATA_EXTENSIONS, "Gathering completed: " + playerName); logger.getDebugLogger().logOn(DebugChannels.DATA_EXTENSIONS, "Gathering completed: " + playerName);
} catch (Exception | NoClassDefFoundError | NoSuchMethodError | NoSuchFieldError e) { } catch (DataExtensionMethodCallException methodCallFailed) {
logger.warn(gatherer.getPluginName() + " ran into (but failed safely) " + e.getClass().getSimpleName() + logFailure(playerName, methodCallFailed);
" when updating value for '" + playerName + gatherer.disableMethodFromUse(methodCallFailed.getMethod());
"', (You can disable integration with setting 'Plugins." + gatherer.getPluginName() + ".Enabled')" + // Try again
" reason: '" + e.getMessage() + updatePlayerValues(gatherer, playerUUID, playerName, event);
} catch (Exception | NoClassDefFoundError | NoSuchFieldError | NoSuchMethodError unexpectedError) {
logger.warn(gatherer.getPluginName() + " ran into unexpected error (please report this)" + unexpectedError +
" (but failed safely) when updating value for '" + playerName +
"', stack trace to follow:"); "', stack trace to follow:");
errorHandler.log(L.WARN, gatherer.getClass(), e); errorHandler.log(L.WARN, gatherer.getClass(), unexpectedError);
} }
} }
private void logFailure(String playerName, DataExtensionMethodCallException methodCallFailed) {
Throwable cause = methodCallFailed.getCause();
String causeName = cause.getClass().getSimpleName();
logger.warn(methodCallFailed.getPluginName() + " ran into " + causeName +
" (but failed safely) when updating value for '" + playerName +
"', the method was disabled temporarily (won't be called until next Plan reload)" +
", stack trace to follow:");
errorHandler.log(L.WARN, getClass(), cause);
}
public void updateServerValues(CallEvents event) { public void updateServerValues(CallEvents event) {
for (ProviderValueGatherer gatherer : extensionGatherers.values()) { for (ProviderValueGatherer gatherer : extensionGatherers.values()) {
updateServerValues(gatherer, event); updateServerValues(gatherer, event);
@ -176,13 +189,15 @@ public class ExtensionServiceImplementation implements ExtensionService {
gatherer.updateValues(); gatherer.updateValues();
logger.getDebugLogger().logOn(DebugChannels.DATA_EXTENSIONS, "Gathering completed for server"); logger.getDebugLogger().logOn(DebugChannels.DATA_EXTENSIONS, "Gathering completed for server");
} catch (Exception | NoClassDefFoundError | NoSuchMethodError | NoSuchFieldError e) { } catch (DataExtensionMethodCallException methodCallFailed) {
logger.warn(gatherer.getPluginName() + " ran into (but failed safely) " + e.getClass().getSimpleName() + logFailure("server", methodCallFailed);
" when updating value for server" + gatherer.disableMethodFromUse(methodCallFailed.getMethod());
", (You can disable integration with setting 'Plugins." + gatherer.getPluginName() + ".Enabled')" + // Try again
" reason: '" + e.getMessage() + updateServerValues(gatherer, event);
"', stack trace to follow:"); } catch (Exception | NoClassDefFoundError | NoSuchFieldError | NoSuchMethodError unexpectedError) {
errorHandler.log(L.WARN, gatherer.getClass(), e); logger.warn(gatherer.getPluginName() + " ran into unexpected error (please report this)" + unexpectedError +
" (but failed safely) when updating value for server, stack trace to follow:");
errorHandler.log(L.WARN, gatherer.getClass(), unexpectedError);
} }
} }
} }

View File

@ -19,6 +19,7 @@ package com.djrapitops.plan.extension.implementation.providers;
import com.djrapitops.plan.extension.implementation.MethodType; import com.djrapitops.plan.extension.implementation.MethodType;
import java.util.*; import java.util.*;
import java.util.stream.Collectors;
/** /**
* Group class for handling multiple different types of {@link DataProvider}s. * Group class for handling multiple different types of {@link DataProvider}s.
@ -77,4 +78,24 @@ public class DataProviders {
} }
return byReturnType; return byReturnType;
} }
public void removeProviderWithMethod(MethodWrapper method) {
MethodType methodType = method.getMethodType();
Map<Class, List<DataProvider>> byResultType = byMethodType.getOrDefault(methodType, Collections.emptyMap());
if (byResultType.isEmpty()) {
return;
}
Class resultType = method.getResultType();
List<DataProvider> providers = byResultType.getOrDefault(resultType, Collections.emptyList());
if (providers.isEmpty()) {
return;
}
byResultType.put(resultType, providers.stream()
.filter(provider -> provider.getMethod().equals(method))
.collect(Collectors.toList())
);
byMethodType.put(methodType, byResultType);
}
} }

View File

@ -22,6 +22,7 @@ import com.djrapitops.plan.extension.implementation.MethodType;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.Objects;
import java.util.UUID; import java.util.UUID;
/** /**
@ -95,4 +96,19 @@ public class MethodWrapper<T> {
public Class<T> getResultType() { public Class<T> getResultType() {
return resultType; return resultType;
} }
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof MethodWrapper)) return false;
MethodWrapper<?> that = (MethodWrapper<?>) o;
return method.equals(that.method) &&
resultType.equals(that.resultType) &&
methodType == that.methodType;
}
@Override
public int hashCode() {
return Objects.hash(method, resultType, methodType);
}
} }

View File

@ -16,6 +16,7 @@
*/ */
package com.djrapitops.plan.extension.implementation.providers.gathering; package com.djrapitops.plan.extension.implementation.providers.gathering;
import com.djrapitops.plan.api.exceptions.DataExtensionMethodCallException;
import com.djrapitops.plan.db.Database; import com.djrapitops.plan.db.Database;
import com.djrapitops.plan.db.access.transactions.Transaction; import com.djrapitops.plan.db.access.transactions.Transaction;
import com.djrapitops.plan.extension.DataExtension; import com.djrapitops.plan.extension.DataExtension;
@ -28,7 +29,6 @@ import com.djrapitops.plan.extension.implementation.storage.transactions.StoreIc
import com.djrapitops.plan.extension.implementation.storage.transactions.providers.StoreBooleanProviderTransaction; import com.djrapitops.plan.extension.implementation.storage.transactions.providers.StoreBooleanProviderTransaction;
import com.djrapitops.plan.extension.implementation.storage.transactions.results.StorePlayerBooleanResultTransaction; import com.djrapitops.plan.extension.implementation.storage.transactions.results.StorePlayerBooleanResultTransaction;
import com.djrapitops.plan.extension.implementation.storage.transactions.results.StoreServerBooleanResultTransaction; import com.djrapitops.plan.extension.implementation.storage.transactions.results.StoreServerBooleanResultTransaction;
import com.djrapitops.plugin.logging.console.PluginLogger;
import java.util.*; import java.util.*;
import java.util.concurrent.Callable; import java.util.concurrent.Callable;
@ -48,20 +48,17 @@ class BooleanProviderValueGatherer {
private final Database database; private final Database database;
private final DataProviders dataProviders; private final DataProviders dataProviders;
private final PluginLogger logger;
BooleanProviderValueGatherer( BooleanProviderValueGatherer(
String pluginName, DataExtension extension, String pluginName, DataExtension extension,
UUID serverUUID, Database database, UUID serverUUID, Database database,
DataProviders dataProviders, DataProviders dataProviders
PluginLogger logger
) { ) {
this.pluginName = pluginName; this.pluginName = pluginName;
this.extension = extension; this.extension = extension;
this.serverUUID = serverUUID; this.serverUUID = serverUUID;
this.database = database; this.database = database;
this.dataProviders = dataProviders; this.dataProviders = dataProviders;
this.logger = logger;
} }
Conditions gatherBooleanDataOfPlayer(UUID playerUUID, String playerName) { Conditions gatherBooleanDataOfPlayer(UUID playerUUID, String playerName) {
@ -127,10 +124,7 @@ class BooleanProviderValueGatherer {
boolean hidden = BooleanDataProvider.isHidden(booleanProvider); boolean hidden = BooleanDataProvider.isHidden(booleanProvider);
MethodWrapper<Boolean> method = booleanProvider.getMethod(); MethodWrapper<Boolean> method = booleanProvider.getMethod();
Boolean result = getMethodResult( Boolean result = getMethodResult(methodCaller.apply(method), method);
methodCaller.apply(method),
throwable -> pluginName + " has invalid implementation, method " + method.getMethodName() + " threw exception: " + throwable.toString()
);
if (result == null) { if (result == null) {
// Error during method call // Error during method call
satisfied.add(booleanProvider); // Prevents further attempts to call this provider for this player. satisfied.add(booleanProvider); // Prevents further attempts to call this provider for this player.
@ -155,13 +149,11 @@ class BooleanProviderValueGatherer {
return satisfied; return satisfied;
} }
private <T> T getMethodResult(Callable<T> callable, Function<Throwable, String> errorMsg) { private <T> T getMethodResult(Callable<T> callable, MethodWrapper<T> method) {
try { try {
return callable.call(); return callable.call();
} catch (Exception | NoSuchFieldError | NoSuchMethodError e) { } catch (Exception | NoClassDefFoundError | NoSuchFieldError | NoSuchMethodError e) {
logger.warn(errorMsg.apply(e)); throw new DataExtensionMethodCallException(e, pluginName, method);
return null;
} }
} }
} }

View File

@ -16,6 +16,7 @@
*/ */
package com.djrapitops.plan.extension.implementation.providers.gathering; package com.djrapitops.plan.extension.implementation.providers.gathering;
import com.djrapitops.plan.api.exceptions.DataExtensionMethodCallException;
import com.djrapitops.plan.db.Database; import com.djrapitops.plan.db.Database;
import com.djrapitops.plan.db.access.transactions.Transaction; import com.djrapitops.plan.db.access.transactions.Transaction;
import com.djrapitops.plan.extension.DataExtension; import com.djrapitops.plan.extension.DataExtension;
@ -30,7 +31,6 @@ import com.djrapitops.plan.extension.implementation.storage.transactions.results
import com.djrapitops.plan.extension.implementation.storage.transactions.results.StorePlayerPercentageResultTransaction; import com.djrapitops.plan.extension.implementation.storage.transactions.results.StorePlayerPercentageResultTransaction;
import com.djrapitops.plan.extension.implementation.storage.transactions.results.StoreServerDoubleResultTransaction; import com.djrapitops.plan.extension.implementation.storage.transactions.results.StoreServerDoubleResultTransaction;
import com.djrapitops.plan.extension.implementation.storage.transactions.results.StoreServerPercentageResultTransaction; import com.djrapitops.plan.extension.implementation.storage.transactions.results.StoreServerPercentageResultTransaction;
import com.djrapitops.plugin.logging.console.PluginLogger;
import java.util.Optional; import java.util.Optional;
import java.util.UUID; import java.util.UUID;
@ -51,20 +51,17 @@ class DoubleAndPercentageProviderValueGatherer {
private final Database database; private final Database database;
private final DataProviders dataProviders; private final DataProviders dataProviders;
private final PluginLogger logger;
DoubleAndPercentageProviderValueGatherer( DoubleAndPercentageProviderValueGatherer(
String pluginName, DataExtension extension, String pluginName, DataExtension extension,
UUID serverUUID, Database database, UUID serverUUID, Database database,
DataProviders dataProviders, DataProviders dataProviders
PluginLogger logger
) { ) {
this.pluginName = pluginName; this.pluginName = pluginName;
this.extension = extension; this.extension = extension;
this.serverUUID = serverUUID; this.serverUUID = serverUUID;
this.database = database; this.database = database;
this.dataProviders = dataProviders; this.dataProviders = dataProviders;
this.logger = logger;
} }
void gatherDoubleDataOfPlayer(UUID playerUUID, String playerName, Conditions conditions) { void gatherDoubleDataOfPlayer(UUID playerUUID, String playerName, Conditions conditions) {
@ -105,10 +102,7 @@ class DoubleAndPercentageProviderValueGatherer {
} }
MethodWrapper<Double> method = doubleProvider.getMethod(); MethodWrapper<Double> method = doubleProvider.getMethod();
Double result = getMethodResult( Double result = getMethodResult(methodCaller.apply(method), method);
methodCaller.apply(method),
throwable -> pluginName + " has invalid implementation, method " + method.getMethodName() + " threw exception: " + throwable.toString()
);
if (result == null) { if (result == null) {
return; return;
} }
@ -123,13 +117,11 @@ class DoubleAndPercentageProviderValueGatherer {
} }
} }
private <T> T getMethodResult(Callable<T> callable, Function<Throwable, String> errorMsg) { private <T> T getMethodResult(Callable<T> callable, MethodWrapper<T> method) {
try { try {
return callable.call(); return callable.call();
} catch (Exception | NoSuchFieldError | NoSuchMethodError e) { } catch (Exception | NoClassDefFoundError | NoSuchFieldError | NoSuchMethodError e) {
logger.warn(errorMsg.apply(e)); throw new DataExtensionMethodCallException(e, pluginName, method);
return null;
} }
} }
} }

View File

@ -16,6 +16,7 @@
*/ */
package com.djrapitops.plan.extension.implementation.providers.gathering; package com.djrapitops.plan.extension.implementation.providers.gathering;
import com.djrapitops.plan.api.exceptions.DataExtensionMethodCallException;
import com.djrapitops.plan.db.Database; import com.djrapitops.plan.db.Database;
import com.djrapitops.plan.db.access.transactions.Transaction; import com.djrapitops.plan.db.access.transactions.Transaction;
import com.djrapitops.plan.extension.DataExtension; import com.djrapitops.plan.extension.DataExtension;
@ -29,7 +30,6 @@ import com.djrapitops.plan.extension.implementation.storage.transactions.StoreIc
import com.djrapitops.plan.extension.implementation.storage.transactions.providers.StoreNumberProviderTransaction; import com.djrapitops.plan.extension.implementation.storage.transactions.providers.StoreNumberProviderTransaction;
import com.djrapitops.plan.extension.implementation.storage.transactions.results.StorePlayerNumberResultTransaction; import com.djrapitops.plan.extension.implementation.storage.transactions.results.StorePlayerNumberResultTransaction;
import com.djrapitops.plan.extension.implementation.storage.transactions.results.StoreServerNumberResultTransaction; import com.djrapitops.plan.extension.implementation.storage.transactions.results.StoreServerNumberResultTransaction;
import com.djrapitops.plugin.logging.console.PluginLogger;
import java.util.Optional; import java.util.Optional;
import java.util.UUID; import java.util.UUID;
@ -50,20 +50,17 @@ class NumberProviderValueGatherer {
private final Database database; private final Database database;
private final DataProviders dataProviders; private final DataProviders dataProviders;
private final PluginLogger logger;
NumberProviderValueGatherer( NumberProviderValueGatherer(
String pluginName, DataExtension extension, String pluginName, DataExtension extension,
UUID serverUUID, Database database, UUID serverUUID, Database database,
DataProviders dataProviders, DataProviders dataProviders
PluginLogger logger
) { ) {
this.pluginName = pluginName; this.pluginName = pluginName;
this.extension = extension; this.extension = extension;
this.serverUUID = serverUUID; this.serverUUID = serverUUID;
this.database = database; this.database = database;
this.dataProviders = dataProviders; this.dataProviders = dataProviders;
this.logger = logger;
} }
void gatherNumberDataOfPlayer(UUID playerUUID, String playerName, Conditions conditions) { void gatherNumberDataOfPlayer(UUID playerUUID, String playerName, Conditions conditions) {
@ -100,10 +97,7 @@ class NumberProviderValueGatherer {
} }
MethodWrapper<Long> method = numberProvider.getMethod(); MethodWrapper<Long> method = numberProvider.getMethod();
Long result = getMethodResult( Long result = getMethodResult(methodCaller.apply(method), method);
methodCaller.apply(method),
throwable -> pluginName + " has invalid implementation, method " + method.getMethodName() + " threw exception: " + throwable.toString()
);
if (result == null) { if (result == null) {
return; return;
} }
@ -115,12 +109,11 @@ class NumberProviderValueGatherer {
database.executeTransaction(storeTransactionCreator.apply(method, result)); database.executeTransaction(storeTransactionCreator.apply(method, result));
} }
private <T> T getMethodResult(Callable<T> callable, Function<Throwable, String> errorMsg) { private <T> T getMethodResult(Callable<T> callable, MethodWrapper<T> method) {
try { try {
return callable.call(); return callable.call();
} catch (Exception | NoSuchFieldError | NoSuchMethodError e) { } catch (Exception | NoClassDefFoundError | NoSuchFieldError | NoSuchMethodError e) {
logger.warn(errorMsg.apply(e)); throw new DataExtensionMethodCallException(e, pluginName, method);
return null;
} }
} }
} }

View File

@ -23,6 +23,7 @@ import com.djrapitops.plan.extension.icon.Icon;
import com.djrapitops.plan.extension.implementation.DataProviderExtractor; import com.djrapitops.plan.extension.implementation.DataProviderExtractor;
import com.djrapitops.plan.extension.implementation.TabInformation; import com.djrapitops.plan.extension.implementation.TabInformation;
import com.djrapitops.plan.extension.implementation.providers.DataProviders; import com.djrapitops.plan.extension.implementation.providers.DataProviders;
import com.djrapitops.plan.extension.implementation.providers.MethodWrapper;
import com.djrapitops.plan.extension.implementation.storage.transactions.StoreIconTransaction; import com.djrapitops.plan.extension.implementation.storage.transactions.StoreIconTransaction;
import com.djrapitops.plan.extension.implementation.storage.transactions.StorePluginTransaction; import com.djrapitops.plan.extension.implementation.storage.transactions.StorePluginTransaction;
import com.djrapitops.plan.extension.implementation.storage.transactions.StoreTabInformationTransaction; import com.djrapitops.plan.extension.implementation.storage.transactions.StoreTabInformationTransaction;
@ -44,12 +45,15 @@ public class ProviderValueGatherer {
private final DataProviderExtractor extractor; private final DataProviderExtractor extractor;
private final DBSystem dbSystem; private final DBSystem dbSystem;
private final ServerInfo serverInfo; private final ServerInfo serverInfo;
private DataProviders dataProviders;
private BooleanProviderValueGatherer booleanGatherer; private BooleanProviderValueGatherer booleanGatherer;
private NumberProviderValueGatherer numberGatherer; private NumberProviderValueGatherer numberGatherer;
private DoubleAndPercentageProviderValueGatherer doubleAndPercentageGatherer; private DoubleAndPercentageProviderValueGatherer doubleAndPercentageGatherer;
private StringProviderValueGatherer stringGatherer; private StringProviderValueGatherer stringGatherer;
private TableProviderValueGatherer tableGatherer; private TableProviderValueGatherer tableGatherer;
public ProviderValueGatherer( public ProviderValueGatherer(
DataExtension extension, DataExtension extension,
DataProviderExtractor extractor, DataProviderExtractor extractor,
@ -65,24 +69,28 @@ public class ProviderValueGatherer {
String pluginName = extractor.getPluginName(); String pluginName = extractor.getPluginName();
UUID serverUUID = serverInfo.getServerUUID(); UUID serverUUID = serverInfo.getServerUUID();
Database database = dbSystem.getDatabase(); Database database = dbSystem.getDatabase();
DataProviders dataProviders = extractor.getDataProviders(); dataProviders = extractor.getDataProviders();
booleanGatherer = new BooleanProviderValueGatherer( booleanGatherer = new BooleanProviderValueGatherer(
pluginName, extension, serverUUID, database, dataProviders, logger pluginName, extension, serverUUID, database, dataProviders
); );
numberGatherer = new NumberProviderValueGatherer( numberGatherer = new NumberProviderValueGatherer(
pluginName, extension, serverUUID, database, dataProviders, logger pluginName, extension, serverUUID, database, dataProviders
); );
doubleAndPercentageGatherer = new DoubleAndPercentageProviderValueGatherer( doubleAndPercentageGatherer = new DoubleAndPercentageProviderValueGatherer(
pluginName, extension, serverUUID, database, dataProviders, logger pluginName, extension, serverUUID, database, dataProviders
); );
stringGatherer = new StringProviderValueGatherer( stringGatherer = new StringProviderValueGatherer(
pluginName, extension, serverUUID, database, dataProviders, logger pluginName, extension, serverUUID, database, dataProviders
); );
tableGatherer = new TableProviderValueGatherer( tableGatherer = new TableProviderValueGatherer(
pluginName, extension, serverUUID, database, dataProviders, logger pluginName, extension, serverUUID, database, dataProviders
); );
} }
public void disableMethodFromUse(MethodWrapper method) {
dataProviders.removeProviderWithMethod(method);
}
public boolean canCallEvent(CallEvents event) { public boolean canCallEvent(CallEvents event) {
if (event == CallEvents.MANUAL) { if (event == CallEvents.MANUAL) {
return true; return true;

View File

@ -16,6 +16,7 @@
*/ */
package com.djrapitops.plan.extension.implementation.providers.gathering; package com.djrapitops.plan.extension.implementation.providers.gathering;
import com.djrapitops.plan.api.exceptions.DataExtensionMethodCallException;
import com.djrapitops.plan.db.Database; import com.djrapitops.plan.db.Database;
import com.djrapitops.plan.db.access.transactions.Transaction; import com.djrapitops.plan.db.access.transactions.Transaction;
import com.djrapitops.plan.extension.DataExtension; import com.djrapitops.plan.extension.DataExtension;
@ -28,7 +29,6 @@ import com.djrapitops.plan.extension.implementation.storage.transactions.StoreIc
import com.djrapitops.plan.extension.implementation.storage.transactions.providers.StoreStringProviderTransaction; import com.djrapitops.plan.extension.implementation.storage.transactions.providers.StoreStringProviderTransaction;
import com.djrapitops.plan.extension.implementation.storage.transactions.results.StorePlayerStringResultTransaction; import com.djrapitops.plan.extension.implementation.storage.transactions.results.StorePlayerStringResultTransaction;
import com.djrapitops.plan.extension.implementation.storage.transactions.results.StoreServerStringResultTransaction; import com.djrapitops.plan.extension.implementation.storage.transactions.results.StoreServerStringResultTransaction;
import com.djrapitops.plugin.logging.console.PluginLogger;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import java.util.Optional; import java.util.Optional;
@ -50,20 +50,17 @@ class StringProviderValueGatherer {
private final Database database; private final Database database;
private final DataProviders dataProviders; private final DataProviders dataProviders;
private final PluginLogger logger;
StringProviderValueGatherer( StringProviderValueGatherer(
String pluginName, DataExtension extension, String pluginName, DataExtension extension,
UUID serverUUID, Database database, UUID serverUUID, Database database,
DataProviders dataProviders, DataProviders dataProviders
PluginLogger logger
) { ) {
this.pluginName = pluginName; this.pluginName = pluginName;
this.extension = extension; this.extension = extension;
this.serverUUID = serverUUID; this.serverUUID = serverUUID;
this.database = database; this.database = database;
this.dataProviders = dataProviders; this.dataProviders = dataProviders;
this.logger = logger;
} }
void gatherStringDataOfPlayer(UUID playerUUID, String playerName, Conditions conditions) { void gatherStringDataOfPlayer(UUID playerUUID, String playerName, Conditions conditions) {
@ -101,10 +98,7 @@ class StringProviderValueGatherer {
} }
MethodWrapper<String> method = stringProvider.getMethod(); MethodWrapper<String> method = stringProvider.getMethod();
String result = getMethodResult( String result = getMethodResult(methodCaller.apply(method), method);
methodCaller.apply(method),
throwable -> pluginName + " has invalid implementation, method " + method.getMethodName() + " threw exception: " + throwable.toString()
);
if (result == null) { if (result == null) {
return; return;
} }
@ -116,12 +110,11 @@ class StringProviderValueGatherer {
database.executeTransaction(storeTransactionCreator.apply(method, result)); database.executeTransaction(storeTransactionCreator.apply(method, result));
} }
private <T> T getMethodResult(Callable<T> callable, Function<Throwable, String> errorMsg) { private <T> T getMethodResult(Callable<T> callable, MethodWrapper<String> method) {
try { try {
return callable.call(); return callable.call();
} catch (Exception | NoSuchFieldError | NoSuchMethodError e) { } catch (Exception | NoClassDefFoundError | NoSuchFieldError | NoSuchMethodError e) {
logger.warn(errorMsg.apply(e)); throw new DataExtensionMethodCallException(e, pluginName, method);
return null;
} }
} }

View File

@ -16,6 +16,7 @@
*/ */
package com.djrapitops.plan.extension.implementation.providers.gathering; package com.djrapitops.plan.extension.implementation.providers.gathering;
import com.djrapitops.plan.api.exceptions.DataExtensionMethodCallException;
import com.djrapitops.plan.db.Database; import com.djrapitops.plan.db.Database;
import com.djrapitops.plan.db.access.transactions.Transaction; import com.djrapitops.plan.db.access.transactions.Transaction;
import com.djrapitops.plan.extension.DataExtension; import com.djrapitops.plan.extension.DataExtension;
@ -30,7 +31,6 @@ import com.djrapitops.plan.extension.implementation.storage.transactions.provide
import com.djrapitops.plan.extension.implementation.storage.transactions.results.StorePlayerTableResultTransaction; import com.djrapitops.plan.extension.implementation.storage.transactions.results.StorePlayerTableResultTransaction;
import com.djrapitops.plan.extension.implementation.storage.transactions.results.StoreServerTableResultTransaction; import com.djrapitops.plan.extension.implementation.storage.transactions.results.StoreServerTableResultTransaction;
import com.djrapitops.plan.extension.table.Table; import com.djrapitops.plan.extension.table.Table;
import com.djrapitops.plugin.logging.console.PluginLogger;
import java.util.Optional; import java.util.Optional;
import java.util.UUID; import java.util.UUID;
@ -51,20 +51,17 @@ class TableProviderValueGatherer {
private final Database database; private final Database database;
private final DataProviders dataProviders; private final DataProviders dataProviders;
private final PluginLogger logger;
TableProviderValueGatherer( TableProviderValueGatherer(
String pluginName, DataExtension extension, String pluginName, DataExtension extension,
UUID serverUUID, Database database, UUID serverUUID, Database database,
DataProviders dataProviders, DataProviders dataProviders
PluginLogger logger
) { ) {
this.pluginName = pluginName; this.pluginName = pluginName;
this.extension = extension; this.extension = extension;
this.serverUUID = serverUUID; this.serverUUID = serverUUID;
this.database = database; this.database = database;
this.dataProviders = dataProviders; this.dataProviders = dataProviders;
this.logger = logger;
} }
void gatherTableDataOfPlayer(UUID playerUUID, String playerName, Conditions conditions) { void gatherTableDataOfPlayer(UUID playerUUID, String playerName, Conditions conditions) {
@ -102,10 +99,7 @@ class TableProviderValueGatherer {
} }
MethodWrapper<Table> method = tableProvider.getMethod(); MethodWrapper<Table> method = tableProvider.getMethod();
Table result = getMethodResult( Table result = getMethodResult(methodCaller.apply(method), method);
methodCaller.apply(method),
throwable -> pluginName + " has invalid implementation, method " + method.getMethodName() + " threw exception: " + throwable.toString()
);
if (result == null) { if (result == null) {
return; return;
} }
@ -119,12 +113,11 @@ class TableProviderValueGatherer {
database.executeTransaction(storeTransactionCreator.apply(method, result)); database.executeTransaction(storeTransactionCreator.apply(method, result));
} }
private <T> T getMethodResult(Callable<T> callable, Function<Throwable, String> errorMsg) { private <T> T getMethodResult(Callable<T> callable, MethodWrapper<T> method) {
try { try {
return callable.call(); return callable.call();
} catch (Exception | NoSuchFieldError | NoSuchMethodError e) { } catch (Exception | NoClassDefFoundError | NoSuchFieldError | NoSuchMethodError e) {
logger.warn(errorMsg.apply(e)); throw new DataExtensionMethodCallException(e, pluginName, method);
return null;
} }
} }

View File

@ -1,3 +1,19 @@
/*
* This file is part of Player Analytics (Plan).
*
* Plan is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License v3 as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Plan is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Plan. If not, see <https://www.gnu.org/licenses/>.
*/
package com.djrapitops.plan.utilities.html.tables; package com.djrapitops.plan.utilities.html.tables;
import com.djrapitops.plan.api.PlanAPI; import com.djrapitops.plan.api.PlanAPI;