Skip to content

Commit

Permalink
Split: without extracted ConfigurationBeanLoader modifications
Browse files Browse the repository at this point in the history
    Co-authored-by: William Welling <8352733+wwelling@users.noreply.github.com>
    Co-authored-by: Kevin Day <kday@library.tamu.edu>
    Co-authored-by: Dragan Ivanovic <chenejac@uns.ac.rs>
    Co-authored-by: chenejac <chenejac@gmail.com>

    correct context path vs servlet path

    Refactor Integration Tests to use the full word Test.

    This allows for the tests to be properly picked up and executed.

    Merge pull request #281 from kaladay/dynapi-rpc_endpoint_it_to_itest

    [3678] Refactor Integration Tests to use the full word Test.
    Merge branch 'sprint-dynapi-2022-feb-staging' of github.com:vivo-project/Vitro into servlet-path

    Merge pull request #280 from wwelling/servlet-path

    Correct context path vs servlet path
    Update of the ontology. Introducing structured parameter types (object and array)

    rest endpoint corrections and integration tests

    Updating binding of the ontology to Java classes and n3 test examples.To be in accordance with changes in the ontology.

    Adding files for primitive types and APIInformation java bean.

    Adding new line at the end of file and retrieving history of deleted files by using git mv

    Adding new line at the end of file

    Merge pull request #283 from chenejac/3653_definition_of_the_ontology

    3653 definition of the ontology
    Merge branch 'sprint-dynapi-2022-feb-staging' of github.com:vivo-project/Vitro into 3667-rest-it
  • Loading branch information
litvinovg committed Apr 19, 2024
1 parent a3018a7 commit adeae77
Show file tree
Hide file tree
Showing 65 changed files with 4,787 additions and 387 deletions.
13 changes: 10 additions & 3 deletions api/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@
<artifactId>fluent-hc</artifactId>
<version>4.5.6</version>
</dependency>

<dependency>
<groupId>org.vivoweb</groupId>
<artifactId>vitro-dependencies</artifactId>
Expand All @@ -111,9 +112,15 @@
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.easymock</groupId>
<artifactId>easymock</artifactId>
<version>3.5</version>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>4.3.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-inline</artifactId>
<version>4.3.1</version>
<scope>test</scope>
</dependency>
<dependency>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,203 @@
package edu.cornell.mannlib.vitro.webapp.dynapi;

import static edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary.RDF_TYPE;
import static edu.cornell.mannlib.vitro.webapp.modelaccess.ModelNames.FULL_UNION;
import static edu.cornell.mannlib.vitro.webapp.utils.configuration.ConfigurationBeanLoader.toJavaUri;
import static java.lang.String.format;

import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.ConcurrentNavigableMap;
import java.util.concurrent.ConcurrentSkipListMap;

import javax.servlet.ServletContext;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.jena.ontology.OntModel;
import org.apache.jena.rdf.model.NodeIterator;
import org.apache.jena.rdf.model.Property;
import org.apache.jena.rdf.model.RDFNode;
import org.apache.jena.rdf.model.Resource;

import edu.cornell.mannlib.vitro.webapp.dynapi.components.Poolable;
import edu.cornell.mannlib.vitro.webapp.modelaccess.ContextModelAccess;
import edu.cornell.mannlib.vitro.webapp.modelaccess.ModelAccess;
import edu.cornell.mannlib.vitro.webapp.utils.configuration.ConfigurationBeanLoader;
import edu.cornell.mannlib.vitro.webapp.utils.configuration.ConfigurationBeanLoaderException;

