diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/jena/FauxPropertyDaoJena.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/jena/FauxPropertyDaoJena.java index 2ebe030d6..6b3a4a50d 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/jena/FauxPropertyDaoJena.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/jena/FauxPropertyDaoJena.java @@ -34,9 +34,9 @@ import edu.cornell.mannlib.vitro.webapp.dao.InsertException; import edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary; import edu.cornell.mannlib.vitro.webapp.utils.SparqlQueryRunner; import edu.cornell.mannlib.vitro.webapp.utils.SparqlQueryRunner.QueryParser; -import edu.cornell.mannlib.vitro.webapp.utils.jena.Critical.LockableOntModel; -import edu.cornell.mannlib.vitro.webapp.utils.jena.Critical.LockedOntModel; -import edu.cornell.mannlib.vitro.webapp.utils.jena.Critical.LockingOntModelSelector; +import edu.cornell.mannlib.vitro.webapp.utils.jena.criticalsection.LockableOntModel; +import edu.cornell.mannlib.vitro.webapp.utils.jena.criticalsection.LockableOntModelSelector; +import edu.cornell.mannlib.vitro.webapp.utils.jena.criticalsection.LockedOntModel; /** * TODO @@ -80,11 +80,11 @@ public class FauxPropertyDaoJena extends JenaBaseDao implements FauxPropertyDao // The instance // ---------------------------------------------------------------------- - private final LockingOntModelSelector models; + private final LockableOntModelSelector models; public FauxPropertyDaoJena(WebappDaoFactoryJena wadf) { super(wadf); - this.models = new LockingOntModelSelector(wadf.getOntModelSelector()); + this.models = new LockableOntModelSelector(wadf.getOntModelSelector()); } /** diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/rdfservice/impl/logging/LoggingRDFService.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/rdfservice/impl/logging/LoggingRDFService.java index 9d98722ec..99d50b095 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/rdfservice/impl/logging/LoggingRDFService.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/rdfservice/impl/logging/LoggingRDFService.java @@ -126,4 +126,9 @@ public class LoggingRDFService implements RDFService { public void close() { innerService.close(); } + + @Override + public String toString() { + return "LoggingRDFService[inner=" + innerService + "]"; + } } diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/rdfservice/impl/logging/LoggingRDFServiceFactory.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/rdfservice/impl/logging/LoggingRDFServiceFactory.java index 894b208d1..fec57486d 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/rdfservice/impl/logging/LoggingRDFServiceFactory.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/rdfservice/impl/logging/LoggingRDFServiceFactory.java @@ -40,4 +40,9 @@ public class LoggingRDFServiceFactory implements RDFServiceFactory { factory.unregisterListener(changeListener); } + @Override + public String toString() { + return "LoggingRDFServiceFactory[factory=" + factory + "]"; + } + } diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/servlet/setup/rdfsetup/impl/sdb/ContentDataStructuresProviderSDB.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/servlet/setup/rdfsetup/impl/sdb/ContentDataStructuresProviderSDB.java index ba6d249de..2bd411900 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/servlet/setup/rdfsetup/impl/sdb/ContentDataStructuresProviderSDB.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/servlet/setup/rdfsetup/impl/sdb/ContentDataStructuresProviderSDB.java @@ -39,6 +39,7 @@ import edu.cornell.mannlib.vitro.webapp.modelaccess.ontmodels.UnionModelsOntMode import edu.cornell.mannlib.vitro.webapp.rdfservice.RDFService; import edu.cornell.mannlib.vitro.webapp.rdfservice.RDFServiceFactory; import edu.cornell.mannlib.vitro.webapp.rdfservice.impl.jena.sdb.RDFServiceFactorySDB; +import edu.cornell.mannlib.vitro.webapp.rdfservice.impl.logging.LoggingRDFServiceFactory; import edu.cornell.mannlib.vitro.webapp.servlet.setup.JenaDataSourceSetupBase; import edu.cornell.mannlib.vitro.webapp.servlet.setup.rdfsetup.impl.ContentDataStructuresProvider; import edu.cornell.mannlib.vitro.webapp.startup.StartupStatus; @@ -122,7 +123,8 @@ public class ContentDataStructuresProviderSDB extends setupSDB(store); } - return new RDFServiceFactorySDB(ds, storeDesc); + return new LoggingRDFServiceFactory(new RDFServiceFactorySDB(ds, + storeDesc)); } /** diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/servlet/setup/rdfsetup/impl/sparql/ContentDataStructuresProviderSPARQL.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/servlet/setup/rdfsetup/impl/sparql/ContentDataStructuresProviderSPARQL.java index 9b43cbcbe..a0917dae6 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/servlet/setup/rdfsetup/impl/sparql/ContentDataStructuresProviderSPARQL.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/servlet/setup/rdfsetup/impl/sparql/ContentDataStructuresProviderSPARQL.java @@ -17,6 +17,7 @@ import edu.cornell.mannlib.vitro.webapp.modelaccess.ontmodels.OntModelCache; import edu.cornell.mannlib.vitro.webapp.rdfservice.RDFService; import edu.cornell.mannlib.vitro.webapp.rdfservice.RDFServiceFactory; import edu.cornell.mannlib.vitro.webapp.rdfservice.impl.RDFServiceFactorySingle; +import edu.cornell.mannlib.vitro.webapp.rdfservice.impl.logging.LoggingRDFServiceFactory; import edu.cornell.mannlib.vitro.webapp.rdfservice.impl.sparql.RDFServiceSparql; import edu.cornell.mannlib.vitro.webapp.servlet.setup.rdfsetup.impl.ContentDataStructuresProvider; import edu.cornell.mannlib.vitro.webapp.startup.StartupStatus; @@ -58,8 +59,8 @@ public class ContentDataStructuresProviderSPARQL extends this.updateEndpointURI = props .getProperty(PROPERTY_SPARQL_UPDATE_ENDPOINT_URI); - this.rdfService = createRDFService(); - this.rdfServiceFactory = createRDFServiceFactory(); + this.rdfServiceFactory = createRDFServiceFactory(createRDFService()); + this.rdfService = this.rdfServiceFactory.getRDFService(); this.dataset = createDataset(); this.modelMaker = createModelMaker(); } @@ -75,8 +76,9 @@ public class ContentDataStructuresProviderSPARQL extends } } - private RDFServiceFactory createRDFServiceFactory() { - return new RDFServiceFactorySingle(this.rdfService); + private RDFServiceFactory createRDFServiceFactory(RDFService service) { + return new LoggingRDFServiceFactory( + new RDFServiceFactorySingle(service)); } private Dataset createDataset() { diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/servlet/setup/rdfsetup/impl/tdb/ConfigurationDataStructuresProviderTDB.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/servlet/setup/rdfsetup/impl/tdb/ConfigurationDataStructuresProviderTDB.java index 003cdb1f6..e65363904 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/servlet/setup/rdfsetup/impl/tdb/ConfigurationDataStructuresProviderTDB.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/servlet/setup/rdfsetup/impl/tdb/ConfigurationDataStructuresProviderTDB.java @@ -22,6 +22,7 @@ import edu.cornell.mannlib.vitro.webapp.rdfservice.RDFService; import edu.cornell.mannlib.vitro.webapp.rdfservice.RDFServiceFactory; import edu.cornell.mannlib.vitro.webapp.rdfservice.impl.RDFServiceFactorySingle; import edu.cornell.mannlib.vitro.webapp.rdfservice.impl.jena.tdb.RDFServiceTDB; +import edu.cornell.mannlib.vitro.webapp.rdfservice.impl.logging.LoggingRDFServiceFactory; import edu.cornell.mannlib.vitro.webapp.servlet.setup.rdfsetup.impl.ConfigurationDataStructuresProvider; import edu.cornell.mannlib.vitro.webapp.startup.StartupStatus; import edu.cornell.mannlib.vitro.webapp.utils.logging.ToString; @@ -60,8 +61,8 @@ public class ConfigurationDataStructuresProviderTDB extends + DIRECTORY_TDB; try { - this.rdfService = new RDFServiceTDB(tdbPath); - this.rdfServiceFactory = createRDFServiceFactory(); + this.rdfServiceFactory = createRDFServiceFactory(tdbPath); + this.rdfService = this.rdfServiceFactory.getRDFService(); this.dataset = new RDFServiceDataset(this.rdfService); this.modelMaker = createModelMaker(); ss.info(ctxListener, "Initialized the RDF source for TDB"); @@ -75,8 +76,10 @@ public class ConfigurationDataStructuresProviderTDB extends TDB.getContext().setTrue(TDB.symUnionDefaultGraph); } - private RDFServiceFactory createRDFServiceFactory() { - return new RDFServiceFactorySingle(this.rdfService); + private RDFServiceFactory createRDFServiceFactory(String tdbPath) + throws IOException { + return new LoggingRDFServiceFactory(new RDFServiceFactorySingle( + new RDFServiceTDB(tdbPath))); } private ModelMaker createModelMaker() { diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/servlet/setup/rdfsetup/impl/tdb/ContentDataStructuresProviderTDB.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/servlet/setup/rdfsetup/impl/tdb/ContentDataStructuresProviderTDB.java index 641f2d02c..bcd95680f 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/servlet/setup/rdfsetup/impl/tdb/ContentDataStructuresProviderTDB.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/servlet/setup/rdfsetup/impl/tdb/ContentDataStructuresProviderTDB.java @@ -21,6 +21,7 @@ import edu.cornell.mannlib.vitro.webapp.rdfservice.RDFService; import edu.cornell.mannlib.vitro.webapp.rdfservice.RDFServiceFactory; import edu.cornell.mannlib.vitro.webapp.rdfservice.impl.RDFServiceFactorySingle; import edu.cornell.mannlib.vitro.webapp.rdfservice.impl.jena.tdb.RDFServiceTDB; +import edu.cornell.mannlib.vitro.webapp.rdfservice.impl.logging.LoggingRDFServiceFactory; import edu.cornell.mannlib.vitro.webapp.servlet.setup.rdfsetup.impl.ContentDataStructuresProvider; import edu.cornell.mannlib.vitro.webapp.startup.StartupStatus; import edu.cornell.mannlib.vitro.webapp.utils.logging.ToString; @@ -74,7 +75,8 @@ public class ContentDataStructuresProviderTDB extends } private RDFServiceFactory createRDFServiceFactory() { - return new RDFServiceFactorySingle(this.rdfService); + return new LoggingRDFServiceFactory(new RDFServiceFactorySingle( + this.rdfService)); } private ModelMaker createModelMaker() { diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/utils/configuration/ConfigurationBeanLoader.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/utils/configuration/ConfigurationBeanLoader.java index 584797e5b..fa7249297 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/utils/configuration/ConfigurationBeanLoader.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/utils/configuration/ConfigurationBeanLoader.java @@ -6,6 +6,7 @@ import static com.hp.hpl.jena.rdf.model.ResourceFactory.createResource; import java.util.HashSet; import java.util.List; +import java.util.Objects; import java.util.Set; import javax.servlet.ServletContext; @@ -15,8 +16,8 @@ import com.hp.hpl.jena.rdf.model.Model; import com.hp.hpl.jena.rdf.model.Resource; import com.hp.hpl.jena.vocabulary.RDF; -import edu.cornell.mannlib.vitro.webapp.utils.jena.Critical.LockableModel; -import edu.cornell.mannlib.vitro.webapp.utils.jena.Critical.LockedModel; +import edu.cornell.mannlib.vitro.webapp.utils.jena.criticalsection.LockableModel; +import edu.cornell.mannlib.vitro.webapp.utils.jena.criticalsection.LockedModel; /** * Load one or more Configuration beans from a specified model. @@ -50,7 +51,7 @@ public class ConfigurationBeanLoader { // ---------------------------------------------------------------------- /** Must not be null. */ - private final LockableModel model; + private final LockableModel locking; /** * May be null, but the loader will be unable to satisfy instances of @@ -65,26 +66,34 @@ public class ConfigurationBeanLoader { private final HttpServletRequest req; public ConfigurationBeanLoader(Model model) { - this(model, null, null); + this(new LockableModel(model), null, null); + } + + public ConfigurationBeanLoader(LockableModel locking) { + this(locking, null, null); } public ConfigurationBeanLoader(Model model, ServletContext ctx) { - this(model, ctx, null); + this(new LockableModel(model), ctx, null); + } + + public ConfigurationBeanLoader(LockableModel locking, ServletContext ctx) { + this(locking, ctx, null); } public ConfigurationBeanLoader(Model model, HttpServletRequest req) { - this(model, - (req == null) ? null : req.getSession().getServletContext(), - req); + this(new LockableModel(model), req); } - private ConfigurationBeanLoader(Model model, ServletContext ctx, - HttpServletRequest req) { - if (model == null) { - throw new NullPointerException("model may not be null."); - } + public ConfigurationBeanLoader(LockableModel locking, HttpServletRequest req) { + this(locking, (req == null) ? null : req.getSession() + .getServletContext(), req); + } - this.model = new LockableModel(model); + private ConfigurationBeanLoader(LockableModel locking, ServletContext ctx, + HttpServletRequest req) { + this.locking = Objects.requireNonNull(locking, + "locking may not be null."); this.req = req; this.ctx = ctx; } @@ -102,8 +111,8 @@ public class ConfigurationBeanLoader { } try { - ConfigurationRdf parsedRdf = ConfigurationRdfParser.parse(model, - uri, resultClass); + ConfigurationRdf parsedRdf = ConfigurationRdfParser.parse( + locking, uri, resultClass); WrappedInstance wrapper = InstanceWrapper.wrap(parsedRdf .getConcreteClass()); wrapper.satisfyInterfaces(ctx, req); @@ -122,7 +131,7 @@ public class ConfigurationBeanLoader { public Set loadAll(Class resultClass) throws ConfigurationBeanLoaderException { Set uris = new HashSet<>(); - try (LockedModel m = model.read()) { + try (LockedModel m = locking.read()) { List resources = m.listResourcesWithProperty(RDF.type, createResource(toJavaUri(resultClass))).toList(); for (Resource r : resources) { diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/utils/configuration/ConfigurationRdfParser.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/utils/configuration/ConfigurationRdfParser.java index 88df4d53f..72dc8223a 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/utils/configuration/ConfigurationRdfParser.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/utils/configuration/ConfigurationRdfParser.java @@ -11,6 +11,7 @@ import static edu.cornell.mannlib.vitro.webapp.utils.configuration.Configuration import java.lang.reflect.Modifier; import java.util.HashSet; import java.util.List; +import java.util.Objects; import java.util.Set; import com.hp.hpl.jena.rdf.model.Property; @@ -22,67 +23,61 @@ import com.hp.hpl.jena.vocabulary.RDF; import edu.cornell.mannlib.vitro.webapp.utils.configuration.PropertyType.PropertyStatement; import edu.cornell.mannlib.vitro.webapp.utils.configuration.PropertyType.PropertyTypeException; -import edu.cornell.mannlib.vitro.webapp.utils.jena.Critical.LockableModel; -import edu.cornell.mannlib.vitro.webapp.utils.jena.Critical.LockedModel; +import edu.cornell.mannlib.vitro.webapp.utils.jena.criticalsection.LockableModel; +import edu.cornell.mannlib.vitro.webapp.utils.jena.criticalsection.LockedModel; /** * Parse the RDF for a single individual in the model to create a * ConfigurationRdf object. */ public class ConfigurationRdfParser { - public static ConfigurationRdf parse(LockableModel model, + public static ConfigurationRdf parse(LockableModel locking, String uri, Class resultClass) throws InvalidConfigurationRdfException { - if (model == null) { - throw new NullPointerException("model may not be null."); - } - if (uri == null) { - throw new NullPointerException("uri may not be null."); - } - if (resultClass == null) { - throw new NullPointerException("resultClass may not be null."); - } + Objects.requireNonNull(locking, "locking may not be null."); + Objects.requireNonNull(uri, "uri may not be null."); + Objects.requireNonNull(resultClass, "resultClass may not be null."); - confirmExistenceInModel(model, uri); + confirmExistenceInModel(locking, uri); - confirmEligibilityForResultClass(model, uri, resultClass); + confirmEligibilityForResultClass(locking, uri, resultClass); - Set properties = loadProperties(model, uri); + Set properties = loadProperties(locking, uri); - Class concreteClass = determineConcreteClass(model, uri, + Class concreteClass = determineConcreteClass(locking, uri, resultClass); return new ConfigurationRdf(concreteClass, properties); } - private static void confirmExistenceInModel(LockableModel model, String uri) - throws InvalidConfigurationRdfException { + private static void confirmExistenceInModel(LockableModel locking, + String uri) throws InvalidConfigurationRdfException { Selector s = new SimpleSelector(createResource(uri), null, (RDFNode) null); - try (LockedModel m = model.read()) { + try (LockedModel m = locking.read()) { if (m.listStatements(s).toList().isEmpty()) { throw individualDoesNotAppearInModel(uri); } } } - private static void confirmEligibilityForResultClass(LockableModel model, + private static void confirmEligibilityForResultClass(LockableModel locking, String uri, Class resultClass) throws InvalidConfigurationRdfException { Statement s = createStatement(createResource(uri), RDF.type, createResource(toJavaUri(resultClass))); - try (LockedModel m = model.read()) { + try (LockedModel m = locking.read()) { if (!m.contains(s)) { throw noTypeStatementForResultClass(s); } } } - private static Set loadProperties(LockableModel model, + private static Set loadProperties(LockableModel locking, String uri) throws InvalidConfigurationRdfException { Set set = new HashSet<>(); - try (LockedModel m = model.read()) { + try (LockedModel m = locking.read()) { List rawStatements = m.listStatements( m.getResource(uri), (Property) null, (RDFNode) null) .toList(); @@ -108,11 +103,11 @@ public class ConfigurationRdfParser { } private static Class determineConcreteClass( - LockableModel model, String uri, Class resultClass) + LockableModel locking, String uri, Class resultClass) throws InvalidConfigurationRdfException { Set> concreteClasses = new HashSet<>(); - try (LockedModel m = model.read()) { + try (LockedModel m = locking.read()) { for (RDFNode node : m.listObjectsOfProperty(createResource(uri), RDF.type).toSet()) { if (!node.isURIResource()) { diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/utils/jena/Critical.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/utils/jena/Critical.java deleted file mode 100644 index f0d85122a..000000000 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/utils/jena/Critical.java +++ /dev/null @@ -1,149 +0,0 @@ -/* $This file is distributed under the terms of the license in /doc/license.txt$ */ - -package edu.cornell.mannlib.vitro.webapp.utils.jena; - -import com.hp.hpl.jena.ontology.OntModel; -import com.hp.hpl.jena.rdf.model.Model; -import com.hp.hpl.jena.shared.Lock; - -import edu.cornell.mannlib.vitro.webapp.dao.jena.OntModelSelector; -import edu.cornell.mannlib.vitro.webapp.rdfservice.adapters.AbstractModelDecorator; -import edu.cornell.mannlib.vitro.webapp.rdfservice.adapters.AbstractOntModelDecorator; - -/** - * AutoCloseable helper classes for using models in a try-with-resources block. - * - * TODO - create separate classes in criticalsection package - * Locked - * LockerFor - * Add to develop. - * Remove Critical and convert configurationBeanLoader - * Merge to faux. - */ -public abstract class Critical { - /** - * Use this when you have a bare OntModelSelector. It returns - * LockableOntModels, which can then be locked in a critical section. - * - *
-	 * LockingOntModelSelector lockingOms = new LockingOntModelSelector(oms);
-	 * 
- */ - public static class LockingOntModelSelector { - private final OntModelSelector oms; - - public LockingOntModelSelector(OntModelSelector oms) { - this.oms = oms; - } - - public LockableOntModel getDisplayModel() { - return new LockableOntModel(oms.getDisplayModel()); - } - - public LockableOntModel getTBoxModel() { - return new LockableOntModel(oms.getTBoxModel()); - } - } - - /** - * Returned by the LockingOntModelSelector, or it can be wrapped around a - * bare OntModel. Cannot be used without locking. - * - *
-	 * try (LockedOntModel m = lockingOms.getDisplayModel.read()) {
-	 *    ...
-	 * }
-	 * 
- */ - public static class LockableOntModel { - private final OntModel ontModel; - - public LockableOntModel(OntModel ontModel) { - this.ontModel = ontModel; - } - - public LockedOntModel read() { - ontModel.enterCriticalSection(Lock.READ); - return new LockedOntModel(ontModel); - } - - public LockedOntModel write() { - ontModel.enterCriticalSection(Lock.WRITE); - return new LockedOntModel(ontModel); - } - } - - /** - * A simple OntModel, except that it can only be created by locking a - * LockableOntModel. It is AutoCloseable, but the close method has been - * hijacked to simply release the lock, and not to actually close the - * wrapped model. - */ - public static class LockedOntModel extends AbstractOntModelDecorator - implements AutoCloseable { - - private LockedOntModel(OntModel m) { - super(m); - } - - /** - * Just unlocks the model. Doesn't actually close it, because we may - * want to use it again. - */ - @Override - public void close() { - super.leaveCriticalSection(); - } - } - - /** - * Can be wrapped around a bare OntModel. Cannot be used without locking. - * - *
-	 * try (LockedModel m = lockableModel.read()) {
-	 *    ...
-	 * }
-	 * 
- */ - public static class LockableModel { - private final Model model; - - public LockableModel(Model model) { - this.model = model; - } - - public LockedModel read() { - model.enterCriticalSection(Lock.READ); - return new LockedModel(model); - } - - public LockedModel write() { - model.enterCriticalSection(Lock.WRITE); - return new LockedModel(model); - } - } - - /** - * A simple Model, except that it can only be created by locking a - * LockableModel. It is AutoCloseable, but the close method has been - * hijacked to simply release the lock, and not to actually close the - * wrapped model. - */ - public static class LockedModel extends AbstractModelDecorator - implements AutoCloseable { - - private LockedModel(Model m) { - super(m); - } - - /** - * Just unlocks the model. Doesn't actually close it, because we may - * want to use it again. - */ - @Override - public void close() { - super.leaveCriticalSection(); - } - } - -} diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/utils/jena/criticalsection/LockableModel.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/utils/jena/criticalsection/LockableModel.java new file mode 100644 index 000000000..e66f65578 --- /dev/null +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/utils/jena/criticalsection/LockableModel.java @@ -0,0 +1,39 @@ +/* $This file is distributed under the terms of the license in /doc/license.txt$ */ + +package edu.cornell.mannlib.vitro.webapp.utils.jena.criticalsection; + +import java.util.Objects; + +import com.hp.hpl.jena.rdf.model.Model; +import com.hp.hpl.jena.shared.Lock; + +/** + * Makes it easy to use a Jena Model in a try-with-resources block. At the end + * of the block, the close() method will not close the model, but will merely + * release the lock. + * + * Wraps around a bare Model. Cannot be used without locking. + * + *
+ * try (LockedModel m = new LockableModel(model).read()) {
+ *    ...
+ * }
+ * 
+ */ +public class LockableModel { + private final Model model; + + public LockableModel(Model model) { + this.model = Objects.requireNonNull(model, "model may not be null."); + } + + public LockedModel read() { + model.enterCriticalSection(Lock.READ); + return new LockedModel(model); + } + + public LockedModel write() { + model.enterCriticalSection(Lock.WRITE); + return new LockedModel(model); + } +} diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/utils/jena/criticalsection/LockableOntModel.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/utils/jena/criticalsection/LockableOntModel.java new file mode 100644 index 000000000..75a05c82d --- /dev/null +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/utils/jena/criticalsection/LockableOntModel.java @@ -0,0 +1,49 @@ +/* $This file is distributed under the terms of the license in /doc/license.txt$ */ + +package edu.cornell.mannlib.vitro.webapp.utils.jena.criticalsection; + +import java.util.Objects; + +import com.hp.hpl.jena.ontology.OntModel; +import com.hp.hpl.jena.shared.Lock; + +/** + * Makes it easy to use a Jena OntModel in a try-with-resources block. At the + * end of the block, the close() method will not close the model, but will + * merely release the lock. + * + * Returned by the LockableOntModelSelector, or it can be wrapped around a bare + * OntModel. Cannot be used without locking. + * + *
+ * try (LockedOntModel m = lockableOms.getDisplayModel.read()) {
+ *    ...
+ * }
+ * 
+ * + * or + * + *
+ * try (LockedOntModel m = new LockableOntModel(ontModel).read()) {
+ *    ...
+ * }
+ * 
+ */ +public class LockableOntModel { + private final OntModel ontModel; + + public LockableOntModel(OntModel ontModel) { + this.ontModel = Objects.requireNonNull(ontModel, + "ontModel may not be null."); + } + + public LockedOntModel read() { + ontModel.enterCriticalSection(Lock.READ); + return new LockedOntModel(ontModel); + } + + public LockedOntModel write() { + ontModel.enterCriticalSection(Lock.WRITE); + return new LockedOntModel(ontModel); + } +} diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/utils/jena/criticalsection/LockableOntModelSelector.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/utils/jena/criticalsection/LockableOntModelSelector.java new file mode 100644 index 000000000..24b0dd0e1 --- /dev/null +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/utils/jena/criticalsection/LockableOntModelSelector.java @@ -0,0 +1,53 @@ +/* $This file is distributed under the terms of the license in /doc/license.txt$ */ + +package edu.cornell.mannlib.vitro.webapp.utils.jena.criticalsection; + +import java.util.Objects; + +import edu.cornell.mannlib.vitro.webapp.dao.jena.OntModelSelector; + +/** + * Makes it easy to use a Jena OntModel with a try-with-resources block. If you + * have access to an OntModelSelector, you can wrap it and then use it obtain + * LockableOntModels. + * + *
+ * LockableOntModelSelector lockableOms = new LockableOntModelSelector(oms);
+ *  
+ * try (LockedOntModel m = lockableOms.getDisplayModel.read()) {
+ *    ...
+ * }
+ * 
+ */ +public class LockableOntModelSelector { + private final OntModelSelector oms; + + public LockableOntModelSelector(OntModelSelector oms) { + this.oms = Objects.requireNonNull(oms, "oms may not be null."); + } + + public LockableOntModel getFullModel() { + return new LockableOntModel(oms.getFullModel()); + } + + public LockableOntModel getABoxModel() { + return new LockableOntModel(oms.getABoxModel()); + } + + public LockableOntModel getTBoxModel() { + return new LockableOntModel(oms.getTBoxModel()); + } + + public LockableOntModel getApplicationMetadataModel() { + return new LockableOntModel(oms.getApplicationMetadataModel()); + } + + public LockableOntModel getUserAccountsModel() { + return new LockableOntModel(oms.getUserAccountsModel()); + } + + public LockableOntModel getDisplayModel() { + return new LockableOntModel(oms.getDisplayModel()); + } + +} diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/utils/jena/criticalsection/LockedModel.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/utils/jena/criticalsection/LockedModel.java new file mode 100644 index 000000000..7d9cdec98 --- /dev/null +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/utils/jena/criticalsection/LockedModel.java @@ -0,0 +1,40 @@ +/* $This file is distributed under the terms of the license in /doc/license.txt$ */ + +package edu.cornell.mannlib.vitro.webapp.utils.jena.criticalsection; + +import com.hp.hpl.jena.rdf.model.Model; + +import edu.cornell.mannlib.vitro.webapp.rdfservice.adapters.AbstractModelDecorator; + +/** + * A model that is easy to use in a try-with-resources code block. It can only + * be created by locking a LockableModel. + * + *
+ * try (LockedModel m = lockableModel.read()) {
+ *    ...
+ * }
+ * 
+ * + * The close method has been hijacked to simply release the lock, and not to + * actually close the wrapped model. + */ +public class LockedModel extends AbstractModelDecorator implements + AutoCloseable { + + /** + * Should only be created by LockableModel. + */ + LockedModel(Model m) { + super(m); + } + + /** + * Just unlocks the model. Doesn't actually close it, because we may want to + * use it again. + */ + @Override + public void close() { + super.leaveCriticalSection(); + } +} diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/utils/jena/criticalsection/LockedOntModel.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/utils/jena/criticalsection/LockedOntModel.java new file mode 100644 index 000000000..5f310d84a --- /dev/null +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/utils/jena/criticalsection/LockedOntModel.java @@ -0,0 +1,32 @@ +/* $This file is distributed under the terms of the license in /doc/license.txt$ */ + +package edu.cornell.mannlib.vitro.webapp.utils.jena.criticalsection; + +import com.hp.hpl.jena.ontology.OntModel; + +import edu.cornell.mannlib.vitro.webapp.rdfservice.adapters.AbstractOntModelDecorator; + +/** + * A simple OntModel, except that it can only be created by locking a + * LockableOntModel. It is AutoCloseable, but the close method has been hijacked + * to simply release the lock, and not to actually close the wrapped model. + */ +public class LockedOntModel extends AbstractOntModelDecorator implements + AutoCloseable { + + /** + * Can only be created by LockableOntModel. + */ + LockedOntModel(OntModel m) { + super(m); + } + + /** + * Just unlocks the model. Doesn't actually close it, because we may want to + * use it again. + */ + @Override + public void close() { + super.leaveCriticalSection(); + } +} diff --git a/webapp/test/edu/cornell/mannlib/vitro/webapp/utils/configuration/ConfigurationBeanLoaderTest.java b/webapp/test/edu/cornell/mannlib/vitro/webapp/utils/configuration/ConfigurationBeanLoaderTest.java index a6b17e116..b1e8ccb4b 100644 --- a/webapp/test/edu/cornell/mannlib/vitro/webapp/utils/configuration/ConfigurationBeanLoaderTest.java +++ b/webapp/test/edu/cornell/mannlib/vitro/webapp/utils/configuration/ConfigurationBeanLoaderTest.java @@ -101,7 +101,7 @@ public class ConfigurationBeanLoaderTest extends AbstractTestClass { expectException(NullPointerException.class, "model may not be null"); @SuppressWarnings("unused") - Object unused = new ConfigurationBeanLoader(null); + Object unused = new ConfigurationBeanLoader((Model) null); } // ----------------------------------------------------------------------