diff --git a/license.txt b/license.txt new file mode 100644 index 0000000..28631e6 --- /dev/null +++ b/license.txt @@ -0,0 +1,32 @@ +==== + MOTECH PLATFORM OPENSOURCE LICENSE AGREEMENT + + Copyright (c) 2011 Grameen Foundation USA. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. 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. + + 3. Neither the name of Grameen Foundation USA, nor its respective contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY GRAMEEN FOUNDATION USA AND ITS 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 GRAMEEN FOUNDATION USA OR ITS 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. +==== + diff --git a/motech-delivery-config/motech-delivery-config.iml b/motech-delivery-config/motech-delivery-config.iml deleted file mode 100644 index ef582b1..0000000 --- a/motech-delivery-config/motech-delivery-config.iml +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/motech-delivery-config/pom.xml b/motech-delivery-config/pom.xml index 8b6bfc7..7238088 100644 --- a/motech-delivery-config/pom.xml +++ b/motech-delivery-config/pom.xml @@ -5,11 +5,9 @@ motech-delivery motech-delivery - 0.1 + 0.3-SNAPSHOT 4.0.0 - motech-delivery-config - - + Motech Delivery Config \ No newline at end of file diff --git a/motech-delivery-deploy/motech-delivery-deploy.iml b/motech-delivery-deploy/motech-delivery-deploy.iml deleted file mode 100644 index ef582b1..0000000 --- a/motech-delivery-deploy/motech-delivery-deploy.iml +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/motech-delivery-deploy/pom.xml b/motech-delivery-deploy/pom.xml index 851d249..7f92314 100644 --- a/motech-delivery-deploy/pom.xml +++ b/motech-delivery-deploy/pom.xml @@ -5,11 +5,9 @@ motech-delivery motech-delivery - 0.1 + 0.3-SNAPSHOT 4.0.0 - motech-delivery-deploy - - + Motech Delivery Deploy \ No newline at end of file diff --git a/motech-delivery-tools/motech-datetime-simulator/pom.xml b/motech-delivery-tools/motech-datetime-simulator/pom.xml new file mode 100644 index 0000000..8b3533f --- /dev/null +++ b/motech-delivery-tools/motech-datetime-simulator/pom.xml @@ -0,0 +1,63 @@ + + + + motech-delivery-tools + motech-delivery + 0.3-SNAPSHOT + + 4.0.0 + + motech-datetime-simulator + Motech DateTime Simulator + jar + + + 3.0.5.RELEASE + 1.6.1 + UTF-8 + 0.3-SNAPSHOT + + + + + org.springframework + spring-webmvc + ${spring.version} + + + commons-logging + commons-logging + + + + + org.motechproject + motech-platform-common + ${motech.version} + + + commons-lang + commons-lang + 2.6 + provided + + + javax.servlet + servlet-api + 2.5 + + + + + + + org.apache.maven.plugins + maven-war-plugin + 2.1.1 + + + + + \ No newline at end of file diff --git a/motech-delivery-tools/motech-datetime-simulator/src/main/java/org/motechproject/deliverytools/datetimesimulator/domain/TimeMachine.java b/motech-delivery-tools/motech-datetime-simulator/src/main/java/org/motechproject/deliverytools/datetimesimulator/domain/TimeMachine.java new file mode 100644 index 0000000..292c71f --- /dev/null +++ b/motech-delivery-tools/motech-datetime-simulator/src/main/java/org/motechproject/deliverytools/datetimesimulator/domain/TimeMachine.java @@ -0,0 +1,48 @@ +package org.motechproject.deliverytools.datetimesimulator.domain; + +import org.apache.commons.lang.StringUtils; +import org.joda.time.DateTime; +import org.joda.time.DateTimeZone; +import org.joda.time.LocalDate; +import org.motechproject.util.DateUtil; +import org.motechproject.util.datetime.DateTimeSource; + +public class TimeMachine implements DateTimeSource { + private String today; + private String hour; + private String minute; + private DateTimeSource dateTimeSource; + + public TimeMachine(DateTimeSource dateTimeSource) { + this.dateTimeSource = dateTimeSource; + } + + @Override + public DateTimeZone timeZone() { + return dateTimeSource.timeZone(); + } + + @Override + public DateTime now() { + DateTime dateTime = new DateTime(timeZone()); + LocalDate today = today(); + dateTime = dateTime.withYear(today.getYear()).withMonthOfYear(today.getMonthOfYear()).withDayOfMonth(today.getDayOfMonth()); + + if (StringUtils.isEmpty(hour) || StringUtils.isEmpty(minute)) return dateTime; + return dateTime.withHourOfDay(Integer.parseInt(hour)).withMinuteOfHour(Integer.parseInt(minute)); + } + + @Override + public LocalDate today() { + if (StringUtils.isEmpty(today)) return new LocalDate(timeZone()); + + LocalDate configuredDate = LocalDate.parse(today); + return new LocalDate(timeZone()).withYear(configuredDate.getYear()).withMonthOfYear(configuredDate.getMonthOfYear()).withDayOfMonth(configuredDate.getDayOfMonth()); + } + + public void update(String date, String hour, String minute) { + this.today = StringUtils.isEmpty(date) ? this.today : date; + this.hour = StringUtils.isEmpty(hour) ? this.hour : hour; + this.minute = StringUtils.isEmpty(minute) ? this.minute : minute; + } +} diff --git a/motech-delivery-tools/motech-datetime-simulator/src/main/java/org/motechproject/deliverytools/datetimesimulator/web/DateTimeController.java b/motech-delivery-tools/motech-datetime-simulator/src/main/java/org/motechproject/deliverytools/datetimesimulator/web/DateTimeController.java new file mode 100644 index 0000000..73d9fca --- /dev/null +++ b/motech-delivery-tools/motech-datetime-simulator/src/main/java/org/motechproject/deliverytools/datetimesimulator/web/DateTimeController.java @@ -0,0 +1,44 @@ +package org.motechproject.deliverytools.datetimesimulator.web; + +import org.apache.log4j.Logger; +import org.motechproject.deliverytools.datetimesimulator.domain.TimeMachine; +import org.motechproject.util.DateTimeSourceUtil; +import org.motechproject.util.DateUtil; +import org.motechproject.util.datetime.DefaultDateTimeSource; +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.RequestParam; +import org.springframework.web.bind.annotation.ResponseBody; + +import javax.servlet.http.HttpServletResponse; + +@RequestMapping("/motech-delivery-tools/datetime") +@Controller +public class DateTimeController { + private Logger logger = Logger.getLogger(this.getClass().getName()); + + @RequestMapping(value = "update", method = RequestMethod.GET) + @ResponseBody + public String update(@RequestParam String date, @RequestParam String hour, @RequestParam String minute, HttpServletResponse response) { + try { + TimeMachine sourceInstance; + if (!(DateTimeSourceUtil.SourceInstance instanceof TimeMachine)) { + DateTimeSourceUtil.SourceInstance = new TimeMachine(DateTimeSourceUtil.SourceInstance); + } + sourceInstance = (TimeMachine) DateTimeSourceUtil.SourceInstance; + sourceInstance.update(date, hour, minute); + return String.format("Successfully set datetime to: %s", DateUtil.now()); + } catch (Exception e) { + response.setStatus(500); + logger.error(String.format("Could not set the datetime from Date=%s, Hour=%s, Minute=%s. Did you use something like: 2011-10-17", date, hour, minute), e); + return e.toString(); + } + } + + @RequestMapping(value = "get", method = RequestMethod.GET) + @ResponseBody + public String get() { + return DateUtil.today().toString(); + } +} diff --git a/motech-delivery-tools/motech-datetime-simulator/src/main/resources/applicationDateTimeSimulatorContext.xml b/motech-delivery-tools/motech-datetime-simulator/src/main/resources/applicationDateTimeSimulatorContext.xml new file mode 100644 index 0000000..88a3d7a --- /dev/null +++ b/motech-delivery-tools/motech-datetime-simulator/src/main/resources/applicationDateTimeSimulatorContext.xml @@ -0,0 +1,9 @@ + + + + + \ No newline at end of file diff --git a/motech-delivery-tools/motech-datetime-simulator/src/test/java/org/motechproject/deliverytools/datetimesimulator/domain/TimeMachineTest.java b/motech-delivery-tools/motech-datetime-simulator/src/test/java/org/motechproject/deliverytools/datetimesimulator/domain/TimeMachineTest.java new file mode 100644 index 0000000..da0ed52 --- /dev/null +++ b/motech-delivery-tools/motech-datetime-simulator/src/test/java/org/motechproject/deliverytools/datetimesimulator/domain/TimeMachineTest.java @@ -0,0 +1,70 @@ +package org.motechproject.deliverytools.datetimesimulator.domain; + +import org.joda.time.DateTime; +import org.joda.time.DateTimeZone; +import org.joda.time.LocalDate; +import org.junit.Before; +import org.junit.Test; +import org.motechproject.util.datetime.DateTimeSource; + +import static junit.framework.Assert.assertEquals; +import static junit.framework.Assert.assertNotNull; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +public class TimeMachineTest { + private TimeMachine timeMachine; + + @Before + public void setUp() { + DateTimeSource dateTimeSource = mock(DateTimeSource.class); + when(dateTimeSource.timeZone()).thenReturn(DateTimeZone.UTC); + timeMachine = new TimeMachine(dateTimeSource); + } + + @Test + public void whenDateAndTimeIsNotSetShouldBeToday() { + assertNotNull(timeMachine.today()); + assertNotNull(timeMachine.now()); + } + + @Test + public void whenOnlyDateIsSetup() { + timeMachine.update("2011-10-17", "", null); + assertDate(); + } + + private void assertDate() { + //Joda should have used interface for getYear/month etc methods + LocalDate today = timeMachine.today(); + assertNotNull(today); + assertEquals(2011, today.getYear()); + assertEquals(10, today.getMonthOfYear()); + assertEquals(17, today.getDayOfMonth()); + + DateTime now = timeMachine.now(); + assertNotNull(now); + assertEquals(2011, now.getYear()); + assertEquals(10, now.getMonthOfYear()); + assertEquals(17, now.getDayOfMonth()); + } + + @Test + public void whenBothDateAndTimeIsSet() { + timeMachine.update("2011-10-17", "14", "20"); + assertDate(); + DateTime now = timeMachine.now(); + assertEquals(14, now.getHourOfDay()); + assertEquals(20, now.getMinuteOfHour()); + } + + @Test + public void useTheLastSetValues() { + timeMachine.update("2011-10-17", "14", "20"); + timeMachine.update(null, null, null); + assertDate(); + DateTime now = timeMachine.now(); + assertEquals(14, now.getHourOfDay()); + assertEquals(20, now.getMinuteOfHour()); + } +} diff --git a/motech-delivery-tools/motech-datetime-simulator/src/test/java/org/motechproject/deliverytools/datetimesimulator/web/DateTimeControllerTest.java b/motech-delivery-tools/motech-datetime-simulator/src/test/java/org/motechproject/deliverytools/datetimesimulator/web/DateTimeControllerTest.java new file mode 100644 index 0000000..e724da7 --- /dev/null +++ b/motech-delivery-tools/motech-datetime-simulator/src/test/java/org/motechproject/deliverytools/datetimesimulator/web/DateTimeControllerTest.java @@ -0,0 +1,61 @@ +package org.motechproject.deliverytools.datetimesimulator.web; + +import org.joda.time.DateTimeZone; +import org.junit.Before; +import org.junit.Test; +import org.motechproject.util.DateTimeSourceUtil; +import org.motechproject.util.DateUtil; +import org.motechproject.util.datetime.DateTimeConfiguration; +import org.motechproject.util.datetime.ExternalDateTimeSource; + +import javax.servlet.http.HttpServletResponse; + +import static junit.framework.Assert.assertEquals; +import static org.mockito.Mockito.*; + +public class DateTimeControllerTest { + private DateTimeController controller; + private HttpServletResponse servletResponse; + + @Before + public void setUp() { + controller = new DateTimeController(); + servletResponse = mock(HttpServletResponse.class); + } + + @Test + public void invalidInput() { + controller.update("afsdff", null, null, servletResponse); + verify(servletResponse).setStatus(500); + } + + @Test + public void todayIsNotSetWhenExternalDateTimeSourceIsNotSet() { + controller.update("2011-10-17", null, null, servletResponse); + verifyZeroInteractions(servletResponse); + } + + @Test + public void todayIsSet() { + DateTimeConfiguration dateTimeConfiguration = mock(DateTimeConfiguration.class); + when(dateTimeConfiguration.timeZone()).thenReturn(DateTimeZone.UTC); + DateTimeSourceUtil.SourceInstance = new ExternalDateTimeSource(dateTimeConfiguration); + + controller.update("2011-10-17", "", "", servletResponse); + assertEquals(10, DateUtil.today().getMonthOfYear()); + assertEquals(17, DateUtil.now().getDayOfMonth()); + verifyZeroInteractions(servletResponse); + } + + @Test + public void setTimeWithoutDate() { + DateTimeConfiguration dateTimeConfiguration = mock(DateTimeConfiguration.class); + when(dateTimeConfiguration.timeZone()).thenReturn(DateTimeZone.UTC); + DateTimeSourceUtil.SourceInstance = new ExternalDateTimeSource(dateTimeConfiguration); + + controller.update("2011-10-17", "14", "30", servletResponse); + assertEquals(10, DateUtil.today().getMonthOfYear()); + assertEquals(30, DateUtil.now().getMinuteOfHour()); + verifyZeroInteractions(servletResponse); + } +} diff --git a/motech-delivery-tools/motech-deliverytools-common/pom.xml b/motech-delivery-tools/motech-deliverytools-common/pom.xml new file mode 100644 index 0000000..5da27ac --- /dev/null +++ b/motech-delivery-tools/motech-deliverytools-common/pom.xml @@ -0,0 +1,15 @@ + + + + motech-delivery + motech-delivery + 0.3-SNAPSHOT + + 4.0.0 + + motech-deliverytools-common + Motech Delivery Common + + \ No newline at end of file diff --git a/motech-delivery-tools/motech-deliverytools-common/src/main/java/org/motechproject/deliverytools/common/DeliveryToolsObject.java b/motech-delivery-tools/motech-deliverytools-common/src/main/java/org/motechproject/deliverytools/common/DeliveryToolsObject.java new file mode 100644 index 0000000..56a3f26 --- /dev/null +++ b/motech-delivery-tools/motech-deliverytools-common/src/main/java/org/motechproject/deliverytools/common/DeliveryToolsObject.java @@ -0,0 +1,25 @@ +package org.motechproject.deliverytools.common; + +import org.apache.log4j.Logger; + +public class DeliveryToolsObject { + protected Logger logger = Logger.getLogger(this.getClass()); + + static { + doNotInheritRootLoggerFor("org.motechproject"); + doNotInheritRootLoggerFor("org.motechproject.deliverytools"); + } + + protected static void doNotInheritRootLoggerFor(String name) { + Logger logger = Logger.getLogger(name); + logger.setAdditivity(false); + } + + protected void logInfo(String message, String ... params) { + logger.info(String.format(message, params)); + } + + protected void logInfo(String message, Object ... params) { + logger.info(String.format(message, params)); + } +} diff --git a/motech-delivery-tools/motech-job-handler-invoker/logs/deliverytools.log b/motech-delivery-tools/motech-job-handler-invoker/logs/deliverytools.log new file mode 100644 index 0000000..e69de29 diff --git a/motech-delivery-tools/motech-job-handler-invoker/pom.xml b/motech-delivery-tools/motech-job-handler-invoker/pom.xml new file mode 100644 index 0000000..bedd6a3 --- /dev/null +++ b/motech-delivery-tools/motech-job-handler-invoker/pom.xml @@ -0,0 +1,73 @@ + + + + motech-delivery + motech-delivery + 0.3-SNAPSHOT + + 4.0.0 + + motech-job-handler-invoker + Motech Job Handler Invoker + + + 3.0.5.RELEASE + 1.6.1 + UTF-8 + 0.3-SNAPSHOT + + + + + org.springframework + spring-webmvc + ${spring.version} + + + commons-logging + commons-logging + + + + + org.motechproject + motech-platform-common + ${motech.version} + + + org.motechproject + motech-platform-scheduler + ${motech.version} + + + commons-lang + commons-lang + 2.6 + provided + + + javax.servlet + servlet-api + 2.5 + + + org.quartz-scheduler + quartz + 1.8.4 + + + org.motechproject.deliverytools + motech-deliverytools-common + 0.3-SNAPSHOT + + + org.springframework + spring-test + 3.0.5.RELEASE + test + + + + \ No newline at end of file diff --git a/motech-delivery-tools/motech-job-handler-invoker/src/main/java/org/motechproject/deliverytools/jobhandlerinvoker/AllScheduledJobs.java b/motech-delivery-tools/motech-job-handler-invoker/src/main/java/org/motechproject/deliverytools/jobhandlerinvoker/AllScheduledJobs.java new file mode 100644 index 0000000..0abf1a0 --- /dev/null +++ b/motech-delivery-tools/motech-job-handler-invoker/src/main/java/org/motechproject/deliverytools/jobhandlerinvoker/AllScheduledJobs.java @@ -0,0 +1,37 @@ +package org.motechproject.deliverytools.jobhandlerinvoker; + +import org.motechproject.deliverytools.jobhandlerinvoker.domain.ScheduledJob; +import org.motechproject.scheduler.MotechSchedulerServiceImpl; +import org.quartz.*; +import org.quartz.impl.StdSchedulerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.scheduling.quartz.SchedulerFactoryBean; +import org.springframework.stereotype.Component; + +@Component +public class AllScheduledJobs { + private SchedulerFactoryBean schedulerFactory; + private QueriedJobs queriedJobs; + + @Autowired + public AllScheduledJobs(SchedulerFactoryBean schedulerFactory, QueriedJobs queriedJobs) throws SchedulerException { + this.schedulerFactory = schedulerFactory; + this.queriedJobs = queriedJobs; + } + + public ScheduledJob get(String name) { + try { + Scheduler scheduler = schedulerFactory.getScheduler(); + JobDetail jobDetail = scheduler.getJobDetail(name, MotechSchedulerServiceImpl.JOB_GROUP_NAME); + if (jobDetail == null) + throw new IllegalArgumentException("No job named:" + name); + Trigger[] triggers = scheduler.getTriggersOfJob(name, MotechSchedulerServiceImpl.JOB_GROUP_NAME); + if (triggers.length == 0 || triggers.length > 1) + throw new AssertionError(String.format("There should be exactly one trigger for every job. Found %s triggers for %s", triggers.length, name)); + queriedJobs.add(name); + return new ScheduledJob(jobDetail, triggers[0]); + } catch (SchedulerException e) { + throw new RuntimeException(e); + } + } +} diff --git a/motech-delivery-tools/motech-job-handler-invoker/src/main/java/org/motechproject/deliverytools/jobhandlerinvoker/JobHandlerInvokeRequest.java b/motech-delivery-tools/motech-job-handler-invoker/src/main/java/org/motechproject/deliverytools/jobhandlerinvoker/JobHandlerInvokeRequest.java new file mode 100644 index 0000000..dc12cf1 --- /dev/null +++ b/motech-delivery-tools/motech-job-handler-invoker/src/main/java/org/motechproject/deliverytools/jobhandlerinvoker/JobHandlerInvokeRequest.java @@ -0,0 +1,52 @@ +package org.motechproject.deliverytools.jobhandlerinvoker; + +public class JobHandlerInvokeRequest { + private String className; + private String methodName; + private String jobId; + private boolean isRepeating; + + public String className() { + return className; + } + + public void setClassName(String className) { + this.className = className; + } + + public String methodName() { + return methodName; + } + + public void setMethodName(String methodName) { + this.methodName = methodName; + } + + public void setJobId(String jobId) { + this.jobId = jobId; + } + + public String jobId() { + return jobId; + } + + public boolean isRepeating() { + return isRepeating; + } + + public void setRepeating(boolean repeating) { + isRepeating = repeating; + } + + @Override + public String toString() { + final StringBuilder sb = new StringBuilder(); + sb.append("JobHandlerInvokeRequest"); + sb.append("{className='").append(className).append('\''); + sb.append(", methodName='").append(methodName).append('\''); + sb.append(", jobId='").append(jobId).append('\''); + sb.append(", isRepeating=").append(isRepeating); + sb.append('}'); + return sb.toString(); + } +} \ No newline at end of file diff --git a/motech-delivery-tools/motech-job-handler-invoker/src/main/java/org/motechproject/deliverytools/jobhandlerinvoker/QueriedJobs.java b/motech-delivery-tools/motech-job-handler-invoker/src/main/java/org/motechproject/deliverytools/jobhandlerinvoker/QueriedJobs.java new file mode 100644 index 0000000..df81ed8 --- /dev/null +++ b/motech-delivery-tools/motech-job-handler-invoker/src/main/java/org/motechproject/deliverytools/jobhandlerinvoker/QueriedJobs.java @@ -0,0 +1,25 @@ +package org.motechproject.deliverytools.jobhandlerinvoker; + +import org.springframework.stereotype.Component; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +@Component +public class QueriedJobs { + private Set jobNames = new HashSet(); + + public void add(String name) { + jobNames.add(name); + } + + public String[] list() { + return jobNames.toArray(new String[jobNames.size()]); + } + + public void clear() { + jobNames.clear(); + } +} diff --git a/motech-delivery-tools/motech-job-handler-invoker/src/main/java/org/motechproject/deliverytools/jobhandlerinvoker/ScheduledJobController.java b/motech-delivery-tools/motech-job-handler-invoker/src/main/java/org/motechproject/deliverytools/jobhandlerinvoker/ScheduledJobController.java new file mode 100644 index 0000000..bc3743d --- /dev/null +++ b/motech-delivery-tools/motech-job-handler-invoker/src/main/java/org/motechproject/deliverytools/jobhandlerinvoker/ScheduledJobController.java @@ -0,0 +1,94 @@ +package org.motechproject.deliverytools.jobhandlerinvoker; + +import org.apache.commons.lang.exception.ExceptionUtils; +import org.apache.log4j.Logger; +import org.motechproject.deliverytools.jobhandlerinvoker.domain.MotechEventInvocation; +import org.motechproject.deliverytools.jobhandlerinvoker.domain.ScheduledJob; +import org.motechproject.deliverytools.jobhandlerinvoker.domain.ScheduledJobName; +import org.motechproject.model.MotechEvent; +import org.motechproject.util.DateUtil; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationContext; +import org.springframework.stereotype.Controller; +import org.springframework.util.ReflectionUtils; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.ResponseBody; + +import javax.servlet.http.HttpServletResponse; +import java.lang.reflect.Method; +import java.util.Date; +import java.util.List; + +@RequestMapping("/motech-delivery-tools/jobhandler") +@Controller +public class ScheduledJobController { + private ApplicationContext applicationContext; + private AllScheduledJobs allScheduledJobs; + private QueriedJobs queriedJobs; + private Logger logger = Logger.getLogger(this.getClass().getName()); + + @Autowired + public ScheduledJobController(ApplicationContext applicationContext, AllScheduledJobs allScheduledJobs, QueriedJobs queriedJobs) { + this.applicationContext = applicationContext; + this.allScheduledJobs = allScheduledJobs; + this.queriedJobs = queriedJobs; + } + + @RequestMapping(value = "invoke", method = RequestMethod.GET) + @ResponseBody + public String invoke(JobHandlerInvokeRequest request, HttpServletResponse response) { + try { + String className = request.className(); + String beanName = className.substring(0, 1).toLowerCase() + className.substring(1, className.length()); + Object bean = applicationContext.getBean(beanName); + Method method = ReflectionUtils.findMethod(bean.getClass(), request.methodName(), MotechEvent.class); + + ScheduledJobName scheduledJobName = new ScheduledJobName(request.jobId(), method); + ScheduledJob scheduledJob = allScheduledJobs.get(scheduledJobName.jobId(request.isRepeating())); + MotechEventInvocation invocation = new MotechEventInvocation(scheduledJob); + ReflectionUtils.invokeMethod(method, bean, invocation.event()); + return "All Good"; + } catch (Throwable e) { + response.setStatus(500); + logger.error(String.format("Could not handle the request: %s", request.toString()), e); + return ExceptionUtils.getStackTrace(e); + } + } + + @RequestMapping(value = "list", method = RequestMethod.GET) + @ResponseBody + public String list(TriggerListRequest request) throws Exception { + try { + StringBuilder stringBuilder = new StringBuilder(); + stringBuilder.append("NOW: ").append(DateUtil.now().toDate().toString()).append("
"); + String[] jobNames = queriedJobs.list(); + for (String jobName : jobNames) { + ScheduledJob scheduledJob = allScheduledJobs.get(jobName); + stringBuilder.append(String.format("

%s

", jobName)); + + List triggerDateTimes = scheduledJob.triggerSummary(request.number()); + for (Date date : triggerDateTimes) { + stringBuilder.append(String.format("

%s

", date)); + } + stringBuilder.append("
"); + } + return stringBuilder.toString(); + } catch (Throwable e) { + logger.error("Could not handle the request to list", e); + return ExceptionUtils.getStackTrace(e); + } + } + + @RequestMapping(value = "clear", method = RequestMethod.GET) + @ResponseBody + public String clear() { + try { + queriedJobs.clear(); + return "All Good"; + } catch (Throwable e) { + logger.error("Could not handle the request to clear", e); + return ExceptionUtils.getStackTrace(e); + } + } +} diff --git a/motech-delivery-tools/motech-job-handler-invoker/src/main/java/org/motechproject/deliverytools/jobhandlerinvoker/TriggerListRequest.java b/motech-delivery-tools/motech-job-handler-invoker/src/main/java/org/motechproject/deliverytools/jobhandlerinvoker/TriggerListRequest.java new file mode 100644 index 0000000..cbd14e2 --- /dev/null +++ b/motech-delivery-tools/motech-job-handler-invoker/src/main/java/org/motechproject/deliverytools/jobhandlerinvoker/TriggerListRequest.java @@ -0,0 +1,13 @@ +package org.motechproject.deliverytools.jobhandlerinvoker; + +public class TriggerListRequest { + private int number; + + public void setNumber(int number) { + this.number = number; + } + + public int number() { + return number == 0 ? 3 : number; + } +} diff --git a/motech-delivery-tools/motech-job-handler-invoker/src/main/java/org/motechproject/deliverytools/jobhandlerinvoker/domain/MotechEventInvocation.java b/motech-delivery-tools/motech-job-handler-invoker/src/main/java/org/motechproject/deliverytools/jobhandlerinvoker/domain/MotechEventInvocation.java new file mode 100644 index 0000000..8e26231 --- /dev/null +++ b/motech-delivery-tools/motech-job-handler-invoker/src/main/java/org/motechproject/deliverytools/jobhandlerinvoker/domain/MotechEventInvocation.java @@ -0,0 +1,18 @@ +package org.motechproject.deliverytools.jobhandlerinvoker.domain; + +import org.motechproject.model.MotechEvent; + +import java.util.HashMap; +import java.util.Map; + +public class MotechEventInvocation { + private HashMap map = new HashMap(); + + public MotechEventInvocation(ScheduledJob scheduledJob) { + map.putAll(scheduledJob.payload()); + } + + public MotechEvent event() { + return new MotechEvent("notrelevant", map); + } +} diff --git a/motech-delivery-tools/motech-job-handler-invoker/src/main/java/org/motechproject/deliverytools/jobhandlerinvoker/domain/ScheduledJob.java b/motech-delivery-tools/motech-job-handler-invoker/src/main/java/org/motechproject/deliverytools/jobhandlerinvoker/domain/ScheduledJob.java new file mode 100644 index 0000000..5ff0663 --- /dev/null +++ b/motech-delivery-tools/motech-job-handler-invoker/src/main/java/org/motechproject/deliverytools/jobhandlerinvoker/domain/ScheduledJob.java @@ -0,0 +1,34 @@ +package org.motechproject.deliverytools.jobhandlerinvoker.domain; + +import org.motechproject.util.DateUtil; +import org.quartz.JobDetail; +import org.quartz.Trigger; + +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.Map; + +public class ScheduledJob { + private JobDetail jobDetail; + private Trigger trigger; + + public ScheduledJob(JobDetail jobDetail, Trigger trigger) { + this.jobDetail = jobDetail; + this.trigger = trigger; + } + + public List triggerSummary(int number) { + Date currentDateTime = DateUtil.now().toDate(); + ArrayList followingDates = new ArrayList(); + for (int i = 0; i < number; i++) { + currentDateTime = trigger.getFireTimeAfter(currentDateTime); + followingDates.add(currentDateTime); + } + return followingDates; + } + + public Map payload() { + return jobDetail.getJobDataMap().getWrappedMap(); + } +} diff --git a/motech-delivery-tools/motech-job-handler-invoker/src/main/java/org/motechproject/deliverytools/jobhandlerinvoker/domain/ScheduledJobName.java b/motech-delivery-tools/motech-job-handler-invoker/src/main/java/org/motechproject/deliverytools/jobhandlerinvoker/domain/ScheduledJobName.java new file mode 100644 index 0000000..07f7b39 --- /dev/null +++ b/motech-delivery-tools/motech-job-handler-invoker/src/main/java/org/motechproject/deliverytools/jobhandlerinvoker/domain/ScheduledJobName.java @@ -0,0 +1,23 @@ +package org.motechproject.deliverytools.jobhandlerinvoker.domain; + +import org.motechproject.scheduler.MotechSchedulerServiceImpl; +import org.motechproject.server.event.annotations.MotechListener; + +import java.lang.reflect.Method; + +public class ScheduledJobName { + private String uniqueId; + private Method method; + + public ScheduledJobName(String uniqueId, Method handlingMethod) { + this.uniqueId = uniqueId; + this.method = handlingMethod; + } + + public String jobId(boolean isRepeating) { + MotechListener annotation = method.getAnnotation(MotechListener.class); + String jobId = String.format("%s-%s", annotation.subjects()[0], uniqueId); + if (isRepeating) return jobId + MotechSchedulerServiceImpl.REPEAT_JOB_SUFFIX; + return jobId; + } +} diff --git a/motech-delivery-tools/motech-job-handler-invoker/src/main/resources/applicationJobHandlerInvokerContext.xml b/motech-delivery-tools/motech-job-handler-invoker/src/main/resources/applicationJobHandlerInvokerContext.xml new file mode 100644 index 0000000..7a0dfbd --- /dev/null +++ b/motech-delivery-tools/motech-job-handler-invoker/src/main/resources/applicationJobHandlerInvokerContext.xml @@ -0,0 +1,9 @@ + + + + + \ No newline at end of file diff --git a/motech-delivery-tools/motech-job-handler-invoker/src/test/java/org/motechproject/deliverytools/jobhandlerinvoker/AllScheduledJobsIT.java b/motech-delivery-tools/motech-job-handler-invoker/src/test/java/org/motechproject/deliverytools/jobhandlerinvoker/AllScheduledJobsIT.java new file mode 100644 index 0000000..80d8886 --- /dev/null +++ b/motech-delivery-tools/motech-job-handler-invoker/src/test/java/org/motechproject/deliverytools/jobhandlerinvoker/AllScheduledJobsIT.java @@ -0,0 +1,55 @@ +package org.motechproject.deliverytools.jobhandlerinvoker; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.motechproject.deliverytools.jobhandlerinvoker.domain.ScheduledJob; +import org.motechproject.scheduler.MotechSchedulerServiceImpl; +import org.motechproject.util.DateUtil; +import org.quartz.JobDataMap; +import org.quartz.JobDetail; +import org.quartz.SchedulerException; +import org.quartz.SimpleTrigger; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.scheduling.quartz.SchedulerFactoryBean; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import static junit.framework.Assert.assertEquals; +import static junit.framework.Assert.assertNotNull; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(locations = {"/applicationJobHandlerInvokerContextForTest.xml"}) +public class AllScheduledJobsIT { + @Autowired + private AllScheduledJobs allScheduledJobs; + @Autowired + private SchedulerFactoryBean schedulerFactory; + + private final String jobName = "jobNameForAllScheduledJobsIT"; + + @Before + public void setUp() throws SchedulerException { + schedulerFactory.getScheduler().deleteJob(jobName, MotechSchedulerServiceImpl.JOB_GROUP_NAME); + } + + @Test + public void shouldLoadJobFromQuartzDataStore() throws SchedulerException { + JobDetail jobDetail = new JobDetail(); + jobDetail.setName(jobName); + jobDetail.setGroup(MotechSchedulerServiceImpl.JOB_GROUP_NAME); + jobDetail.setJobClass(JobForAllScheduledJobsIT.class); + JobDataMap jobDataMap = new JobDataMap(); + jobDataMap.put("foo", "bar"); + jobDetail.setJobDataMap(jobDataMap); + + SimpleTrigger simpleTrigger = new SimpleTrigger(); + simpleTrigger.setName("triggerName"); + simpleTrigger.setStartTime(DateUtil.now().plusDays(1).toDate()); + schedulerFactory.getScheduler().scheduleJob(jobDetail, simpleTrigger); + ScheduledJob scheduledJob = allScheduledJobs.get(jobDetail.getName()); + assertNotNull(scheduledJob); + assertEquals("bar", scheduledJob.payload().get("foo")); + assertNotNull(scheduledJob.triggerSummary(1).get(0)); + } +} diff --git a/motech-delivery-tools/motech-job-handler-invoker/src/test/java/org/motechproject/deliverytools/jobhandlerinvoker/HandlerForJobHandlerInvokerTests.java b/motech-delivery-tools/motech-job-handler-invoker/src/test/java/org/motechproject/deliverytools/jobhandlerinvoker/HandlerForJobHandlerInvokerTests.java new file mode 100644 index 0000000..7d2b0e6 --- /dev/null +++ b/motech-delivery-tools/motech-job-handler-invoker/src/test/java/org/motechproject/deliverytools/jobhandlerinvoker/HandlerForJobHandlerInvokerTests.java @@ -0,0 +1,18 @@ +package org.motechproject.deliverytools.jobhandlerinvoker; + +import org.motechproject.model.MotechEvent; +import org.motechproject.server.event.annotations.MotechListener; + +public class HandlerForJobHandlerInvokerTests { + private MotechEvent motechEvent; + public static final String SAMPLE_SUBJECT = "SampleSubject"; + + public MotechEvent motechEvent() { + return motechEvent; + } + + @MotechListener(subjects = SAMPLE_SUBJECT) + public void handle(MotechEvent motechEvent) { + this.motechEvent = motechEvent; + } +} diff --git a/motech-delivery-tools/motech-job-handler-invoker/src/test/java/org/motechproject/deliverytools/jobhandlerinvoker/JobForAllScheduledJobsIT.java b/motech-delivery-tools/motech-job-handler-invoker/src/test/java/org/motechproject/deliverytools/jobhandlerinvoker/JobForAllScheduledJobsIT.java new file mode 100644 index 0000000..6bf647a --- /dev/null +++ b/motech-delivery-tools/motech-job-handler-invoker/src/test/java/org/motechproject/deliverytools/jobhandlerinvoker/JobForAllScheduledJobsIT.java @@ -0,0 +1,11 @@ +package org.motechproject.deliverytools.jobhandlerinvoker; + +import org.quartz.Job; +import org.quartz.JobExecutionContext; +import org.quartz.JobExecutionException; + +public class JobForAllScheduledJobsIT implements Job { + @Override + public void execute(JobExecutionContext context) throws JobExecutionException { + } +} diff --git a/motech-delivery-tools/motech-job-handler-invoker/src/test/java/org/motechproject/deliverytools/jobhandlerinvoker/ScheduledJobControllerTest.java b/motech-delivery-tools/motech-job-handler-invoker/src/test/java/org/motechproject/deliverytools/jobhandlerinvoker/ScheduledJobControllerTest.java new file mode 100644 index 0000000..871d11b --- /dev/null +++ b/motech-delivery-tools/motech-job-handler-invoker/src/test/java/org/motechproject/deliverytools/jobhandlerinvoker/ScheduledJobControllerTest.java @@ -0,0 +1,36 @@ +package org.motechproject.deliverytools.jobhandlerinvoker; + +import org.junit.Test; +import org.motechproject.deliverytools.common.DeliveryToolsObject; +import org.motechproject.deliverytools.jobhandlerinvoker.domain.ScheduledJob; +import org.quartz.JobDetail; +import org.springframework.context.ApplicationContext; + +import javax.servlet.http.HttpServletResponse; + +import static org.junit.Assert.assertNotNull; +import static org.mockito.Matchers.anyString; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +public class ScheduledJobControllerTest extends DeliveryToolsObject { + @Test + public void shouldInvoke() { + JobHandlerInvokeRequest request = new JobHandlerInvokeRequest(); + request.setClassName(HandlerForJobHandlerInvokerTests.class.getSimpleName()); + request.setMethodName("handle"); + request.setJobId("job1234"); + + ApplicationContext applicationContext = mock(ApplicationContext.class); + HandlerForJobHandlerInvokerTests jobHandler = new HandlerForJobHandlerInvokerTests(); + when(applicationContext.getBean("handlerForJobHandlerInvokerTests")).thenReturn(jobHandler); + + HttpServletResponse response = mock(HttpServletResponse.class); + AllScheduledJobs allScheduledJobs = mock(AllScheduledJobs.class); + when(allScheduledJobs.get(anyString())).thenReturn(new ScheduledJob(new JobDetail(), null)); + + ScheduledJobController controllerScheduled = new ScheduledJobController(applicationContext, allScheduledJobs, new QueriedJobs()); + controllerScheduled.invoke(request, response); + assertNotNull(jobHandler.motechEvent()); + } +} diff --git a/motech-delivery-tools/motech-job-handler-invoker/src/test/java/org/motechproject/deliverytools/jobhandlerinvoker/domain/ScheduledJobNameTest.java b/motech-delivery-tools/motech-job-handler-invoker/src/test/java/org/motechproject/deliverytools/jobhandlerinvoker/domain/ScheduledJobNameTest.java new file mode 100644 index 0000000..244742d --- /dev/null +++ b/motech-delivery-tools/motech-job-handler-invoker/src/test/java/org/motechproject/deliverytools/jobhandlerinvoker/domain/ScheduledJobNameTest.java @@ -0,0 +1,21 @@ +package org.motechproject.deliverytools.jobhandlerinvoker.domain; + +import org.junit.Test; +import org.motechproject.deliverytools.jobhandlerinvoker.HandlerForJobHandlerInvokerTests; +import org.motechproject.model.MotechEvent; +import org.motechproject.scheduler.MotechSchedulerServiceImpl; +import org.springframework.util.ReflectionUtils; + +import java.lang.reflect.Method; + +import static org.junit.Assert.assertEquals; + +public class ScheduledJobNameTest { + @Test + public void jobId() { + Method method = ReflectionUtils.findMethod(HandlerForJobHandlerInvokerTests.class, "handle", MotechEvent.class); + ScheduledJobName scheduledJobName = new ScheduledJobName("abcd", method); + assertEquals(String.format("%s-abcd", HandlerForJobHandlerInvokerTests.SAMPLE_SUBJECT), scheduledJobName.jobId(false)); + assertEquals(String.format("%s-abcd%s", HandlerForJobHandlerInvokerTests.SAMPLE_SUBJECT, MotechSchedulerServiceImpl.REPEAT_JOB_SUFFIX), scheduledJobName.jobId(true)); + } +} diff --git a/motech-delivery-tools/motech-job-handler-invoker/src/test/resources/applicationJobHandlerInvokerContextForTest.xml b/motech-delivery-tools/motech-job-handler-invoker/src/test/resources/applicationJobHandlerInvokerContextForTest.xml new file mode 100644 index 0000000..3d18e8e --- /dev/null +++ b/motech-delivery-tools/motech-job-handler-invoker/src/test/resources/applicationJobHandlerInvokerContextForTest.xml @@ -0,0 +1,14 @@ + + + + + classpath:quartz.properties + + + applicationContext + + + + \ No newline at end of file diff --git a/motech-delivery-tools/motech-job-handler-invoker/src/test/resources/log4j.xml b/motech-delivery-tools/motech-job-handler-invoker/src/test/resources/log4j.xml new file mode 100644 index 0000000..26969c3 --- /dev/null +++ b/motech-delivery-tools/motech-job-handler-invoker/src/test/resources/log4j.xml @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/motech-delivery-tools/motech-job-handler-invoker/src/test/resources/quartz.properties b/motech-delivery-tools/motech-job-handler-invoker/src/test/resources/quartz.properties new file mode 100644 index 0000000..63037ad --- /dev/null +++ b/motech-delivery-tools/motech-job-handler-invoker/src/test/resources/quartz.properties @@ -0,0 +1,6 @@ +org.quartz.scheduler.instanceName = MotechScheduler + +org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool +org.quartz.threadPool.threadCount = 3 + +org.quartz.jobStore.class = org.quartz.simpl.RAMJobStore diff --git a/motech-delivery-tools/motech-kookoo-automation/pom.xml b/motech-delivery-tools/motech-kookoo-automation/pom.xml new file mode 100644 index 0000000..9ff02be --- /dev/null +++ b/motech-delivery-tools/motech-kookoo-automation/pom.xml @@ -0,0 +1,53 @@ + + + + motech-delivery + motech-delivery + 0.3-SNAPSHOT + + 4.0.0 + + motech-kookoo-automation + Motech KooKoo Automation + + + 3.0.5.RELEASE + 1.6.1 + UTF-8 + 0.3-SNAPSHOT + + + + + org.springframework + spring-webmvc + ${spring.version} + + + commons-logging + commons-logging + + + + + org.motechproject + motech-platform-common + ${motech.version} + + + commons-lang + commons-lang + 2.6 + provided + + + org.motechproject + motech-ivr-kookoo + 0.3-SNAPSHOT + provided + + + + \ No newline at end of file diff --git a/motech-delivery-tools/motech-kookoo-automation/src/main/java/org/motechproject/deliverytools/kookoo/IncomingCall.java b/motech-delivery-tools/motech-kookoo-automation/src/main/java/org/motechproject/deliverytools/kookoo/IncomingCall.java new file mode 100644 index 0000000..669f874 --- /dev/null +++ b/motech-delivery-tools/motech-kookoo-automation/src/main/java/org/motechproject/deliverytools/kookoo/IncomingCall.java @@ -0,0 +1,49 @@ +package org.motechproject.deliverytools.kookoo; + +import com.google.gson.reflect.TypeToken; +import org.motechproject.dao.MotechJsonReader; +import org.motechproject.ivr.kookoo.KookooCallServiceImpl; + +import java.io.IOException; +import java.lang.reflect.Type; +import java.net.URL; +import java.net.URLDecoder; +import java.util.HashMap; + +public class IncomingCall { + private String apiKey; + private String phoneNumber; + private HashMap customParams; + + public IncomingCall(String queryString) throws IOException { + QueryParams queryParams = QueryParams.fromQueryString(queryString); + apiKey = queryParams.getString(KookooCallServiceImpl.API_KEY_KEY); + phoneNumber = queryParams.getString(KookooCallServiceImpl.PHONE_NUMBER_KEY); + + MotechJsonReader jsonReader = new MotechJsonReader(); + Type type = new TypeToken>() { + }.getType(); + + String urlString = URLDecoder.decode(URLDecoder.decode(queryParams.getString(KookooCallServiceImpl.URL_KEY), "UTF-8"), "UTF-8"); + URL callbackURL = new URL(urlString); + String customQuery = callbackURL.getQuery(); + QueryParams customQueryParams = QueryParams.fromQueryString(customQuery); + customParams = (HashMap) jsonReader.from(customQueryParams.getString(KookooCallServiceImpl.CUSTOM_DATA_KEY), type); + } + + public String apiKey() { + return apiKey; + } + + public String phoneNumber() { + return phoneNumber; + } + + public String customData(String customDataKey) { + return customParams.get(customDataKey); + } + + public HashMap customParams() { + return customParams; + } +} diff --git a/motech-delivery-tools/motech-kookoo-automation/src/main/java/org/motechproject/deliverytools/kookoo/QueryParams.java b/motech-delivery-tools/motech-kookoo-automation/src/main/java/org/motechproject/deliverytools/kookoo/QueryParams.java new file mode 100644 index 0000000..775d786 --- /dev/null +++ b/motech-delivery-tools/motech-kookoo-automation/src/main/java/org/motechproject/deliverytools/kookoo/QueryParams.java @@ -0,0 +1,38 @@ +package org.motechproject.deliverytools.kookoo; + +import org.apache.commons.lang.StringUtils; + +import java.util.HashMap; +import java.util.Map; +import java.util.StringTokenizer; + +public class QueryParams { + private Map params = new HashMap(); + + public static QueryParams fromQueryString(String string) { + QueryParams queryParams = new QueryParams(); + String[] keyValuePairs = StringUtils.split(string, "&"); + for (String keyValuePair : keyValuePairs) { + String[] keyAndValue = StringUtils.split(keyValuePair, "="); + queryParams.put(keyAndValue[0], keyAndValue[1]); + } + return queryParams; + } + + public QueryParams put(String key, Object value) { + params.put(key, value); + return this; + } + + public Map params() { + return params; + } + + public Object get(String key) { + return params.get(key); + } + + public String getString(String key) { + return (String) get(key); + } +} diff --git a/motech-delivery-tools/motech-kookoo-automation/src/test/java/org/motechproject/deliverytools/kookoo/IncomingCallTest.java b/motech-delivery-tools/motech-kookoo-automation/src/test/java/org/motechproject/deliverytools/kookoo/IncomingCallTest.java new file mode 100644 index 0000000..040a892 --- /dev/null +++ b/motech-delivery-tools/motech-kookoo-automation/src/test/java/org/motechproject/deliverytools/kookoo/IncomingCallTest.java @@ -0,0 +1,38 @@ +package org.motechproject.deliverytools.kookoo; + +import org.json.JSONObject; +import org.junit.Test; +import org.motechproject.ivr.kookoo.KookooCallServiceImpl; + +import java.io.IOException; +import java.net.URLEncoder; +import java.util.HashMap; + +import static junit.framework.Assert.assertEquals; + +public class IncomingCallTest { + @Test + public void shouldParseWebResponse() throws IOException { + HashMap customParams = new HashMap(); + customParams.put(KookooCallServiceImpl.IS_OUTBOUND_CALL, "true"); + JSONObject json = new JSONObject(customParams); + String callbackBaseURL = "http://fds"; + String callbackURL = String.format("%s?%s=%s", callbackBaseURL, KookooCallServiceImpl.CUSTOM_DATA_KEY, json.toString()); + + IncomingCall incomingCall = new IncomingCall(String.format("%s=foo&%s=676&%s=%s", + KookooCallServiceImpl.API_KEY_KEY, KookooCallServiceImpl.PHONE_NUMBER_KEY, + KookooCallServiceImpl.URL_KEY, URLEncoder.encode(callbackURL, "UTF-8"))); + assertEquals("foo", incomingCall.apiKey()); + assertEquals("676", incomingCall.phoneNumber()); + assertEquals("true", incomingCall.customData(KookooCallServiceImpl.IS_OUTBOUND_CALL)); + } + + @Test + public void doubleEncodedURL() throws IOException { + String callbackURL = "http%253A%252F%252Flocalhost%253A8080%252Ftama%252Fivr%252Freply%253FdataMap%253D%257B%2522is_outbound_call%2522%253A%2522true%2522%257D&phone_no=01705589013"; + IncomingCall incomingCall = new IncomingCall(String.format("%s=foo&%s=676&%s=%s", + KookooCallServiceImpl.API_KEY_KEY, KookooCallServiceImpl.PHONE_NUMBER_KEY, + KookooCallServiceImpl.URL_KEY, callbackURL)); + assertEquals("true", incomingCall.customData(KookooCallServiceImpl.IS_OUTBOUND_CALL)); + } +} diff --git a/motech-delivery-tools/motech-kookoo-automation/src/test/java/org/motechproject/deliverytools/kookoo/QueryParamsTest.java b/motech-delivery-tools/motech-kookoo-automation/src/test/java/org/motechproject/deliverytools/kookoo/QueryParamsTest.java new file mode 100644 index 0000000..f0f78b2 --- /dev/null +++ b/motech-delivery-tools/motech-kookoo-automation/src/test/java/org/motechproject/deliverytools/kookoo/QueryParamsTest.java @@ -0,0 +1,13 @@ +package org.motechproject.deliverytools.kookoo; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +public class QueryParamsTest { + @Test + public void fromQueryString() { + QueryParams queryParams = QueryParams.fromQueryString("foo=bar&baz=quack"); + assertEquals("bar", queryParams.get("foo")); + } +} diff --git a/motech-delivery-tools/motech-outbound-endpoint/pom.xml b/motech-delivery-tools/motech-outbound-endpoint/pom.xml new file mode 100644 index 0000000..f2eaaea --- /dev/null +++ b/motech-delivery-tools/motech-outbound-endpoint/pom.xml @@ -0,0 +1,57 @@ + + + + motech-delivery + motech-delivery + 0.3-SNAPSHOT + + 4.0.0 + + motech-outbound-endpoint + Motech Outbound Endpoint + + + 3.0.5.RELEASE + 1.6.1 + UTF-8 + 0.3-SNAPSHOT + + + + + org.springframework + spring-webmvc + ${spring.version} + + + commons-logging + commons-logging + + + + + org.motechproject + motech-platform-common + ${motech.version} + + + commons-lang + commons-lang + 2.6 + provided + + + javax.servlet + servlet-api + 2.5 + + + org.motechproject.deliverytools + motech-deliverytools-common + ${motech.version} + + + + \ No newline at end of file diff --git a/motech-delivery-tools/motech-outbound-endpoint/src/main/java/org/motechproject/deliverytools/outboundendpoint/GetLastReceivedRequest.java b/motech-delivery-tools/motech-outbound-endpoint/src/main/java/org/motechproject/deliverytools/outboundendpoint/GetLastReceivedRequest.java new file mode 100644 index 0000000..aa68af8 --- /dev/null +++ b/motech-delivery-tools/motech-outbound-endpoint/src/main/java/org/motechproject/deliverytools/outboundendpoint/GetLastReceivedRequest.java @@ -0,0 +1,13 @@ +package org.motechproject.deliverytools.outboundendpoint; + +public class GetLastReceivedRequest { + private int waitForSeconds; + + public void setWaitForSeconds(int waitForSeconds) { + this.waitForSeconds = waitForSeconds; + } + + public int waitForSeconds() { + return waitForSeconds; + } +} diff --git a/motech-delivery-tools/motech-outbound-endpoint/src/main/java/org/motechproject/deliverytools/outboundendpoint/HttpEndpoint.java b/motech-delivery-tools/motech-outbound-endpoint/src/main/java/org/motechproject/deliverytools/outboundendpoint/HttpEndpoint.java new file mode 100644 index 0000000..b2c3a22 --- /dev/null +++ b/motech-delivery-tools/motech-outbound-endpoint/src/main/java/org/motechproject/deliverytools/outboundendpoint/HttpEndpoint.java @@ -0,0 +1,50 @@ +package org.motechproject.deliverytools.outboundendpoint; + +import org.apache.log4j.Logger; +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 javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +@RequestMapping("/motech-delivery-tools/outbound") +@Controller +public class HttpEndpoint { + private static Request lastRequest; + private Logger logger = Logger.getLogger(this.getClass().getName()); + + @RequestMapping(value = "receive", method = RequestMethod.GET) + public void receive(HttpServletRequest servletRequest) { + String queryString = servletRequest.getQueryString(); + logger.info(String.format("Received request: %s", queryString)); + lastRequest = new Request(queryString); + } + + @RequestMapping(value = "lastreceived", method = RequestMethod.GET) + @ResponseBody + public String lastRequest(GetLastReceivedRequest getLastReceivedRequest, HttpServletResponse response) throws InterruptedException { + if (getLastReceivedRequest.waitForSeconds() > 0) { + for (int i = 0; i < getLastReceivedRequest.waitForSeconds(); i++) { + if (lastRequest != null) return lastRequestQuery(response); + Thread.sleep(1000); + } + } + return lastRequestQuery(response); + } + + private String lastRequestQuery(HttpServletResponse response) { + if (lastRequest == null) { + return ""; + } + return lastRequest.queryString(); + } + + @RequestMapping(value = "clear", method = RequestMethod.GET) + @ResponseBody + public String clear() { + lastRequest = null; + return "All Good"; + } +} diff --git a/motech-delivery-tools/motech-outbound-endpoint/src/main/java/org/motechproject/deliverytools/outboundendpoint/Request.java b/motech-delivery-tools/motech-outbound-endpoint/src/main/java/org/motechproject/deliverytools/outboundendpoint/Request.java new file mode 100644 index 0000000..b2d3a0b --- /dev/null +++ b/motech-delivery-tools/motech-outbound-endpoint/src/main/java/org/motechproject/deliverytools/outboundendpoint/Request.java @@ -0,0 +1,18 @@ +package org.motechproject.deliverytools.outboundendpoint; + +import org.codehaus.jackson.annotate.JsonProperty; + +import java.util.Map; + +public class Request { + @JsonProperty + private String queryString; + + public Request(String queryString) { + this.queryString = queryString; + } + + public String queryString() { + return queryString; + } +} diff --git a/motech-delivery-tools/pom.xml b/motech-delivery-tools/pom.xml new file mode 100644 index 0000000..db3d219 --- /dev/null +++ b/motech-delivery-tools/pom.xml @@ -0,0 +1,25 @@ + + + + motech-delivery + motech-delivery + 0.3-SNAPSHOT + + 4.0.0 + pom + Motech Delivery Tools + motech-delivery-tools + + + + motech-datetime-simulator + motech-deliverytools-common + motech-job-handler-invoker + motech-kookoo-automation + motech-outbound-endpoint + + + + \ No newline at end of file diff --git a/pom.xml b/pom.xml index d91a641..fcf7612 100644 --- a/pom.xml +++ b/pom.xml @@ -3,15 +3,253 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 - motech-delivery motech-delivery pom - 0.1 + 0.3-SNAPSHOT + Motech Delivery motech-delivery-config motech-delivery-deploy + motech-delivery-tools + + UTF-8 + 3.0.5.RELEASE + + + + + www.motechproject.org + file:////var/www/site + + + + + + motech-repo + Motech Maven Repository + http://nexus.motechproject.org/content/repositories/public + + + + + + motech-repo + Motech Maven Repository + http://nexus.motechproject.org/content/repositories/public + + true + + + + + + + + junit + junit + 4.8.2 + test + + + org.hamcrest + hamcrest-library + 1.1 + test + + + org.mockito + mockito-core + 1.8.5 + test + + + log4j + log4j + 1.2.16 + + + joda-time + joda-time + 2.0 + + + org.springframework + spring-core + ${spring.version} + + + commons-logging + commons-logging + + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 2.3.2 + + 1.6 + 1.6 + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.9 + + + **/**/*ForTest.java + + + + + org.apache.maven.plugins + maven-eclipse-plugin + 2.6 + + 2.0 + true + + + + com.mycila.maven-license-plugin + maven-license-plugin + 1.9.0 + +
header.txt
+ true + + **/jquery-autocomplete/** + +
+
+ + org.apache.maven.plugins + maven-site-plugin + 2.2 + + + org.apache.maven.plugins + maven-failsafe-plugin + 2.9 + + UTF-8 + + + + +
+
+ + + + + org.apache.maven.plugins + maven-plugin-plugin + 2.7 + + + org.apache.maven.plugins + maven-surefire-report-plugin + 2.9 + + ${project.reporting.outputDirectory}/../xref-test + true + + + + org.apache.maven.plugins + maven-jxr-plugin + 2.1 + + true + + + + org.apache.maven.plugins + maven-javadoc-plugin + 2.7 + + true + + + + aggregate + + aggregate + + + + + + org.apache.maven.plugins + maven-pmd-plugin + 2.5 + + ${project.reporting.outputDirectory}/../xref + + + + org.apache.maven.plugins + maven-project-info-reports-plugin + 2.3.1 + + + + index + dependencies + mailing-list + cim + issue-tracking + license + scm + summary + + + + + + org.codehaus.mojo + taglist-maven-plugin + 2.4 + + + + + + + + MOTECH PLATFORM OPENSOURCE LICENSE AGREEMENT + license.txt + + + + + hudson + http://ci.motechproject.org/ + + + + + MOTECH Dev + motech-dev+subscribe@googlegroups.com + motech-dev+unsubscribe@googlegroups.com + motech-dev@googlegroups.com + http://groups.google.com/group/motech-dev + + + + + scm:git:http://github.com/motech/motech-delivery-tools.git + scm:git:git@github.com:motech/motech-delivery-tools.git + http://github.com/motech/motech-delivery-tools + \ No newline at end of file