← Back to team overview

dhis2-devs team mailing list archive

[Branch ~dhis2-devs-core/dhis2/trunk] Rev 15742: add support for jsonp

 

------------------------------------------------------------
revno: 15742
committer: Morten Olav Hansen <mortenoh@xxxxxxxxx>
branch nick: dhis2
timestamp: Wed 2014-06-18 11:05:19 +0200
message:
  add support for jsonp
added:
  dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/messageconverter/JsonPMessageConverter.java
modified:
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/node/AbstractNodeSerializer.java
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/node/config/Config.java
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/node/serializers/Jackson2JsonNodeSerializer.java
  dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/messageconverter/JsonMessageConverter.java
  dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/messageconverter/XmlMessageConverter.java
  dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/view/CustomPathExtensionContentNegotiationStrategy.java
  dhis-2/dhis-web/dhis-web-api/src/main/resources/META-INF/dhis/servlet.xml


--
lp:dhis2
https://code.launchpad.net/~dhis2-devs-core/dhis2/trunk

Your team DHIS 2 developers is subscribed to branch lp:dhis2.
To unsubscribe from this branch go to https://code.launchpad.net/~dhis2-devs-core/dhis2/trunk/+edit-subscription
=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/node/AbstractNodeSerializer.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/node/AbstractNodeSerializer.java	2014-06-17 14:33:44 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/node/AbstractNodeSerializer.java	2014-06-18 09:05:19 +0000
@@ -51,7 +51,7 @@
 
     protected abstract void flushStream() throws Exception;
 
-    private Config config;
+    protected Config config;
 
     @Override
     public void serialize( RootNode rootNode, OutputStream outputStream ) throws Exception

=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/node/config/Config.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/node/config/Config.java	2014-06-17 14:33:44 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/node/config/Config.java	2014-06-18 09:05:19 +0000
@@ -28,6 +28,10 @@
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE
  */
 
+import com.google.common.collect.Maps;
+
+import java.util.Map;
+
 /**
  * @author Morten Olav Hansen <mortenoh@xxxxxxxxx>
  */
@@ -40,6 +44,12 @@
      */
     private InclusionStrategy inclusionStrategy = InclusionStrategy.Include.NON_NULL;
 
+    /**
+     * Property map that can hold any key=value pair, can be used to set custom
+     * properties that only certain serializers know about.
+     */
+    private final Map<String, Object> properties = Maps.newHashMap();
+
     public Config()
     {
     }
@@ -53,4 +63,9 @@
     {
         this.inclusionStrategy = inclusionStrategy;
     }
+
+    public Map<String, Object> getProperties()
+    {
+        return properties;
+    }
 }

=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/node/serializers/Jackson2JsonNodeSerializer.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/node/serializers/Jackson2JsonNodeSerializer.java	2014-06-17 14:06:57 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/node/serializers/Jackson2JsonNodeSerializer.java	2014-06-18 09:05:19 +0000
@@ -48,11 +48,13 @@
  * @author Morten Olav Hansen <mortenoh@xxxxxxxxx>
  */
 @Component