public abstract class AbstractPool<K, C extends Poolable<K>, P extends Pool<K, C>> implements Pool<K, C> {

private final Log log = LogFactory.getLog(this.getClass());

private static final Object mutex = new Object();

private ConcurrentNavigableMap<K, C> components;
private ServletContext ctx;
private ConfigurationBeanLoader loader;
private ContextModelAccess modelAccess;
private OntModel dynamicAPIModel;
private ConcurrentLinkedQueue<C> obsoleteComponents;

protected AbstractPool() {
components = new ConcurrentSkipListMap<>();
obsoleteComponents = new ConcurrentLinkedQueue<>();
}

protected ConcurrentNavigableMap<K, C> getComponents() {
return components;
}

public abstract P getPool();

public abstract C getDefault();

public abstract Class<C> getType();

public C get(K key) {
C component = components.get(key);

if (component == null) {
return getDefault();
}

component.addClient();
return component;
}

public void printKeys() {
for (Map.Entry<K, C> entry : components.entrySet()) {
log.debug(format("%s in pool: '%s'", getType().getName(), entry.getKey()));
}
}

public void add(String uri, C component) {
K key = component.getKey();
log.info(format("Adding component %s with URI %s", key, uri));
if (isInModel(uri)) {
synchronized (mutex) {
C oldComponent = components.put(key, component);
if (oldComponent != null) {
obsoleteComponents.add(oldComponent);
unloadObsoleteComponents();
}
}
} else {
throw new RuntimeException(format("%s %s with URI %s not found in model. Not adding to pool.",
getType().getName(), key, uri));
}
}

public void remove(String uri, K key) {
log.info(format("Removing component %s with URI %s", key, uri));
if (!isInModel(uri)) {
synchronized (mutex) {
C oldComponent = components.remove(key);
if (oldComponent != null) {
obsoleteComponents.add(oldComponent);
unloadObsoleteComponents();
}
}
} else {
throw new RuntimeException(format("%s %s with URI %s still exists in model. Not removing from pool.",
getType().getName(), key, uri));
}
}

private boolean isInModel(String uri) {
Resource s = dynamicAPIModel.getResource(uri);
Property p = dynamicAPIModel.getProperty(RDF_TYPE);

String javaUri = toJavaUri(getType());

NodeIterator nit = dynamicAPIModel.listObjectsOfProperty(s, p);
while (nit.hasNext()) {
RDFNode node = nit.next();
if (node.isResource() && node.toString().replace("#", ".").equals(javaUri)) {
return true;
}
}

return false;
}

public void reload(String uri) {
try {
add(uri, loader.loadInstance(uri, getType()));
} catch (ConfigurationBeanLoaderException e) {
throw new RuntimeException(format("Failed to reload %s with URI %s.", getType().getName(), uri));
}
}

public synchronized void reload() {
if (ctx == null) {
log.error(format("Context is null. Can't reload %s.", this.getClass().getName()));
return;
}
if (loader == null) {
log.error(format("Loader is null. Can't reload %s.", this.getClass().getName()));
return;
}
ConcurrentNavigableMap<K, C> newActions = new ConcurrentSkipListMap<>();
loadComponents(newActions);
ConcurrentNavigableMap<K, C> oldActions = this.components;
components = newActions;
for (Map.Entry<K, C> component : oldActions.entrySet()) {
obsoleteComponents.add(component.getValue());
oldActions.remove(component.getKey());
}
unloadObsoleteComponents();
}

public void init(ServletContext ctx) {
this.ctx = ctx;
modelAccess = ModelAccess.on(ctx);
dynamicAPIModel = modelAccess.getOntModel(FULL_UNION);
loader = new ConfigurationBeanLoader(dynamicAPIModel, ctx);
log.debug("Context Initialization ...");
loadComponents(components);
}

private void loadComponents(ConcurrentNavigableMap<K, C> components) {
Set<C> newActions = loader.loadEach(getType());
log.debug(format("Context Initialization. %s %s(s) currently loaded.", components.size(), getType().getName()));
for (C component : newActions) {
if (component.isValid()) {
components.put(component.getKey(), component);
} else {
log.error(format("%s with rpcName %s is invalid.", getType().getName(), component.getKey()));
}
}
log.debug(format("Context Initialization finished. %s %s(s) loaded.", components.size(), getType().getName()));
}

private void unloadObsoleteComponents() {
for (C component : obsoleteComponents) {
if (!isComponentInUse(component)) {
component.dereference();
obsoleteComponents.remove(component);
}
}
}

private boolean isComponentInUse(C component) {
if (!component.hasClients()) {
return false;
}
component.removeDeadClients();
if (!component.hasClients()) {
return false;
}
return true;
}

public long obsoleteCount() {
return obsoleteComponents.size();
}

public long count() {
return components.size();
}

}
Original file line number Diff line number Diff line change
@@ -1,99 +1,29 @@
package edu.cornell.mannlib.vitro.webapp.dynapi;

