diff --git a/config/alfresco/templates/webscripts/org/alfresco/repository/publishing/publishing-events-query.post.json.ftl b/config/alfresco/templates/webscripts/org/alfresco/repository/publishing/publishing-events-query.post.json.ftl new file mode 100644 index 0000000000..ab6b289ccd --- /dev/null +++ b/config/alfresco/templates/webscripts/org/alfresco/repository/publishing/publishing-events-query.post.json.ftl @@ -0,0 +1,6 @@ +<#-- List Channels --> +<#import "publishing.lib.ftl" as publishLib /> +{ + "data": + <@publishLib.eventsJSON events=data /> +} diff --git a/config/alfresco/templates/webscripts/org/alfresco/repository/publishing/publishing-queue.post.desc.xml b/config/alfresco/templates/webscripts/org/alfresco/repository/publishing/publishing-queue.post.desc.xml index 75591cb40e..17cc3376c4 100644 --- a/config/alfresco/templates/webscripts/org/alfresco/repository/publishing/publishing-queue.post.desc.xml +++ b/config/alfresco/templates/webscripts/org/alfresco/repository/publishing/publishing-queue.post.desc.xml @@ -25,7 +25,7 @@ { "channelName": string, "comment": string, - "schedule": + "scheduledTime": { "dateTime": string, "format": string, diff --git a/config/alfresco/templates/webscripts/org/alfresco/repository/publishing/publishing.lib.ftl b/config/alfresco/templates/webscripts/org/alfresco/repository/publishing/publishing.lib.ftl index 8d0e64aa7b..9ed996f173 100644 --- a/config/alfresco/templates/webscripts/org/alfresco/repository/publishing/publishing.lib.ftl +++ b/config/alfresco/templates/webscripts/org/alfresco/repository/publishing/publishing.lib.ftl @@ -1,3 +1,62 @@ +<#-- Renders a List of Publishing Events --> +<#macro eventsJSON events> +<#escape x as jsonUtils.encodeJSONString(x)> +[ + <#if events??> + <#list events as event> + <@eventJSON event=event /> + <#if event_has_next>, + + +] + + + + +<#-- Renders a Publishing Event. --> +<#macro eventJSON event> +{ + "id": "${event.id}", + "url": "${event.url}", + "status": "${event.status}", + <#if event.comment?? >"comment": "${event.comment}", + <#if event.scheduledTime?? > + "scheduledTime": + <@calendarJSON calendar=event.scheduledTime />, + + "creator": "${event.creator}", + "createdTime": + <@dateJSON date=event.createdTime/>, + "publishNodes": + <@publishNodesJSON nodes=event.publishNodes/>, + "unpublishNodes": + <@publishNodesJSON nodes=event.unpublishNodes/>, + "channel": + <@channelJSON channel=event.channel/> +} + + +<#-- Renders a List of Nodes to be published/unpublished. --> +<#macro publishNodesJSON nodes> +[ + <#if nodes??> + <#list nodes as node> + <@publishNodeJSON node=node/> + <#if node_has_next>, + + +] + + +<#-- Renders a Published/Unpublished Node. --> +<#macro publishNodeJSON node> +{ + <#if node.name?? >"name": "${node.name}", + <#if node.version?? >"version": "${node.version}", + "nodeRef": "${node.nodeRef}" +} + + <#-- Renders a List of Channel.s --> <#macro channelsJSON channels> <#escape x as jsonUtils.encodeJSONString(x)> @@ -55,3 +114,20 @@ [] + +<#-- Renders a date. --> +<#macro dateJSON date> +{ + "dateTime": "${date.dateTime}", + "format": "${date.format}" +} + + +<#-- Renders a calendar. --> +<#macro calendarJSON calendar> +{ + "dateTime": "${calendar.dateTime}", + "format": "${calendar.format}", + "timeZone": "${calendar.timeZone}" +} + diff --git a/config/alfresco/web-scripts-application-context.xml b/config/alfresco/web-scripts-application-context.xml index 80e788a2a4..0bcddaafd8 100644 --- a/config/alfresco/web-scripts-application-context.xml +++ b/config/alfresco/web-scripts-application-context.xml @@ -1114,6 +1114,16 @@ class="org.alfresco.repo.web.scripts.publishing.PublishingQueuePost" parent="webscript"> + + + + + + + + @@ -1449,4 +1459,4 @@ parent="abstractCalendarWebScript"> - + \ No newline at end of file diff --git a/source/java/org/alfresco/repo/web/scripts/WebScriptUtil.java b/source/java/org/alfresco/repo/web/scripts/WebScriptUtil.java new file mode 100644 index 0000000000..45a7ac7c0d --- /dev/null +++ b/source/java/org/alfresco/repo/web/scripts/WebScriptUtil.java @@ -0,0 +1,147 @@ +/* + * Copyright (C) 2005-2010 Alfresco Software Limited. + * + * This file is part of Alfresco + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + */ + +package org.alfresco.repo.web.scripts; + +import java.io.IOException; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Calendar; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.TimeZone; + +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.util.ISO8601DateFormat; +import org.json.JSONObject; +import org.springframework.extensions.surf.util.Content; +import org.springframework.extensions.webscripts.WebScriptRequest; + +/** + * @author Nick Smith + * @since 4.0 + * + */ +public class WebScriptUtil +{ + // General Keys + public static final String DATA_KEY = "data"; + + // NodeRef Keys + public static final String STORE_PROTOCOL = "store_protocol"; + public static final String STORE_ID = "store_id"; + public static final String NODE_ID = "node_id"; + + //Date/Calendar Keys + public static final String DATE_TIME= "dateTime"; + public static final String FORMAT= "format"; + public static final String TIME_ZONE= "timeZone"; + public static final String ISO8601 = "ISO8601"; + + public static String getContent(WebScriptRequest request) throws IOException + { + Content content = request.getContent(); + return content.getContent(); + } + + public static Map buildCalendarModel(Calendar calendar) + { + Map model = buildDateModel(calendar.getTime()); + model.put(TIME_ZONE, calendar.getTimeZone().getID()); + return model; + } + + public static Map buildDateModel(Date dateTime) + { + String dateStr = ISO8601DateFormat.format(dateTime); + Map model = new HashMap(); + model.put(DATE_TIME, dateStr); + model.put(FORMAT, ISO8601); + return model; + } + + public static Calendar getCalendar(JSONObject json) throws ParseException + { + Date date = getDate(json); + if(date == null) + { + return null; + } + Calendar calendar = Calendar.getInstance(); + String timeZone = json.optString(TIME_ZONE); + if(timeZone != null) + { + TimeZone zone = TimeZone.getTimeZone(timeZone); + calendar.setTimeZone(zone); + } + calendar.setTime(date); + return calendar; + } + + public static Date getDate(JSONObject json) throws ParseException + { + if(json == null) + { + return null; + } + String dateTime = json.optString(DATE_TIME); + if(dateTime == null) + { + return null; + } + String format = json.optString(FORMAT); + if(format!= null && ISO8601.equals(format) == false) + { + SimpleDateFormat dateFormat = new SimpleDateFormat(format); + return dateFormat.parse(dateTime); + } + return ISO8601DateFormat.parse(dateTime); + } + + + public static Map createBaseModel(Map result) + { + Map model = new HashMap(); + model.put(DATA_KEY, result); + return model; + } + + public static Map createBaseModel(List> results) + { + Map model = new HashMap(); + model.put(DATA_KEY, results); + return model; + } + + public static NodeRef getNodeRef(Map params) + { + String protocol = params.get(STORE_PROTOCOL); + String storeId= params.get(STORE_ID); + String nodeId= params.get(NODE_ID); + if(protocol == null || storeId == null || nodeId==null ) + { + return null; + } + return new NodeRef(protocol, storeId, nodeId); + } + + +} diff --git a/source/java/org/alfresco/repo/web/scripts/publishing/AbstractPublishingWebscript.java b/source/java/org/alfresco/repo/web/scripts/publishing/AbstractPublishingWebscript.java deleted file mode 100644 index 0b6637d6e1..0000000000 --- a/source/java/org/alfresco/repo/web/scripts/publishing/AbstractPublishingWebscript.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (C) 2005-2010 Alfresco Software Limited. - * - * This file is part of Alfresco - * - * Alfresco is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Alfresco is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Alfresco. If not, see . - */ - -package org.alfresco.repo.web.scripts.publishing; - -/** - * @author Nick Smith - * @since 4.0 - * - */ -public class AbstractPublishingWebscript -{ - -} diff --git a/source/java/org/alfresco/repo/web/scripts/publishing/ChannelsGet.java b/source/java/org/alfresco/repo/web/scripts/publishing/ChannelsGet.java index 24d6f69725..04515109bd 100644 --- a/source/java/org/alfresco/repo/web/scripts/publishing/ChannelsGet.java +++ b/source/java/org/alfresco/repo/web/scripts/publishing/ChannelsGet.java @@ -19,12 +19,18 @@ package org.alfresco.repo.web.scripts.publishing; +import static org.alfresco.repo.web.scripts.publishing.PublishingWebScriptConstants.PUBLISHING_CHANNELS; +import static org.alfresco.repo.web.scripts.publishing.PublishingWebScriptConstants.SITE_ID; +import static org.alfresco.repo.web.scripts.publishing.PublishingWebScriptConstants.STATUS_UPDATE_CHANNELS; +import static org.alfresco.repo.web.scripts.publishing.PublishingWebScriptConstants.URL_LENGTH; + import java.util.HashMap; import java.util.List; import java.util.Map; import javax.servlet.http.HttpServletResponse; +import org.alfresco.repo.web.scripts.WebScriptUtil; import org.alfresco.service.cmr.publishing.channels.Channel; import org.alfresco.service.cmr.publishing.channels.ChannelService; import org.alfresco.service.cmr.repository.NodeRef; @@ -41,17 +47,7 @@ import org.springframework.extensions.webscripts.WebScriptRequest; */ public class ChannelsGet extends DeclarativeWebScript { - public static final String SITE_ID = "site_id"; - public static final String STORE_PROTOCOL = "store_protocol"; - public static final String STORE_ID = "store_id"; - public static final String NODE_ID = "node_id"; - - // Model Keys - public static final String DATA_KEY = "data"; - public static final String URL_LENGTH = "urlLength"; - public static final String PUBLISHING_CHANNELS = "publishChannels"; - public static final String STATUS_UPDATE_CHANNELS = "statusUpdateChannels"; - + private final PublishingModelBuilder builder = new PublishingModelBuilder(); private ChannelService channelService; /** @@ -59,13 +55,6 @@ public class ChannelsGet extends DeclarativeWebScript */ @Override protected Map executeImpl(WebScriptRequest req, Status status, Cache cache) - { - PublishingModelBuilder builder = new PublishingModelBuilder(); - return buildModel(builder, req, status, cache); - } - - private Map buildModel(PublishingModelBuilder builder, - WebScriptRequest req, Status status, Cache cache) { Map params = req.getServiceMatch().getTemplateVars(); String siteId = params.get(SITE_ID); @@ -79,7 +68,7 @@ public class ChannelsGet extends DeclarativeWebScript } else { - NodeRef node = getNodeRef(params); + NodeRef node = WebScriptUtil.getNodeRef(params); if(node == null) { String msg = "Either a Site ID or valid NodeRef must be specified!"; @@ -96,33 +85,7 @@ public class ChannelsGet extends DeclarativeWebScript model.put(PUBLISHING_CHANNELS, builder.buildChannels(publishingChannels)); model.put(STATUS_UPDATE_CHANNELS, builder.buildChannels(statusUpdateChannels)); - return createBaseModel(model); - } - - private NodeRef getNodeRef(Map params) - { - String protocol = params.get(STORE_PROTOCOL); - String storeId= params.get(STORE_ID); - String nodeId= params.get(NODE_ID); - if(protocol == null || storeId == null || nodeId==null ) - { - return null; - } - return new NodeRef(protocol, storeId, nodeId); - } - - protected Map createBaseModel(Map result) - { - Map model = new HashMap(); - model.put(DATA_KEY, result); - return model; - } - - protected Map createBaseModel(List> results) - { - Map model = new HashMap(); - model.put(DATA_KEY, results); - return model; + return WebScriptUtil.createBaseModel(model); } /** diff --git a/source/java/org/alfresco/repo/web/scripts/publishing/PUblishingEventsQueryPost.java b/source/java/org/alfresco/repo/web/scripts/publishing/PUblishingEventsQueryPost.java new file mode 100644 index 0000000000..9bb7aba111 --- /dev/null +++ b/source/java/org/alfresco/repo/web/scripts/publishing/PUblishingEventsQueryPost.java @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2005-2010 Alfresco Software Limited. + * + * This file is part of Alfresco + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + */ + +package org.alfresco.repo.web.scripts.publishing; + +import java.util.List; +import java.util.Map; + +import javax.servlet.http.HttpServletResponse; + +import org.alfresco.repo.web.scripts.WebScriptUtil; +import org.alfresco.service.cmr.publishing.Environment; +import org.alfresco.service.cmr.publishing.PublishingEvent; +import org.alfresco.util.Pair; +import org.springframework.extensions.webscripts.Cache; +import org.springframework.extensions.webscripts.Status; +import org.springframework.extensions.webscripts.WebScriptException; +import org.springframework.extensions.webscripts.WebScriptRequest; + +/** + * @author Nick Smith + * @since 4.0 + * + */ +public class PUblishingEventsQueryPost extends PublishingEnvironmentWebScript +{ + /** + * {@inheritDoc} + */ + @Override + protected Map executeImpl(WebScriptRequest req, Status status, Cache cache) + { + Pair siteAndEnvironment = getSiteAndEnvironment(req); + String siteId = siteAndEnvironment.getFirst(); + Environment environment = siteAndEnvironment.getSecond(); + String content = null; + try + { + content = WebScriptUtil.getContent(req); + List events = jsonParser.query(environment, content); + List> model = builder.buildPublishingEvents(events, channelService, siteId); + return WebScriptUtil.createBaseModel(model); + } + catch(Exception e) + { + String msg = "Failed to query for publishing events. POST body: " + content; + throw new WebScriptException(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, msg, e); + } + } +} \ No newline at end of file diff --git a/source/java/org/alfresco/repo/web/scripts/publishing/PublishingEnvironmentWebScript.java b/source/java/org/alfresco/repo/web/scripts/publishing/PublishingEnvironmentWebScript.java new file mode 100644 index 0000000000..b7ad359269 --- /dev/null +++ b/source/java/org/alfresco/repo/web/scripts/publishing/PublishingEnvironmentWebScript.java @@ -0,0 +1,104 @@ +/* + * Copyright (C) 2005-2010 Alfresco Software Limited. + * + * This file is part of Alfresco + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + */ + +package org.alfresco.repo.web.scripts.publishing; + +import static org.alfresco.repo.web.scripts.publishing.PublishingWebScriptConstants.ENVIRONMENT_ID; +import static org.alfresco.repo.web.scripts.publishing.PublishingWebScriptConstants.SITE_ID; + +import java.util.Map; + +import javax.servlet.http.HttpServletResponse; + +import org.alfresco.service.cmr.publishing.Environment; +import org.alfresco.service.cmr.publishing.PublishingService; +import org.alfresco.service.cmr.publishing.channels.ChannelService; +import org.alfresco.util.Pair; +import org.springframework.extensions.webscripts.DeclarativeWebScript; +import org.springframework.extensions.webscripts.WebScriptException; +import org.springframework.extensions.webscripts.WebScriptRequest; + +/** + * @author Nick Smith + * @since 4.0 + * + */ +public abstract class PublishingEnvironmentWebScript extends DeclarativeWebScript +{ + protected final PublishingJsonParser jsonParser = new PublishingJsonParser(); + protected final PublishingModelBuilder builder= new PublishingModelBuilder(); + + protected PublishingService publishingService; + protected ChannelService channelService; + private String defaultEnvironmentId; + + protected Pair getSiteAndEnvironment(WebScriptRequest req) + { + Map params = req.getServiceMatch().getTemplateVars(); + String siteId = params.get(SITE_ID); + + if(siteId == null) + { + String msg = "A Site ID must be specified!"; + throw new WebScriptException(HttpServletResponse.SC_BAD_REQUEST, msg); + } + String environmentId = params.get(ENVIRONMENT_ID); + if(environmentId == null) + { + if(defaultEnvironmentId == null) + { + String msg = "An Environment ID must be specified!"; + throw new WebScriptException(HttpServletResponse.SC_BAD_REQUEST, msg); + } + environmentId = defaultEnvironmentId; + } + + Environment environment = publishingService.getEnvironment(siteId, environmentId); + if(environment == null) + { + String msg = "Environment " +environmentId + " does not exist in site " +siteId; + throw new WebScriptException(HttpServletResponse.SC_BAD_REQUEST, msg); + } + return new Pair(siteId, environment); + } + + /** + * @param defaultEnvironmentId the defaultEnvironmentId to set + */ + public void setDefaultEnvironmentId(String defaultEnvironmentId) + { + this.defaultEnvironmentId = defaultEnvironmentId; + } + + /** + * @param publishingService the publishingService to set + */ + public void setPublishingService(PublishingService publishingService) + { + this.publishingService = publishingService; + } + + /** + * @param channelService the channelService to set + */ + public void setChannelService(ChannelService channelService) + { + this.channelService = channelService; + } +} \ No newline at end of file diff --git a/source/java/org/alfresco/repo/web/scripts/publishing/PublishingJsonParser.java b/source/java/org/alfresco/repo/web/scripts/publishing/PublishingJsonParser.java index 53207ca919..651d1281bb 100644 --- a/source/java/org/alfresco/repo/web/scripts/publishing/PublishingJsonParser.java +++ b/source/java/org/alfresco/repo/web/scripts/publishing/PublishingJsonParser.java @@ -19,22 +19,36 @@ package org.alfresco.repo.web.scripts.publishing; +import static org.alfresco.repo.web.scripts.WebScriptUtil.getCalendar; +import static org.alfresco.repo.web.scripts.publishing.PublishingWebScriptConstants.CHANNEL_NAME; +import static org.alfresco.repo.web.scripts.publishing.PublishingWebScriptConstants.CHANNEL_NAMES; +import static org.alfresco.repo.web.scripts.publishing.PublishingWebScriptConstants.COMMENT; +import static org.alfresco.repo.web.scripts.publishing.PublishingWebScriptConstants.IDS; +import static org.alfresco.repo.web.scripts.publishing.PublishingWebScriptConstants.MESSAGE; +import static org.alfresco.repo.web.scripts.publishing.PublishingWebScriptConstants.NODE_REF; +import static org.alfresco.repo.web.scripts.publishing.PublishingWebScriptConstants.PUBLISH_NODES; +import static org.alfresco.repo.web.scripts.publishing.PublishingWebScriptConstants.SCHEDULED_TIME; +import static org.alfresco.repo.web.scripts.publishing.PublishingWebScriptConstants.STATUS_UPDATE; +import static org.alfresco.repo.web.scripts.publishing.PublishingWebScriptConstants.UNPUBLISH_NODES; + import java.text.ParseException; -import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Calendar; import java.util.Collection; import java.util.Collections; -import java.util.Date; import java.util.List; -import java.util.TimeZone; +import org.alfresco.repo.node.NodeUtils; +import org.alfresco.service.cmr.publishing.Environment; import org.alfresco.service.cmr.publishing.MutablePublishingPackage; +import org.alfresco.service.cmr.publishing.PublishingEvent; +import org.alfresco.service.cmr.publishing.PublishingEventFilter; import org.alfresco.service.cmr.publishing.PublishingPackage; import org.alfresco.service.cmr.publishing.PublishingQueue; import org.alfresco.service.cmr.publishing.StatusUpdate; import org.alfresco.service.cmr.repository.NodeRef; -import org.alfresco.util.ISO8601DateFormat; +import org.alfresco.util.collections.Function; +import org.alfresco.util.collections.JsonUtils; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; @@ -47,33 +61,42 @@ import org.json.JSONTokener; */ public class PublishingJsonParser { - /** - * - */ - public static final String STATUS_UPDATE = "statusUpdate"; - public static final String SCHEDULE = "schedule"; - public static final String COMMENT = "comment"; - public static final String CHANNEL_NAME = "channelName"; - public static final String CHANNEL_NAMES = "channelNames"; - public static final String NODE_REF = "nodeRef"; - public static final String MESSAGE = "message"; - public static final String UNPUBLISH_NODES = "unpublishNodes"; - public static final String PUBLISH_NODES = "publishNodes"; - public static final String TIME_ZONE = "timeZone"; - public static final String FORMAT = "format"; - public static final String DATE_TIME = "dateTime"; public JSONObject getJson(String jsonStr) throws JSONException { - return new JSONObject(new JSONTokener(jsonStr)); + if(jsonStr!=null && jsonStr.isEmpty()==false) + { + return new JSONObject(new JSONTokener(jsonStr)); + } + return new JSONObject(); } + public List query(Environment environment, String content) throws JSONException + { + JSONObject json = getJson(content); + PublishingEventFilter filter = buildFilter(environment, json); + return environment.getPublishingEvents(filter); + } + + private PublishingEventFilter buildFilter(Environment environment, JSONObject json) + { + List publishNodes = toNodes(json.optJSONArray(PUBLISH_NODES)); + List unpublishNodes = toNodes(json.optJSONArray(UNPUBLISH_NODES)); + List ids = JsonUtils.toListOfStrings(json.optJSONArray(IDS)); + + PublishingEventFilter filter = environment.createPublishingEventFilter() + .setIds(ids) + .setPublishedNodes(publishNodes) + .setUnpublishedNodes(unpublishNodes); + return filter; + } + public String schedulePublishingEvent(PublishingQueue queue, String jsonStr) throws ParseException, JSONException { JSONObject json = getJson(jsonStr); String channelName = json.optString(CHANNEL_NAME); String comment = json.optString(COMMENT); - Calendar schedule = getCalendar(json.optJSONObject(SCHEDULE)); + Calendar schedule = getCalendar(json.optJSONObject(SCHEDULED_TIME)); PublishingPackage publishingPackage = getPublishingPackage(queue, json); StatusUpdate statusUpdate = getStatusUpdate(queue, json.optJSONObject(STATUS_UPDATE)); return queue.scheduleNewEvent(publishingPackage, channelName, schedule, comment, statusUpdate); @@ -108,17 +131,8 @@ public class PublishingJsonParser public List toNodes(JSONArray json) { - if(json == null || json.length() == 0) - { - return Collections.emptyList(); - } - ArrayList results = new ArrayList(json.length()); - for (int i = 0; i < json.length(); i++) - { - String nodeStr = json.optString(i); - results.add(new NodeRef(nodeStr)); - } - return results; + Function transformer = NodeUtils.toNodeRef(); + return JsonUtils.transform(json, transformer); } private List toStrings(JSONArray json) @@ -135,41 +149,4 @@ public class PublishingJsonParser return results; } - public Calendar getCalendar(JSONObject json) throws ParseException - { - Date date = getDate(json); - if(date == null) - { - return null; - } - Calendar calendar = Calendar.getInstance(); - String timeZone = json.optString(TIME_ZONE); - if(timeZone != null) - { - TimeZone zone = TimeZone.getTimeZone(timeZone); - calendar.setTimeZone(zone); - } - calendar.setTime(date); - return calendar; - } - - public Date getDate(JSONObject json) throws ParseException - { - if(json == null) - { - return null; - } - String dateTime = json.optString(DATE_TIME); - if(dateTime == null) - { - return null; - } - String format = json.optString(FORMAT); - if(format!= null) - { - SimpleDateFormat dateFormat = new SimpleDateFormat(format); - return dateFormat.parse(dateTime); - } - return ISO8601DateFormat.parse(dateTime); - } } diff --git a/source/java/org/alfresco/repo/web/scripts/publishing/PublishingModelBuilder.java b/source/java/org/alfresco/repo/web/scripts/publishing/PublishingModelBuilder.java index 903c921699..a148f977a1 100644 --- a/source/java/org/alfresco/repo/web/scripts/publishing/PublishingModelBuilder.java +++ b/source/java/org/alfresco/repo/web/scripts/publishing/PublishingModelBuilder.java @@ -19,13 +19,47 @@ package org.alfresco.repo.web.scripts.publishing; -import static org.alfresco.util.collections.CollectionUtils.*; +import static org.alfresco.repo.web.scripts.WebScriptUtil.buildCalendarModel; +import static org.alfresco.repo.web.scripts.WebScriptUtil.buildDateModel; +import static org.alfresco.repo.web.scripts.publishing.PublishingWebScriptConstants.CAN_PUBLISH; +import static org.alfresco.repo.web.scripts.publishing.PublishingWebScriptConstants.CAN_PUBLISH_STATUS_UPDATES; +import static org.alfresco.repo.web.scripts.publishing.PublishingWebScriptConstants.CAN_UNPUBLISH; +import static org.alfresco.repo.web.scripts.publishing.PublishingWebScriptConstants.CHANNEL; +import static org.alfresco.repo.web.scripts.publishing.PublishingWebScriptConstants.CHANNEL_NODE_TYPE; +import static org.alfresco.repo.web.scripts.publishing.PublishingWebScriptConstants.CHANNEL_TYPE; +import static org.alfresco.repo.web.scripts.publishing.PublishingWebScriptConstants.COMMENT; +import static org.alfresco.repo.web.scripts.publishing.PublishingWebScriptConstants.CREATED_TIME; +import static org.alfresco.repo.web.scripts.publishing.PublishingWebScriptConstants.CREATOR; +import static org.alfresco.repo.web.scripts.publishing.PublishingWebScriptConstants.ICON; +import static org.alfresco.repo.web.scripts.publishing.PublishingWebScriptConstants.ID; +import static org.alfresco.repo.web.scripts.publishing.PublishingWebScriptConstants.MAX_STATUS_LENGTH; +import static org.alfresco.repo.web.scripts.publishing.PublishingWebScriptConstants.NAME; +import static org.alfresco.repo.web.scripts.publishing.PublishingWebScriptConstants.NODEREF; +import static org.alfresco.repo.web.scripts.publishing.PublishingWebScriptConstants.PUBLISH_NODES; +import static org.alfresco.repo.web.scripts.publishing.PublishingWebScriptConstants.SCHEDULED_TIME; +import static org.alfresco.repo.web.scripts.publishing.PublishingWebScriptConstants.STATUS; +import static org.alfresco.repo.web.scripts.publishing.PublishingWebScriptConstants.SUPPORTED_CONTENT_TYPES; +import static org.alfresco.repo.web.scripts.publishing.PublishingWebScriptConstants.SUPPORTED_MIME_TYPES; +import static org.alfresco.repo.web.scripts.publishing.PublishingWebScriptConstants.TITLE; +import static org.alfresco.repo.web.scripts.publishing.PublishingWebScriptConstants.UNPUBLISH_NODES; +import static org.alfresco.repo.web.scripts.publishing.PublishingWebScriptConstants.URL; +import static org.alfresco.repo.web.scripts.publishing.PublishingWebScriptConstants.VERSION; +import static org.alfresco.util.collections.CollectionUtils.toListOfStrings; +import static org.alfresco.util.collections.CollectionUtils.transform; +import java.util.ArrayList; +import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; +import org.alfresco.model.ContentModel; +import org.alfresco.service.cmr.publishing.NodeSnapshot; +import org.alfresco.service.cmr.publishing.PublishingEvent; +import org.alfresco.service.cmr.publishing.PublishingPackage; +import org.alfresco.service.cmr.publishing.PublishingPackageEntry; import org.alfresco.service.cmr.publishing.channels.Channel; +import org.alfresco.service.cmr.publishing.channels.ChannelService; import org.alfresco.service.cmr.publishing.channels.ChannelType; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.StoreRef; @@ -39,26 +73,47 @@ import org.springframework.extensions.surf.util.URLEncoder; */ public class PublishingModelBuilder { - // General Keys - public static final String ID = "id"; - public static final String URL = "url"; - public static final String ICON = "icon"; - public static final String TITLE = "title"; - - // Channel Type Keys - public static final String CHANNEL_NODE_TYPE = "channelNodeType"; - public static final String CONTENT_ROOT_NODE_TYPE = "contentRootNodeType"; - public static final String SUPPORTED_CONTENT_TYPES = "supportedContentTypes"; - public static final String SUPPORTED_MIME_TYPES = "supportedMimeTypes"; - public static final String CAN_PUBLISH = "canPublish"; - public static final String CAN_PUBLISH_STATUS_UPDATES = "canPublishStatusUpdates"; - public static final String CAN_UNPUBLISH = "canUnpublish"; - public static final String MAX_STATUS_LENGTH = "maxStatusLength"; - - // Channel Keys - public static final String NAME = "name"; - public static final String CHANNEL_TYPE = "channelType"; + public Map buildPublishingEvent(PublishingEvent event, ChannelService channelService, String siteId) + { + Map model = new HashMap(); + model.put(ID, event.getId()); + model.put(URL, getUrl(event)); + model.put(STATUS, event.getStatus().name()); + model.put(COMMENT, event.getComment()); + model.put(SCHEDULED_TIME, buildCalendarModel(event.getScheduledTime())); + model.put(CREATOR, event.getCreator()); + model.put(CREATED_TIME, buildDateModel(event.getCreatedTime())); + + model.put(PUBLISH_NODES, buildNodes(event.getPackage(), true)); + model.put(UNPUBLISH_NODES, buildNodes(event.getPackage(), false)); + + String channelName = event.getChannelName(); + Channel channel = channelService.getChannel(siteId, channelName); + if(channel!= null) + { + model.put(CHANNEL, buildChannel(channel)); + } + else + { + model.put(CHANNEL_TYPE, channelName); + } + return model; + } + + public List> buildPublishingEvents(List events, + final ChannelService channelService, + final String siteId) + { + return transform(events, new Function>() + { + public Map apply(PublishingEvent event) + { + return buildPublishingEvent(event, channelService, siteId); + } + }); + } + public Map buildChannel(Channel channel) { Map model = new HashMap(); @@ -102,11 +157,16 @@ public class PublishingModelBuilder return model; } + public static String getUrl(PublishingEvent event) + { + return "api/publishing/events/"+URLEncoder.encode(event.getId()); + } + public static String getUrl(ChannelType type) { return "api/publishing/channelTypes/"+URLEncoder.encode(type.getId()); } - + public static String getUrl(Channel channel) { NodeRef node = channel.getNodeRef(); @@ -124,4 +184,41 @@ public class PublishingModelBuilder return Boolean.toString(b); } + + private List> buildNodes(PublishingPackage pckg, boolean isPublish) + { + Collection nodes = isPublish ? pckg.getNodesToPublish() : pckg.getNodesToUnpublish(); + return buildNodes(pckg, nodes); + } + + private List> buildNodes(PublishingPackage pckg, Collection nodes) + { + List> results = new ArrayList>(nodes.size()); + Map entryMap = pckg.getEntryMap(); + for (NodeRef node : nodes) + { + PublishingPackageEntry entry = entryMap.get(node); + results.add(buildPackageEntry(entry)); + } + return results; + } + + private Map buildPackageEntry(PublishingPackageEntry entry) + { + Map model = new HashMap(); + NodeSnapshot snapshot = entry.getSnapshot(); + model.put(NODEREF, snapshot.getNodeRef().toString()); + String version = snapshot.getVersion(); + if(version!=null && version.isEmpty()) + { + model.put(VERSION, version); + } + String name = (String) snapshot.getProperties().get(ContentModel.PROP_NAME); + if(name != null && name.isEmpty() == false) + { + model.put(NAME, name); + } + return model; + } + } diff --git a/source/java/org/alfresco/repo/web/scripts/publishing/PublishingQueuePost.java b/source/java/org/alfresco/repo/web/scripts/publishing/PublishingQueuePost.java index f6ecf13fc4..182738e483 100644 --- a/source/java/org/alfresco/repo/web/scripts/publishing/PublishingQueuePost.java +++ b/source/java/org/alfresco/repo/web/scripts/publishing/PublishingQueuePost.java @@ -19,17 +19,16 @@ package org.alfresco.repo.web.scripts.publishing; -import java.io.IOException; import java.util.Map; import javax.servlet.http.HttpServletResponse; +import org.alfresco.repo.web.scripts.WebScriptUtil; import org.alfresco.service.cmr.publishing.Environment; +import org.alfresco.service.cmr.publishing.PublishingEvent; import org.alfresco.service.cmr.publishing.PublishingQueue; -import org.alfresco.service.cmr.publishing.PublishingService; -import org.springframework.extensions.surf.util.Content; +import org.alfresco.util.Pair; import org.springframework.extensions.webscripts.Cache; -import org.springframework.extensions.webscripts.DeclarativeWebScript; import org.springframework.extensions.webscripts.Status; import org.springframework.extensions.webscripts.WebScriptException; import org.springframework.extensions.webscripts.WebScriptRequest; @@ -39,82 +38,41 @@ import org.springframework.extensions.webscripts.WebScriptRequest; * @since 4.0 * */ -public class PublishingQueuePost extends DeclarativeWebScript +public class PublishingQueuePost extends PublishingEnvironmentWebScript { - private static final String ENVIRONMENT_ID = "environment_id"; - private static final String SITE_ID = "site_id"; - - private final PublishingJsonParser jsonParser = new PublishingJsonParser(); - private PublishingService publishingService; - private String defaultEnvironmentId; - /** * {@inheritDoc} */ @Override protected Map executeImpl(WebScriptRequest req, Status status, Cache cache) { - Map params = req.getServiceMatch().getTemplateVars(); - String siteId = params.get(SITE_ID); - String environmentId = params.get(ENVIRONMENT_ID); - - if(siteId == null) - { - String msg = "A Site ID must be specified!"; - throw new WebScriptException(HttpServletResponse.SC_BAD_REQUEST, msg); - } - if(environmentId == null) - { - if(defaultEnvironmentId == null) - { - String msg = "An Environment ID must be specified!"; - throw new WebScriptException(HttpServletResponse.SC_BAD_REQUEST, msg); - } - environmentId = defaultEnvironmentId; - } - - Environment environment = publishingService.getEnvironment(siteId, environmentId); - if(environment == null) - { - String msg = "Environment " +environmentId + " does not exist in site " +siteId; - throw new WebScriptException(HttpServletResponse.SC_BAD_REQUEST, msg); - } + Pair siteAndEnvironment = getSiteAndEnvironment(req); + String siteId = siteAndEnvironment.getFirst(); + Environment environment = siteAndEnvironment.getSecond(); PublishingQueue queue = environment.getPublishingQueue(); String content = null; try { - content = getContent(req); - jsonParser.schedulePublishingEvent(queue, content); + content = WebScriptUtil.getContent(req); + if(content == null || content.isEmpty()) + { + throw new WebScriptException(HttpServletResponse.SC_BAD_REQUEST, "No publishing event was posted!"); + } + String eventId = jsonParser.schedulePublishingEvent(queue, content); + PublishingEvent event = publishingService.getPublishingEvent(eventId); + Map eventModel = builder.buildPublishingEvent(event, channelService, siteId); + return WebScriptUtil.createBaseModel(eventModel); + } + catch(WebScriptException we) + { + throw we; } catch(Exception e) { String msg = "Failed to schedule publishing event. POST body: " + content; throw new WebScriptException(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, msg, e); } - return null; } - - protected String getContent(WebScriptRequest request) throws IOException - { - Content content = request.getContent(); - return content.getContent(); - } - - /** - * @param publishingService the publishingService to set - */ - public void setPublishingService(PublishingService publishingService) - { - this.publishingService = publishingService; - } - - /** - * @param defaultEnvironmentId the defaultEnvironmentId to set - */ - public void setDefaultEnvironmentId(String defaultEnvironmentId) - { - this.defaultEnvironmentId = defaultEnvironmentId; - } } diff --git a/source/java/org/alfresco/repo/web/scripts/publishing/PublishingRestApiTest.java b/source/java/org/alfresco/repo/web/scripts/publishing/PublishingRestApiTest.java index b073053a58..6e50e1ec23 100644 --- a/source/java/org/alfresco/repo/web/scripts/publishing/PublishingRestApiTest.java +++ b/source/java/org/alfresco/repo/web/scripts/publishing/PublishingRestApiTest.java @@ -21,26 +21,36 @@ package org.alfresco.repo.web.scripts.publishing; import static org.alfresco.model.ContentModel.TYPE_CONTENT; import static org.alfresco.repo.publishing.PublishingModel.TYPE_DELIVERY_CHANNEL; -import static org.alfresco.repo.web.scripts.publishing.PublishingJsonParser.CHANNEL_NAME; -import static org.alfresco.repo.web.scripts.publishing.PublishingJsonParser.CHANNEL_NAMES; -import static org.alfresco.repo.web.scripts.publishing.PublishingJsonParser.COMMENT; -import static org.alfresco.repo.web.scripts.publishing.PublishingJsonParser.MESSAGE; -import static org.alfresco.repo.web.scripts.publishing.PublishingJsonParser.NODE_REF; -import static org.alfresco.repo.web.scripts.publishing.PublishingJsonParser.PUBLISH_NODES; -import static org.alfresco.repo.web.scripts.publishing.PublishingJsonParser.STATUS_UPDATE; -import static org.alfresco.repo.web.scripts.publishing.PublishingModelBuilder.CAN_PUBLISH; -import static org.alfresco.repo.web.scripts.publishing.PublishingModelBuilder.CAN_PUBLISH_STATUS_UPDATES; -import static org.alfresco.repo.web.scripts.publishing.PublishingModelBuilder.CAN_UNPUBLISH; -import static org.alfresco.repo.web.scripts.publishing.PublishingModelBuilder.CHANNEL_NODE_TYPE; -import static org.alfresco.repo.web.scripts.publishing.PublishingModelBuilder.CHANNEL_TYPE; -import static org.alfresco.repo.web.scripts.publishing.PublishingModelBuilder.ICON; -import static org.alfresco.repo.web.scripts.publishing.PublishingModelBuilder.ID; -import static org.alfresco.repo.web.scripts.publishing.PublishingModelBuilder.MAX_STATUS_LENGTH; -import static org.alfresco.repo.web.scripts.publishing.PublishingModelBuilder.NAME; -import static org.alfresco.repo.web.scripts.publishing.PublishingModelBuilder.SUPPORTED_CONTENT_TYPES; -import static org.alfresco.repo.web.scripts.publishing.PublishingModelBuilder.SUPPORTED_MIME_TYPES; -import static org.alfresco.repo.web.scripts.publishing.PublishingModelBuilder.TITLE; -import static org.alfresco.repo.web.scripts.publishing.PublishingModelBuilder.URL; +import static org.alfresco.repo.web.scripts.publishing.PublishingWebScriptConstants.CAN_PUBLISH; +import static org.alfresco.repo.web.scripts.publishing.PublishingWebScriptConstants.CAN_PUBLISH_STATUS_UPDATES; +import static org.alfresco.repo.web.scripts.publishing.PublishingWebScriptConstants.CAN_UNPUBLISH; +import static org.alfresco.repo.web.scripts.publishing.PublishingWebScriptConstants.CHANNEL; +import static org.alfresco.repo.web.scripts.publishing.PublishingWebScriptConstants.CHANNEL_NAME; +import static org.alfresco.repo.web.scripts.publishing.PublishingWebScriptConstants.CHANNEL_NAMES; +import static org.alfresco.repo.web.scripts.publishing.PublishingWebScriptConstants.CHANNEL_NODE_TYPE; +import static org.alfresco.repo.web.scripts.publishing.PublishingWebScriptConstants.CHANNEL_TYPE; +import static org.alfresco.repo.web.scripts.publishing.PublishingWebScriptConstants.COMMENT; +import static org.alfresco.repo.web.scripts.publishing.PublishingWebScriptConstants.CREATED_TIME; +import static org.alfresco.repo.web.scripts.publishing.PublishingWebScriptConstants.CREATOR; +import static org.alfresco.repo.web.scripts.publishing.PublishingWebScriptConstants.ICON; +import static org.alfresco.repo.web.scripts.publishing.PublishingWebScriptConstants.ID; +import static org.alfresco.repo.web.scripts.publishing.PublishingWebScriptConstants.MAX_STATUS_LENGTH; +import static org.alfresco.repo.web.scripts.publishing.PublishingWebScriptConstants.MESSAGE; +import static org.alfresco.repo.web.scripts.publishing.PublishingWebScriptConstants.NAME; +import static org.alfresco.repo.web.scripts.publishing.PublishingWebScriptConstants.NODE_REF; +import static org.alfresco.repo.web.scripts.publishing.PublishingWebScriptConstants.PUBLISHING_CHANNELS; +import static org.alfresco.repo.web.scripts.publishing.PublishingWebScriptConstants.PUBLISH_NODES; +import static org.alfresco.repo.web.scripts.publishing.PublishingWebScriptConstants.SCHEDULED_TIME; +import static org.alfresco.repo.web.scripts.publishing.PublishingWebScriptConstants.STATUS; +import static org.alfresco.repo.web.scripts.publishing.PublishingWebScriptConstants.STATUS_UPDATE; +import static org.alfresco.repo.web.scripts.publishing.PublishingWebScriptConstants.STATUS_UPDATE_CHANNELS; +import static org.alfresco.repo.web.scripts.publishing.PublishingWebScriptConstants.SUPPORTED_CONTENT_TYPES; +import static org.alfresco.repo.web.scripts.publishing.PublishingWebScriptConstants.SUPPORTED_MIME_TYPES; +import static org.alfresco.repo.web.scripts.publishing.PublishingWebScriptConstants.TITLE; +import static org.alfresco.repo.web.scripts.publishing.PublishingWebScriptConstants.UNPUBLISH_NODES; +import static org.alfresco.repo.web.scripts.publishing.PublishingWebScriptConstants.URL; +import static org.alfresco.repo.web.scripts.publishing.PublishingWebScriptConstants.URL_LENGTH; +import static org.alfresco.repo.web.scripts.publishing.PublishingWebScriptConstants.VERSION; import static org.mockito.Matchers.any; import static org.mockito.Matchers.anyMap; import static org.mockito.Matchers.anyString; @@ -52,11 +62,16 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import java.io.File; +import java.io.UnsupportedEncodingException; import java.text.MessageFormat; import java.util.ArrayList; +import java.util.Arrays; +import java.util.Calendar; import java.util.Collection; import java.util.Collections; +import java.util.Date; import java.util.List; +import java.util.Map; import java.util.Set; import org.alfresco.model.ContentModel; @@ -64,16 +79,23 @@ import org.alfresco.repo.content.MimetypeMap; import org.alfresco.repo.content.transform.AbstractContentTransformerTest; import org.alfresco.repo.publishing.ChannelHelper; import org.alfresco.repo.publishing.ChannelServiceImpl; +import org.alfresco.repo.publishing.PublishServiceImpl; import org.alfresco.repo.publishing.PublishingObjectFactory; import org.alfresco.repo.security.authentication.AuthenticationUtil; import org.alfresco.repo.web.scripts.BaseWebScriptTest; +import org.alfresco.repo.web.scripts.WebScriptUtil; import org.alfresco.service.ServiceRegistry; import org.alfresco.service.cmr.model.FileFolderService; import org.alfresco.service.cmr.publishing.Environment; +import org.alfresco.service.cmr.publishing.MutablePublishingPackage; +import org.alfresco.service.cmr.publishing.NodeSnapshot; import org.alfresco.service.cmr.publishing.PublishingEvent; import org.alfresco.service.cmr.publishing.PublishingEvent.Status; import org.alfresco.service.cmr.publishing.PublishingEventFilter; import org.alfresco.service.cmr.publishing.PublishingPackage; +import org.alfresco.service.cmr.publishing.PublishingPackageEntry; +import org.alfresco.service.cmr.publishing.PublishingQueue; +import org.alfresco.service.cmr.publishing.PublishingService; import org.alfresco.service.cmr.publishing.StatusUpdate; import org.alfresco.service.cmr.publishing.channels.Channel; import org.alfresco.service.cmr.publishing.channels.ChannelService; @@ -84,6 +106,7 @@ import org.alfresco.service.cmr.repository.StoreRef; import org.alfresco.service.cmr.site.SiteService; import org.alfresco.service.cmr.site.SiteVisibility; import org.alfresco.util.GUID; +import org.alfresco.util.ISO8601DateFormat; import org.alfresco.util.collections.CollectionUtils; import org.json.JSONArray; import org.json.JSONException; @@ -111,12 +134,14 @@ public class PublishingRestApiTest extends BaseWebScriptTest private static final String CHANNELS_SITE_URL = "api/publishing/site/{0}/channels"; private static final String CHANNELS_NODE_URL = "api/publishing/{0}/{1}/{2}/channels"; private static final String PUBLISHING_QUEUE_URL = "api/publishing/{0}/queue"; + private static final String PUBLISHING_EVENT_QUERY_URL = "api/publishing/{0}/events/query"; private static final String JSON = "application/json"; private SiteService siteService; private FileFolderService fileFolderService; private ChannelService channelService; + private PublishingService publishingService; private ChannelHelper channelHelper; private Environment environment; @@ -141,10 +166,10 @@ public class PublishingRestApiTest extends BaseWebScriptTest JSONObject data = getJsonData(response); //TODO Fix hard coding. - assertEquals(20, data.getInt(ChannelsGet.URL_LENGTH)); - JSONArray publishingChannels = data.getJSONArray(ChannelsGet.PUBLISHING_CHANNELS); + assertEquals(20, data.getInt(URL_LENGTH)); + JSONArray publishingChannels = data.getJSONArray(PUBLISHING_CHANNELS); assertEquals(0, publishingChannels.length()); - JSONArray statusChannels = data.getJSONArray(ChannelsGet.STATUS_UPDATE_CHANNELS); + JSONArray statusChannels = data.getJSONArray(STATUS_UPDATE_CHANNELS); assertEquals(0, statusChannels.length()); Channel publishAnyChannel = createChannel(publishAnyType); @@ -156,9 +181,9 @@ public class PublishingRestApiTest extends BaseWebScriptTest data = getJsonData(response); //TODO Fix hard coding. - assertEquals(20, data.getInt(ChannelsGet.URL_LENGTH)); - publishingChannels = data.getJSONArray(ChannelsGet.PUBLISHING_CHANNELS); - statusChannels = data.getJSONArray(ChannelsGet.STATUS_UPDATE_CHANNELS); + assertEquals(20, data.getInt(URL_LENGTH)); + publishingChannels = data.getJSONArray(PUBLISHING_CHANNELS); + statusChannels = data.getJSONArray(STATUS_UPDATE_CHANNELS); checkChannels(publishingChannels, publishAnyChannel); checkChannels(statusChannels, statusUpdateChannel); @@ -168,9 +193,9 @@ public class PublishingRestApiTest extends BaseWebScriptTest data = getJsonData(response); //TODO Fix hard coding. - assertEquals(20, data.getInt(ChannelsGet.URL_LENGTH)); - publishingChannels = data.getJSONArray(ChannelsGet.PUBLISHING_CHANNELS); - statusChannels = data.getJSONArray(ChannelsGet.STATUS_UPDATE_CHANNELS); + assertEquals(20, data.getInt(URL_LENGTH)); + publishingChannels = data.getJSONArray(PUBLISHING_CHANNELS); + statusChannels = data.getJSONArray(STATUS_UPDATE_CHANNELS); checkChannels(publishingChannels, publishAnyChannel, publishPdfChannel); checkChannels(statusChannels, statusUpdateChannel); @@ -187,10 +212,10 @@ public class PublishingRestApiTest extends BaseWebScriptTest JSONObject data = getJsonData(response); //TODO Fix hard coding. - assertEquals(20, data.getInt(ChannelsGet.URL_LENGTH)); - JSONArray publishingChannels = data.getJSONArray(ChannelsGet.PUBLISHING_CHANNELS); + assertEquals(20, data.getInt(URL_LENGTH)); + JSONArray publishingChannels = data.getJSONArray(PUBLISHING_CHANNELS); assertEquals(0, publishingChannels.length()); - JSONArray statusChannels = data.getJSONArray(ChannelsGet.STATUS_UPDATE_CHANNELS); + JSONArray statusChannels = data.getJSONArray(STATUS_UPDATE_CHANNELS); assertEquals(0, statusChannels.length()); Channel publishAnyChannel = createChannel(publishAnyType); @@ -202,15 +227,14 @@ public class PublishingRestApiTest extends BaseWebScriptTest data = getJsonData(response); //TODO Fix hard coding. - assertEquals(20, data.getInt(ChannelsGet.URL_LENGTH)); - publishingChannels = data.getJSONArray(ChannelsGet.PUBLISHING_CHANNELS); - statusChannels = data.getJSONArray(ChannelsGet.STATUS_UPDATE_CHANNELS); + assertEquals(20, data.getInt(URL_LENGTH)); + publishingChannels = data.getJSONArray(PUBLISHING_CHANNELS); + statusChannels = data.getJSONArray(STATUS_UPDATE_CHANNELS); checkChannels(publishingChannels, publishAnyChannel, publishPdfChannel); checkChannels(statusChannels, statusUpdateChannel); } - @SuppressWarnings("unchecked") public void testPublishingQueuePost() throws Exception { @@ -224,7 +248,7 @@ public class PublishingRestApiTest extends BaseWebScriptTest String pubQueueUrl = MessageFormat.format(PUBLISHING_QUEUE_URL, siteId); // Post empty content. - sendRequest(new PostRequest(pubQueueUrl, "", JSON), 500); + sendRequest(new PostRequest(pubQueueUrl, "", JSON), 400); String comment = "The comment"; String statusMessage = "The status message"; @@ -296,6 +320,171 @@ public class PublishingRestApiTest extends BaseWebScriptTest sendRequest(new PostRequest(pubQueueUrl, jsonStr, JSON), 200); } + public void testPublishingEventsQueryPostPublishedNode() throws Exception + { + Channel publishChannel = createChannel(publishAnyType); + NodeRef textNode1 = createContentNode("plain1.txt", "This is some plain text", MimetypeMap.MIMETYPE_TEXT_PLAIN); + NodeRef textNode2 = createContentNode("plain2.txt", "This is some more plain text", MimetypeMap.MIMETYPE_TEXT_PLAIN); + + String badQueryUrl = MessageFormat.format(PUBLISHING_EVENT_QUERY_URL, "foo"); + + // Post empty string with bad site name. + sendRequest(new PostRequest(badQueryUrl, "", JSON), 500); + + String queryUrl = MessageFormat.format(PUBLISHING_EVENT_QUERY_URL, siteId); + + // Post empty string with correct site name. + Response response = sendRequest(new PostRequest(queryUrl, "", JSON), 200); + + // SHould return all events (currently none). + JSONArray data = getDataArray(response); + assertEquals(0, data.length()); + + // Create publishing event for textNode1. + PublishingQueue queue = environment.getPublishingQueue(); + MutablePublishingPackage pckg1 = queue.createPublishingPackage(); + pckg1.addNodesToPublish(textNode1); + StatusUpdate statusUpdate = null; + String comment = "This is a comment"; + Calendar schedule = Calendar.getInstance(); + schedule.add(Calendar.YEAR, 1); + + String event1Id = queue.scheduleNewEvent(pckg1, publishChannel.getName(), schedule, comment, statusUpdate); + + // Query for all events. + response = sendRequest(new PostRequest(queryUrl, "", JSON), 200); + data = getDataArray(response); + checkContainsEvents(data, event1Id); + + JSONObject json = new JSONObject(); + json.put(PUBLISH_NODES, Arrays.asList(textNode1.toString())); + + // Query for events on textNode1. + response = sendRequest(new PostRequest(queryUrl, json.toString(), JSON), 200); + data = getDataArray(response); + checkContainsEvents(data, event1Id); + + json = new JSONObject(); + json.put(PUBLISH_NODES, Arrays.asList(textNode2.toString())); + + // Query for events on textNode2. + response = sendRequest(new PostRequest(queryUrl, json.toString(), JSON), 200); + data = getDataArray(response); + assertEquals(0, data.length()); + + json = new JSONObject(); + json.put(PUBLISH_NODES, Arrays.asList(textNode1.toString(), textNode2.toString())); + + // Query for events on both textNode1 and textNode2. + response = sendRequest(new PostRequest(queryUrl, json.toString(), JSON), 200); + data = getDataArray(response); + checkContainsEvent(data, event1Id); + } + + private void checkContainsEvents(JSONArray data, String... eventIds) throws Exception + { + assertEquals(eventIds.length, data.length()); + for (String eventId : eventIds) + { + checkContainsEvent(data, eventId); + } + } + + private void checkContainsEvent(JSONArray data, String eventId) throws Exception + { + for (int i = 0; i < data.length(); i++) + { + JSONObject json = data.optJSONObject(i); + if(eventId.equals(json.optString(ID))) + { + PublishingEvent event = publishingService.getPublishingEvent(eventId); + checkJsonEvent(event, json); + return; + } + } + fail("Failed to find Publishing Event: " + eventId); + } + + private void checkJsonEvent(PublishingEvent event, JSONObject json) throws Exception + { + String url = "api/publishing/events/" + URLEncoder.encode(event.getId()); + assertEquals(url, json.getString(URL)); + + assertEquals(event.getStatus().name(), json.getString(STATUS)); + + assertEquals(event.getComment(), json.optString(COMMENT)); + checkCalendar(event.getScheduledTime(), json.optJSONObject(SCHEDULED_TIME)); + assertEquals(event.getCreator(), json.getString(CREATOR)); + checkDate(event.getCreatedTime(), json.getJSONObject(CREATED_TIME)); + + PublishingPackage pckg = event.getPackage(); + checkContainsNodes(pckg, json.getJSONArray(PUBLISH_NODES), true); + checkContainsNodes(pckg, json.getJSONArray(UNPUBLISH_NODES), false); + + Channel channel = channelService.getChannel(siteId, event.getChannelName()); + checkChannel(json.optJSONObject(CHANNEL), channel); + } + + private void checkContainsNodes(PublishingPackage pckg, JSONArray json, boolean isPublish) throws JSONException + { + Collection nodes = isPublish ? pckg.getNodesToPublish() : pckg.getNodesToUnpublish(); + checkContainsNodes(nodes, pckg.getEntryMap(), json); + } + + private void checkContainsNodes(Collection nodes, Map entryMap, JSONArray json) throws JSONException + { + assertEquals(nodes.size(), json.length()); + for (NodeRef node : nodes) + { + checkContainsNode(entryMap.get(node), json); + } + } + + private void checkContainsNode(PublishingPackageEntry entry, JSONArray jsonArray) throws JSONException + { + String nodeId = entry.getNodeRef().toString(); + for (int i = 0; i < jsonArray.length(); i++) + { + JSONObject json = jsonArray.getJSONObject(i); + if(nodeId.equals(json.getString(NODE_REF))) + { + checkNode(entry, json); + return; + } + } + fail("NodeRef was not found!"); + } + + private void checkNode(PublishingPackageEntry entry, JSONObject json) throws JSONException + { + NodeSnapshot snapshot = entry.getSnapshot(); + String version = snapshot.getVersion(); + if(version != null && version.isEmpty() == false) + { + assertEquals(version, json.getString(VERSION)); + } + String name = (String) snapshot.getProperties().get(ContentModel.PROP_NAME); + if(name != null && name.isEmpty() == false) + { + assertEquals(name, json.getString(NAME)); + } + } + + private void checkCalendar(Calendar calendar, JSONObject json) throws JSONException + { + checkDate(calendar.getTime(), json); + String timeZone = calendar.getTimeZone().getID(); + assertEquals(timeZone, json.getString(WebScriptUtil.TIME_ZONE)); + } + + private void checkDate(Date date, JSONObject json) throws JSONException + { + assertEquals(WebScriptUtil.ISO8601, json.getString(WebScriptUtil.FORMAT)); + String dateStr = json.getString(WebScriptUtil.DATE_TIME); + Date actualDate = ISO8601DateFormat.parse(dateStr); + assertEquals(date, actualDate); + } + private JSONObject buildJson(NodeRef node, Channel publishChannel, String comment, String statusMessage, Channel... statusChannels) throws JSONException @@ -303,6 +492,9 @@ public class PublishingRestApiTest extends BaseWebScriptTest JSONObject json = new JSONObject(); json.put(CHANNEL_NAME, publishChannel.getName()); json.put(COMMENT, comment); + Calendar schedule = Calendar.getInstance(); + schedule.add(Calendar.SECOND, 1); + json.put(SCHEDULED_TIME, WebScriptUtil.buildCalendarModel(schedule)); Collection publishNodes = Collections.singleton(node.toString()); json.put(PUBLISH_NODES, publishNodes); json.put(STATUS_UPDATE, buildStatusUpdate(statusMessage, node, statusChannels)); @@ -417,14 +609,27 @@ public class PublishingRestApiTest extends BaseWebScriptTest private JSONObject getJsonData(Response response) throws Exception { - String jsonStr = response.getContentAsString(); - assertNotNull("The JSON is null!", jsonStr); - JSONObject json = new JSONObject(jsonStr); + JSONObject json = getJson(response); JSONObject data = json.getJSONObject("data"); assertNotNull("Data was null!", data); return data; } + public JSONArray getDataArray(Response response) throws Exception + { + JSONObject json = getJson(response); + JSONArray data = json.getJSONArray("data"); + assertNotNull("Data was null!", data); + return data; + } + + private JSONObject getJson(Response response) throws UnsupportedEncodingException, JSONException + { + String jsonStr = response.getContentAsString(); + assertNotNull("The JSON is null!", jsonStr); + return new JSONObject(jsonStr); + } + private NodeRef createContentNode(String name, File theContent, String mimetype) { NodeRef source = fileFolderService.create(docLib, name, TYPE_CONTENT).getNodeRef(); @@ -483,6 +688,7 @@ public class PublishingRestApiTest extends BaseWebScriptTest this.siteService = serviceRegistry.getSiteService(); this.fileFolderService = serviceRegistry.getFileFolderService(); this.channelService = (ChannelService) ctx.getBean(ChannelServiceImpl.NAME); + this.publishingService= (PublishingService) ctx.getBean(PublishServiceImpl.NAME); this.channelHelper = (ChannelHelper) ctx.getBean(ChannelHelper.NAME); PublishingObjectFactory factory = (PublishingObjectFactory) ctx.getBean(PublishingObjectFactory.NAME); @@ -510,6 +716,20 @@ public class PublishingRestApiTest extends BaseWebScriptTest @Override public void tearDown() throws Exception { + //FInd all events + PublishingEventFilter filter = environment.createPublishingEventFilter(); + List events = environment.getPublishingEvents(filter); + for (PublishingEvent event : events) + { + try + { + publishingService.cancelPublishingEvent(event.getId()); + } + catch(Throwable t) + { + //NOOP + } + } try { siteService.deleteSite(siteId); diff --git a/source/java/org/alfresco/repo/web/scripts/publishing/PublishingWebScriptConstants.java b/source/java/org/alfresco/repo/web/scripts/publishing/PublishingWebScriptConstants.java new file mode 100644 index 0000000000..78151a7a8c --- /dev/null +++ b/source/java/org/alfresco/repo/web/scripts/publishing/PublishingWebScriptConstants.java @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2005-2010 Alfresco Software Limited. + * + * This file is part of Alfresco + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + */ + +package org.alfresco.repo.web.scripts.publishing; + +/** + * @author Nick Smith + * @since 4.0 + * + */ +public interface PublishingWebScriptConstants +{ + // URL Template Keys. + public static final String SITE_ID = "site_id"; + public static final String ENVIRONMENT_ID = "environment_id"; + + // General Model Keys + public static final String ID = "id"; + public static final String URL = "url"; + public static final String ICON = "icon"; + public static final String TITLE = "title"; + + // Channel Type Model Keys + public static final String CHANNEL_NODE_TYPE = "channelNodeType"; + public static final String CONTENT_ROOT_NODE_TYPE = "contentRootNodeType"; + public static final String SUPPORTED_CONTENT_TYPES = "supportedContentTypes"; + public static final String SUPPORTED_MIME_TYPES = "supportedMimeTypes"; + public static final String CAN_PUBLISH = "canPublish"; + public static final String CAN_PUBLISH_STATUS_UPDATES = "canPublishStatusUpdates"; + public static final String CAN_UNPUBLISH = "canUnpublish"; + public static final String MAX_STATUS_LENGTH = "maxStatusLength"; + + // Channel Keys + public static final String NAME = "name"; + public static final String CHANNEL_TYPE = "channelType"; + + // Publishing Event Model Keys + public static final String CHANNEL = "channel"; + public static final String STATUS = "status"; + public static final String COMMENT = "comment"; + public static final String SCHEDULED_TIME = "scheduledTime"; + public static final String CREATOR = "creator"; + public static final String CREATED_TIME = "createdTime"; + public static final String PUBLISH_NODES = "publishNodes"; + public static final String UNPUBLISH_NODES = "unpublishNodes"; + public static final String NODEREF = "nodeRef"; + public static final String VERSION = "version"; + public static final String STATUS_UPDATE = "statusUpdate"; + public static final String CHANNEL_NAME = "channelName"; + + // Status Update Model Keys + public static final String CHANNEL_NAMES = "channelNames"; + public static final String NODE_REF = "nodeRef"; + public static final String MESSAGE = "message"; + + // Publishing Event Filter Modek Keys + public static final String IDS = "ids"; + + // channels.get Model Keys + public static final String URL_LENGTH = "urlLength"; + public static final String PUBLISHING_CHANNELS = "publishChannels"; + public static final String STATUS_UPDATE_CHANNELS = "statusUpdateChannels"; + +} diff --git a/source/java/org/alfresco/repo/web/scripts/publishing/SupportedChannelsGet.java b/source/java/org/alfresco/repo/web/scripts/publishing/SupportedChannelsGet.java deleted file mode 100644 index e5535f7d5d..0000000000 --- a/source/java/org/alfresco/repo/web/scripts/publishing/SupportedChannelsGet.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (C) 2005-2010 Alfresco Software Limited. - * - * This file is part of Alfresco - * - * Alfresco is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Alfresco is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Alfresco. If not, see . - */ - -package org.alfresco.repo.web.scripts.publishing; - -import org.springframework.extensions.webscripts.DeclarativeWebScript; - -/** - * @author Nick Smith - * @since 4.0 - * - */ -public class SupportedChannelsGet extends DeclarativeWebScript -{ - -}