Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/rsmd-guidelines #4014

Open
wants to merge 12 commits into
base: main
Choose a base branch
from
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package edu.cornell.mannlib.vitro.webapp.controller.software;

public class AuthorDTO {

public String name;

public String type;

public String identifier;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package edu.cornell.mannlib.vitro.webapp.controller.software;

public class FunderRequestDTO {

public String name;

public String type;

public String grantName;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package edu.cornell.mannlib.vitro.webapp.controller.software;

public class FunderResponseDTO {

public String name;

public String type;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
package edu.cornell.mannlib.vitro.webapp.controller.software;

import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.util.Objects;
import java.util.UUID;
import java.util.function.BiConsumer;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import edu.cornell.mannlib.vitro.webapp.application.ApplicationUtils;
import edu.cornell.mannlib.vitro.webapp.beans.ApplicationBean;
import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
import edu.cornell.mannlib.vitro.webapp.dao.jena.RDFServiceDataset;
import edu.cornell.mannlib.vitro.webapp.modules.searchIndexer.SearchIndexer;
import org.apache.jena.query.Dataset;
import org.apache.jena.query.ReadWrite;
import org.apache.jena.update.GraphStore;
import org.apache.jena.update.GraphStoreFactory;

public class IndividualApiCommonCRUDUtility {

public static void executeWithTransaction(HttpServletRequest req, HttpServletResponse resp,
BiConsumer<GraphStore, String> action) throws IOException {
VitroRequest vreq = new VitroRequest(req);
SearchIndexer indexer = ApplicationUtils.instance().getSearchIndexer();
Dataset ds = new RDFServiceDataset(vreq.getUnfilteredRDFService());
GraphStore graphStore = GraphStoreFactory.create(ds);

String entityUri;
if (req.getMethod().equalsIgnoreCase("POST")) {
entityUri = IndividualApiSparqlUtility.buildIndividualUri(UUID.randomUUID().toString());
} else {
String pathInfo = req.getPathInfo();
if (Objects.isNull(pathInfo) || pathInfo.isEmpty()) {
IndividualApiNetworkUtility.do400BadRequest("You have to provide a record identifier.", resp);
return;
}

entityUri = IndividualApiSparqlUtility.buildIndividualUri(pathInfo.substring(1));
}

try {
pauseIndexer(indexer);
beginTransaction(ds);

action.accept(graphStore, entityUri);

} finally {
commitTransaction(ds);
unpauseIndexer(indexer);
}
}

private static void pauseIndexer(SearchIndexer indexer) {
if (indexer != null) {
indexer.pause();
}
}

private static void unpauseIndexer(SearchIndexer indexer) {
if (indexer != null) {
indexer.unpause();
}
}

private static void beginTransaction(Dataset ds) {
if (ds.supportsTransactions()) {
ds.begin(ReadWrite.WRITE);
}
}

private static void commitTransaction(Dataset ds) {
if (ds.supportsTransactions()) {
ds.commit();
ds.end();
}
}

public static void performDeleteOperation(HttpServletRequest req, HttpServletResponse resp)
throws IOException {
String pathInfo = req.getPathInfo();
if (Objects.isNull(pathInfo) || pathInfo.isEmpty()) {
IndividualApiNetworkUtility.do400BadRequest("You have to provide a record identifier.", resp);
return;
}

VitroRequest vreq = new VitroRequest(req);
ApplicationBean appBean = vreq.getAppBean();
String appName = appBean.getApplicationName().toLowerCase();
URL url = new URL("http://" + req.getServerName() + ":" + req.getServerPort() + "/" + appName +
"/deleteIndividualController?individualUri=" +
URLEncoder.encode(IndividualApiSparqlUtility.buildIndividualUri(pathInfo.substring(1))) +
"&redirectUrl=%2F");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
connection.setRequestProperty("Accept", "application/json");

addCookiesToRequest(req, connection);

connection.getResponseCode();

resp.setStatus(HttpServletResponse.SC_NO_CONTENT);

connection.disconnect();
}

private static void addCookiesToRequest(HttpServletRequest req, HttpURLConnection connection) {
Cookie[] cookies = req.getCookies();
if (cookies != null) {
StringBuilder cookieHeader = new StringBuilder();
for (Cookie cookie : cookies) {
cookieHeader.append(cookie.getName()).append("=").append(cookie.getValue()).append("; ");
}
// Remove the trailing "; " at the end of the cookie string
if (cookieHeader.length() > 0) {
cookieHeader.setLength(cookieHeader.length() - 2);
}
connection.setRequestProperty("Cookie", cookieHeader.toString());
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
package edu.cornell.mannlib.vitro.webapp.controller.software;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import edu.cornell.mannlib.vitro.webapp.controller.api.sparqlquery.InvalidQueryTypeException;
import edu.cornell.mannlib.vitro.webapp.rdfservice.RDFServiceException;
import org.apache.jena.query.QueryParseException;

public class IndividualApiNetworkUtility {

public static void handleResponseContentType(HttpServletRequest req, HttpServletResponse resp) {
String acceptHeader = req.getHeader("Accept");
if (acceptHeader != null && !acceptHeader.isEmpty()) {
resp.setContentType(acceptHeader);
} else {
resp.setContentType("application/json");
}
}

public static String serializeToJSON(Object serializationObject) throws IOException {
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.enable(SerializationFeature.INDENT_OUTPUT);
objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
objectMapper.setSerializationInclusion(JsonInclude.Include.NON_EMPTY);
return objectMapper.writeValueAsString(serializationObject);
}

public static boolean isJsonRequest(HttpServletRequest req) {
String acceptHeader = req.getHeader("Accept");
return acceptHeader != null && acceptHeader.equals("application/json");
}

public static <T> T parseRequestBody(HttpServletRequest req, Class<T> clazz) throws IOException {
ObjectMapper objectMapper = new ObjectMapper();
return objectMapper.readValue(req.getInputStream(), clazz);
}

public static void handleException(Exception e, String queryString, HttpServletResponse resp) throws IOException {
if (e instanceof InvalidQueryTypeException) {
do400BadRequest("Invalid query type: '" + queryString + "'", resp);
} else if (e instanceof QueryParseException) {
do400BadRequest("Failed to parse query: '" + queryString + "'", resp);
} else if (e instanceof RDFServiceException) {
do500InternalServerError("Problem executing the query.", e, resp);
}
}

public static void do400BadRequest(String message, HttpServletResponse resp)
throws IOException {
resp.setStatus(400);
resp.getWriter().println(message);
}

public static void do404NotFound(String message, HttpServletResponse resp)
throws IOException {
resp.setStatus(404);
resp.getWriter().println(message);
}

public static void do500InternalServerError(String message, Exception e,
HttpServletResponse resp) throws IOException {
resp.setStatus(500);
PrintWriter w = resp.getWriter();
w.println(message);
e.printStackTrace(w);

Check warning

Code scanning / CodeQL

Information exposure through a stack trace

[Error information](1) can be exposed to an external user.
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
package edu.cornell.mannlib.vitro.webapp.controller.software;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import edu.cornell.mannlib.vitro.webapp.config.ConfigurationProperties;
import edu.cornell.mannlib.vitro.webapp.controller.api.sparqlquery.SparqlQueryApiExecutor;
import edu.cornell.mannlib.vitro.webapp.rdfservice.RDFServiceException;
import org.apache.commons.lang3.StringEscapeUtils;
import org.apache.jena.update.GraphStore;
import org.apache.jena.update.UpdateAction;
import org.apache.jena.update.UpdateFactory;
import org.apache.jena.update.UpdateRequest;

public class IndividualApiSparqlUtility {

public static String getSparqlQueryResponse(SparqlQueryApiExecutor core) throws IOException, RDFServiceException {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
core.executeAndFormat(outputStream);

String sparqlResponse = outputStream.toString("UTF-8");

outputStream.close();

return sparqlResponse;
}

public static List<Map<String, String>> parseBindings(String jsonResponse) throws IOException {
ObjectMapper objectMapper = new ObjectMapper();
JsonNode rootNode = objectMapper.readTree(jsonResponse);

JsonNode bindingsNode = rootNode.path("results").path("bindings");

List<Map<String, String>> recordsList = new ArrayList<>();

for (JsonNode bindingNode : bindingsNode) {
Map<String, String> recordMap = new HashMap<>();

Iterator<Map.Entry<String, JsonNode>> fieldsIterator = bindingNode.fields();
while (fieldsIterator.hasNext()) {
Map.Entry<String, JsonNode> field = fieldsIterator.next();

String fieldName = field.getKey();
String fieldValue = field.getValue().path("value").asText();

recordMap.put(fieldName, fieldValue);
}

recordsList.add(recordMap);
}

return recordsList;
}

public static void addPrefixClauses(StringBuilder queryBuilder) {
queryBuilder
.append("PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>\n")
.append("PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>\n")
.append("PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>\n")
.append("PREFIX owl: <http://www.w3.org/2002/07/owl#>\n")
.append("PREFIX swrl: <http://www.w3.org/2003/11/swrl#>\n")
.append("PREFIX swrlb: <http://www.w3.org/2003/11/swrlb#>\n")
.append("PREFIX vitro: <http://vitro.mannlib.cornell.edu/ns/vitro/0.7#>\n")
.append("PREFIX bibo: <http://purl.org/ontology/bibo/>\n")
.append("PREFIX c4o: <http://purl.org/spar/c4o/>\n")
.append("PREFIX cito: <http://purl.org/spar/cito/>\n")
.append("PREFIX dcterms: <http://purl.org/dc/terms/>\n")
.append("PREFIX event: <http://purl.org/NET/c4dm/event.owl#>\n")
.append("PREFIX fabio: <http://purl.org/spar/fabio/>\n")
.append("PREFIX foaf: <http://xmlns.com/foaf/0.1/>\n")
.append("PREFIX geo: <http://aims.fao.org/aos/geopolitical.owl#>\n")
.append("PREFIX obo: <http://purl.obolibrary.org/obo/>\n")
.append("PREFIX vivo: <http://vivoweb.org/ontology/core#>\n")
.append("PREFIX vcard: <http://www.w3.org/2006/vcard/ns#>\n");
}

public static void executeUpdate(GraphStore graphStore, String query) {
UpdateRequest updateRequest = UpdateFactory.create(query);
UpdateAction.execute(updateRequest, graphStore);
}

public static String buildIndividualUri(String entityId) {
String defaultNamespace =
Objects.requireNonNull(ConfigurationProperties.getInstance().getProperty("Vitro.defaultNamespace"));
return defaultNamespace + StringEscapeUtils.escapeJava(entityId);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package edu.cornell.mannlib.vitro.webapp.controller.software;

import java.util.ArrayList;
import java.util.List;

public class InformationContentEntityResponseDTO {

public String internalIdentifier;

public String name;

public String datePublished;

public List<AuthorDTO> authors = new ArrayList<>();

public List<String> fundings = new ArrayList<>();

public List<FunderResponseDTO> funders = new ArrayList<>();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package edu.cornell.mannlib.vitro.webapp.controller.software;

import java.util.Map;
import java.util.Objects;

public class InformationContentEntityResponseUtility {

public static void addAuthorToICE(Map<String, String> binding, InformationContentEntityResponseDTO entity) {
if (!Objects.nonNull(binding.get("author"))) {
return;
}

if (entity.authors.stream().anyMatch(author -> author.name.equals(binding.get("author")))) {
return;
}

AuthorDTO author = new AuthorDTO();
author.name = binding.getOrDefault("author", null);
author.type = binding.getOrDefault("authorType", null);
author.identifier = binding.getOrDefault("authorIdentifier", null);
entity.authors.add(author);
}

public static void addFundingToICE(Map<String, String> binding, InformationContentEntityResponseDTO entity) {
if (!Objects.nonNull(binding.get("funding"))) {
return;
}

if (entity.fundings.stream().anyMatch(funding -> funding.equals(binding.get("funding")))) {
return;
}

entity.fundings.add(binding.get("funding"));
}

public static void addFundersToICE(Map<String, String> binding, InformationContentEntityResponseDTO entity) {
if (!Objects.nonNull(binding.get("funder"))) {
return;
}

if (entity.funders.stream().anyMatch(funder -> funder.name.equals(binding.get("funder")))) {
return;
}

FunderResponseDTO funder = new FunderResponseDTO();
funder.name = binding.get("funder");
funder.type = binding.getOrDefault("funderType", null);
entity.funders.add(funder);
}
}
Loading
Loading