Added defensive null checking code to DB

Relates to https://github.com/BentoBoxWorld/BentoBox/issues/447
This commit is contained in:
tastybento 2019-01-07 07:46:59 -08:00
parent 9eec14ffb3
commit acb6cd5650
5 changed files with 75 additions and 10 deletions

View File

@ -1,8 +1,5 @@
package world.bentobox.bentobox.database.json; package world.bentobox.bentobox.database.json;
import world.bentobox.bentobox.BentoBox;
import world.bentobox.bentobox.database.DatabaseConnector;
import java.beans.IntrospectionException; import java.beans.IntrospectionException;
import java.beans.PropertyDescriptor; import java.beans.PropertyDescriptor;
import java.io.File; import java.io.File;
@ -19,6 +16,10 @@ import java.util.List;
import java.util.Locale; import java.util.Locale;
import java.util.Objects; import java.util.Objects;
import world.bentobox.bentobox.BentoBox;
import world.bentobox.bentobox.database.DatabaseConnector;
import world.bentobox.bentobox.database.objects.DataObject;
public class JSONDatabaseHandler<T> extends AbstractJSONDatabaseHandler<T> { public class JSONDatabaseHandler<T> extends AbstractJSONDatabaseHandler<T> {
private static final String JSON = ".json"; private static final String JSON = ".json";
@ -84,6 +85,15 @@ public class JSONDatabaseHandler<T> extends AbstractJSONDatabaseHandler<T> {
@Override @Override
public void saveObject(T instance) throws IllegalAccessException, InvocationTargetException, IntrospectionException { public void saveObject(T instance) throws IllegalAccessException, InvocationTargetException, IntrospectionException {
// Null check
if (instance == null) {
plugin.logError("JSON database request to store a null. ");
return;
}
if (!(instance instanceof DataObject)) {
plugin.logError("This class is not a DataObject: " + instance.getClass().getName());
return;
}
String path = DATABASE_FOLDER_NAME + File.separator + dataObject.getSimpleName(); String path = DATABASE_FOLDER_NAME + File.separator + dataObject.getSimpleName();
// Obtain the value of uniqueId within the instance (which must be a DataObject) // Obtain the value of uniqueId within the instance (which must be a DataObject)
@ -114,6 +124,16 @@ public class JSONDatabaseHandler<T> extends AbstractJSONDatabaseHandler<T> {
@Override @Override
public void deleteObject(T instance) throws IllegalAccessException, InvocationTargetException, IntrospectionException { public void deleteObject(T instance) throws IllegalAccessException, InvocationTargetException, IntrospectionException {
// Null check
if (instance == null) {
plugin.logError("JSON database request to delete a null. ");
return;
}
if (!(instance instanceof DataObject)) {
plugin.logError("This class is not a DataObject: " + instance.getClass().getName());
return;
}
// Obtain the value of uniqueId within the instance (which must be a DataObject) // Obtain the value of uniqueId within the instance (which must be a DataObject)
PropertyDescriptor propertyDescriptor = new PropertyDescriptor("uniqueId", dataObject); PropertyDescriptor propertyDescriptor = new PropertyDescriptor("uniqueId", dataObject);
Method method = propertyDescriptor.getReadMethod(); Method method = propertyDescriptor.getReadMethod();

View File

@ -15,8 +15,8 @@ import com.mongodb.client.model.Indexes;
import com.mongodb.util.JSON; import com.mongodb.util.JSON;
import world.bentobox.bentobox.BentoBox; import world.bentobox.bentobox.BentoBox;
import world.bentobox.bentobox.database.json.AbstractJSONDatabaseHandler;
import world.bentobox.bentobox.database.DatabaseConnector; import world.bentobox.bentobox.database.DatabaseConnector;
import world.bentobox.bentobox.database.json.AbstractJSONDatabaseHandler;
import world.bentobox.bentobox.database.objects.DataObject; import world.bentobox.bentobox.database.objects.DataObject;
/** /**
@ -78,6 +78,11 @@ public class MongoDBDatabaseHandler<T> extends AbstractJSONDatabaseHandler<T> {
@Override @Override
public void saveObject(T instance) { public void saveObject(T instance) {
// Null check
if (instance == null) {
plugin.logError("MongoDB database request to store a null. ");
return;
}
if (!(instance instanceof DataObject)) { if (!(instance instanceof DataObject)) {
plugin.logError("This class is not a DataObject: " + instance.getClass().getName()); plugin.logError("This class is not a DataObject: " + instance.getClass().getName());
return; return;
@ -103,6 +108,11 @@ public class MongoDBDatabaseHandler<T> extends AbstractJSONDatabaseHandler<T> {
@Override @Override
public void deleteObject(T instance) { public void deleteObject(T instance) {
// Null check
if (instance == null) {
plugin.logError("MondDB database request to delete a null. ");
return;
}
if (!(instance instanceof DataObject)) { if (!(instance instanceof DataObject)) {
plugin.logError("This class is not a DataObject: " + instance.getClass().getName()); plugin.logError("This class is not a DataObject: " + instance.getClass().getName());
return; return;

View File

@ -115,6 +115,11 @@ public class MySQLDatabaseHandler<T> extends AbstractJSONDatabaseHandler<T> {
@Override @Override
public void saveObject(T instance) { public void saveObject(T instance) {
// Null check
if (instance == null) {
plugin.logError("MySQL database request to store a null. ");
return;
}
if (!(instance instanceof DataObject)) { if (!(instance instanceof DataObject)) {
plugin.logError("This class is not a DataObject: " + instance.getClass().getName()); plugin.logError("This class is not a DataObject: " + instance.getClass().getName());
return; return;
@ -138,6 +143,11 @@ public class MySQLDatabaseHandler<T> extends AbstractJSONDatabaseHandler<T> {
@Override @Override
public void deleteObject(T instance) { public void deleteObject(T instance) {
// Null check
if (instance == null) {
plugin.logError("MySQL database request to delete a null. ");
return;
}
if (!(instance instanceof DataObject)) { if (!(instance instanceof DataObject)) {
plugin.logError("This class is not a DataObject: " + instance.getClass().getName()); plugin.logError("This class is not a DataObject: " + instance.getClass().getName());
return; return;

View File

@ -34,6 +34,7 @@ import world.bentobox.bentobox.api.configuration.StoreAt;
import world.bentobox.bentobox.api.localization.TextVariables; import world.bentobox.bentobox.api.localization.TextVariables;
import world.bentobox.bentobox.database.AbstractDatabaseHandler; import world.bentobox.bentobox.database.AbstractDatabaseHandler;
import world.bentobox.bentobox.database.DatabaseConnector; import world.bentobox.bentobox.database.DatabaseConnector;
import world.bentobox.bentobox.database.objects.DataObject;
import world.bentobox.bentobox.database.objects.adapters.Adapter; import world.bentobox.bentobox.database.objects.adapters.Adapter;
import world.bentobox.bentobox.database.objects.adapters.AdapterInterface; import world.bentobox.bentobox.database.objects.adapters.AdapterInterface;
import world.bentobox.bentobox.util.Util; import world.bentobox.bentobox.util.Util;
@ -293,6 +294,16 @@ public class YamlDatabaseHandler<T> extends AbstractDatabaseHandler<T> {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@Override @Override
public void saveObject(T instance) throws IllegalAccessException, InvocationTargetException, IntrospectionException { public void saveObject(T instance) throws IllegalAccessException, InvocationTargetException, IntrospectionException {
// Null check
if (instance == null) {
plugin.logError("YAML database request to store a null. ");
return;
}
// DataObject check
if (!(instance instanceof DataObject)) {
plugin.logError("This class is not a DataObject: " + instance.getClass().getName());
return;
}
// This is the Yaml Configuration that will be used and saved at the end // This is the Yaml Configuration that will be used and saved at the end
YamlConfiguration config = new YamlConfiguration(); YamlConfiguration config = new YamlConfiguration();
@ -547,6 +558,16 @@ public class YamlDatabaseHandler<T> extends AbstractDatabaseHandler<T> {
*/ */
@Override @Override
public void deleteObject(T instance) throws IllegalAccessException, InvocationTargetException, IntrospectionException { public void deleteObject(T instance) throws IllegalAccessException, InvocationTargetException, IntrospectionException {
// Null check
if (instance == null) {
plugin.logError("YAM database request to delete a null. ");
return;
}
if (!(instance instanceof DataObject)) {
plugin.logError("This class is not a DataObject: " + instance.getClass().getName());
return;
}
// Obtain the value of uniqueId within the instance (which must be a DataObject) // Obtain the value of uniqueId within the instance (which must be a DataObject)
PropertyDescriptor propertyDescriptor = new PropertyDescriptor("uniqueId", dataObject); PropertyDescriptor propertyDescriptor = new PropertyDescriptor("uniqueId", dataObject);
Method method = propertyDescriptor.getReadMethod(); Method method = propertyDescriptor.getReadMethod();

View File

@ -19,7 +19,7 @@ import org.bukkit.World;
import org.bukkit.World.Environment; import org.bukkit.World.Environment;
import org.bukkit.inventory.ItemFactory; import org.bukkit.inventory.ItemFactory;
import org.bukkit.plugin.PluginManager; import org.bukkit.plugin.PluginManager;
import org.junit.BeforeClass; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.mockito.Mock; import org.mockito.Mock;
@ -39,7 +39,7 @@ import world.bentobox.bentobox.managers.IslandWorldManager;
import world.bentobox.bentobox.util.Util; import world.bentobox.bentobox.util.Util;
@RunWith(PowerMockRunner.class) @RunWith(PowerMockRunner.class)
@PrepareForTest( { BentoBox.class, Util.class }) @PrepareForTest( { Bukkit.class, BentoBox.class, Util.class })
public class MySQLDatabaseHandlerTest { public class MySQLDatabaseHandlerTest {
private static MySQLDatabaseHandler<Island> handler; private static MySQLDatabaseHandler<Island> handler;
@ -52,8 +52,8 @@ public class MySQLDatabaseHandlerTest {
private static IslandWorldManager iwm; private static IslandWorldManager iwm;
@BeforeClass @Before
public static void setUpBeforeClass() throws Exception { public void setUp() throws Exception {
Server server = mock(Server.class); Server server = mock(Server.class);
world = mock(World.class); world = mock(World.class);
when(server.getLogger()).thenReturn(Logger.getAnonymousLogger()); when(server.getLogger()).thenReturn(Logger.getAnonymousLogger());
@ -66,8 +66,7 @@ public class MySQLDatabaseHandlerTest {
ItemFactory itemFactory = mock(ItemFactory.class); ItemFactory itemFactory = mock(ItemFactory.class);
when(server.getItemFactory()).thenReturn(itemFactory); when(server.getItemFactory()).thenReturn(itemFactory);
Bukkit.setServer(server); PowerMockito.mockStatic(Bukkit.class);
when(Bukkit.getLogger()).thenReturn(Logger.getAnonymousLogger()); when(Bukkit.getLogger()).thenReturn(Logger.getAnonymousLogger());
Whitebox.setInternalState(BentoBox.class, "instance", plugin); Whitebox.setInternalState(BentoBox.class, "instance", plugin);
@ -100,6 +99,11 @@ public class MySQLDatabaseHandlerTest {
} }
@Test
public void testSaveNullObject() {
handler.saveObject(null);
}
@Test @Test
public void testSaveObject() { public void testSaveObject() {
handler.saveObject(instance); handler.saveObject(instance);