import static edu.cornell.mannlib.vitro.webapp.modelaccess.ModelNames.FULL_UNION;

import java.util.HashMap;
import java.util.Map;
import java.util.Set;

import javax.servlet.ServletContext;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.jena.ontology.OntModel;

import edu.cornell.mannlib.vitro.webapp.dynapi.components.Action;
import edu.cornell.mannlib.vitro.webapp.dynapi.components.DefaultAction;
import edu.cornell.mannlib.vitro.webapp.modelaccess.ContextModelAccess;
import edu.cornell.mannlib.vitro.webapp.modelaccess.ModelAccess;
import edu.cornell.mannlib.vitro.webapp.utils.configuration.ConfigurationBeanLoader;

public class ActionPool {
public class ActionPool extends AbstractPool<String, Action, ActionPool> {

private static ActionPool INSTANCE = null;
private static final Log log = LogFactory.getLog(ActionPool.class);

private Map<String,Action> actions;
private ServletContext ctx;
private ConfigurationBeanLoader loader;
private ContextModelAccess modelAccess;
private OntModel dynamicAPIModel;
private static ActionPool INSTANCE = new ActionPool();

private ActionPool(){
this.actions = new HashMap<String,Action>();
INSTANCE = this;
}

public static ActionPool getInstance() {
if (INSTANCE == null) {
INSTANCE = new ActionPool();
}
return INSTANCE;
}

public Action getByName(String name) {
Action action = actions.get(name);
if (action == null) {
action = new DefaultAction();
}
return action;
}

public void printActionNames() {
for (Map.Entry<String,Action> entry : actions.entrySet()) {
log.debug("Action in pool: '" + entry.getKey() + "'");
}
}

public void reload() {
if (ctx == null ) {
log.error("Context is null. Can't reload action pool.");
return;
}
if (loader == null ) {
log.error("Loader is null. Can't reload action pool.");
return;
}
for (Map.Entry<String,Action> entry : actions.entrySet()) {
entry.getValue().dereference();
}
actions.clear();
loadActions();
}

public void init(ServletContext ctx) {
this.ctx = ctx;
modelAccess = ModelAccess.on(ctx);
dynamicAPIModel = modelAccess.getOntModel(FULL_UNION);
loader = new ConfigurationBeanLoader( dynamicAPIModel, ctx);
log.debug("Context Initialization ...");
loadActions();
@Override
public ActionPool getPool() {
return getInstance();
}

private void loadActions() {
Set<Action> actions = loader.loadEach(Action.class);
log.debug("Context Initialization. actions loaded: " + actions.size());
for (Action action : actions) {
if (action.isValid()) {
add(action);
} else {
log.error("Action with rpcName " + action.getName() + " is invalid.");
}
}
log.debug("Context Initialization finished. " + actions.size() + " actions loaded.");
@Override
public Action getDefault() {
return new DefaultAction();
}

private void add(Action action) {
actions.put(action.getName(), action);
@Override
public Class<Action> getType() {
return Action.class;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@

public class OperationData {

private Map<String, String[]> params;
private ServletContext context;
private final Map<String, String[]> params;
private final ServletContext context;

public OperationData(HttpServletRequest request) {
params = request.getParameterMap();
Expand All @@ -20,10 +20,7 @@ public ServletContext getContext() {
}

public boolean has(String paramName) {
if (params.containsKey(paramName)) {
return true;
}
return false;
return params.containsKey(paramName);
}

public String[] get(String paramName) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package edu.cornell.mannlib.vitro.webapp.dynapi;

import javax.servlet.ServletContext;

import edu.cornell.mannlib.vitro.webapp.dynapi.components.Poolable;

public interface Pool<K, C extends Poolable<K>> {

public C get(K key);

public void printKeys();

public void add(String uri, C component);

public void remove(String uri, K key);

public void reload();

public void reload(String uri);

public void init(ServletContext ctx);

public long obsoleteCount();

public long count();

}
Loading

0 comments on commit adeae77

Please sign in to comment.