dhis2-devs team mailing list archive
-
dhis2-devs team
-
Mailing list archive
-
Message #31420
[Branch ~dhis2-devs-core/dhis2/trunk] Rev 15995: WIP on data synchronization feature. Impl configuration for remote server url and credentials. Im...
------------------------------------------------------------
revno: 15995
committer: Lars Helge Overland <larshelge@xxxxxxxxx>
branch nick: dhis2
timestamp: Mon 2014-07-07 12:06:36 +0200
message:
WIP on data synchronization feature. Impl configuration for remote server url and credentials. Impl function for checking if remote server isa available / system is online. Impl function for basic authentication with rest template.
added:
dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/synch/
dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/synch/AvailabilityStatus.java
dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/synch/DefaultSynchronizationManager.java
dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/synch/SynchronizationManager.java
dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/controller/SynchronizationController.java
modified:
dhis-2/dhis-services/dhis-service-dxf2/src/main/resources/META-INF/dhis/beans.xml
dhis-2/dhis-support/dhis-support-system/src/main/java/org/hisp/dhis/system/util/CodecUtils.java
dhis-2/dhis-support/dhis-support-system/src/main/resources/META-INF/dhis/beans.xml
dhis-2/dhis-web/dhis-web-api/src/main/resources/META-INF/dhis/beans.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
=== added directory 'dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/synch'
=== added file 'dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/synch/AvailabilityStatus.java'
--- dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/synch/AvailabilityStatus.java 1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/synch/AvailabilityStatus.java 2014-07-07 10:06:36 +0000
@@ -0,0 +1,72 @@
+package org.hisp.dhis.dxf2.synch;
+
+/*
+ * 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 javax.xml.bind.annotation.XmlRootElement;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+/**
+ * @author Lars Helge Overland
+ */
+@XmlRootElement(name = "availabilityStatus")
+public class AvailabilityStatus
+{
+ private boolean available;
+
+ private String message;
+
+ protected AvailabilityStatus()
+ {
+ }
+
+ public AvailabilityStatus( boolean available, String message )
+ {
+ this.available = available;
+ this.message = message;
+ }
+
+ @JsonProperty
+ public boolean isAvailable()
+ {
+ return available;
+ }
+
+ @JsonProperty
+ public String getMessage()
+ {
+ return message;
+ }
+
+ @Override
+ public String toString()
+ {
+ return "[Available: " + available + ", message: " + message + "]";
+ }
+}
=== added file 'dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/synch/DefaultSynchronizationManager.java'
--- dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/synch/DefaultSynchronizationManager.java 1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/synch/DefaultSynchronizationManager.java 2014-07-07 10:06:36 +0000
@@ -0,0 +1,231 @@
+package org.hisp.dhis.dxf2.synch;
+
+/*
+ * 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 static org.apache.commons.lang.StringUtils.trimToNull;
+
+import java.util.Date;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.hisp.dhis.configuration.Configuration;
+import org.hisp.dhis.configuration.ConfigurationService;
+import org.hisp.dhis.dxf2.datavalueset.DataValueSetService;
+import org.hisp.dhis.period.Cal;
+import org.hisp.dhis.setting.SystemSettingManager;
+import org.hisp.dhis.system.util.CodecUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpEntity;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.scheduling.TaskScheduler;
+import org.springframework.scheduling.support.CronTrigger;
+import org.springframework.web.client.HttpClientErrorException;
+import org.springframework.web.client.HttpServerErrorException;
+import org.springframework.web.client.ResourceAccessException;
+import org.springframework.web.client.RestTemplate;
+
+/**
+ * @author Lars Helge Overland
+ */
+public class DefaultSynchronizationManager
+ implements SynchronizationManager
+{
+ private static final Log log = LogFactory.getLog( DefaultSynchronizationManager.class );
+
+ private static final String KEY_LAST_SUCCESSFUL_SYNC = "keyLastSuccessfulSynch";
+
+ private static CronTrigger CRON = new CronTrigger( "5 * * * * *" ); // Every 5 minutes
+
+ private static final String PING_PATH = "/api/system/ping";
+ private static final String HEADER_AUTHORIZATION = "Authorization";
+
+ @Autowired
+ private DataValueSetService dataValueSetService;
+
+ @Autowired
+ private ConfigurationService configurationService;
+
+ @Autowired
+ private SystemSettingManager systemSettingManager;
+
+ @Autowired
+ private RestTemplate restTemplate;
+
+ @Autowired
+ private TaskScheduler taskScheduler;
+
+ // -------------------------------------------------------------------------
+ // SynchronizatonManager implementation
+ // -------------------------------------------------------------------------
+
+ public AvailabilityStatus isRemoteServerAvailable()
+ {
+ Configuration config = configurationService.getConfiguration();
+
+ if ( !isRemoteServerConfigured( config ) )
+ {
+ return new AvailabilityStatus( false, "Remote server is not configured" );
+ }
+
+ String url = config.getRemoteServerUrl() + PING_PATH;
+
+ log.info( "Remote server ping URL: " + url + ", username: " + config.getRemoteServerUsername() );
+
+ HttpEntity<String> request = getBasicAuthRequestEntity( config.getRemoteServerUsername(), config.getRemoteServerPassword() );
+
+ ResponseEntity<String> response = null;
+ HttpStatus sc = null;
+ AvailabilityStatus status = null;
+
+ try
+ {
+ response = restTemplate.exchange( url, HttpMethod.GET, request, String.class );
+ sc = response.getStatusCode();
+ }
+ catch ( HttpClientErrorException ex )
+ {
+ sc = ex.getStatusCode();
+ }
+ catch ( HttpServerErrorException ex )
+ {
+ sc = ex.getStatusCode();
+ }
+ catch( ResourceAccessException ex )
+ {
+ return new AvailabilityStatus( false, "Network is unreachable" );
+ }
+
+ log.info( "Response: " + response + ", status code: " + sc );
+
+ if ( HttpStatus.FOUND.equals( sc ) )
+ {
+ status = new AvailabilityStatus( false, "Server is available but no authentication was provided" );
+ }
+ else if ( HttpStatus.UNAUTHORIZED.equals( sc ) )
+ {
+ status = new AvailabilityStatus( false, "Server is available but authentication failed" );
+ }
+ else if ( HttpStatus.INTERNAL_SERVER_ERROR.equals( sc ) )
+ {
+ status = new AvailabilityStatus( false, "Server is available but experienced an internal error" );
+ }
+ else if ( HttpStatus.OK.equals( sc ) )
+ {
+ status = new AvailabilityStatus( true, "Server is available and authentication was successful" );
+ }
+ else
+ {
+ status = new AvailabilityStatus( false, "Server is not available for unknown reason: " + sc );
+ }
+
+ log.info( status );
+
+ return status;
+ }
+
+ public void enableDataSynch()
+ {
+ }
+
+ public void disableDataSynch()
+ {
+ }
+
+ public boolean isDataSyncEnabled()
+ {
+ return false;
+ }
+
+ public boolean executeDataSynch()
+ {
+ Date now = new Date();
+
+ Date date = getLastSynchSuccess();
+
+ setLastSynchSuccess( now );
+
+ return true;
+ }
+
+ // -------------------------------------------------------------------------
+ // Supportive methods
+ // -------------------------------------------------------------------------
+
+ /**
+ * Gets the time of the last successful synchronization operation.
+ */
+ private Date getLastSynchSuccess()
+ {
+ Date date = (Date) systemSettingManager.getSystemSetting( KEY_LAST_SUCCESSFUL_SYNC );
+
+ return date != null ? date : new Cal().set( 0, 1, 1 ).time();
+ }
+
+ /**
+ * Sets the time of the last successful synchronization operation.
+ */
+ private void setLastSynchSuccess( Date date )
+ {
+ systemSettingManager.saveSystemSetting( KEY_LAST_SUCCESSFUL_SYNC, date );
+ }
+
+ /**
+ * Indicates whether a remote server has been properly configured.
+ */
+ private boolean isRemoteServerConfigured( Configuration config )
+ {
+ if ( trimToNull( config.getRemoteServerUrl() ) == null )
+ {
+ log.info( "Remote server URL not set" );
+ return false;
+ }
+
+ if ( trimToNull( config.getRemoteServerUsername() ) == null || trimToNull( config.getRemoteServerPassword() ) == null )
+ {
+ log.info( "Remote server username or password not set" );
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Creates an HTTP entity for requests with appropriate header for basic
+ * authentication.
+ */
+ private <T> HttpEntity<T> getBasicAuthRequestEntity( String username, String password )
+ {
+ HttpHeaders headers = new HttpHeaders();
+ headers.set( HEADER_AUTHORIZATION, CodecUtils.getBasicAuthString( username, password ) );
+ return new HttpEntity<T>( headers );
+ }
+}
=== added file 'dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/synch/SynchronizationManager.java'
--- dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/synch/SynchronizationManager.java 1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/synch/SynchronizationManager.java 2014-07-07 10:06:36 +0000
@@ -0,0 +1,12 @@
+package org.hisp.dhis.dxf2.synch;
+
+public interface SynchronizationManager
+{
+ AvailabilityStatus isRemoteServerAvailable();
+
+ boolean executeDataSynch();
+
+ void enableDataSynch();
+
+ void disableDataSynch();
+}
=== modified file 'dhis-2/dhis-services/dhis-service-dxf2/src/main/resources/META-INF/dhis/beans.xml'
--- dhis-2/dhis-services/dhis-service-dxf2/src/main/resources/META-INF/dhis/beans.xml 2014-06-20 11:14:18 +0000
+++ dhis-2/dhis-services/dhis-service-dxf2/src/main/resources/META-INF/dhis/beans.xml 2014-07-07 10:06:36 +0000
@@ -37,6 +37,8 @@
<bean id="org.hisp.dhis.dxf2.metadata.MetaDataDependencyService" class="org.hisp.dhis.dxf2.metadata.DefaultMetaDataDependencyService"
scope="prototype" />
+ <bean id="org.hisp.dhis.dxf2.synch.SynchronizationManager" class="org.hisp.dhis.dxf2.synch.DefaultSynchronizationManager" />
+
<!-- register idObject handlers -->
<bean id="organisationUnitObjectHandler"
=== modified file 'dhis-2/dhis-support/dhis-support-system/src/main/java/org/hisp/dhis/system/util/CodecUtils.java'
--- dhis-2/dhis-support/dhis-support-system/src/main/java/org/hisp/dhis/system/util/CodecUtils.java 2014-03-18 08:10:10 +0000
+++ dhis-2/dhis-support/dhis-support-system/src/main/java/org/hisp/dhis/system/util/CodecUtils.java 2014-07-07 10:06:36 +0000
@@ -38,7 +38,6 @@
/**
* @author Lars Helge Overland
- * @version $Id$
*/
public class CodecUtils
{
@@ -163,5 +162,12 @@
return string;
}
+
+ public static String getBasicAuthString( String username, String password )
+ {
+ String string = username + ":" + password;
+
+ return "Basic " + Base64.encodeBase64String( string.getBytes() );
+ }
}
=== modified file 'dhis-2/dhis-support/dhis-support-system/src/main/resources/META-INF/dhis/beans.xml'
--- dhis-2/dhis-support/dhis-support-system/src/main/resources/META-INF/dhis/beans.xml 2013-12-17 17:58:55 +0000
+++ dhis-2/dhis-support/dhis-support-system/src/main/resources/META-INF/dhis/beans.xml 2014-07-07 10:06:36 +0000
@@ -25,6 +25,8 @@
<property name="taskExecutor" ref="taskScheduler" />
</bean>
+ <bean id="restTemplate" class="org.springframework.web.client.RestTemplate"/>
+
<bean id="org.hisp.dhis.system.velocity.VelocityManager" class="org.hisp.dhis.system.velocity.VelocityManager" />
<bean id="notifier" class="org.hisp.dhis.system.notification.InMemoryNotifier" />
=== added file 'dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/controller/SynchronizationController.java'
--- dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/controller/SynchronizationController.java 1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/controller/SynchronizationController.java 2014-07-07 10:06:36 +0000
@@ -0,0 +1,60 @@
+package org.hisp.dhis.webapi.controller;
+
+/*
+ * 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 org.hisp.dhis.dxf2.synch.AvailabilityStatus;
+import org.hisp.dhis.dxf2.synch.SynchronizationManager;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.ResponseBody;
+import org.springframework.web.client.RestTemplate;
+
+/**
+ * @author Lars Helge Overland
+ */
+@Controller
+@RequestMapping( value = SynchronizationController.RESOURCE_PATH )
+public class SynchronizationController
+{
+ public static final String RESOURCE_PATH = "/synchronization";
+
+ @Autowired
+ private RestTemplate restTemplate;
+
+ @Autowired
+ private SynchronizationManager synchronizationManager;
+
+ @RequestMapping( value = "/availability", method = RequestMethod.GET, produces = "application/json" )
+ public @ResponseBody AvailabilityStatus isRemoteServerAvailable()
+ {
+ return synchronizationManager.isRemoteServerAvailable();
+ }
+}
=== modified file 'dhis-2/dhis-web/dhis-web-api/src/main/resources/META-INF/dhis/beans.xml'
--- dhis-2/dhis-web/dhis-web-api/src/main/resources/META-INF/dhis/beans.xml 2014-05-22 12:40:24 +0000
+++ dhis-2/dhis-web/dhis-web-api/src/main/resources/META-INF/dhis/beans.xml 2014-07-07 10:06:36 +0000
@@ -5,6 +5,5 @@
<bean id="contextUtils" class="org.hisp.dhis.webapi.utils.ContextUtils"/>
<bean id="inputUtils" class="org.hisp.dhis.webapi.utils.InputUtils" />
- <bean id="restTemplate" class="org.springframework.web.client.RestTemplate"/>
</beans>