diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/application/ApplicationImpl.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/application/ApplicationImpl.java index 544340e00..45842830f 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/application/ApplicationImpl.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/application/ApplicationImpl.java @@ -16,6 +16,7 @@ import edu.cornell.mannlib.vitro.webapp.modules.ComponentStartupStatus; import edu.cornell.mannlib.vitro.webapp.modules.fileStorage.FileStorage; import edu.cornell.mannlib.vitro.webapp.modules.imageProcessor.ImageProcessor; import edu.cornell.mannlib.vitro.webapp.modules.searchEngine.SearchEngine; +import edu.cornell.mannlib.vitro.webapp.modules.tboxreasoner.TBoxReasonerModule; import edu.cornell.mannlib.vitro.webapp.modules.tripleSource.ConfigurationTripleSource; import edu.cornell.mannlib.vitro.webapp.modules.tripleSource.ContentTripleSource; import edu.cornell.mannlib.vitro.webapp.rdfservice.impl.RDFServiceUtils; @@ -41,6 +42,7 @@ public class ApplicationImpl implements Application { private FileStorage fileStorage; private ContentTripleSource contentTripleSource; private ConfigurationTripleSource configurationTripleSource; + private TBoxReasonerModule tboxReasonerModule; public void setServletContext(ServletContext ctx) { this.ctx = ctx; @@ -140,6 +142,22 @@ public class ApplicationImpl implements Application { } } + @Override + public TBoxReasonerModule getTBoxReasonerModule() { + return tboxReasonerModule; + } + + @Property(uri = "http://vitro.mannlib.cornell.edu/ns/vitro/ApplicationSetup#hasTBoxReasonerModule") + public void setTBoxReasonerModule(TBoxReasonerModule module) { + if (tboxReasonerModule == null) { + tboxReasonerModule = module; + } else { + throw new IllegalStateException( + "Configuration includes multiple intances of TBoxReasonerModule: " + + tboxReasonerModule + ", and " + module); + } + } + @Validation public void validate() throws Exception { if (searchEngine == null) { @@ -162,6 +180,10 @@ public class ApplicationImpl implements Application { throw new IllegalStateException( "Configuration did not include a ConfigurationTripleSource."); } + if (tboxReasonerModule == null) { + throw new IllegalStateException( + "Configuration did not include a TBoxReasonerModule."); + } } @Override @@ -244,4 +266,30 @@ public class ApplicationImpl implements Application { } } + // ---------------------------------------------------------------------- + // Setup the reasoners. + // + // This must happen after the FileGraphSetup. + // ---------------------------------------------------------------------- + + public static class ReasonersSetup implements ServletContextListener { + @Override + public void contextInitialized(ServletContextEvent sce) { + ServletContext ctx = sce.getServletContext(); + Application app = ApplicationUtils.instance(); + StartupStatus ss = StartupStatus.getBean(ctx); + ComponentStartupStatus css = new ComponentStartupStatusImpl(this, + ss); + + TBoxReasonerModule tboxReasoner = app.getTBoxReasonerModule(); + tboxReasoner.startup(app, css); + ss.info(this, "Started the TBoxReasonerModule: " + tboxReasoner); + } + + @Override + public void contextDestroyed(ServletContextEvent sce) { + Application app = ApplicationUtils.instance(); + app.getTBoxReasonerModule().shutdown(app); + } + } } diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/freemarker/BaseSiteAdminController.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/freemarker/BaseSiteAdminController.java index 09d423428..9ac27834c 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/freemarker/BaseSiteAdminController.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/freemarker/BaseSiteAdminController.java @@ -15,6 +15,7 @@ import org.apache.commons.logging.LogFactory; import edu.cornell.mannlib.vedit.beans.Option; import edu.cornell.mannlib.vedit.util.FormUtils; +import edu.cornell.mannlib.vitro.webapp.application.ApplicationUtils; import edu.cornell.mannlib.vitro.webapp.auth.permissions.SimplePermission; import edu.cornell.mannlib.vitro.webapp.auth.policy.PolicyHelper; import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.AuthorizationRequest; @@ -24,10 +25,9 @@ import edu.cornell.mannlib.vitro.webapp.controller.freemarker.UrlBuilder.ParamMa import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.ResponseValues; import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.TemplateResponseValues; import edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactory; +import edu.cornell.mannlib.vitro.webapp.modules.tboxreasoner.TBoxReasonerStatus; import edu.cornell.mannlib.vitro.webapp.search.controller.IndexController; import edu.cornell.mannlib.vitro.webapp.startup.StartupStatus; -import edu.cornell.mannlib.vitro.webapp.tboxreasoner.TBoxReasonerDriver; -import edu.cornell.mannlib.vitro.webapp.tboxreasoner.TBoxReasonerDriver.Status; public class BaseSiteAdminController extends FreemarkerHttpServlet { @@ -160,24 +160,21 @@ public class BaseSiteAdminController extends FreemarkerHttpServlet { if (PolicyHelper.isAuthorizedForActions(vreq, SimplePermission.EDIT_ONTOLOGY.ACTION)) { - String pelletError = null; - String pelletExplanation = null; - Object tbrObj = getServletContext().getAttribute("tboxReasoner"); - if ( tbrObj instanceof TBoxReasonerDriver) { - Status status = ((TBoxReasonerDriver) tbrObj).getStatus(); - if (!status.isConsistent()) { - pelletError = "INCONSISTENT ONTOLOGY: reasoning halted."; - pelletExplanation = status.getExplanation(); - } else if ( status.isInErrorState() ) { - pelletError = "An error occurred during reasoning. Reasoning has been halted. See error log for details."; - } + String error = null; + String explanation = null; + TBoxReasonerStatus status = ApplicationUtils.instance().getTBoxReasonerModule().getStatus(); + if (!status.isConsistent()) { + error = "INCONSISTENT ONTOLOGY: reasoning halted."; + explanation = status.getExplanation(); + } else if ( status.isInErrorState() ) { + error = "An error occurred during reasoning. Reasoning has been halted. See error log for details."; } - if (pelletError != null) { + if (error != null) { Map pellet = new HashMap(); - pellet.put("error", pelletError); - if (pelletExplanation != null) { - pellet.put("explanation", pelletExplanation); + pellet.put("error", error); + if (explanation != null) { + pellet.put("explanation", explanation); } map.put("pellet", pellet); } diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/jena/JenaAdminActions.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/jena/JenaAdminActions.java index a5eff2069..65e164714 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/jena/JenaAdminActions.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/jena/JenaAdminActions.java @@ -44,11 +44,12 @@ import com.hp.hpl.jena.vocabulary.RDF; import com.hp.hpl.jena.vocabulary.RDFS; import edu.cornell.mannlib.vedit.controller.BaseEditController; +import edu.cornell.mannlib.vitro.webapp.application.ApplicationUtils; import edu.cornell.mannlib.vitro.webapp.auth.permissions.SimplePermission; import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest; import edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary; import edu.cornell.mannlib.vitro.webapp.modelaccess.ModelAccess; -import edu.cornell.mannlib.vitro.webapp.tboxreasoner.TBoxReasoner; +import edu.cornell.mannlib.vitro.webapp.modules.tboxreasoner.TBoxReasonerModule; public class JenaAdminActions extends BaseEditController { @@ -191,9 +192,8 @@ public class JenaAdminActions extends BaseEditController { } private void printRestrictions() { - TBoxReasoner reasoner = (TBoxReasoner) getServletContext().getAttribute("tboxReasonerWrapper"); + TBoxReasonerModule reasoner = ApplicationUtils.instance().getTBoxReasonerModule(); for (Restriction rest : reasoner.listRestrictions() ) { - //System.out.println(); if (rest.isAllValuesFromRestriction()) { log.trace("All values from: "); AllValuesFromRestriction avfr = rest.asAllValuesFromRestriction(); diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/jena/DataPropertyDaoJena.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/jena/DataPropertyDaoJena.java index d2c185086..5afeca4d8 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/jena/DataPropertyDaoJena.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/jena/DataPropertyDaoJena.java @@ -41,6 +41,7 @@ import com.hp.hpl.jena.vocabulary.OWL; import com.hp.hpl.jena.vocabulary.RDF; import com.hp.hpl.jena.vocabulary.RDFS; +import edu.cornell.mannlib.vitro.webapp.application.ApplicationUtils; import edu.cornell.mannlib.vitro.webapp.beans.BaseResourceBean; import edu.cornell.mannlib.vitro.webapp.beans.DataProperty; import edu.cornell.mannlib.vitro.webapp.beans.DataPropertyStatement; @@ -51,8 +52,8 @@ import edu.cornell.mannlib.vitro.webapp.dao.DataPropertyDao; import edu.cornell.mannlib.vitro.webapp.dao.InsertException; import edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary; import edu.cornell.mannlib.vitro.webapp.dao.jena.event.EditEvent; +import edu.cornell.mannlib.vitro.webapp.modules.tboxreasoner.TBoxReasonerStatus; import edu.cornell.mannlib.vitro.webapp.rdfservice.RDFService; -import edu.cornell.mannlib.vitro.webapp.tboxreasoner.TBoxReasonerDriver; public class DataPropertyDaoJena extends PropertyDaoJena implements DataPropertyDao { @@ -357,10 +358,8 @@ public class DataPropertyDaoJena extends PropertyDaoJena implements } protected boolean reasoningAvailable() { - TBoxReasonerDriver pl = getWebappDaoFactory().getTBoxReasonerDriver(); - return !( - ( pl == null || !pl.getStatus().isConsistent() || pl.getStatus().isInErrorState() ) - ); + TBoxReasonerStatus status = ApplicationUtils.instance().getTBoxReasonerModule().getStatus(); + return status.isConsistent() && !status.isInErrorState(); } private String getRequiredDatatypeURI(Individual individual, DataProperty dataprop, List vclassURIs) { diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/jena/WebappDaoFactoryJena.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/jena/WebappDaoFactoryJena.java index db38709e3..4114c7fbd 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/jena/WebappDaoFactoryJena.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/jena/WebappDaoFactoryJena.java @@ -50,7 +50,6 @@ import edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactoryConfig; import edu.cornell.mannlib.vitro.webapp.modelaccess.ModelNames; import edu.cornell.mannlib.vitro.webapp.rdfservice.RDFService; import edu.cornell.mannlib.vitro.webapp.rdfservice.impl.jena.model.RDFServiceModel; -import edu.cornell.mannlib.vitro.webapp.tboxreasoner.TBoxReasonerDriver; import edu.cornell.mannlib.vitro.webapp.utils.jena.URIUtils; public class WebappDaoFactoryJena implements WebappDaoFactory { @@ -70,8 +69,6 @@ public class WebappDaoFactoryJena implements WebappDaoFactory { protected WebappDaoFactoryConfig config; - protected TBoxReasonerDriver tbrd; - protected String userURI; private Map properties = new HashMap(); @@ -238,18 +235,6 @@ public class WebappDaoFactoryJena implements WebappDaoFactory { return config.getNonUserNamespaces(); } - /** - * This enables the WebappDaoFactory to check the status of a reasoner. - * This will likely be refactored in future releases. - */ - public void setTBoxReasonerDriver(TBoxReasonerDriver tbrd) { - this.tbrd = tbrd; - } - - public TBoxReasonerDriver getTBoxReasonerDriver() { - return this.tbrd; - } - @Override public List getCommentsForResource(String resourceURI) { List commentList = new LinkedList(); diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/fields/IndividualsViaVClassOptions.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/fields/IndividualsViaVClassOptions.java index 15ae28fa4..a245f9a59 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/fields/IndividualsViaVClassOptions.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/fields/IndividualsViaVClassOptions.java @@ -8,12 +8,12 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import edu.cornell.mannlib.vitro.webapp.application.ApplicationUtils; import edu.cornell.mannlib.vitro.webapp.beans.Individual; import edu.cornell.mannlib.vitro.webapp.dao.IndividualDao; import edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactory; -import edu.cornell.mannlib.vitro.webapp.dao.jena.WebappDaoFactoryJena; import edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.EditConfigurationVTwo; -import edu.cornell.mannlib.vitro.webapp.tboxreasoner.TBoxReasonerDriver; +import edu.cornell.mannlib.vitro.webapp.modules.tboxreasoner.TBoxReasonerStatus; public class IndividualsViaVClassOptions implements FieldOptions { @@ -101,20 +101,13 @@ public class IndividualsViaVClassOptions implements FieldOptions { return individualMap; } - protected boolean isReasoningAvailable( WebappDaoFactory wDaoFact){ - boolean inferenceAvailable = false; - if (wDaoFact instanceof WebappDaoFactoryJena) { - TBoxReasonerDriver pl = ((WebappDaoFactoryJena) wDaoFact).getTBoxReasonerDriver(); - if (pl != null && pl.getStatus().isConsistent() && !pl.getStatus().isInErrorState() - && !pl.isReasoning()) { - inferenceAvailable = true; - } - } - return inferenceAvailable; + protected boolean isReasoningAvailable(){ + TBoxReasonerStatus status = ApplicationUtils.instance().getTBoxReasonerModule().getStatus(); + return status.isConsistent() && !status.isInErrorState(); } protected Map addWhenMissingInference( String classUri , WebappDaoFactory wDaoFact ){ - boolean inferenceAvailable = isReasoningAvailable(wDaoFact); + boolean inferenceAvailable = isReasoningAvailable(); Map individualMap = new HashMap(); if ( !inferenceAvailable ) { for (String subclassURI : wDaoFact.getVClassDao().getAllSubClassURIs(classUri)) { diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/modules/Application.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/modules/Application.java index 2708634f3..7d875f707 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/modules/Application.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/modules/Application.java @@ -8,6 +8,7 @@ import edu.cornell.mannlib.vitro.webapp.application.VitroHomeDirectory; import edu.cornell.mannlib.vitro.webapp.modules.fileStorage.FileStorage; import edu.cornell.mannlib.vitro.webapp.modules.imageProcessor.ImageProcessor; import edu.cornell.mannlib.vitro.webapp.modules.searchEngine.SearchEngine; +import edu.cornell.mannlib.vitro.webapp.modules.tboxreasoner.TBoxReasonerModule; import edu.cornell.mannlib.vitro.webapp.modules.tripleSource.ConfigurationTripleSource; import edu.cornell.mannlib.vitro.webapp.modules.tripleSource.ContentTripleSource; @@ -29,6 +30,8 @@ public interface Application { ConfigurationTripleSource getConfigurationTripleSource(); + TBoxReasonerModule getTBoxReasonerModule(); + void shutdown(); public interface Component { diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/modules/tboxreasoner/TBoxReasonerModule.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/modules/tboxreasoner/TBoxReasonerModule.java new file mode 100644 index 000000000..3110d9960 --- /dev/null +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/modules/tboxreasoner/TBoxReasonerModule.java @@ -0,0 +1,29 @@ +/* $This file is distributed under the terms of the license in /doc/license.txt$ */ + +package edu.cornell.mannlib.vitro.webapp.modules.tboxreasoner; + +import java.util.List; + +import com.hp.hpl.jena.ontology.Restriction; + +import edu.cornell.mannlib.vitro.webapp.modules.Application; + +/** + * A wrapper around the TBox reasoner + */ +public interface TBoxReasonerModule extends Application.Module { + /** + * What is the TBox reasoner doing now? + */ + TBoxReasonerStatus getStatus(); + + /** + * What restrictions are currently in the reasoner's internal model? + */ + List listRestrictions(); + + /** + * Wait until the TBox reasoner becomes quiet. + */ + void waitForTBoxReasoning(); +} diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/modules/tboxreasoner/TBoxReasonerStatus.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/modules/tboxreasoner/TBoxReasonerStatus.java new file mode 100644 index 000000000..d799ff8f9 --- /dev/null +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/modules/tboxreasoner/TBoxReasonerStatus.java @@ -0,0 +1,29 @@ +/* $This file is distributed under the terms of the license in /doc/license.txt$ */ + +package edu.cornell.mannlib.vitro.webapp.modules.tboxreasoner; + +/** + * What is the current state of the TBox reasoner? + */ +public interface TBoxReasonerStatus { + /** + * Is reasoning in progress based on changes to the TBox? + */ + boolean isReasoning(); + + /** + * Is the TBox free of inconsistency? + */ + boolean isConsistent(); + + /** + * Did the reasoner fail in its most recent attempt? + */ + boolean isInErrorState(); + + /** + * A description of the error state, or an empty string (never null). + */ + String getExplanation(); + +} diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/servlet/setup/PelletReasonerSetup.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/servlet/setup/PelletReasonerSetup.java deleted file mode 100644 index c3c7e6ce8..000000000 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/servlet/setup/PelletReasonerSetup.java +++ /dev/null @@ -1,95 +0,0 @@ -/* $This file is distributed under the terms of the license in /doc/license.txt$ */ - -package edu.cornell.mannlib.vitro.webapp.servlet.setup; - -import static edu.cornell.mannlib.vitro.webapp.modelaccess.ModelNames.TBOX_ASSERTIONS; -import static edu.cornell.mannlib.vitro.webapp.modelaccess.ModelNames.TBOX_INFERENCES; -import static edu.cornell.mannlib.vitro.webapp.modelaccess.ModelNames.TBOX_UNION; - -import javax.servlet.ServletContext; -import javax.servlet.ServletContextEvent; -import javax.servlet.ServletContextListener; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import com.hp.hpl.jena.ontology.OntModel; -import com.hp.hpl.jena.rdf.model.Model; - -import edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactory; -import edu.cornell.mannlib.vitro.webapp.dao.jena.WebappDaoFactoryJena; -import edu.cornell.mannlib.vitro.webapp.modelaccess.ContextModelAccess; -import edu.cornell.mannlib.vitro.webapp.modelaccess.ModelAccess; -import edu.cornell.mannlib.vitro.webapp.startup.StartupStatus; -import edu.cornell.mannlib.vitro.webapp.tboxreasoner.BasicTBoxReasonerDriver; -import edu.cornell.mannlib.vitro.webapp.tboxreasoner.ReasonerConfiguration; -import edu.cornell.mannlib.vitro.webapp.tboxreasoner.TBoxReasonerDriver; -import edu.cornell.mannlib.vitro.webapp.tboxreasoner.TBoxReasoner; -import edu.cornell.mannlib.vitro.webapp.tboxreasoner.impl.pellet.PelletTBoxReasoner; - -/** - * Start the Pellet reasoner on the TBox. - */ -public class PelletReasonerSetup implements ServletContextListener { - private static final Log log = LogFactory.getLog(PelletReasonerSetup.class); - - @Override - public void contextInitialized(ServletContextEvent sce) { - ServletContext ctx = sce.getServletContext(); - StartupStatus ss = StartupStatus.getBean(ctx); - - ContextModelAccess contextModels = ModelAccess.on(ctx); - OntModel tboxAssertionsModel = contextModels - .getOntModel(TBOX_ASSERTIONS); - Model tboxInferencesModel = contextModels - .getOntModel(TBOX_INFERENCES).getBaseModel(); - OntModel tboxUnionModel = contextModels.getOntModel(TBOX_UNION); - WebappDaoFactory wadf = contextModels.getWebappDaoFactory(); - - TBoxReasoner reasoner = new PelletTBoxReasoner( - ReasonerConfiguration.DEFAULT); - TBoxReasonerDriver driver = new BasicTBoxReasonerDriver( - tboxAssertionsModel, tboxInferencesModel, tboxUnionModel, - reasoner, ReasonerConfiguration.DEFAULT); - - sce.getServletContext().setAttribute("tboxReasoner", driver); - sce.getServletContext().setAttribute("tboxReasonerWrapper", reasoner); - - if (wadf instanceof WebappDaoFactoryJena) { - ((WebappDaoFactoryJena) wadf).setTBoxReasonerDriver(driver); - } - - ss.info(this, "Pellet reasoner connected for the TBox"); - - waitForTBoxReasoning(sce); - } - - public static void waitForTBoxReasoning(ServletContextEvent sce) { - TBoxReasonerDriver driver = (TBoxReasonerDriver) sce.getServletContext().getAttribute("tboxReasoner"); - if (driver == null) { - return; - } - int sleeps = 0; - // sleep at least once to make sure the TBox reasoning gets started - while ((0 == sleeps) - || ((sleeps < 1000) && driver.isReasoning())) { - if (((sleeps - 1) % 10) == 0) { // print message at 10 second - // intervals - log.info("Waiting for initial TBox reasoning to complete"); - } - try { - Thread.sleep(1000); - } catch (InterruptedException e) { - // This should never happen. - e.printStackTrace(); - } - sleeps++; - } - } - - @Override - public void contextDestroyed(ServletContextEvent sce) { - // Nothing to tear down - } - -} diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/servlet/setup/UpdateKnowledgeBase.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/servlet/setup/UpdateKnowledgeBase.java index 92a4e81e5..3419300d6 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/servlet/setup/UpdateKnowledgeBase.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/servlet/setup/UpdateKnowledgeBase.java @@ -89,7 +89,11 @@ public class UpdateKnowledgeBase implements ServletContextListener { putReportingPathsIntoSettings(ctx, settings); putNonReportingPathsIntoSettings(ctx, settings); - PelletReasonerSetup.waitForTBoxReasoning(sce); + try { + ApplicationUtils.instance().getTBoxReasonerModule().waitForTBoxReasoning(); + } catch (Exception e) { + // Should mean that the reasoner is not even started yet. + } WebappDaoFactory wadf = ModelAccess.on(ctx).getWebappDaoFactory(); settings.setDefaultNamespace(wadf.getDefaultNamespace()); diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/tboxreasoner/BasicTBoxReasonerDriver.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/tboxreasoner/BasicTBoxReasonerDriver.java deleted file mode 100644 index 131670bbc..000000000 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/tboxreasoner/BasicTBoxReasonerDriver.java +++ /dev/null @@ -1,135 +0,0 @@ -/* $This file is distributed under the terms of the license in /doc/license.txt$ */ - -package edu.cornell.mannlib.vitro.webapp.tboxreasoner; - -import java.util.Collections; -import java.util.HashSet; -import java.util.List; -import java.util.Set; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import com.hp.hpl.jena.ontology.OntModel; -import com.hp.hpl.jena.rdf.model.Model; -import com.hp.hpl.jena.rdf.model.RDFNode; -import com.hp.hpl.jena.rdf.model.Resource; - -import edu.cornell.mannlib.vitro.webapp.dao.jena.event.EditEvent; -import edu.cornell.mannlib.vitro.webapp.utils.jena.criticalsection.LockableModel; -import edu.cornell.mannlib.vitro.webapp.utils.jena.criticalsection.LockableOntModel; -import edu.cornell.mannlib.vitro.webapp.utils.jena.criticalsection.LockedOntModel; - -/** - * The basic implementation of the TBoxReasonerDriver. - */ -public class BasicTBoxReasonerDriver implements TBoxReasonerDriver { - private static final Log log = LogFactory - .getLog(BasicTBoxReasonerDriver.class); - - private final LockableOntModel lockableAssertionsModel; - private final LockableModel lockableInferencesModel; - private final LockableOntModel lockableFullModel; - - private final ReasonerConfiguration reasonerConfiguration; - - private final ConfiguredReasonerListener listener; - - private final Set pendingChangeSets; - - private final ExecutorService executorService; - - private final TBoxReasoner reasoner; - - private TBoxReasonerDriver.Status status; - - public BasicTBoxReasonerDriver(OntModel assertionsModel, - Model inferencesModel, OntModel fullModel, TBoxReasoner reasoner, - ReasonerConfiguration reasonerConfiguration) { - this.lockableAssertionsModel = new LockableOntModel(assertionsModel); - this.lockableInferencesModel = new LockableModel(inferencesModel); - this.lockableFullModel = new LockableOntModel(fullModel); - this.reasoner = reasoner; - this.reasonerConfiguration = reasonerConfiguration; - - this.listener = new ConfiguredReasonerListener(reasonerConfiguration, - this); - - this.pendingChangeSets = Collections.synchronizedSet(new HashSet()); - - this.executorService = Executors.newFixedThreadPool(1); - - assertionsModel.getBaseModel().register(listener); - fullModel.getBaseModel().register(listener); - - doInitialReasoning(); - } - - private void doInitialReasoning() { - try (LockedOntModel assertionsModel = lockableAssertionsModel.read()) { - for (ReasonerStatementPattern pat : reasonerConfiguration - .getInferenceDrivingPatternAllowSet()) { - listener.addedStatements(assertionsModel.listStatements( - (Resource) null, pat.getPredicate(), (RDFNode) null)); - } - } - listener.notifyEvent(null, new EditEvent(null, false)); - } - - - - @Override - public Status getStatus() { - return status; - } - - @Override - public boolean isReasoning() { - return !pendingChangeSets.isEmpty(); - } - - @Override - public void runSynchronizer(TBoxChanges changeSet) { - if (!changeSet.isEmpty()) { - executorService.execute(new ReasoningTask(changeSet)); - } - } - - private class ReasoningTask implements Runnable { - private final TBoxChanges changes; - private List patternList; - - public ReasoningTask(TBoxChanges changes) { - this.changes = changes; - pendingChangeSets.add(changes); - } - - @Override - public void run() { - try { - reasoner.updateReasonerModel(changes); - status = reasoner.performReasoning(); - - buildPatternList(); - updateInferencesModel(); - } finally { - pendingChangeSets.remove(changes); - } - } - - private void buildPatternList() { - PatternListBuilder patternListBuilder = new PatternListBuilder( - reasonerConfiguration, reasoner, changes); - this.patternList = patternListBuilder.build(); - } - - private void updateInferencesModel() { - InferenceModelUpdater inferenceModelUpdater = new InferenceModelUpdater( - reasoner, lockableInferencesModel, lockableFullModel, listener); - inferenceModelUpdater.update(patternList); - } - } - -} diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/tboxreasoner/InferenceModelUpdater.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/tboxreasoner/InferenceModelUpdater.java index 9f54173fe..1fcfaaabe 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/tboxreasoner/InferenceModelUpdater.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/tboxreasoner/InferenceModelUpdater.java @@ -67,7 +67,7 @@ public class InferenceModelUpdater { addNewInferences(filteredReasonerModel); removeOldInferences(filterInferencesModel(patternList), filteredReasonerModel); - log.warn("Added: " + addCount + ", Retracted: " + retractCount); + log.debug("Added: " + addCount + ", Retracted: " + retractCount); } private void addNewInferences(List filteredReasonerModel) { @@ -96,7 +96,7 @@ public class InferenceModelUpdater { filtered.add(pattern.matchStatementsFromModel(inferencesModel)); } } - log.warn("Filtered inferences model: " + filtered.size()); + log.debug("Filtered inferences model: " + filtered.size()); return filtered; } diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/tboxreasoner/TBoxReasoner.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/tboxreasoner/TBoxReasoner.java index 2c9de054f..5839193ca 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/tboxreasoner/TBoxReasoner.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/tboxreasoner/TBoxReasoner.java @@ -9,8 +9,6 @@ import com.hp.hpl.jena.ontology.ObjectProperty; import com.hp.hpl.jena.ontology.Restriction; import com.hp.hpl.jena.rdf.model.Statement; -import edu.cornell.mannlib.vitro.webapp.tboxreasoner.TBoxReasonerDriver.Status; - /** * The functionality of a TBox reasoner. * @@ -53,5 +51,37 @@ public interface TBoxReasoner { * updating and reasoning. */ List filterResults(List patternList); + + public static class Status { + public static final Status SUCCESS = new Status(true, false, ""); + public static final Status ERROR = new Status(true, true, ""); + + public static final Status inconsistent(String explanation) { + return new Status(false, false, explanation); + } + + private final boolean consistent; + private final boolean inErrorState; + private final String explanation; + + private Status(boolean consistent, boolean inErrorState, + String explanation) { + this.consistent = consistent; + this.inErrorState = inErrorState; + this.explanation = explanation; + } + + public boolean isConsistent() { + return consistent; + } + + public boolean isInErrorState() { + return inErrorState; + } + + public String getExplanation() { + return explanation; + } + } } diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/tboxreasoner/TBoxReasonerDriver.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/tboxreasoner/TBoxReasonerDriver.java index 5412d0ed3..edd3da3a9 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/tboxreasoner/TBoxReasonerDriver.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/tboxreasoner/TBoxReasonerDriver.java @@ -2,6 +2,8 @@ package edu.cornell.mannlib.vitro.webapp.tboxreasoner; +import edu.cornell.mannlib.vitro.webapp.modules.tboxreasoner.TBoxReasonerStatus; + /** * What calls can the ConfiguredReasonerListener make to drive the TBox @@ -11,40 +13,5 @@ public interface TBoxReasonerDriver { void runSynchronizer(TBoxChanges changeSet); - boolean isReasoning(); - - Status getStatus(); - - public static class Status { - public static final Status SUCCESS = new Status(true, false, ""); - public static final Status ERROR = new Status(true, true, ""); - - public static final Status inconsistent(String explanation) { - return new Status(false, false, explanation); - } - - private final boolean consistent; - private final boolean inErrorState; - private final String explanation; - - private Status(boolean consistent, boolean inErrorState, - String explanation) { - this.consistent = consistent; - this.inErrorState = inErrorState; - this.explanation = explanation; - } - - public boolean isConsistent() { - return consistent; - } - - public boolean isInErrorState() { - return inErrorState; - } - - public String getExplanation() { - return explanation; - } - - } + TBoxReasonerStatus getStatus(); } diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/tboxreasoner/impl/BasicTBoxReasonerDriver.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/tboxreasoner/impl/BasicTBoxReasonerDriver.java new file mode 100644 index 000000000..9ffe21cb5 --- /dev/null +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/tboxreasoner/impl/BasicTBoxReasonerDriver.java @@ -0,0 +1,253 @@ +/* $This file is distributed under the terms of the license in /doc/license.txt$ */ + +package edu.cornell.mannlib.vitro.webapp.tboxreasoner.impl; + +import static edu.cornell.mannlib.vitro.webapp.utils.threads.VitroBackgroundThread.WorkLevel.IDLE; +import static edu.cornell.mannlib.vitro.webapp.utils.threads.VitroBackgroundThread.WorkLevel.WORKING; + +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.TimeUnit; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import com.hp.hpl.jena.ontology.OntModel; +import com.hp.hpl.jena.rdf.model.Model; +import com.hp.hpl.jena.rdf.model.RDFNode; +import com.hp.hpl.jena.rdf.model.Resource; + +import edu.cornell.mannlib.vitro.webapp.dao.jena.event.EditEvent; +import edu.cornell.mannlib.vitro.webapp.modules.tboxreasoner.TBoxReasonerStatus; +import edu.cornell.mannlib.vitro.webapp.tboxreasoner.ConfiguredReasonerListener; +import edu.cornell.mannlib.vitro.webapp.tboxreasoner.InferenceModelUpdater; +import edu.cornell.mannlib.vitro.webapp.tboxreasoner.PatternListBuilder; +import edu.cornell.mannlib.vitro.webapp.tboxreasoner.ReasonerConfiguration; +import edu.cornell.mannlib.vitro.webapp.tboxreasoner.ReasonerStatementPattern; +import edu.cornell.mannlib.vitro.webapp.tboxreasoner.TBoxChanges; +import edu.cornell.mannlib.vitro.webapp.tboxreasoner.TBoxReasoner; +import edu.cornell.mannlib.vitro.webapp.tboxreasoner.TBoxReasoner.Status; +import edu.cornell.mannlib.vitro.webapp.tboxreasoner.TBoxReasonerDriver; +import edu.cornell.mannlib.vitro.webapp.utils.jena.criticalsection.LockableModel; +import edu.cornell.mannlib.vitro.webapp.utils.jena.criticalsection.LockableOntModel; +import edu.cornell.mannlib.vitro.webapp.utils.jena.criticalsection.LockedOntModel; +import edu.cornell.mannlib.vitro.webapp.utils.threads.VitroBackgroundThread; + +/** + * The basic implementation of the TBoxReasonerDriver. It gets help from a + * listener, an executor, and a reasoner. + * + * Create a listener that listens for changes to the TBox, but filters them + * according to a ReasonerConfiguration object. The listener accumulates the + * changes it likes, until it detects an ending EditEvent. Then it passes the + * change set back to the driver. + * + * Each time a change set is received, a task is created and given to the + * executor to run. The executor is single-threaded, so the change sets are + * processed in sequence. + * + * Processing involves the following steps: + * + * 1. Telling the reasoner about the changes, so it can update its own internal + * ontology model. + * + * 2. Telling the reasoner to re-inference its model. A status is returned. + * + * 3. Asking the reasoner for the inferences from its model. As with the initial + * changes, these inferences are filtered according to the + * ReasonerConfiguration. + * + * 4. Synchronizing the applications TBox inferences model with the inferences + * obtained from the reasoner. + * + * ---------------------- + * + * Possible optimization: if change sets come in quickly enough that the third + * set is received while the first is still being processed, it would be + * reasonable to merge the second and third sets into one. + */ +public class BasicTBoxReasonerDriver implements TBoxReasonerDriver { + private static final Log log = LogFactory + .getLog(BasicTBoxReasonerDriver.class); + + private final LockableOntModel lockableAssertionsModel; + private final LockableModel lockableInferencesModel; + private final LockableOntModel lockableFullModel; + + private final ReasonerConfiguration reasonerConfiguration; + + private final ConfiguredReasonerListener listener; + + private final Set pendingChangeSets; + + private final ExecutorService executorService; + + private final TBoxReasoner reasoner; + + private TBoxReasoner.Status innerStatus; + + public BasicTBoxReasonerDriver(OntModel assertionsModel, + Model inferencesModel, OntModel fullModel, TBoxReasoner reasoner, + ReasonerConfiguration reasonerConfiguration) { + this.lockableAssertionsModel = new LockableOntModel(assertionsModel); + this.lockableInferencesModel = new LockableModel(inferencesModel); + this.lockableFullModel = new LockableOntModel(fullModel); + this.reasoner = reasoner; + this.reasonerConfiguration = reasonerConfiguration; + + this.listener = new ConfiguredReasonerListener(reasonerConfiguration, + this); + + this.pendingChangeSets = Collections + .synchronizedSet(new HashSet()); + + this.executorService = Executors.newFixedThreadPool(1, + new VitroBackgroundThread.Factory("TBoxReasoner")); + + assertionsModel.getBaseModel().register(listener); + fullModel.getBaseModel().register(listener); + + doInitialReasoning(); + } + + private void doInitialReasoning() { + try (LockedOntModel assertionsModel = lockableAssertionsModel.read()) { + for (ReasonerStatementPattern pat : reasonerConfiguration + .getInferenceDrivingPatternAllowSet()) { + listener.addedStatements(assertionsModel.listStatements( + (Resource) null, pat.getPredicate(), (RDFNode) null)); + } + } + listener.notifyEvent(null, new EditEvent(null, false)); + } + + @Override + public TBoxReasonerStatus getStatus() { + return new FullStatus(innerStatus, !pendingChangeSets.isEmpty()); + } + + @Override + public void runSynchronizer(TBoxChanges changeSet) { + if (!changeSet.isEmpty()) { + executorService.execute(new ReasoningTask(changeSet)); + } + } + + /** + * Shut down the thread that runs the reasoning tasks. Don't wait longer + * than 1 minute. + */ + public void shutdown() { + executorService.shutdown(); + int waited = 0; + while (waited < 60 && !executorService.isTerminated()) { + try { + log.info("Waiting for TBox reasoner to terminate."); + executorService.awaitTermination(5, TimeUnit.SECONDS); + waited += 5; + } catch (InterruptedException e) { + // Should never happen. + e.printStackTrace(); + break; + } + } + if (!executorService.isTerminated()) { + log.warn("Forcing TBox reasoner to terminate."); + executorService.shutdownNow(); + } + if (!executorService.isTerminated()) { + log.error("TBox reasoner did not terminate."); + } + } + + private class ReasoningTask implements Runnable { + private final TBoxChanges changes; + private List patternList; + + public ReasoningTask(TBoxChanges changes) { + this.changes = changes; + pendingChangeSets.add(changes); + } + + @Override + public void run() { + try { + setWorking(); + + reasoner.updateReasonerModel(changes); + innerStatus = reasoner.performReasoning(); + + buildPatternList(); + updateInferencesModel(); + + setIdle(); + } finally { + pendingChangeSets.remove(changes); + } + } + + private void setWorking() { + Thread current = Thread.currentThread(); + if (current instanceof VitroBackgroundThread) { + ((VitroBackgroundThread) current).setWorkLevel(WORKING); + } + } + + private void setIdle() { + Thread current = Thread.currentThread(); + if (current instanceof VitroBackgroundThread) { + ((VitroBackgroundThread) current).setWorkLevel(IDLE); + } + } + + private void buildPatternList() { + PatternListBuilder patternListBuilder = new PatternListBuilder( + reasonerConfiguration, reasoner, changes); + this.patternList = patternListBuilder.build(); + } + + private void updateInferencesModel() { + InferenceModelUpdater inferenceModelUpdater = new InferenceModelUpdater( + reasoner, lockableInferencesModel, lockableFullModel, + listener); + inferenceModelUpdater.update(patternList); + } + } + + private static class FullStatus implements TBoxReasonerStatus { + private final TBoxReasoner.Status reasonerStatus; + private final boolean reasoning; + + public FullStatus(Status reasonerStatus, boolean reasoning) { + this.reasonerStatus = reasonerStatus; + this.reasoning = reasoning; + } + + @Override + public boolean isReasoning() { + return reasoning; + } + + @Override + public boolean isConsistent() { + return reasonerStatus.isConsistent(); + } + + @Override + public boolean isInErrorState() { + return reasonerStatus.isInErrorState(); + } + + @Override + public String getExplanation() { + String explanation = reasonerStatus.getExplanation(); + return explanation == null ? "" : explanation; + } + + } + +} diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/tboxreasoner/impl/pellet/PelletTBoxReasoner.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/tboxreasoner/impl/pellet/PelletTBoxReasoner.java index e6167e199..72b2ed49f 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/tboxreasoner/impl/pellet/PelletTBoxReasoner.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/tboxreasoner/impl/pellet/PelletTBoxReasoner.java @@ -22,7 +22,6 @@ import com.hp.hpl.jena.vocabulary.RDFS; import edu.cornell.mannlib.vitro.webapp.tboxreasoner.ReasonerConfiguration; import edu.cornell.mannlib.vitro.webapp.tboxreasoner.ReasonerStatementPattern; import edu.cornell.mannlib.vitro.webapp.tboxreasoner.TBoxChanges; -import edu.cornell.mannlib.vitro.webapp.tboxreasoner.TBoxReasonerDriver.Status; import edu.cornell.mannlib.vitro.webapp.tboxreasoner.TBoxReasoner; import edu.cornell.mannlib.vitro.webapp.utils.jena.criticalsection.LockableOntModel; import edu.cornell.mannlib.vitro.webapp.utils.jena.criticalsection.LockedOntModel; diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/tboxreasoner/impl/pellet/PelletTBoxReasonerModule.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/tboxreasoner/impl/pellet/PelletTBoxReasonerModule.java new file mode 100644 index 000000000..e04c7c54d --- /dev/null +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/tboxreasoner/impl/pellet/PelletTBoxReasonerModule.java @@ -0,0 +1,102 @@ +/* $This file is distributed under the terms of the license in /doc/license.txt$ */ + +package edu.cornell.mannlib.vitro.webapp.tboxreasoner.impl.pellet; + +import static edu.cornell.mannlib.vitro.webapp.modelaccess.ModelNames.TBOX_ASSERTIONS; +import static edu.cornell.mannlib.vitro.webapp.modelaccess.ModelNames.TBOX_INFERENCES; +import static edu.cornell.mannlib.vitro.webapp.modelaccess.ModelNames.TBOX_UNION; + +import java.util.List; + +import javax.servlet.ServletContext; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import com.hp.hpl.jena.ontology.OntModel; +import com.hp.hpl.jena.ontology.Restriction; +import com.hp.hpl.jena.rdf.model.Model; + +import edu.cornell.mannlib.vitro.webapp.modelaccess.ContextModelAccess; +import edu.cornell.mannlib.vitro.webapp.modelaccess.ModelAccess; +import edu.cornell.mannlib.vitro.webapp.modules.Application; +import edu.cornell.mannlib.vitro.webapp.modules.ComponentStartupStatus; +import edu.cornell.mannlib.vitro.webapp.modules.tboxreasoner.TBoxReasonerModule; +import edu.cornell.mannlib.vitro.webapp.modules.tboxreasoner.TBoxReasonerStatus; +import edu.cornell.mannlib.vitro.webapp.tboxreasoner.ReasonerConfiguration; +import edu.cornell.mannlib.vitro.webapp.tboxreasoner.impl.BasicTBoxReasonerDriver; + +/** + * Configure a Pellet reasoner on the TBox. + */ +public class PelletTBoxReasonerModule implements TBoxReasonerModule { + private static final Log log = LogFactory + .getLog(PelletTBoxReasonerModule.class); + + private PelletTBoxReasoner reasoner; + private BasicTBoxReasonerDriver driver; + + @Override + public void startup(Application application, ComponentStartupStatus ss) { + ServletContext ctx = application.getServletContext(); + + ContextModelAccess contextModels = ModelAccess.on(ctx); + OntModel tboxAssertionsModel = contextModels + .getOntModel(TBOX_ASSERTIONS); + Model tboxInferencesModel = contextModels.getOntModel(TBOX_INFERENCES) + .getBaseModel(); + OntModel tboxUnionModel = contextModels.getOntModel(TBOX_UNION); + + reasoner = new PelletTBoxReasoner(ReasonerConfiguration.DEFAULT); + driver = new BasicTBoxReasonerDriver(tboxAssertionsModel, + tboxInferencesModel, tboxUnionModel, reasoner, + ReasonerConfiguration.DEFAULT); + + ss.info("Pellet reasoner connected for the TBox"); + + waitForTBoxReasoning(); + } + + @Override + public TBoxReasonerStatus getStatus() { + if (driver == null) { + throw new IllegalStateException( + "PelletTBoxReasonerModule has not been started."); + } + return driver.getStatus(); + } + + @Override + public List listRestrictions() { + if (reasoner == null) { + throw new IllegalStateException( + "PelletTBoxReasonerModule has not been started."); + } + return reasoner.listRestrictions(); + } + + @Override + public void shutdown(Application application) { + driver.shutdown(); + } + + @Override + public void waitForTBoxReasoning() { + int sleeps = 0; + // sleep at least once to make sure the TBox reasoning gets started + while ((0 == sleeps) + || ((sleeps < 1000) && getStatus().isReasoning())) { + if (((sleeps - 1) % 10) == 0) { // print message at 10 second + // intervals + log.info("Waiting for initial TBox reasoning to complete"); + } + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + // This should never happen. + e.printStackTrace(); + } + sleeps++; + } + } +} diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/utils/threads/VitroBackgroundThread.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/utils/threads/VitroBackgroundThread.java index 47780558f..437b8d48d 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/utils/threads/VitroBackgroundThread.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/utils/threads/VitroBackgroundThread.java @@ -10,6 +10,8 @@ import java.util.Collections; import java.util.Date; import java.util.List; import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.atomic.AtomicInteger; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -106,4 +108,25 @@ public class VitroBackgroundThread extends Thread { return flags; } } + + /** + * A factory class, for use in Executors, that creates threads with + * successive names. + */ + public static class Factory implements ThreadFactory{ + private final String threadName; + private final AtomicInteger index; + + public Factory(String threadName) { + this.threadName = threadName; + this.index = new AtomicInteger(); + } + + @Override + public Thread newThread(Runnable r) { + return new VitroBackgroundThread(r, threadName + "_" + index.getAndIncrement()); + } + + } + } diff --git a/webapp/test/stubs/edu/cornell/mannlib/vitro/webapp/modules/ApplicationStub.java b/webapp/test/stubs/edu/cornell/mannlib/vitro/webapp/modules/ApplicationStub.java index f5aeaf92f..b8534649c 100644 --- a/webapp/test/stubs/edu/cornell/mannlib/vitro/webapp/modules/ApplicationStub.java +++ b/webapp/test/stubs/edu/cornell/mannlib/vitro/webapp/modules/ApplicationStub.java @@ -12,6 +12,7 @@ import edu.cornell.mannlib.vitro.webapp.modules.Application; import edu.cornell.mannlib.vitro.webapp.modules.fileStorage.FileStorage; import edu.cornell.mannlib.vitro.webapp.modules.imageProcessor.ImageProcessor; import edu.cornell.mannlib.vitro.webapp.modules.searchEngine.SearchEngine; +import edu.cornell.mannlib.vitro.webapp.modules.tboxreasoner.TBoxReasonerModule; import edu.cornell.mannlib.vitro.webapp.modules.tripleSource.ConfigurationTripleSource; import edu.cornell.mannlib.vitro.webapp.modules.tripleSource.ContentTripleSource; @@ -101,4 +102,11 @@ public class ApplicationStub implements Application { "ApplicationStub.getConfigurationTripleSource() not implemented."); } + @Override + public TBoxReasonerModule getTBoxReasonerModule() { + // TODO Auto-generated method stub + throw new RuntimeException("ApplicationStub.getTBoxReasonerModule() not implemented."); + + } + } diff --git a/webapp/web/WEB-INF/resources/startup_listeners.txt b/webapp/web/WEB-INF/resources/startup_listeners.txt index 02a1f48fd..9c3fc7a42 100644 --- a/webapp/web/WEB-INF/resources/startup_listeners.txt +++ b/webapp/web/WEB-INF/resources/startup_listeners.txt @@ -34,7 +34,7 @@ edu.cornell.mannlib.vitro.webapp.servlet.setup.RemoveObsoletePermissions edu.cornell.mannlib.vitro.webapp.servlet.setup.FileGraphSetup -edu.cornell.mannlib.vitro.webapp.servlet.setup.PelletListenerSetup +edu.cornell.mannlib.vitro.webapp.application.ApplicationImpl$ReasonersSetup edu.cornell.mannlib.vitro.webapp.servlet.setup.SimpleReasonerSetup #edu.cornell.mannlib.vitro.webapp.servlet.setup.UpdateKnowledgeBase