-@Scope(value = "prototype", proxyMode = ScopedProxyMode.INTERFACES)
+@Scope( value = "prototype", proxyMode = ScopedProxyMode.INTERFACES )
 public class Jackson2JsonNodeSerializer extends AbstractNodeSerializer
 {
     public static final String CONTENT_TYPE = "application/json";
 
+    public static final String JSONP_CALLBACK = "org.hisp.dhis.node.serializers.Jackson2JsonNodeSerializer.callback";
+
     private final static ObjectMapper objectMapper = new ObjectMapper();
 
     static
@@ -86,7 +88,11 @@
     @Override
     protected void startWriteRootNode( RootNode rootNode ) throws Exception
     {
-        //generator.writeRaw( "callback(" );
+        if ( config.getProperties().containsKey( JSONP_CALLBACK ) )
+        {
+            generator.writeRaw( config.getProperties().get( JSONP_CALLBACK ) + "(" );
+        }
+
         generator.writeStartObject();
     }
 
@@ -94,7 +100,11 @@
     protected void endWriteRootNode( RootNode rootNode ) throws Exception
     {
         generator.writeEndObject();
-        //generator.writeRaw( ")" );
+
+        if ( config.getProperties().containsKey( JSONP_CALLBACK ) )
+        {
+            generator.writeRaw( ")" );
+        }
     }
 
     @Override

=== modified file 'dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/messageconverter/JsonMessageConverter.java'
--- dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/messageconverter/JsonMessageConverter.java	2014-06-18 07:15:48 +0000
+++ dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/messageconverter/JsonMessageConverter.java	2014-06-18 09:05:19 +0000
@@ -41,7 +41,6 @@
 import org.springframework.stereotype.Component;
 
 import java.io.IOException;
-import java.nio.charset.Charset;
 
 /**
  * @author Morten Olav Hansen <mortenoh@xxxxxxxxx>
@@ -49,13 +48,13 @@
 @Component
 public class JsonMessageConverter extends AbstractHttpMessageConverter<RootNode>
 {
+    public static final ImmutableList<MediaType> SUPPORTED_MEDIA_TYPES = ImmutableList.<MediaType>builder()
+        .add( new MediaType( "application", "json" ) )
+        .build();
+
     @Autowired
     private NodeService nodeService;
 
-    public final ImmutableList<MediaType> SUPPORTED_MEDIA_TYPES = ImmutableList.<MediaType>builder()
-        .add( new MediaType( "application", "json", Charset.forName( "UTF-8" ) ) )
-        .build();
-
     public JsonMessageConverter()
     {
         setSupportedMediaTypes( SUPPORTED_MEDIA_TYPES );

=== added file 'dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/messageconverter/JsonPMessageConverter.java'
--- dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/messageconverter/JsonPMessageConverter.java	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/messageconverter/JsonPMessageConverter.java	2014-06-18 09:05:19 +0000
@@ -0,0 +1,112 @@
+package org.hisp.dhis.webapi.messageconverter;
+
+/*
+ * Copyright (c) 2004-2014, University of Oslo
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * Neither the name of the HISP project nor the names of its contributors may
+ * be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE
+ */
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Lists;
+import org.hisp.dhis.node.NodeService;
+import org.hisp.dhis.node.serializers.Jackson2JsonNodeSerializer;
+import org.hisp.dhis.node.types.RootNode;
+import org.hisp.dhis.webapi.service.ContextService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpInputMessage;
+import org.springframework.http.HttpOutputMessage;
+import org.springframework.http.MediaType;
+import org.springframework.http.converter.AbstractHttpMessageConverter;
+import org.springframework.http.converter.HttpMessageNotReadableException;
+import org.springframework.http.converter.HttpMessageNotWritableException;
+import org.springframework.stereotype.Component;
+
+import java.io.IOException;
+import java.util.List;
+
+/**
+ * @author Morten Olav Hansen <mortenoh@xxxxxxxxx>
+ */
+@Component
+public class JsonPMessageConverter extends AbstractHttpMessageConverter<RootNode>
+{
+    public static final String DEFAULT_CALLBACK_PARAMETER = "callback";
+
+    public static final ImmutableList<MediaType> SUPPORTED_MEDIA_TYPES = ImmutableList.<MediaType>builder()
+        .add( new MediaType( "application", "javascript" ) )
+        .add( new MediaType( "application", "x-javascript" ) )
+        .add( new MediaType( "text", "javascript" ) )
+        .build();
+
+    @Autowired
+    private NodeService nodeService;
+
+    @Autowired
+    private ContextService contextService;
+
+    public JsonPMessageConverter()
+    {
+        setSupportedMediaTypes( SUPPORTED_MEDIA_TYPES );
+    }
+
+    @Override
+    protected boolean supports( Class<?> clazz )
+    {
+        return RootNode.class.equals( clazz );
+    }
+
+    @Override
+    protected boolean canRead( MediaType mediaType )
+    {
+        return false;
+    }
+
+    @Override
+    protected RootNode readInternal( Class<? extends RootNode> clazz, HttpInputMessage inputMessage ) throws IOException, HttpMessageNotReadableException
+    {
+        return null;
+    }
+
+    @Override
+    protected void writeInternal( RootNode rootNode, HttpOutputMessage outputMessage ) throws IOException, HttpMessageNotWritableException
+    {
+        List<String> callbacks = Lists.newArrayList( contextService.getParameterValues( DEFAULT_CALLBACK_PARAMETER ) );
+
+        String callbackParam;
+
+        if ( callbacks.isEmpty() )
+        {
+            callbackParam = DEFAULT_CALLBACK_PARAMETER;
+        }
+        else
+        {
+            callbackParam = callbacks.get( 0 );
+        }
+
+        rootNode.getConfig().getProperties().put( Jackson2JsonNodeSerializer.JSONP_CALLBACK, callbackParam );
+
+        nodeService.serialize( rootNode, "application/json", outputMessage.getBody() );
+    }
+}

=== modified file 'dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/messageconverter/XmlMessageConverter.java'
--- dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/messageconverter/XmlMessageConverter.java	2014-06-18 07:15:48 +0000
+++ dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/messageconverter/XmlMessageConverter.java	2014-06-18 09:05:19 +0000
@@ -41,7 +41,6 @@
 import org.springframework.stereotype.Component;
 
 import java.io.IOException;
-import java.nio.charset.Charset;
 
 /**
  * @author Morten Olav Hansen <mortenoh@xxxxxxxxx>
@@ -49,14 +48,14 @@
 @Component
 public class XmlMessageConverter extends AbstractHttpMessageConverter<RootNode>
 {
+    public static final ImmutableList<MediaType> SUPPORTED_MEDIA_TYPES = ImmutableList.<MediaType>builder()
+        .add( new MediaType( "application", "xml" ) )
+        .add( new MediaType( "text", "xml" ) )
+        .build();
+
     @Autowired
     private NodeService nodeService;
 
-    public final ImmutableList<MediaType> SUPPORTED_MEDIA_TYPES = ImmutableList.<MediaType>builder()
-        .add( new MediaType( "application", "xml", Charset.forName( "UTF-8" ) ) )
-        .add( new MediaType( "text", "xml", Charset.forName( "UTF-8" ) ) )
-        .build();
-
     public XmlMessageConverter()
     {
         setSupportedMediaTypes( SUPPORTED_MEDIA_TYPES );

=== modified file 'dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/view/CustomPathExtensionContentNegotiationStrategy.java'
--- dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/view/CustomPathExtensionContentNegotiationStrategy.java	2014-05-22 12:40:24 +0000
+++ dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/view/CustomPathExtensionContentNegotiationStrategy.java	2014-06-18 09:05:19 +0000
@@ -99,5 +99,4 @@
         }
         return path.substring( extIndex + 1 );
     }
-
 }

=== modified file 'dhis-2/dhis-web/dhis-web-api/src/main/resources/META-INF/dhis/servlet.xml'
--- dhis-2/dhis-web/dhis-web-api/src/main/resources/META-INF/dhis/servlet.xml	2014-06-18 07:15:48 +0000
+++ dhis-2/dhis-web/dhis-web-api/src/main/resources/META-INF/dhis/servlet.xml	2014-06-18 09:05:19 +0000
@@ -23,10 +23,11 @@
     </constructor-arg>
   </bean>
 
-  <mvc:annotation-driven>
+  <mvc:annotation-driven content-negotiation-manager="contentNegotiationManager">
     <mvc:message-converters register-defaults="true">
+      <ref bean="jsonMessageConverter" />
+      <ref bean="jsonPMessageConverter" />
       <ref bean="xmlMessageConverter" />
-      <ref bean="jsonMessageConverter" />
       <ref bean="org.hisp.dhis.webapi.utils.RenderServiceMessageConverter" />
       <bean class="org.hisp.dhis.api.mobile.support.DataStreamSerializableMessageConverter" />
     </mvc:message-converters>
@@ -41,7 +42,7 @@
 
   <bean id="headerContentNegotiationStrategy" class="org.springframework.web.accept.HeaderContentNegotiationStrategy" />
 
-  <bean id="pathExtensionContentNegotiationStrategy" class="org.hisp.dhis.webapi.view.CustomPathExtensionContentNegotiationStrategy">
+  <bean id="customPathExtensionContentNegotiationStrategy" class="org.hisp.dhis.webapi.view.CustomPathExtensionContentNegotiationStrategy">
     <constructor-arg name="mediaTypes">
       <map>
         <entry key="json" value="application/json" />
@@ -55,12 +56,28 @@
         <entry key="csv" value="application/csv" />
       </map>
     </constructor-arg>
+    <property name="useJaf" value="false" />
+  </bean>
+
+  <bean id="parameterContentNegotiationStrategy" class="org.springframework.web.accept.ParameterContentNegotiationStrategy">
+    <constructor-arg name="mediaTypes">
+      <map>
+        <entry key="json" value="application/json" />
+        <entry key="jsonp" value="application/javascript" />
+        <entry key="xml" value="application/xml" />
+        <entry key="png" value="image/png" />
+        <entry key="pdf" value="application/pdf" />
+        <entry key="xls" value="application/vnd.ms-excel" />
+        <entry key="csv" value="application/csv" />
+      </map>
+    </constructor-arg>
   </bean>
 
   <bean id="contentNegotiationManager" class="org.springframework.web.accept.ContentNegotiationManager">
     <constructor-arg>
       <list>
-        <ref bean="pathExtensionContentNegotiationStrategy" />
+        <ref bean="customPathExtensionContentNegotiationStrategy" />
+        <ref bean="parameterContentNegotiationStrategy" />
         <ref bean="headerContentNegotiationStrategy" />
         <ref bean="fixedContentNegotiationStrategy" />
       </list>