diff --git a/build.gradle b/build.gradle index 8b3159eb7d921506e4ee41cc22366ceab5e892f7..45afa1f18801119db8abb6c77098f7e2004984c2 100644 --- a/build.gradle +++ b/build.gradle @@ -126,11 +126,27 @@ cargo { } } +task sourceJar(type: Jar, dependsOn: classes) { + from sourceSets.main.allSource +} + +task javadocJar(type: Jar, dependsOn: javadoc) { + from javadoc.destinationDir +} + publishing { publications { mavenJava(MavenPublication) { from components.java + artifact sourceJar { + classifier "sources" + } + + artifact javadocJar { + classifier "javadoc" + } + pom.withXml { def root = asNode() root.appendNode('name', 'XNAT Server') diff --git a/src/main/java/org/nrg/dcm/preferences/DicomSCPInstance.java b/src/main/java/org/nrg/dcm/preferences/DicomSCPInstance.java index 096f3d7f3d433b152e9c384ef70be27668f64f81..0d3a43d1bf1dce89d5f7e47d982375f09c4e53d3 100644 --- a/src/main/java/org/nrg/dcm/preferences/DicomSCPInstance.java +++ b/src/main/java/org/nrg/dcm/preferences/DicomSCPInstance.java @@ -1,11 +1,8 @@ package org.nrg.dcm.preferences; import com.fasterxml.jackson.annotation.JsonInclude; -import com.fasterxml.jackson.core.JsonParser; -import com.fasterxml.jackson.databind.ObjectMapper; - -import java.io.IOException; +@SuppressWarnings("WeakerAccess") @JsonInclude(JsonInclude.Include.NON_DEFAULT) public class DicomSCPInstance { @SuppressWarnings("unused") @@ -29,14 +26,6 @@ public class DicomSCPInstance { setFileNamer(fileNamer); } - public static DicomSCPInstance deserialize(final String json) throws IOException { - return _mapper.readValue(json, DicomSCPInstance.class); - } - - public static String serialize(final DicomSCPInstance instance) throws IOException { - return _mapper.writeValueAsString(instance); - } - public String getScpId() { return _scpId; } @@ -97,11 +86,6 @@ public class DicomSCPInstance { '}'; } - private static final ObjectMapper _mapper = new ObjectMapper(); - static { - _mapper.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true); - } - private String _scpId; private int _port; private String _aeTitle; diff --git a/src/main/java/org/nrg/xnat/configuration/SerializerConfig.java b/src/main/java/org/nrg/xnat/configuration/SerializerConfig.java new file mode 100644 index 0000000000000000000000000000000000000000..f4702c9e57e2c3e2f71ac2d2ffc3ab16919d54f8 --- /dev/null +++ b/src/main/java/org/nrg/xnat/configuration/SerializerConfig.java @@ -0,0 +1,47 @@ +package org.nrg.xnat.configuration; + +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.PrettyPrinter; +import com.fasterxml.jackson.core.util.DefaultIndenter; +import com.fasterxml.jackson.core.util.DefaultPrettyPrinter; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.dataformat.yaml.YAMLFactory; +import org.jetbrains.annotations.NotNull; +import org.nrg.xnat.utils.SerializerService; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class SerializerConfig { + + @Bean + @NotNull + public PrettyPrinter prettyPrinter() { + final DefaultIndenter indenter = new DefaultIndenter(" ", DefaultIndenter.SYS_LF); + final DefaultPrettyPrinter printer = new DefaultPrettyPrinter(); + printer.indentObjectsWith(indenter); + printer.indentArraysWith(indenter); + return printer; + } + + @Bean + public ObjectMapper jsonObjectMapper() { + final PrettyPrinter printer = prettyPrinter(); + final ObjectMapper mapper = new ObjectMapper().setDefaultPrettyPrinter(printer); + mapper.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true); + return mapper; + } + + @Bean + public ObjectMapper yamlObjectMapper() { + final PrettyPrinter printer = prettyPrinter(); + final ObjectMapper mapper = new ObjectMapper(new YAMLFactory()).setDefaultPrettyPrinter(printer); + mapper.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true); + return mapper; + } + + @Bean + public SerializerService serializerService() { + return new SerializerService(); + } +} diff --git a/src/main/java/org/nrg/xnat/configuration/SpawnerConfig.java b/src/main/java/org/nrg/xnat/configuration/SpawnerConfig.java new file mode 100644 index 0000000000000000000000000000000000000000..93f2d7afcef20a7354af68cf67573b9e31e5d66c --- /dev/null +++ b/src/main/java/org/nrg/xnat/configuration/SpawnerConfig.java @@ -0,0 +1,30 @@ +package org.nrg.xnat.configuration; + +import org.nrg.framework.orm.hibernate.HibernateEntityPackageList; +import org.nrg.xnat.spawner.services.SpawnerResourceLocator; +import org.nrg.xnat.spawner.services.impl.SpawnerWorker; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; + +import java.util.Collections; + +@Configuration +@ComponentScan({"org.nrg.xnat.spawner.controllers", "org.nrg.xnat.spawner.services.impl.hibernate", "org.nrg.xnat.spawner.repositories"}) +public class SpawnerConfig { + @Bean + public SpawnerWorker spawnerWorker() { + return new SpawnerWorker(); + } + + @Bean + public HibernateEntityPackageList spawnerEntityPackages() { + return new HibernateEntityPackageList(Collections.singletonList("org.nrg.xnat.spawner.entities")); + } + + @Bean + public SpawnerResourceLocator spawnerResourceLocator() { + // TODO: This uses the default spawner element pattern. It would be nice to set this as a site configuration property. + return new SpawnerResourceLocator(); + } +} diff --git a/src/main/java/org/nrg/xnat/event/listeners/PipelineEmailHandlerAbst.java b/src/main/java/org/nrg/xnat/event/listeners/PipelineEmailHandlerAbst.java index b9fc9febc1639b56d477bd5726fe434a89b53d03..f62842042a01eb3421d14f38cac51f6da980fc1f 100644 --- a/src/main/java/org/nrg/xnat/event/listeners/PipelineEmailHandlerAbst.java +++ b/src/main/java/org/nrg/xnat/event/listeners/PipelineEmailHandlerAbst.java @@ -1,15 +1,14 @@ package org.nrg.xnat.event.listeners; import com.fasterxml.jackson.core.type.TypeReference; -import com.fasterxml.jackson.databind.ObjectMapper; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import org.apache.commons.lang.StringEscapeUtils; import org.apache.commons.lang.StringUtils; -import org.apache.log4j.Logger; import org.apache.xmlbeans.XmlException; import org.nrg.pipeline.xmlbeans.AllResolvedStepsDocument; import org.nrg.pipeline.xmlbeans.ParameterData; +import org.nrg.xdat.XDAT; import org.nrg.xdat.model.WrkXnatexecutionenvironmentParameterI; import org.nrg.xdat.om.WrkWorkflowdata; import org.nrg.xdat.om.WrkXnatexecutionenvironment; @@ -20,6 +19,9 @@ import org.nrg.xdat.turbine.utils.TurbineUtils; import org.nrg.xft.db.PoolDBUtils; import org.nrg.xft.event.WorkflowStatusEvent; import org.nrg.xnat.notifications.NotifyProjectPipelineListeners; +import org.nrg.xnat.utils.SerializerService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.io.File; import java.io.IOException; @@ -27,26 +29,25 @@ import java.nio.charset.Charset; import java.nio.file.Files; import java.util.*; -/** - * Created by flavin on 2/27/15. - */ +@SuppressWarnings("WeakerAccess") public abstract class PipelineEmailHandlerAbst extends WorkflowStatusEventHandlerAbst { - /** The logger. */ - static Logger logger = Logger.getLogger(PipelineEmailHandlerAbst.class); - /** The default template success. */ public final String DEFAULT_TEMPLATE_SUCCESS = "/screens/PipelineEmail_success.vm"; - + /** The default subject success. */ public final String DEFAULT_SUBJECT_SUCCESS = "processed without errors"; - + /** The default template failure. */ public final String DEFAULT_TEMPLATE_FAILURE = "/screens/PipelineEmail_failure.vm"; - + /** The default subject failure. */ public final String DEFAULT_SUBJECT_FAILURE = ""; + protected PipelineEmailHandlerAbst() { + _serializer = XDAT.getContextService().getBean(SerializerService.class); + } + /** * Send. * @@ -93,14 +94,14 @@ public abstract class PipelineEmailHandlerAbst extends WorkflowStatusEventHandle } if (completed(e) && Float.parseFloat(wrk.getPercentagecomplete()) < 100.0f) { - logger.error("Workflow "+wrk.getWrkWorkflowdataId()+" is \"Complete\" but percentage is less than 100%. Not sending email."); + _log.error("Workflow " + wrk.getWrkWorkflowdataId() + " is \"Complete\" but percentage is less than 100%. Not sending email."); return; } SchemaElement objXsiType; try { objXsiType = SchemaElement.GetElement(wrk.getDataType()); } catch (Throwable e1) { - logger.error("", e1);//this shouldn't happen + _log.error("", e1);//this shouldn't happen return; } @@ -131,24 +132,15 @@ public abstract class PipelineEmailHandlerAbst extends WorkflowStatusEventHandle throw new Exception("Experiment " + wrk.getId() + " associated with workflow " + wrk.getWrkWorkflowdataId() + " is null"); } - - if (wrk.getComments()!=null) { String comments = StringEscapeUtils.unescapeXml(wrk.getComments()); if (StringUtils.isNotBlank(comments)) { - ObjectMapper objectMapper = new ObjectMapper(); - HashMap<String, String> commentsMap = null; try { - commentsMap = objectMapper.readValue(comments, new TypeReference<HashMap<String, String>>(){}); + params.putAll(getSerializer().deserializeJson(comments, new TypeReference<HashMap<String, String>>(){})); } catch (Exception e1) { // Do nothing. This isn't necessarily a problem. - } - - if (commentsMap == null) { params.put("comments",comments); - } else { - params.putAll(commentsMap); } } } @@ -156,7 +148,6 @@ public abstract class PipelineEmailHandlerAbst extends WorkflowStatusEventHandle if(failed(e)) { // Get a list of parameters. Using that information, find the pipeline execution logs. WrkXnatexecutionenvironment wrkEE=null; - List<WrkXnatexecutionenvironmentParameterI> pipelineCmdLineParameters = null; HashMap<String,String> pipelineCmdLineParamsMap = Maps.newHashMap(); HashMap<String,String> pipelineParamsMap = Maps.newHashMap(); Map<String,File> attachments = Maps.newHashMap(); @@ -165,9 +156,9 @@ public abstract class PipelineEmailHandlerAbst extends WorkflowStatusEventHandle try { wrkEE = (WrkXnatexecutionenvironment) wrk.getExecutionenvironment(); } catch (ClassCastException e1){ - logger.error("Workflow Execution Environment is not an XNAT Execution Environment",e1); + _log.error("Workflow Execution Environment is not an XNAT Execution Environment", e1); } - pipelineCmdLineParameters = null==wrkEE ? new ArrayList<WrkXnatexecutionenvironmentParameterI>() : wrkEE.getParameters_parameter(); + final List<WrkXnatexecutionenvironmentParameterI> pipelineCmdLineParameters = null == wrkEE ? new ArrayList<WrkXnatexecutionenvironmentParameterI>() : wrkEE.getParameters_parameter(); // Gather input params from command line for (WrkXnatexecutionenvironmentParameterI pipelineParameter : pipelineCmdLineParameters) { @@ -193,14 +184,14 @@ public abstract class PipelineEmailHandlerAbst extends WorkflowStatusEventHandle stderr = logFileContents; } } catch (IOException e1) { - logger.error("Could not read pipeline log file "+logFileObj.toPath(), e1); + _log.error("Could not read pipeline log file " + logFileObj.toPath(), e1); } } else if (logFileObj.getName().endsWith(".xml")) { AllResolvedStepsDocument pipeParamsDoc = null; try { pipeParamsDoc = AllResolvedStepsDocument.Factory.parse(logFileObj); } catch (XmlException | IOException e1) { - logger.error("Encountered a problem parsing pipeline parameter XML for failure email.",e1); + _log.error("Encountered a problem parsing pipeline parameter XML for failure email.", e1); } if (null!=pipeParamsDoc) { @@ -262,7 +253,7 @@ public abstract class PipelineEmailHandlerAbst extends WorkflowStatusEventHandle } } catch (Throwable e1) { - logger.error("",e1); + _log.error("", e1); } } @@ -283,5 +274,13 @@ public abstract class PipelineEmailHandlerAbst extends WorkflowStatusEventHandle } return retList; } + + protected SerializerService getSerializer() { + return _serializer; + } + + private final static Logger _log = LoggerFactory.getLogger(PipelineEmailHandlerAbst.class); + + private final SerializerService _serializer; } diff --git a/src/main/java/org/nrg/xnat/helpers/prearchive/PrearcDatabase.java b/src/main/java/org/nrg/xnat/helpers/prearchive/PrearcDatabase.java index 0cbc305b2f96a0c5230b934c7966c1695ccc0559..29c48d481823db1c27a021daddde0bab95e19cc0 100644 --- a/src/main/java/org/nrg/xnat/helpers/prearchive/PrearcDatabase.java +++ b/src/main/java/org/nrg/xnat/helpers/prearchive/PrearcDatabase.java @@ -11,7 +11,6 @@ package org.nrg.xnat.helpers.prearchive; import com.fasterxml.jackson.core.JsonFactory; -import com.fasterxml.jackson.databind.ObjectMapper; import com.google.common.base.Strings; import com.google.common.collect.Maps; import org.apache.commons.collections.CollectionUtils; @@ -42,6 +41,7 @@ import org.nrg.xnat.restlet.XNATApplication; import org.nrg.xnat.restlet.actions.PrearcImporterA.PrearcSession; import org.nrg.xnat.restlet.services.Archiver; import org.nrg.xnat.turbine.utils.ArcSpecManager; +import org.nrg.xnat.utils.SerializerService; import org.nrg.xnat.utils.XnatUserProvider; import org.restlet.data.Status; import org.slf4j.Logger; @@ -61,7 +61,6 @@ import java.util.*; public final class PrearcDatabase { private static final Logger logger = LoggerFactory.getLogger(PrearcTableBuilder.class); - public static final ObjectMapper MAPPER = new ObjectMapper(new JsonFactory()); public static Connection conn; final static String table = "prearchive"; final static String tableWithSchema = PoolDBUtils.search_schema_name + "." + PrearcDatabase.table; @@ -73,6 +72,8 @@ public final class PrearcDatabase { private static String prearcPath; + private static SerializerService _serializer; + public static final String SPLIT_PETMR_SESSION_ID = "SplitPetMrSessions"; public static final String DEFAULT_SPLIT_PETMR_SESSION_FILTER = "{\n" + @@ -713,10 +714,17 @@ public final class PrearcDatabase { } else { content = script.getContent(); } - final LinkedHashMap<String, String> keys = MAPPER.readValue(content, SeriesImportFilter.MAP_TYPE_REFERENCE); + final LinkedHashMap<String, String> keys = getSerializer().deserializeJson(content, SeriesImportFilter.MAP_TYPE_REFERENCE); return DicomFilterService.buildSeriesImportFilter(keys); } + private static SerializerService getSerializer() { + if (_serializer == null) { + _serializer = XDAT.getContextService().getBean(SerializerService.class); + } + return _serializer; + } + static String getUniqueSessionLabel(final String stem, final String target, final String replacement, final String projectId, final UserI user) { String label; if (stem.contains(target.toUpperCase())) { diff --git a/src/main/java/org/nrg/xnat/initialization/XnatWebAppInitializer.java b/src/main/java/org/nrg/xnat/initialization/XnatWebAppInitializer.java index 55ca5b3e349e21300aa2e6c15056b69d28ec8518..3c4f7fcdcff0763c666d222a2bcab18d6d9ebe31 100644 --- a/src/main/java/org/nrg/xnat/initialization/XnatWebAppInitializer.java +++ b/src/main/java/org/nrg/xnat/initialization/XnatWebAppInitializer.java @@ -7,6 +7,7 @@ import org.apache.commons.lang3.StringUtils; import org.apache.turbine.Turbine; import org.nrg.framework.exceptions.NrgServiceRuntimeException; import org.nrg.framework.processors.XnatPluginBean; +import org.nrg.framework.utilities.BasicXnatResourceLocator; import org.nrg.xdat.servlet.XDATAjaxServlet; import org.nrg.xdat.servlet.XDATServlet; import org.nrg.xnat.restlet.servlet.XNATRestletServlet; @@ -15,7 +16,6 @@ import org.nrg.xnat.security.XnatSessionEventPublisher; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.core.io.Resource; -import org.springframework.core.io.support.PathMatchingResourcePatternResolver; import org.springframework.core.io.support.PropertiesLoaderUtils; import org.springframework.web.filter.DelegatingFilterProxy; import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer; @@ -114,9 +114,7 @@ public class XnatWebAppInitializer extends AbstractAnnotationConfigDispatcherSer private List<Class<?>> getPluginConfigs() { final List<Class<?>> configs = new ArrayList<>(); try { - final PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver(); - final Resource[] resources = resolver.getResources("classpath*:META-INF/xnat/**/*-plugin.properties"); - for (final Resource resource : resources) { + for (final Resource resource : BasicXnatResourceLocator.getResources("classpath*:META-INF/xnat/**/*-plugin.properties")) { final Properties properties = PropertiesLoaderUtils.loadProperties(resource); final XnatPluginBean plugin = new XnatPluginBean(properties); final Class<?> config = plugin.getConfigClass(); diff --git a/src/main/java/org/nrg/xnat/restlet/extensions/DicomSCPRestlet.java b/src/main/java/org/nrg/xnat/restlet/extensions/DicomSCPRestlet.java index 56617d3280cd269620881c0bc8bb3914b4f61906..03949ce06f1ad400bc72421110cb4507e8c6e79f 100644 --- a/src/main/java/org/nrg/xnat/restlet/extensions/DicomSCPRestlet.java +++ b/src/main/java/org/nrg/xnat/restlet/extensions/DicomSCPRestlet.java @@ -11,7 +11,6 @@ package org.nrg.xnat.restlet.extensions; -import com.fasterxml.jackson.databind.ObjectMapper; import com.google.common.base.Joiner; import org.apache.commons.lang3.StringUtils; import org.nrg.dcm.DicomSCPManager; @@ -42,10 +41,9 @@ public class DicomSCPRestlet extends SecureResource { private static final List<String> ALLOWED_ACTIONS = new ArrayList<>(Arrays.asList("status", "start", "stop", "enable", "disable")); private static final Logger _log = LoggerFactory.getLogger(DicomSCPRestlet.class); - private static final ObjectMapper _mapper = new ObjectMapper(); - private final DicomSCPManager _dicomSCPManager; - private final String _scpId; - private final String _action; + private final DicomSCPManager _dicomSCPManager; + private final String _scpId; + private final String _action; public DicomSCPRestlet(Context context, Request request, Response response) throws ResourceException { super(context, request, response); @@ -86,11 +84,11 @@ public class DicomSCPRestlet extends SecureResource { try { if (Method.DELETE.equals(getRequest().getMethod()) || (StringUtils.isNotBlank(_action) && _action.equalsIgnoreCase("status"))) { - return new StringRepresentation(_mapper.writeValueAsString(_dicomSCPManager.areDicomSCPsStarted())); + return new StringRepresentation(getSerializer().toJson(_dicomSCPManager.areDicomSCPsStarted())); } else if (StringUtils.isBlank(_scpId)) { - return new StringRepresentation(_mapper.writeValueAsString(_dicomSCPManager.getDicomSCPInstances())); + return new StringRepresentation(getSerializer().toJson(_dicomSCPManager.getDicomSCPInstances())); } else { - return new StringRepresentation(DicomSCPInstance.serialize(_dicomSCPManager.getDicomSCPInstance(_scpId))); + return new StringRepresentation(getSerializer().toJson(_dicomSCPManager.getDicomSCPInstance(_scpId))); } } catch (IOException e) { throw new ResourceException(Status.SERVER_ERROR_INTERNAL, "An error occurred marshaling the DICOM SCP statuses", e); @@ -110,8 +108,8 @@ public class DicomSCPRestlet extends SecureResource { getResponse().setStatus(Status.CLIENT_ERROR_BAD_REQUEST, "You should only POST to this URL to create a new DICOM SCP instance. The DICOM SCP ID " + _scpId + " is invalid in this context."); } try { - final String serialized = getRequest().getEntity().getText(); - final DicomSCPInstance instance = DicomSCPInstance.deserialize(serialized); + final String serialized = getRequest().getEntity().getText(); + final DicomSCPInstance instance = getSerializer().deserializeJson(serialized, DicomSCPInstance.class); _dicomSCPManager.create(instance); } catch (IOException e) { getResponse().setStatus(Status.SERVER_ERROR_INTERNAL, e, "An error occurred trying to retrieve the body text of the PUT request."); diff --git a/src/main/java/org/nrg/xnat/restlet/extensions/PipelineDetailsRestlet.java b/src/main/java/org/nrg/xnat/restlet/extensions/PipelineDetailsRestlet.java index 30118abd40e2820e295d66db9f1bec63167c4098..117eb76a178e0ad5db3717ecae704b808e157dc7 100644 --- a/src/main/java/org/nrg/xnat/restlet/extensions/PipelineDetailsRestlet.java +++ b/src/main/java/org/nrg/xnat/restlet/extensions/PipelineDetailsRestlet.java @@ -10,7 +10,6 @@ */ package org.nrg.xnat.restlet.extensions; -import com.fasterxml.jackson.databind.ObjectMapper; import org.apache.commons.lang.StringUtils; import org.nrg.pipeline.PipelineRepositoryManager; import org.nrg.pipeline.utils.PipelineFileUtils; @@ -43,15 +42,13 @@ import java.util.HashMap; import java.util.List; import java.util.Map; - - @XnatRestlet({"/projects/{PROJECT_ID}/pipelines/{PIPELINE_NAME}", "/projects/{PROJECT_ID}/pipelines/{PIPELINE_NAME}/details"}) public class PipelineDetailsRestlet extends SecureResource { public static final String PARAM_PROJECT_ID = "PROJECT_ID"; public static final String PARAM_PIPELINE_NAME = "PIPELINE_NAME"; - private final String _projectId; - private final String _pipelineName; + private final String _projectId; + private final String _pipelineName; private static final Logger _log = LoggerFactory.getLogger(PipelineDetailsRestlet.class); @@ -79,8 +76,7 @@ public class PipelineDetailsRestlet extends SecureResource { Map<String,Object> pipelineDetails = getPipelineDetailsMap(); // Make a json object from the pipelineDetails map - ObjectMapper mapper = new ObjectMapper(); - String json = mapper.writeValueAsString(pipelineDetails); + String json = getSerializer().toJson(pipelineDetails); return new StringRepresentation(json, MediaType.APPLICATION_JSON); } catch (Exception exception) { @@ -119,7 +115,7 @@ public class PipelineDetailsRestlet extends SecureResource { } // Build hash map - Map<String,Object> pipelineDetails = new HashMap<String,Object>(); + Map<String,Object> pipelineDetails = new HashMap<>(); // Basic info pipelineDetails.put("path",pipelineDescriptorPath); @@ -155,9 +151,9 @@ public class PipelineDetailsRestlet extends SecureResource { pipelineDetails.put("publications",doc.getPublications().getPublicationArray()); } if (doc.isSetAuthors()) { - List<Map<String,String>> authorInfoList = new ArrayList<Map<String,String>>(); + List<Map<String,String>> authorInfoList = new ArrayList<>(); for (Author aAuthor : doc.getAuthors().getAuthorArray()) { - Map<String,String> authorInfo = new HashMap<String,String>(); + Map<String,String> authorInfo = new HashMap<>(); if (StringUtils.isNotBlank(aAuthor.getFirstname())) { authorInfo.put("firstname", aAuthor.getFirstname()); } @@ -183,9 +179,9 @@ public class PipelineDetailsRestlet extends SecureResource { } // Step ids and descriptions - List<Map<String,String>> stepInfoList = new ArrayList<Map<String,String>>(); + List<Map<String,String>> stepInfoList = new ArrayList<>(); for (Step aStep : pipelineData.getSteps().getStepArray()) { - Map<String,String> stepInfo = new HashMap<String,String>(); + Map<String,String> stepInfo = new HashMap<>(); stepInfo.put("id",aStep.getId()); if (StringUtils.isNotBlank(aStep.getDescription())) { @@ -196,11 +192,11 @@ public class PipelineDetailsRestlet extends SecureResource { pipelineDetails.put("steps",stepInfoList); // Project-level param defaults - List<Map<String,Object>> paramInfoList = new ArrayList<Map<String,Object>>(); + List<Map<String,Object>> paramInfoList = new ArrayList<>(); for (ArcPipelineparameterdataI aParamI : projectPipelineData.getParameters_parameter()) { ArcPipelineparameterdata aParam = (ArcPipelineparameterdata) aParamI; - Map<String,Object> paramInfo = new HashMap<String,Object>(); + Map<String,Object> paramInfo = new HashMap<>(); paramInfo.put("name",aParam.getName()); if (StringUtils.isNotBlank(aParam.getDescription())) { paramInfo.put("description", aParam.getDescription()); @@ -209,7 +205,7 @@ public class PipelineDetailsRestlet extends SecureResource { String csv = aParam.getCsvvalues(); String schemaLink = aParam.getSchemalink(); if (StringUtils.isNotBlank(schemaLink) || StringUtils.isNotBlank(csv)) { - Map<String,String> paramValues = new HashMap<String,String>(); + Map<String,String> paramValues = new HashMap<>(); if (StringUtils.isNotBlank(schemaLink)) { paramValues.put("schemaLink",schemaLink); } else { @@ -223,5 +219,4 @@ public class PipelineDetailsRestlet extends SecureResource { return pipelineDetails; } - } diff --git a/src/main/java/org/nrg/xnat/restlet/extensions/UserSettingsRestlet.java b/src/main/java/org/nrg/xnat/restlet/extensions/UserSettingsRestlet.java index 84f4b3bf53c99907be68953de22b708aca9716f0..c0e4474383c9b4cebea78fe556b7585afe51669d 100644 --- a/src/main/java/org/nrg/xnat/restlet/extensions/UserSettingsRestlet.java +++ b/src/main/java/org/nrg/xnat/restlet/extensions/UserSettingsRestlet.java @@ -12,7 +12,6 @@ package org.nrg.xnat.restlet.extensions; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -49,8 +48,8 @@ import java.util.*; @XnatRestlet({"/user", "/user/{USER_ID}", "/user/actions/{ACTION}", "/user/actions/{USER_ID}/{ACTION}"}) public class UserSettingsRestlet extends SecureResource { - public static final String PARAM_USER_ID = "USER_ID"; - public static final String PARAM_ACTION = "ACTION"; + private static final String PARAM_USER_ID = "USER_ID"; + private static final String PARAM_ACTION = "ACTION"; public UserSettingsRestlet(Context context, Request request, Response response) throws ResourceException { super(context, request, response); @@ -114,7 +113,7 @@ public class UserSettingsRestlet extends SecureResource { try { if (StringUtils.isBlank(_userId)) { Collection<String> logins = Users.getAllLogins(); - return new StringRepresentation(_isJsonRequested ? _serializer.writeValueAsString(logins) : createLoginListXml(logins)); + return new StringRepresentation(_isJsonRequested ? getSerializer().toJson(logins) : createLoginListXml(logins)); } UserI requestedUser = Users.getUser(_userId); @@ -343,7 +342,7 @@ public class UserSettingsRestlet extends SecureResource { private JsonNode getJsonNode() throws IOException { if (_node == null) { - _node = _serializer.readValue(_payload, JsonNode.class); + _node = getSerializer().deserializeJson(_payload); } return _node; } @@ -411,7 +410,7 @@ public class UserSettingsRestlet extends SecureResource { return new StringRepresentation(output.toString()); } - enum UserAction { + private enum UserAction { Reset, ResetEmailRequests; @@ -437,7 +436,7 @@ public class UserSettingsRestlet extends SecureResource { private static Map<String, UserAction> _actions = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); } - enum UserProperty { + private enum UserProperty { email, enabled, firstname, @@ -458,11 +457,6 @@ public class UserSettingsRestlet extends SecureResource { } private static final Log _log = LogFactory.getLog(UserSettingsRestlet.class); - private static final ObjectMapper _serializer = new ObjectMapper() {{ - // Migration: Get the mix-in annotations working for XDATUser. - // getSerializationConfig().addMixInAnnotations(UserI.class, IgnoreSetValueMixIn.class); - // getSerializationConfig().addMixInAnnotations(GenericWrapperField.class, IgnoreSetValueMixIn.class); - }}; private static final Map<UserProperty, String> XPATH_EXPRESSIONS = new HashMap<UserProperty, String>() {{ put(UserProperty.userAuths, "//userAuths/userAuth"); put(UserProperty.authId, "authId"); diff --git a/src/main/java/org/nrg/xnat/restlet/resources/AutomationResource.java b/src/main/java/org/nrg/xnat/restlet/resources/AutomationResource.java index 77d98174a1fcb1d5b7c52c04c55c8eccfad4c389..c0d62b297e404d0fc4dae92f524856a2d6cb75c1 100644 --- a/src/main/java/org/nrg/xnat/restlet/resources/AutomationResource.java +++ b/src/main/java/org/nrg/xnat/restlet/resources/AutomationResource.java @@ -1,7 +1,9 @@ package org.nrg.xnat.restlet.resources; import org.apache.commons.lang.StringUtils; -import com.fasterxml.jackson.databind.ObjectMapper; +import org.apache.http.NameValuePair; +import org.apache.http.client.utils.URLEncodedUtils; +import org.nrg.action.ServerException; import org.nrg.framework.constants.Scope; import org.nrg.xdat.om.XnatProjectdata; import org.nrg.xft.XFTTable; @@ -11,19 +13,27 @@ import org.nrg.xft.event.persist.PersistentWorkflowI; import org.nrg.xft.event.persist.PersistentWorkflowUtils; import org.nrg.xnat.utils.WorkflowUtils; import org.restlet.Context; +import org.restlet.data.MediaType; import org.restlet.data.Request; import org.restlet.data.Response; import org.restlet.data.Status; +import org.restlet.resource.Representation; import org.restlet.resource.ResourceException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.io.IOException; +import java.nio.charset.Charset; import java.util.HashMap; +import java.util.List; import java.util.Map; +import java.util.Properties; +@SuppressWarnings("WeakerAccess") public abstract class AutomationResource extends SecureResource { - public static final String SITE_SCOPE = Scope.encode(Scope.Site, ""); + static final String SITE_SCOPE = Scope.encode(Scope.Site, ""); + private static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8"); public AutomationResource(final Context context, final Request request, final Response response) throws ResourceException { super(context, request, response); @@ -152,6 +162,29 @@ public abstract class AutomationResource extends SecureResource { return buffer.toString(); } + protected Properties decodeProperties(final Representation entity, final MediaType mediaType) throws ServerException { + final Properties properties; + if (mediaType.equals(MediaType.APPLICATION_WWW_FORM)) { + try { + final List<NameValuePair> formMap = URLEncodedUtils.parse(entity.getText(), DEFAULT_CHARSET); + properties = new Properties(); + for (final NameValuePair entry : formMap) { + properties.setProperty(entry.getName(), entry.getValue()); + } + } catch (IOException e) { + throw new ServerException(Status.SERVER_ERROR_INTERNAL, "An error occurred trying to read the submitted form body.", e); + } + } else { + try { + final String text = entity.getText(); + properties = getSerializer().deserializeJson(text, Properties.class); + } catch (IOException e) { + throw new ServerException(Status.SERVER_ERROR_INTERNAL, "An error occurred processing the script properties", e); + } + } + return properties; + } + private Map<String, String> validateEntityId(final String entityId) throws ResourceException { if (getScope() == null) { return null; @@ -191,8 +224,6 @@ public abstract class AutomationResource extends SecureResource { } } - protected static final ObjectMapper MAPPER = new ObjectMapper(); - private static final Logger _log = LoggerFactory.getLogger(AutomationResource.class); private static final String ENTITY_ID = "ENTITY_ID"; private static final String PROJECT_ID = "PROJECT_ID"; @@ -201,6 +232,7 @@ public abstract class AutomationResource extends SecureResource { private static final String KEY_PROJECTID = "projectId"; private Scope _scope; private boolean _hasProjectId; + private String _projectId; private final String _path; diff --git a/src/main/java/org/nrg/xnat/restlet/resources/EventResource.java b/src/main/java/org/nrg/xnat/restlet/resources/EventResource.java index 14b078f347275d05ac8c8c49e0468882f04e484e..928689f8d727f946d1340afd128dcad2edb07657 100644 --- a/src/main/java/org/nrg/xnat/restlet/resources/EventResource.java +++ b/src/main/java/org/nrg/xnat/restlet/resources/EventResource.java @@ -35,8 +35,8 @@ import java.util.Properties; public class EventResource extends AutomationResource { - public static final String PROPERTY_EVENT_ID = "event_id"; - public static final String PROPERTY_EVENT_LABEL = "event_label"; + private static final String PROPERTY_EVENT_ID = "event_id"; + private static final String PROPERTY_EVENT_LABEL = "event_label"; public EventResource(Context context, Request request, Response response) throws ResourceException { super(context, request, response); @@ -142,7 +142,7 @@ public class EventResource extends AutomationResource { final Map<String, String> event = new HashMap<>(); event.put(PROPERTY_EVENT_ID, getResourceId()); event.put(PROPERTY_EVENT_LABEL, label); - return new StringRepresentation(MAPPER.writeValueAsString(event), mediaType); + return new StringRepresentation(getSerializer().toJson(event), mediaType); } } else { // They're asking for list of existing script events, so give them that. @@ -213,7 +213,7 @@ public class EventResource extends AutomationResource { } else { try { final String text = entity.getText(); - _properties.putAll(MAPPER.readValue(text, Properties.class)); + _properties.putAll(getSerializer().deserializeJson(text, Properties.class)); } catch (IOException e) { throw new ResourceException(Status.SERVER_ERROR_INTERNAL, "An error occurred processing the script properties", e); } diff --git a/src/main/java/org/nrg/xnat/restlet/resources/ProjectPipelineListResource.java b/src/main/java/org/nrg/xnat/restlet/resources/ProjectPipelineListResource.java index b81a49a931033297d58a757f4986fa6f6e83b689..d39440c5619a0955326a55f8cc2991b89697e070 100644 --- a/src/main/java/org/nrg/xnat/restlet/resources/ProjectPipelineListResource.java +++ b/src/main/java/org/nrg/xnat/restlet/resources/ProjectPipelineListResource.java @@ -87,7 +87,7 @@ public class ProjectPipelineListResource extends SecureResource { } } //Send a 200 OK message back - //getResponse().setStatus(Status.SUCCESS_OK,"Pipeline has been removed from project " + proj.getId()); + //getResponse().setStatus(Status.SUCCESS_OK,"Pipeline has been removed from project " + _project.getId()); } }catch(Exception e) { e.printStackTrace(); diff --git a/src/main/java/org/nrg/xnat/restlet/resources/ProjectUserListResource.java b/src/main/java/org/nrg/xnat/restlet/resources/ProjectUserListResource.java index a36eb43908a51030bfe1a4d21dbfc5f27184aa2f..12a5322df1983e49ea4e95d1d9b5279a0813a7ba 100644 --- a/src/main/java/org/nrg/xnat/restlet/resources/ProjectUserListResource.java +++ b/src/main/java/org/nrg/xnat/restlet/resources/ProjectUserListResource.java @@ -17,16 +17,15 @@ import org.nrg.xdat.XDAT; import org.nrg.xdat.om.XnatProjectdata; import org.nrg.xdat.security.helpers.Permissions; import org.nrg.xdat.security.helpers.Roles; -import org.nrg.xdat.security.helpers.UserHelper; import org.nrg.xft.XFTTable; import org.nrg.xft.exception.DBPoolException; -import org.nrg.xft.exception.InvalidItemException; import org.restlet.Context; import org.restlet.data.MediaType; import org.restlet.data.Request; import org.restlet.data.Response; import org.restlet.data.Status; import org.restlet.resource.Representation; +import org.restlet.resource.ResourceException; import org.restlet.resource.Variant; import java.io.IOException; @@ -35,51 +34,50 @@ import java.util.Hashtable; import java.util.List; public class ProjectUserListResource extends SecureResource { - XFTTable table = null; - XnatProjectdata proj = null; - boolean displayHiddenUsers = false; + private final XnatProjectdata _project; + private final boolean _displayHiddenUsers; public ProjectUserListResource(Context context, Request request, Response response) throws Exception { super(context, request, response); + setReadable(true); + setModifiable(false); + getVariants().add(new Variant(MediaType.APPLICATION_JSON)); getVariants().add(new Variant(MediaType.TEXT_HTML)); getVariants().add(new Variant(MediaType.TEXT_XML)); final String projectId = (String) getParameter(request, "PROJECT_ID"); - if (projectId != null) { - proj = XnatProjectdata.getProjectByIDorAlias(projectId, user, false); - } - if (proj == null) { + _project = org.apache.commons.lang3.StringUtils.isNotBlank(projectId) ? XnatProjectdata.getProjectByIDorAlias(projectId, user, false) : null; + if (_project == null) { + _displayHiddenUsers = false; getResponse().setStatus(Status.CLIENT_ERROR_NOT_FOUND, "The project ID " + projectId + " does not appear to be a valid project ID. Please verify your information."); } else { - if (!(Roles.isSiteAdmin(user) || Permissions.canEdit(user, proj) || isWhitelisted(projectId))) { - logger.error("Unauthorized Access to project-level user resources. User: " + userName); - getResponse().setStatus(Status.CLIENT_ERROR_FORBIDDEN, "Access Denied: Only project owners and site managers can access user resources."); - } - displayHiddenUsers = Boolean.parseBoolean((String) getParameter(request, "DISPLAY_HIDDEN_USERS")); + if (!(Roles.isSiteAdmin(user) || Permissions.canEdit(user, _project) || isWhitelisted(projectId))) { + logger.error("Unauthorized Access to project-level user resources. User: " + userName); + getResponse().setStatus(Status.CLIENT_ERROR_FORBIDDEN, "Access Denied: Only project owners and site managers can access user resources."); } + _displayHiddenUsers = Boolean.parseBoolean((String) getParameter(request, "DISPLAY_HIDDEN_USERS")); } - - @Override - public boolean allowGet() { - return true; } @Override - public Representation represent(Variant variant) { + public Representation represent(Variant variant) throws ResourceException { - if (proj != null) { - final StringBuilder query = new StringBuilder("SELECT g.id AS \"GROUP_ID\", displayname,login,firstname,lastname,email FROM xdat_userGroup g RIGHT JOIN xdat_user_Groupid map ON g.id=map.groupid RIGHT JOIN xdat_user u ON map.groups_groupid_xdat_user_xdat_user_id=u.xdat_user_id WHERE tag='").append(proj.getId()).append("' "); + final XFTTable table; + if (_project != null) { + final StringBuilder query = new StringBuilder("SELECT g.id AS \"GROUP_ID\", displayname,login,firstname,lastname,email FROM xdat_userGroup g RIGHT JOIN xdat_user_Groupid map ON g.id=map.groupid RIGHT JOIN xdat_user u ON map.groups_groupid_xdat_user_xdat_user_id=u.xdat_user_id WHERE tag='").append(_project.getId()).append("' "); try { - if(!displayHiddenUsers){ + if(!_displayHiddenUsers){ query.append(" and enabled = 1 "); } query.append(" ORDER BY g.id DESC;"); table = XFTTable.Execute(query.toString(), user.getDBName(), user.getLogin()); } catch (SQLException | DBPoolException e) { - logger.warn("An error occurred trying to run the following query: " + query.toString(), e); + throw new ResourceException(Status.SERVER_ERROR_INTERNAL, "An error occurred trying to run the following query: " + query.toString(), e); } + } else { + table = null; } Hashtable<String, Object> params = new Hashtable<>(); @@ -92,12 +90,12 @@ public class ProjectUserListResource extends SecureResource { } public boolean isWhitelisted() { - final String projectId = (String) proj.getItem().getProps().get("id"); + final String projectId = (String) _project.getItem().getProps().get("id"); final ConfigService configService = XDAT.getConfigService(); final String config = configService.getConfigContents("user-resource-whitelist", "whitelist.json", Scope.Project, projectId); if (!StringUtils.isBlank(config)) { try { - List<String> projectUserResourceWhitelist = OBJECT_MAPPER.readValue(config, TYPE_REFERENCE_LIST_STRING); + List<String> projectUserResourceWhitelist = getSerializer().deserializeJson(config, TYPE_REFERENCE_LIST_STRING); if (projectUserResourceWhitelist != null) { return projectUserResourceWhitelist.contains(user.getUsername()); } diff --git a/src/main/java/org/nrg/xnat/restlet/resources/ScriptResource.java b/src/main/java/org/nrg/xnat/restlet/resources/ScriptResource.java index 6407ba30c303134227511a11a99ca53d64f109ab..92905f33715529813799ac44dc1fa818d0d313e7 100644 --- a/src/main/java/org/nrg/xnat/restlet/resources/ScriptResource.java +++ b/src/main/java/org/nrg/xnat/restlet/resources/ScriptResource.java @@ -1,8 +1,6 @@ package org.nrg.xnat.restlet.resources; import org.apache.commons.lang.StringUtils; -import org.apache.http.NameValuePair; -import org.apache.http.client.utils.URLEncodedUtils; import org.nrg.action.ClientException; import org.nrg.action.ServerException; import org.nrg.automation.entities.Script; @@ -23,7 +21,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.IOException; -import java.nio.charset.Charset; import java.util.ArrayList; import java.util.Hashtable; import java.util.List; @@ -95,7 +92,7 @@ public class ScriptResource extends AutomationResource { try { if (StringUtils.isNotBlank(_version)) { //They're requesting a specific version of a specific script - return new StringRepresentation(MAPPER.writeValueAsString(_scriptService.getVersion(_scriptId, _version)), mediaType); + return new StringRepresentation(toJson(_scriptService.getVersion(_scriptId, _version)), mediaType); } else { // They're requesting a specific script, so return that to them. @@ -110,7 +107,7 @@ public class ScriptResource extends AutomationResource { // have to check if it's null, or else it will return a StringRepresentation containing the word null instead of a 404 if (script != null) { - return new StringRepresentation(MAPPER.writeValueAsString(script), mediaType); + return new StringRepresentation(toJson(script), mediaType); } else { return null; } @@ -200,25 +197,7 @@ public class ScriptResource extends AutomationResource { throw new ClientException(Status.CLIENT_ERROR_UNSUPPORTED_MEDIA_TYPE, "This function currently only supports " + MediaType.APPLICATION_WWW_FORM + " and " + MediaType.APPLICATION_JSON); } - final Properties properties; - if (mediaType.equals(MediaType.APPLICATION_WWW_FORM)) { - try { - final List<NameValuePair> formMap = URLEncodedUtils.parse(entity.getText(), DEFAULT_CHARSET); - properties = new Properties(); - for (final NameValuePair entry : formMap) { - properties.setProperty(entry.getName(), entry.getValue()); - } - } catch (IOException e) { - throw new ServerException(Status.SERVER_ERROR_INTERNAL, "An error occurred trying to read the submitted form body.", e); - } - } else { - try { - final String text = entity.getText(); - properties = MAPPER.readValue(text, Properties.class); - } catch (IOException e) { - throw new ServerException(Status.SERVER_ERROR_INTERNAL, "An error occurred processing the script properties", e); - } - } + final Properties properties = decodeProperties(entity, mediaType); if (properties.containsKey("scriptId")) { properties.remove("scriptId"); @@ -253,7 +232,6 @@ public class ScriptResource extends AutomationResource { private static final String SCRIPT_ID = "SCRIPT_ID"; private static final String VERSION = "VERSION"; - private static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8"); private final ScriptService _scriptService; private final ScriptRunnerService _runnerService; diff --git a/src/main/java/org/nrg/xnat/restlet/resources/ScriptRunnerResource.java b/src/main/java/org/nrg/xnat/restlet/resources/ScriptRunnerResource.java index 18258397708b816d0b82d8bce965d1b449746d94..31c458d3f9c1ab0c9ccea2fac9adc76cecaf1556 100644 --- a/src/main/java/org/nrg/xnat/restlet/resources/ScriptRunnerResource.java +++ b/src/main/java/org/nrg/xnat/restlet/resources/ScriptRunnerResource.java @@ -1,7 +1,5 @@ package org.nrg.xnat.restlet.resources; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; import org.apache.commons.lang.StringUtils; import org.nrg.automation.runners.ScriptRunner; import org.nrg.automation.services.ScriptRunnerService; @@ -58,13 +56,13 @@ public class ScriptRunnerResource extends AutomationResource { if (!_runnerService.hasRunner(_language)) { throw new ResourceException(Status.CLIENT_ERROR_NOT_FOUND, String.format("No script runner found for %s", _language)); } - final String json = _serializer.writeValueAsString(_runnerService.getRunner(_language)); + final String json = toJson(_runnerService.getRunner(_language)); return new StringRepresentation(json, mediaType); } else { final List<String> runners = _runnerService.getRunners(); - return new StringRepresentation(_serializer.writeValueAsString(runners), mediaType); + return new StringRepresentation(toJson(runners), mediaType); } - } catch (JsonProcessingException e) { + } catch (java.io.IOException e) { throw new ResourceException(Status.SERVER_ERROR_INTERNAL, "There was an error processing the script runners to JSON", e); } } @@ -73,7 +71,6 @@ public class ScriptRunnerResource extends AutomationResource { private static final String LANGUAGE = "LANGUAGE"; - private static final ObjectMapper _serializer = new ObjectMapper(); private final ScriptRunnerService _runnerService; private final String _language; } diff --git a/src/main/java/org/nrg/xnat/restlet/resources/ScriptTriggerResource.java b/src/main/java/org/nrg/xnat/restlet/resources/ScriptTriggerResource.java index 1509ea080b85ebd8dc578ab7b2f54911a8e84254..4564240f0462576250900051802ada2ec4df64a4 100644 --- a/src/main/java/org/nrg/xnat/restlet/resources/ScriptTriggerResource.java +++ b/src/main/java/org/nrg/xnat/restlet/resources/ScriptTriggerResource.java @@ -1,8 +1,6 @@ package org.nrg.xnat.restlet.resources; import org.apache.commons.lang.StringUtils; -import org.apache.http.NameValuePair; -import org.apache.http.client.utils.URLEncodedUtils; import org.nrg.action.ClientException; import org.nrg.action.ServerException; import org.nrg.automation.entities.ScriptTrigger; @@ -22,7 +20,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.IOException; -import java.nio.charset.Charset; import java.util.*; public class ScriptTriggerResource extends AutomationResource { @@ -124,7 +121,7 @@ public class ScriptTriggerResource extends AutomationResource { if (_trigger != null) { try { // They're requesting a specific trigger, so return that to them. - return new StringRepresentation(MAPPER.writeValueAsString(mapTrigger(_trigger)), mediaType); + return new StringRepresentation(toJson(mapTrigger(_trigger)), mediaType); } catch (IOException e) { throw new ResourceException(Status.SERVER_ERROR_INTERNAL, "An error occurred marshalling the script trigger data to JSON", e); } @@ -245,25 +242,7 @@ public class ScriptTriggerResource extends AutomationResource { throw new ClientException(Status.CLIENT_ERROR_UNSUPPORTED_MEDIA_TYPE, "This function currently only supports " + MediaType.APPLICATION_WWW_FORM + " and " + MediaType.APPLICATION_JSON); } - final Properties properties; - if (mediaType.equals(MediaType.APPLICATION_WWW_FORM)) { - try { - final List<NameValuePair> formMap = URLEncodedUtils.parse(entity.getText(), DEFAULT_CHARSET); - properties = new Properties(); - for (final NameValuePair entry : formMap) { - properties.setProperty(entry.getName(), entry.getValue()); - } - } catch (IOException e) { - throw new ServerException(Status.SERVER_ERROR_INTERNAL, "An error occurred trying to read the submitted form body.", e); - } - } else { - try { - final String text = entity.getText(); - properties = MAPPER.readValue(text, Properties.class); - } catch (IOException e) { - throw new ServerException(Status.SERVER_ERROR_INTERNAL, "An error occurred processing the script properties", e); - } - } + final Properties properties = decodeProperties(entity, mediaType); // TODO: These remove definitions of scope, entity ID, and script ID that may be passed in on the API call. // TODO: We may consider throwing an exception if something in the body parameters contradicts the URI @@ -364,7 +343,6 @@ public class ScriptTriggerResource extends AutomationResource { private static final String EVENT_ID = "EVENT_ID"; private static final String TRIGGER_ID = "TRIGGER_ID"; - private static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8"); private final EventService _eventService; private final ScriptTriggerService _scriptTriggerService; diff --git a/src/main/java/org/nrg/xnat/restlet/resources/ScriptTriggerTemplateResource.java b/src/main/java/org/nrg/xnat/restlet/resources/ScriptTriggerTemplateResource.java index a4318cad192091527e8b94431a87d13b448e604b..4ebd8205034dd6b4f209daeebab30585696fb367 100644 --- a/src/main/java/org/nrg/xnat/restlet/resources/ScriptTriggerTemplateResource.java +++ b/src/main/java/org/nrg/xnat/restlet/resources/ScriptTriggerTemplateResource.java @@ -2,7 +2,6 @@ package org.nrg.xnat.restlet.resources; import com.google.common.base.Joiner; import org.apache.commons.lang.StringUtils; -import com.fasterxml.jackson.databind.ObjectMapper; import org.nrg.action.ClientException; import org.nrg.automation.entities.ScriptTrigger; import org.nrg.automation.entities.ScriptTriggerTemplate; @@ -224,7 +223,7 @@ public class ScriptTriggerTemplateResource extends AutomationResource { } else if (entity.getMediaType().equals(MediaType.APPLICATION_JSON)) { try { final String text = entity.getText(); - found = MAPPER.readValue(text, ScriptTriggerTemplate.class); + found = getSerializer().deserializeJson(text, ScriptTriggerTemplate.class); } catch (IOException e) { throw new ClientException(Status.SERVER_ERROR_INTERNAL, "An error occurred processing the script properties", e); } @@ -310,6 +309,4 @@ public class ScriptTriggerTemplateResource extends AutomationResource { } return persisted.size() > 0 ? persisted : null; } - - private static final ObjectMapper MAPPER = new ObjectMapper(); } diff --git a/src/main/java/org/nrg/xnat/restlet/resources/ScriptVersionsResource.java b/src/main/java/org/nrg/xnat/restlet/resources/ScriptVersionsResource.java index 4d62c1824fc4e387817d95eae1e6bce9da1f23b0..b017b3a32cf3b26115a0f0a71550b293427a9080 100644 --- a/src/main/java/org/nrg/xnat/restlet/resources/ScriptVersionsResource.java +++ b/src/main/java/org/nrg/xnat/restlet/resources/ScriptVersionsResource.java @@ -21,7 +21,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.IOException; -import java.nio.charset.Charset; import java.util.ArrayList; import java.util.Hashtable; import java.util.List; @@ -88,7 +87,7 @@ public class ScriptVersionsResource extends AutomationResource { // have to check if it's null, or else it will return a StringRepresentation containing the word null instead of a 404 if (versions != null) { - return new StringRepresentation(MAPPER.writeValueAsString(versions), mediaType); + return new StringRepresentation(toJson(versions), mediaType); } else { return null; } @@ -136,7 +135,6 @@ public class ScriptVersionsResource extends AutomationResource { private static final Logger _log = LoggerFactory.getLogger(ScriptVersionsResource.class); private static final String SCRIPT_ID = "SCRIPT_ID"; - private static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8"); private final ScriptService _scriptService; private final ScriptRunnerService _runnerService; diff --git a/src/main/java/org/nrg/xnat/restlet/resources/SecureResource.java b/src/main/java/org/nrg/xnat/restlet/resources/SecureResource.java index 5fc9baa17314e52919d7972b02245a4b34bb0df4..f2d88bc8b39c2d7980a3e2cf40724757ce9aa064 100644 --- a/src/main/java/org/nrg/xnat/restlet/resources/SecureResource.java +++ b/src/main/java/org/nrg/xnat/restlet/resources/SecureResource.java @@ -11,7 +11,6 @@ package org.nrg.xnat.restlet.resources; import com.fasterxml.jackson.core.type.TypeReference; -import com.fasterxml.jackson.databind.ObjectMapper; import com.google.common.collect.Maps; import com.noelios.restlet.http.HttpConstants; import org.apache.commons.beanutils.BeanUtils; @@ -67,6 +66,7 @@ import org.nrg.xnat.restlet.representations.*; import org.nrg.xnat.restlet.util.FileWriterWrapperI; import org.nrg.xnat.restlet.util.RequestUtil; import org.nrg.xnat.turbine.utils.ArchivableItem; +import org.nrg.xnat.utils.SerializerService; import org.nrg.xnat.utils.WorkflowUtils; import org.restlet.Context; import org.restlet.data.*; @@ -137,9 +137,17 @@ public abstract class SecureResource extends Resource { protected String csrfToken = null; + private final SerializerService _serializer; + public SecureResource(Context context, Request request, Response response) { super(context, request, response); + _serializer = XDAT.getContextService().getBean(SerializerService.class); + if (null == _serializer) { + getResponse().setStatus(Status.CLIENT_ERROR_FAILED_DEPENDENCY, "Serializer service was not properly initialized."); + throw new NrgServiceRuntimeException("ERROR: Serializer service was not properly initialized."); + } + requested_format = getQueryVariable("format"); // expects that the user exists in the session (either via traditional @@ -247,6 +255,9 @@ public abstract class SecureResource extends Resource { return convertFormToMap(getQueryVariableForm()); } + protected SerializerService getSerializer() { + return _serializer; + } private Form _body; private MediaType _mediaType; @@ -519,6 +530,10 @@ public abstract class SecureResource extends Resource { } } + protected <T> String toJson(final T instance) throws IOException { + return getSerializer().toJson(instance); + } + public interface ItemHandlerI { String getHandlerString(); @@ -1522,7 +1537,7 @@ public abstract class SecureResource extends Resource { } try { - List<String> userResourceWhitelist = OBJECT_MAPPER.readValue(config, TYPE_REFERENCE_LIST_STRING); + List<String> userResourceWhitelist = getSerializer().deserializeJson(config, TYPE_REFERENCE_LIST_STRING); if (userResourceWhitelist != null) { return userResourceWhitelist.contains(user.getUsername()); } @@ -1534,9 +1549,7 @@ public abstract class SecureResource extends Resource { return false; } - protected final static TypeReference<ArrayList<String>> TYPE_REFERENCE_LIST_STRING = new TypeReference<ArrayList<String>>() { - }; - protected final static ObjectMapper OBJECT_MAPPER = new ObjectMapper(); + protected final static TypeReference<ArrayList<String>> TYPE_REFERENCE_LIST_STRING = new TypeReference<ArrayList<String>>() {}; private static Map<String, List<FilteredResourceHandlerI>> handlers = Maps.newConcurrentMap(); diff --git a/src/main/java/org/nrg/xnat/restlet/services/AliasTokenRestlet.java b/src/main/java/org/nrg/xnat/restlet/services/AliasTokenRestlet.java index 042ce9e13f76650b78b650e4bd65dbbdb4e8d939..fd347ffa82d06f67cfbc5e2ccabc923182bf9d86 100644 --- a/src/main/java/org/nrg/xnat/restlet/services/AliasTokenRestlet.java +++ b/src/main/java/org/nrg/xnat/restlet/services/AliasTokenRestlet.java @@ -11,14 +11,13 @@ package org.nrg.xnat.restlet.services; import com.google.common.collect.Maps; - import org.apache.commons.lang.StringUtils; -import com.fasterxml.jackson.databind.ObjectMapper; import org.nrg.xdat.XDAT; import org.nrg.xdat.entities.AliasToken; import org.nrg.xdat.security.helpers.Roles; import org.nrg.xdat.services.AliasTokenService; import org.nrg.xnat.restlet.resources.SecureResource; +import org.nrg.xnat.utils.SerializerService; import org.restlet.Context; import org.restlet.data.MediaType; import org.restlet.data.Request; @@ -34,15 +33,15 @@ import java.util.HashMap; import java.util.Map; public class AliasTokenRestlet extends SecureResource { - public static final String PARAM_OPERATION = "OPERATION"; - public static final String PARAM_USERNAME = "USERNAME"; - public static final String PARAM_TOKEN = "TOKEN"; - public static final String PARAM_SECRET = "SECRET"; - public static final String OP_ISSUE = "issue"; - public static final String OP_VALIDATE = "validate"; - public static final String OP_INVALIDATE = "invalidate"; + private static final String PARAM_OPERATION = "OPERATION"; + private static final String PARAM_USERNAME = "USERNAME"; + private static final String PARAM_TOKEN = "TOKEN"; + private static final String PARAM_SECRET = "SECRET"; + private static final String OP_ISSUE = "issue"; + private static final String OP_VALIDATE = "validate"; + private static final String OP_INVALIDATE = "invalidate"; - public AliasTokenRestlet(Context context, Request request, Response response) { + public AliasTokenRestlet(Context context, Request request, Response response) throws ResourceException { super(context, request, response); getVariants().add(new Variant(MediaType.APPLICATION_JSON)); _operation = (String) getRequest().getAttributes().get(PARAM_OPERATION); @@ -50,6 +49,12 @@ public class AliasTokenRestlet extends SecureResource { _token = (String) getRequest().getAttributes().get(PARAM_TOKEN); final String secret = (String) getRequest().getAttributes().get(PARAM_SECRET); _secret = StringUtils.isBlank(secret) ? INVALID : Long.parseLong(secret); + + _serializer = XDAT.getContextService().getBean(SerializerService.class); + if (null == _serializer) { + getResponse().setStatus(Status.CLIENT_ERROR_FAILED_DEPENDENCY, "Serializer service was not properly initialized."); + throw new ResourceException(Status.CLIENT_ERROR_FAILED_DEPENDENCY, "ERROR: Serializer service was not properly initialized."); + } } @Override @@ -69,9 +74,9 @@ public class AliasTokenRestlet extends SecureResource { throw new ResourceException(Status.CLIENT_ERROR_UNAUTHORIZED, "You must specify both token and secret to validate a token."); } try { - final HashMap<String, String> results = new HashMap<String, String>(); + final HashMap<String, String> results = new HashMap<>(); results.put("valid", getService().validateToken(_token, _secret)); - return new StringRepresentation(_serializer.writeValueAsString(results)); + return new StringRepresentation(_serializer.toJson(results)); } catch (IOException exception) { throw new ResourceException(Status.SERVER_ERROR_INTERNAL, exception.toString()); } @@ -89,7 +94,7 @@ public class AliasTokenRestlet extends SecureResource { map.put("secret", Long.toString(token.getSecret())); String value = ""; try { - value = _serializer.writeValueAsString(map); + value = _serializer.toJson(map); } catch (IOException e) { // } @@ -109,10 +114,10 @@ public class AliasTokenRestlet extends SecureResource { } private static final int INVALID = -1; - private static final ObjectMapper _serializer = new ObjectMapper(); - private AliasTokenService _service; - private String _operation; - private final String _username; - private final String _token; - private final long _secret; + private final SerializerService _serializer; + private AliasTokenService _service; + private String _operation; + private final String _username; + private final String _token; + private final long _secret; } diff --git a/src/main/java/org/nrg/xnat/restlet/services/SettingsRestlet.java b/src/main/java/org/nrg/xnat/restlet/services/SettingsRestlet.java index e1efa228c74e3f15b34358779f3a04025b9b7a7e..5625fdcfef13fe6c9bc871ca79efc491c07652b4 100644 --- a/src/main/java/org/nrg/xnat/restlet/services/SettingsRestlet.java +++ b/src/main/java/org/nrg/xnat/restlet/services/SettingsRestlet.java @@ -10,8 +10,6 @@ */ package org.nrg.xnat.restlet.services; -import com.fasterxml.jackson.core.JsonFactory; -import com.fasterxml.jackson.databind.ObjectMapper; import org.apache.commons.lang.StringUtils; import org.hibernate.PropertyNotFoundException; import org.nrg.config.entities.Configuration; @@ -66,12 +64,17 @@ public class SettingsRestlet extends SecureResource { public SettingsRestlet(Context context, Request request, Response response) throws IOException { super(context, request, response); + setModifiable(true); - this.getVariants().add(new Variant(MediaType.APPLICATION_JSON)); - this.getVariants().add(new Variant(MediaType.TEXT_XML)); + + getVariants().add(new Variant(MediaType.APPLICATION_JSON)); + getVariants().add(new Variant(MediaType.TEXT_XML)); + + _filterService = XDAT.getContextService().getBean(DicomFilterService.class); _arcSpec = ArcSpecManager.GetInstance(); _property = (String) getRequest().getAttributes().get("PROPERTY"); + if (!StringUtils.isBlank(_property)) { if (_property.equals("initialize")) { if (_arcSpec != null && _arcSpec.isComplete()) { @@ -103,7 +106,7 @@ public class SettingsRestlet extends SecureResource { if (StringUtils.isBlank(_property)) { return mediaType == MediaType.TEXT_XML ? new ItemXMLRepresentation(_arcSpec.getItem(), mediaType) : - new StringRepresentation("{\"ResultSet\":{\"Result\":" + new ObjectMapper().writeValueAsString(getArcSpecAsMap()) + ", \"title\": \"Settings\"}}"); + new StringRepresentation("{\"ResultSet\":{\"Result\":" + toJson(getArcSpecAsMap()) + ", \"title\": \"Settings\"}}"); } else { if (!getArcSpecAsMap().containsKey(_property)) { throw new PropertyNotFoundException(String.format("Setting '%s' was not found in the system.", _property)); @@ -114,7 +117,7 @@ public class SettingsRestlet extends SecureResource { String xml = "<" + _property + ">" + propertyValue.toString() + "</" + _property + ">"; return new StringRepresentation(xml, mediaType); } else { - return new StringRepresentation("{\"ResultSet\":{\"Result\":" + new ObjectMapper().writeValueAsString(propertyValue) + ", \"title\": \"" + _property + "\"}}"); + return new StringRepresentation("{\"ResultSet\":{\"Result\":" + toJson(propertyValue) + ", \"title\": \"" + _property + "\"}}"); } } } catch (PropertyNotFoundException exception) { @@ -180,11 +183,6 @@ public class SettingsRestlet extends SecureResource { } private DicomFilterService getDicomFilterService() { - if (_filterService == null) { - synchronized (_log) { - _filterService = XDAT.getContextService().getBean(DicomFilterService.class); - } - } return _filterService; } @@ -225,7 +223,7 @@ public class SettingsRestlet extends SecureResource { map.put(atoms[0], atoms[1]); } - return MAPPER.writeValueAsString(map); + return toJson(map); } catch (IOException ignored) { // We're not reading from a file, so we shouldn't encounter this. } @@ -234,7 +232,7 @@ public class SettingsRestlet extends SecureResource { } // TODO: Gross. - public static final String ADMIN_USERNAME_FOR_SUBSCRIPTION = "admin"; + private static final String ADMIN_USERNAME_FOR_SUBSCRIPTION = "admin"; /** * This returns the current subscriber or subscribers to a particular <i>site-wide</i> event. If the event doesn't @@ -934,11 +932,9 @@ public class SettingsRestlet extends SecureResource { return users.get(0).getLogin(); } - private static final ObjectMapper MAPPER = new ObjectMapper(new JsonFactory()); - private static final Logger _log = LoggerFactory.getLogger(SettingsRestlet.class); - private DicomFilterService _filterService; + private final DicomFilterService _filterService; private NotificationService _notificationService; private ArcArchivespecification _arcSpec; diff --git a/src/main/java/org/nrg/xnat/services/impl/ThemeServiceImpl.java b/src/main/java/org/nrg/xnat/services/impl/ThemeServiceImpl.java index f72a2cfaab5dae947be92c2b6da130b98c30673c..8f2d1315f6879cf53f9ad0c6562d9c92f3401f8e 100644 --- a/src/main/java/org/nrg/xnat/services/impl/ThemeServiceImpl.java +++ b/src/main/java/org/nrg/xnat/services/impl/ThemeServiceImpl.java @@ -12,11 +12,11 @@ package org.nrg.xnat.services.impl; import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; import org.apache.commons.lang.ArrayUtils; import org.apache.commons.lang.StringUtils; import org.nrg.xnat.configuration.ThemeConfig; import org.nrg.xnat.services.ThemeService; +import org.nrg.xnat.utils.SerializerService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -34,9 +34,11 @@ public class ThemeServiceImpl implements ThemeService { private static String themesPath; private static ThemeConfig themeConfig = null; private static File themeFile = null; - protected final ObjectMapper mapper = new ObjectMapper(); private static final int FILE_BUFFER_SIZE = 4096; + @Autowired + private SerializerService _serializer; + @Autowired private ServletContext servletContext; @@ -75,7 +77,7 @@ System.out.println("Theme Path: "+themeFile); } reader.close(); String contents = sb.toString(); - themeConfig = mapper.readValue(contents, ThemeConfig.class); + themeConfig = _serializer.deserializeJson(contents, ThemeConfig.class); } catch (IOException e) { e.printStackTrace(); } @@ -86,7 +88,7 @@ System.out.println("Theme Path: "+themeFile); e.printStackTrace(); } } - if(role != null){ + if (role != null) { // TODO: implement search through the roles array in the ThemeConfig object for a matching ThemeConfig object for the specified role } return themeConfig; @@ -130,6 +132,7 @@ System.out.println("Theme Path: "+themeFile); private String checkThemeFileExists(ThemeConfig theme, String pageName) { return checkThemeFileExists(theme, pageName, null); } + private String checkThemeFileExists(ThemeConfig theme, String pageName, String type) { String pagePath = null, typeSep = type + "s" + File.separator; String[] extensions = new String[]{}; @@ -174,7 +177,7 @@ System.out.println("Theme Path: "+themeFile); themeConfig = new ThemeConfig(); } if(themeExists(themeConfig.getName())) { - String themeJson = mapper.writeValueAsString(themeConfig); + String themeJson = _serializer.toJson(themeConfig); if (!themeFile.exists()) { themeFile.createNewFile(); } @@ -276,7 +279,7 @@ System.out.println("Theme Path: "+themeFile); * @throws IOException */ public List<String> extractTheme(InputStream inputStream) throws IOException { - ArrayList rootDirs = new ArrayList(); + final List<String> rootDirs = new ArrayList<>(); ZipInputStream zipIn = new ZipInputStream(inputStream); ZipEntry entry = zipIn.getNextEntry(); while (entry != null) { // iterate over entries in the zip file @@ -284,8 +287,7 @@ System.out.println("Theme Path: "+themeFile); if (!entry.isDirectory()) { // if the entry is a file, extract it // TODO: Make sure we get a directory the first iteration through (fail otherwise) so that no files get dumped in the root themes directory this.extractFile(zipIn, filePath); } else { // if the entry is a directory, make the directory - String rootDir = ""; - rootDir = entry.getName(); + String rootDir = entry.getName(); int slashIndex = rootDir.indexOf('/'); if(slashIndex>1){ int nextSlashIndex = rootDir.indexOf('/', slashIndex+1); diff --git a/src/main/java/org/nrg/xnat/spawner/controllers/ManageElementsController.java b/src/main/java/org/nrg/xnat/spawner/controllers/ManageElementsController.java index 2b2ad5a8cd891c4c9c7028fb8eaabaf73c33a6e5..e806046f2010b4aecb9d9785dc8facdeb5896c34 100644 --- a/src/main/java/org/nrg/xnat/spawner/controllers/ManageElementsController.java +++ b/src/main/java/org/nrg/xnat/spawner/controllers/ManageElementsController.java @@ -12,20 +12,23 @@ import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.servlet.ModelAndView; import javax.inject.Inject; +import java.util.List; +@SuppressWarnings("SpringMVCViewInspection") @Controller @RequestMapping(value = "/spawner/elements", produces = "application/json") public class ManageElementsController { @RequestMapping public ModelAndView getAvailableElements() { - return new ModelAndView("spawner/elements", "elements", _service.getAvailableSpawnerElementIds()); + final List<SpawnerElement> elements = _service.getAll(); + return new ModelAndView("spawner/elements", "elements", elements); } @RequestMapping(value = "{elementId}", method = RequestMethod.GET) public ModelAndView getElement(@PathVariable final String elementId) { final SpawnerElement element = _service.retrieve(elementId); - return new ModelAndView("spawner/element", element == null ? "error" : "element", element == null ? "The ID element " + elementId + " was not found in the system." : element); + return new ModelAndView("spawner/element", element == null ? "error" : "elementId", element == null ? "The ID element " + elementId + " was not found in the system." : elementId); } @RequestMapping(value = "{elementId}", method = RequestMethod.PUT) diff --git a/src/main/java/org/nrg/xnat/turbine/modules/screens/LaunchUploadApplet.java b/src/main/java/org/nrg/xnat/turbine/modules/screens/LaunchUploadApplet.java index 2e97b3d45b8a9cf975c0a0430d26c3368aeb11bf..739fb9436059b98b2fd1dea8f28ab38c1d01df2c 100644 --- a/src/main/java/org/nrg/xnat/turbine/modules/screens/LaunchUploadApplet.java +++ b/src/main/java/org/nrg/xnat/turbine/modules/screens/LaunchUploadApplet.java @@ -15,7 +15,6 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.turbine.util.RunData; import org.apache.velocity.context.Context; -import com.fasterxml.jackson.databind.ObjectMapper; import org.nrg.framework.utilities.Reflection; import org.nrg.xdat.om.XnatPvisitdata; import org.nrg.xdat.turbine.utils.TurbineUtils; @@ -28,24 +27,25 @@ import java.util.List; * @author timo * */ +@SuppressWarnings({"WeakerAccess", "unused"}) public class LaunchUploadApplet extends UploadAppletScreen { private static final Log _log = LogFactory.getLog(LaunchUploadApplet.class); - - - @Override + @Override public void doBuildTemplate(RunData data, Context context) { context.put("jsessionid", XnatHttpUtils.getJSESSIONID(data)); - if(StringUtils.trimToEmpty((String)org.nrg.xdat.turbine.utils.TurbineUtils.GetPassedParameter("search_field",data)).equals("xnat:subjectData.ID")) { - context.put("subject", StringUtils.trimToEmpty((String)org.nrg.xdat.turbine.utils.TurbineUtils.GetPassedParameter("search_value",data))); + if(StringUtils.trimToEmpty((String)TurbineUtils.GetPassedParameter("search_field",data)).equals("xnat:subjectData.ID")) { + context.put("subject", StringUtils.trimToEmpty((String)TurbineUtils.GetPassedParameter("search_value",data))); } - if(StringUtils.isNotBlank((String) org.nrg.xdat.turbine.utils.TurbineUtils.GetPassedParameter("pvisit", data))) { - XnatPvisitdata visit = XnatPvisitdata.getXnatPvisitdatasById((String) org.nrg.xdat.turbine.utils.TurbineUtils.GetPassedParameter("pvisit", data), TurbineUtils.getUser(data), false); - context.put("subject", visit.getSubjectId()); - context.put("visit", visit.getId()); + if(StringUtils.isNotBlank((String) TurbineUtils.GetPassedParameter("pvisit", data))) { + final XnatPvisitdata visit = XnatPvisitdata.getXnatPvisitdatasById(TurbineUtils.GetPassedParameter("pvisit", data), TurbineUtils.getUser(data), false); + if (visit != null) { + context.put("subject", visit.getSubjectId()); + context.put("visit", visit.getId()); + } } try { @@ -62,8 +62,7 @@ public class LaunchUploadApplet extends UploadAppletScreen { if (json != null) { try { //we have JSON, so, create applet parameters from it. - ObjectMapper mapper = new ObjectMapper(); - AppletConfig jsonParams = mapper.readValue(json, AppletConfig.class); + AppletConfig jsonParams = getSerializer().deserializeJson(json, AppletConfig.class); if(jsonParams.getLaunch() != null){ for(String key:jsonParams.getLaunch().keySet()){ @@ -79,8 +78,8 @@ public class LaunchUploadApplet extends UploadAppletScreen { } } - public interface ContextAction { - public void execute(RunData data, Context context); + private interface ContextAction { + void execute(RunData data, Context context); } private void dynamicContextExpansion(RunData data, Context context) throws Exception { diff --git a/src/main/java/org/nrg/xnat/turbine/modules/screens/UploadApplet.java b/src/main/java/org/nrg/xnat/turbine/modules/screens/UploadApplet.java index b98bf84bcd5d372a7011f096a1c87b5bb851172a..c78e6e1952416dd77fbc30f17c6b9cecb113a17f 100644 --- a/src/main/java/org/nrg/xnat/turbine/modules/screens/UploadApplet.java +++ b/src/main/java/org/nrg/xnat/turbine/modules/screens/UploadApplet.java @@ -12,7 +12,6 @@ package org.nrg.xnat.turbine.modules.screens; import org.apache.turbine.util.RunData; import org.apache.velocity.context.Context; -import com.fasterxml.jackson.databind.ObjectMapper; import org.nrg.xdat.turbine.utils.TurbineUtils; import org.nrg.xnat.turbine.utils.ArcSpecManager; import org.nrg.xnat.utils.AppletConfig; @@ -20,6 +19,7 @@ import org.nrg.xnat.utils.XnatHttpUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +@SuppressWarnings("unused") public class UploadApplet extends UploadAppletScreen { private static final Logger logger = LoggerFactory.getLogger(UploadApplet.class); @@ -41,19 +41,19 @@ public class UploadApplet extends UploadAppletScreen { // HH:MM or if HH:MM == 00:00 the applet will only verify the scan is on the same day as mm/dd/yyyy. If it receives no // session_date, it will prompt the user for one. With that said, we want to build up the mm/dd/yyyy string if we can. // we'll do it here. - String hhmm = " 00:00"; + String time = " 00:00"; if (TurbineUtils.HasPassedParameter("session_time_h", data) && TurbineUtils.HasPassedParameter("session_time_m", data)) { // parameters are set with drop-downs so no need to validate here. String hr = (String)TurbineUtils.GetPassedParameter("session_time_h", data); String mm =(String)TurbineUtils.GetPassedParameter("session_time_m", data); try{ //poor man's validation - hhmm = Integer.parseInt(hr) + ":" + Integer.parseInt(mm); + time = Integer.parseInt(hr) + ":" + Integer.parseInt(mm); } catch (Exception e){ //if one or both aren't an integer, we'll get here, which is fine. it just means they didn't select a time. } } - context.put("session_date", ((String)TurbineUtils.GetPassedParameter("session_date", data)).replace('.', '/') + " " + hhmm); + context.put("session_date", ((String)TurbineUtils.GetPassedParameter("session_date", data)).replace('.', '/') + " " + time); } else if (TurbineUtils.HasPassedParameter("no_session_date", data)) { context.put("session_date", "no_session_date"); } @@ -67,8 +67,7 @@ public class UploadApplet extends UploadAppletScreen { if (json != null) { try { //we have JSON, so, create applet parameters from it. - ObjectMapper mapper = new ObjectMapper(); - AppletConfig jsonParams = mapper.readValue(json, AppletConfig.class); + AppletConfig jsonParams = getSerializer().deserializeJson(json, AppletConfig.class); StringBuilder sb = new StringBuilder(); if(jsonParams.getParameters() != null) { for(String key:jsonParams.getParameters().keySet()) { diff --git a/src/main/java/org/nrg/xnat/turbine/modules/screens/UploadAppletScreen.java b/src/main/java/org/nrg/xnat/turbine/modules/screens/UploadAppletScreen.java index b6fdafdd84e09fbcfb55b1bf8919e46b867c46fd..46ad360a7cc91d8c106c383877badbb8ad1f263b 100644 --- a/src/main/java/org/nrg/xnat/turbine/modules/screens/UploadAppletScreen.java +++ b/src/main/java/org/nrg/xnat/turbine/modules/screens/UploadAppletScreen.java @@ -8,11 +8,17 @@ import org.nrg.xdat.security.helpers.Permissions; import org.nrg.xdat.turbine.modules.screens.SecureScreen; import org.nrg.xft.security.UserI; import org.nrg.xnat.utils.AppletConfig; +import org.nrg.xnat.utils.SerializerService; /** * Contains basic methods used by upload applet screen classes. */ public abstract class UploadAppletScreen extends SecureScreen { + + protected UploadAppletScreen() { + _serializer = XDAT.getContextService().getBean(SerializerService.class); + } + protected org.nrg.config.entities.Configuration getAppletConfiguration(final UserI user, final String projectName) { //grab the applet config. Project level if it exists, otherwise, do the site-wide ConfigService configService = XDAT.getConfigService(); @@ -53,4 +59,10 @@ public abstract class UploadAppletScreen extends SecureScreen { } return config; } + + protected SerializerService getSerializer() { + return _serializer; + } + + private final SerializerService _serializer; } diff --git a/src/main/java/org/nrg/xnat/utils/SerializerService.java b/src/main/java/org/nrg/xnat/utils/SerializerService.java new file mode 100644 index 0000000000000000000000000000000000000000..529f10b6777439e32150894975a3fb9f594621f2 --- /dev/null +++ b/src/main/java/org/nrg/xnat/utils/SerializerService.java @@ -0,0 +1,53 @@ +package org.nrg.xnat.utils; + +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.springframework.stereotype.Service; + +import javax.inject.Inject; +import javax.inject.Named; +import java.io.IOException; + +@Service +public class SerializerService { + public JsonNode deserializeJson(final String json) throws IOException { + return _jsonObjectMapper.readTree(json); + } + + public <T> T deserializeJson(final String json, final Class<T> clazz) throws IOException { + return _jsonObjectMapper.readValue(json, clazz); + } + + public <T> T deserializeJson(final String json, final TypeReference<T> typeRef) throws IOException { + return _jsonObjectMapper.readValue(json, typeRef); + } + + public <T> String toJson(final T instance) throws IOException { + return _jsonObjectMapper.writeValueAsString(instance); + } + + public JsonNode deserializeYaml(final String yaml) throws IOException { + return _yamlObjectMapper.readTree(yaml); + } + + public <T> T deserializeYaml(final String yaml, Class<T> clazz) throws IOException { + return _yamlObjectMapper.readValue(yaml, clazz); + } + + public <T> T deserializeYaml(final String yaml, final TypeReference<T> typeRef) throws IOException { + return _yamlObjectMapper.readValue(yaml, typeRef); + } + + public <T> String toYaml(final T instance) throws IOException { + return _yamlObjectMapper.writeValueAsString(instance); + } + + @Inject + @Named("jsonObjectMapper") + private ObjectMapper _jsonObjectMapper; + + @Inject + @Named("yamlObjectMapper") + private ObjectMapper _yamlObjectMapper; +} diff --git a/src/main/resources/META-INF/xnat/spawner/site-admin-elements.yaml b/src/main/resources/META-INF/xnat/spawner/site-admin-elements.yaml new file mode 100644 index 0000000000000000000000000000000000000000..f6e1311c8fde5ce996662230e772a31353b1c24e --- /dev/null +++ b/src/main/resources/META-INF/xnat/spawner/site-admin-elements.yaml @@ -0,0 +1,117 @@ +# Initial element declarations for the site admin user interface elements. +siteId: + label: Site ID + type: text + id: site-id + description: Identifies your XNAT site. + placeholder: Enter your XNAT site ID... + url: /xapi/services/prefs/siteId/{siteId} + default: XNAT + validation: + required: true + type: xnat-id + +siteUrl: + label: Site Url + type: url + description: The root URL for the site. This is passed to external services. + placeholder: Enter the URL for your XNAT site... + value: https://cnda.wustl.edu + validation: + required: true + +siteDescriptionPage: + id: desc-page + label: Page + type: site.path + description: The page to display for the site description, e.g. /screens/site_description.vm. + value: /screens/site_description.vm + placeholder: Enter a page for your site description... + validation: + required: true + +siteDescriptionMarkdown: + id: desc-markdown + label: Text (Markdown) + type: markdown + tooltip: XNAT allows you to use GitHub-flavored Markdown to create and format your own site description. [>> View Tutorial](http://foobar) + description: Compose a site description without referencing a template or site page. + validation: + required: true + +siteDescription: + label: Site Description + type: composite + selection: radio + url: /data/services/prefs/{desc} + children: + ${siteDescriptionPage} + ${siteDescriptionMarkdown} + +landingPage: + label: Landing Page + type: site.path + description: The page to display when the user logs in. + value: /screens/QuickSearch.vm + placeholder: Enter the default landing page... + overrides: + target: homePage + type: checkbox + position: right + description: Use this as my home page. + hideTarget: false + validation: + required: true + +homePage: + label: Home Page + type: site.path + description: The page to display when the user clicks the home link. + value: /screens/AdminUsers.vm + placeholder: Enter the default home page... + validation: + required: true + +siteInfo: + label: Site Information + type: panel + controls: + ${siteId} + ${siteUrl} + ${siteDescription} + ${landingPage} + ${homePage} + +siteAdminEmail: + label: Site Admin Email + type: email + placeholder: Administrator email address... + url: /xapi/services/prefs/siteAdminEmail/{siteAdminEmail} + validation: + required: true + +adminInfo: + label: Admin Information + type: panel + controls: + ${siteAdminEmail} + +siteSetup: + label: Site Setup + type: tab + contents: + ${siteInfo} + ${adminInfo} + +xnatSetup: + label: XNAT Setup + type: tabGroup + tabs: + ${siteSetup} + +siteAdmin: + label: Administer XNAT + type: page + contains: tabs + contents: + ${xnatSetup} diff --git a/src/main/webapp/META-INF/context.xml b/src/main/webapp/META-INF/context.xml index 16bd2bec3ce56149a803754e2972b96d298abe37..b4c53f63c28668cc23be5f6c85c64b2487290da0 100644 --- a/src/main/webapp/META-INF/context.xml +++ b/src/main/webapp/META-INF/context.xml @@ -1,5 +1,5 @@ -<?xml version='1.0' encoding='utf-8'?> -<Context antiResourceLocking="true"> +<?xml version="1.0" encoding="utf-8"?> +<Context> <Loader className="org.apache.catalina.loader.VirtualWebappLoader" searchVirtualFirst="true" virtualClasspath="${xnat.home}/plugins/*.jar"/> <JarScanner scanAllDirectories="true" /> <Parameter name="xnatHome" value="${xnat.home}"/> diff --git a/src/main/webapp/WEB-INF/tags/spawner/layout.tag b/src/main/webapp/WEB-INF/tags/spawner/layout.tag index 5e28cd9a34e305364548dab4f76d9faa4c974e4b..b096d29672bf34e178c3f841b9d897b312a33cfb 100644 --- a/src/main/webapp/WEB-INF/tags/spawner/layout.tag +++ b/src/main/webapp/WEB-INF/tags/spawner/layout.tag @@ -723,7 +723,7 @@ <div id="layout_content"> <!--BEGIN SCREEN CONTENT --> - <jsp:doBody scope="page"/> + <jsp:doBody/> <!-- END SCREEN CONTENT --> </div> diff --git a/src/main/webapp/WEB-INF/views/spawner/element.jsp b/src/main/webapp/WEB-INF/views/spawner/element.jsp index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..3954d9e9459d1388d87086a69dd661a5667135ac 100644 --- a/src/main/webapp/WEB-INF/views/spawner/element.jsp +++ b/src/main/webapp/WEB-INF/views/spawner/element.jsp @@ -0,0 +1,30 @@ +<%@ page contentType="text/html" pageEncoding="UTF-8" %> +<%@ taglib prefix="sp" tagdir="/WEB-INF/tags/spawner" %> +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> +<jsp:useBean id="elementId" scope="request" type="java.lang.String"/> + +<c:set var="title" value="Spawner Element: ${elementId}"/> +<sp:layout title="${title}"> + <h3 style="margin:0 0 15px 0;">${title}</h3> + + <div style="margin:15px 0;max-width:696px;min-width:400px;"> + Make your desired changes to the spawner element and click <b>Save</b> when completed. + </div> + +<script type="text/javascript"> + var spawnerElement = $.ajax({ + type : "GET", + url:serverRoot+"/xapi/spawner/${elementId}?XNAT_CSRF=" + window.csrfToken, + cache: false, + async: true, + context: this, + dataType: "yaml" + }); + spawnerElement.done( function( data, textStatus, jqXHR ) { + if (typeof data.ResultSet !== "undefined" && typeof data.ResultSet.Result !== "undefined") { + alert(data); + } + }); + +</script> +</sp:layout> \ No newline at end of file diff --git a/src/main/webapp/WEB-INF/views/spawner/elements.jsp b/src/main/webapp/WEB-INF/views/spawner/elements.jsp index ed05c3b0a19202b2d98b978aaa9e5496e7d20aa3..bea671ed2573041d7d256d8de89739360fd3d41e 100644 --- a/src/main/webapp/WEB-INF/views/spawner/elements.jsp +++ b/src/main/webapp/WEB-INF/views/spawner/elements.jsp @@ -3,13 +3,12 @@ <%@ taglib prefix="sp" tagdir="/WEB-INF/tags/spawner" %> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <jsp:useBean id="elements" scope="request" type="java.util.List"/> -<jsp:useBean id="element" scope="request" type="org.nrg.xnat.spawner.entities.SpawnerElement"/> <sp:layout title="Spawner Elements"> <h3 style="margin:0 0 15px 0;">Spawner Elements</h3> <div style="margin:15px 0;max-width:696px;min-width:400px;"> - The Spawner is XNAT's system for managing dynamically configurable user interface elements. + The Spawner is XNAT's system for creating and updating dynamically configurable user interface elements. </div> <div class="yui-skin-sam"> @@ -105,14 +104,13 @@ <c:forEach var="element" items="${elements}"> <tr class="highlight events-list"> <td class="site-event-id"> - ${element.label} + <a href="elements/${element.elementId}" class="edit-event" data-action="editEvent" + title="edit existing event">${element.label}</a> </td> <td class="site-event-label"> ${element.description} </td> <td class="actions" style="text-align:center;white-space:nowrap;"> - <a href="#!" class="edit-event" data-action="editEvent" - title="edit existing event">edit</a> <a href="#!" class="delete-event" data-action="deleteEvent" title="delete existing event">delete</a> </td> diff --git a/src/main/webapp/resources/ui/skins/default/skin.props b/src/main/webapp/resources/ui/skins/default/skin.props new file mode 100755 index 0000000000000000000000000000000000000000..59eecbe213ab4d3931579d7b71d4cc5e9161da8a --- /dev/null +++ b/src/main/webapp/resources/ui/skins/default/skin.props @@ -0,0 +1,29 @@ +# These are the default properties +bgcolor = #ffffff +sansSerifFonts = verdana,geneva,helvetica +#formLabelColor = #b3cc99 +#formFieldColor = #b3bb99 +#labelColor = #b3cc99 +#dataColor = #b3bb99 +formLabelColor = #ffffff +formFieldColor = #ffffff +labelColor = #ffffff +dataColor = #ffffff +#vlink = #330066 +#alink = #663399 +vlink = #000000 +alink = #000000 +tableCellSpacing = 0 +tableCellPadding = 0 +menuColor = #000000 +buttonAlignment = left +buttonColor = #DDDDDD +# Images alertImage = alert1.gif +logo = logo.jpg +poweredByImage = powered_by_tambora.gif +line = line.gif +#darkColor = #000088 +#lightColor = #DDDDDD +darkColor = #000066 +lightColor = #333399 +tableColor = #AAAAAA \ No newline at end of file diff --git a/src/main/webapp/resources/ui/skins/default/skin.txt b/src/main/webapp/resources/ui/skins/default/skin.txt new file mode 100755 index 0000000000000000000000000000000000000000..081a8930bd907dee5d0de030c6eb6cc8d5746a34 Binary files /dev/null and b/src/main/webapp/resources/ui/skins/default/skin.txt differ