From 5f8546a2298d8b3ec5d8c945f5cb55a50e1d70b7 Mon Sep 17 00:00:00 2001 From: Rick Herrick <jrherrick@wustl.edu> Date: Sun, 10 Apr 2016 17:35:29 -0500 Subject: [PATCH] Added sources and javadoc targets to build. Moved classes to use serializer service rather than separate object mapper instances. Integrated spawner functions. Moved from using resource resolver directly to using XnatResourceLocator. --- build.gradle | 16 +++ .../nrg/dcm/preferences/DicomSCPInstance.java | 18 +-- .../xnat/configuration/SerializerConfig.java | 47 +++++++ .../nrg/xnat/configuration/SpawnerConfig.java | 30 +++++ .../listeners/PipelineEmailHandlerAbst.java | 57 +++++---- .../helpers/prearchive/PrearcDatabase.java | 14 ++- .../initialization/XnatWebAppInitializer.java | 6 +- .../restlet/extensions/DicomSCPRestlet.java | 18 ++- .../extensions/PipelineDetailsRestlet.java | 27 ++-- .../extensions/UserSettingsRestlet.java | 18 +-- .../restlet/resources/AutomationResource.java | 40 +++++- .../xnat/restlet/resources/EventResource.java | 8 +- .../ProjectPipelineListResource.java | 2 +- .../resources/ProjectUserListResource.java | 48 ++++--- .../restlet/resources/ScriptResource.java | 28 +---- .../resources/ScriptRunnerResource.java | 9 +- .../resources/ScriptTriggerResource.java | 26 +--- .../ScriptTriggerTemplateResource.java | 5 +- .../resources/ScriptVersionsResource.java | 4 +- .../restlet/resources/SecureResource.java | 23 +++- .../restlet/services/AliasTokenRestlet.java | 43 ++++--- .../restlet/services/SettingsRestlet.java | 28 ++--- .../xnat/services/impl/ThemeServiceImpl.java | 18 +-- .../controllers/ManageElementsController.java | 7 +- .../modules/screens/LaunchUploadApplet.java | 27 ++-- .../turbine/modules/screens/UploadApplet.java | 11 +- .../modules/screens/UploadAppletScreen.java | 12 ++ .../org/nrg/xnat/utils/SerializerService.java | 53 ++++++++ .../xnat/spawner/site-admin-elements.yaml | 117 ++++++++++++++++++ src/main/webapp/META-INF/context.xml | 4 +- .../webapp/WEB-INF/tags/spawner/layout.tag | 2 +- .../webapp/WEB-INF/views/spawner/element.jsp | 30 +++++ .../webapp/WEB-INF/views/spawner/elements.jsp | 8 +- .../resources/ui/skins/default/skin.props | 29 +++++ .../resources/ui/skins/default/skin.txt | Bin 0 -> 1346 bytes 35 files changed, 568 insertions(+), 265 deletions(-) create mode 100644 src/main/java/org/nrg/xnat/configuration/SerializerConfig.java create mode 100644 src/main/java/org/nrg/xnat/configuration/SpawnerConfig.java create mode 100644 src/main/java/org/nrg/xnat/utils/SerializerService.java create mode 100644 src/main/resources/META-INF/xnat/spawner/site-admin-elements.yaml create mode 100755 src/main/webapp/resources/ui/skins/default/skin.props create mode 100755 src/main/webapp/resources/ui/skins/default/skin.txt diff --git a/build.gradle b/build.gradle index 8b3159eb..45afa1f1 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 096f3d7f..0d3a43d1 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 00000000..f4702c9e --- /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 00000000..93f2d7af --- /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 b9fc9feb..f6284204 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 0cbc305b..29c48d48 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 55ca5b3e..3c4f7fcd 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 56617d32..03949ce0 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 30118abd..117eb76a 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 84f4b3bf..c0e44743 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 77d98174..c0d62b29 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 14b078f3..928689f8 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 b81a49a9..d39440c5 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 a36eb439..12a5322d 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 6407ba30..92905f33 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 18258397..31c458d3 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 1509ea08..4564240f 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 a4318cad..4ebd8205 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 4d62c182..b017b3a3 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 5fc9baa1..f2d88bc8 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 042ce9e1..fd347ffa 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 e1efa228..5625fdcf 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 f72a2cfa..8f2d1315 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 2b2ad5a8..e806046f 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 2e97b3d4..739fb943 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 b98bf84b..c78e6e19 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 b6fdafdd..46ad360a 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 00000000..529f10b6 --- /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 00000000..f6e1311c --- /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 16bd2bec..b4c53f63 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 5e28cd9a..b096d296 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 e69de29b..3954d9e9 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 ed05c3b0..bea671ed 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 00000000..59eecbe2 --- /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 GIT binary patch literal 1346 zcmb7^TWi8V5QXQb1oB#>MJV>654Iu{`cP=!CDBA};{}Z^{`t1w*)?optWt)}Ugpg0 z>}-C%V~gy~W|rBO5m{mzH<#`#vI)DK)14JoqF<w5@y(b^n=@}YjV!gPjnNd04f}gW zjAf7rWMWIcug-doZU}mbANi2Qr_)RvF0m_oX6Q4{wNsXb!zl8YGao|{7xv6Pb%@7S z9;tP~kL?br+YDU=1y!E5N%2_O6#wwA3QEQ$ueoFEeC~n4oZKsmbD1|S&gI=i{+)Fb z7jp*%%q{JMjQmY^VfY%kMZ|E@LP#T&=d<lW)|IFak0Vq%&FVPun}W(<S$$E^S8LA3 zF0<(&Ghy4v7jP3qHPn$2eWZ@tow&K<_$jCoQ3v;3wo_K#UN1$wD7zet-bX;UyJBEL zR9nn=!dK#6fL@3A@NX`h`xrrUV;%5%SBku1y<+9_@Vkz^!;vapqx*6mGkAEgeJ!51 zX(C2cu(y%pa=}_}E@{LQm->VFczzf1QBCTv4L#GYzv8xMJv_t*HfKa@V*^tIu$O)M dj#M{I`GcJDsICm1S?`wP|5=}#u0;0~*)LIe*r)&i literal 0 HcmV?d00001 -- GitLab