Author: adrianc
Date: Sun Jun 28 15:33:24 2009 New Revision: 789112 URL: http://svn.apache.org/viewvc?rev=789112&view=rev Log: More iCalendar work - improved HTTP responses. Modified: ofbiz/trunk/applications/workeffort/src/org/ofbiz/workeffort/workeffort/ICalConverter.java ofbiz/trunk/applications/workeffort/src/org/ofbiz/workeffort/workeffort/ICalWorker.java Modified: ofbiz/trunk/applications/workeffort/src/org/ofbiz/workeffort/workeffort/ICalConverter.java URL: http://svn.apache.org/viewvc/ofbiz/trunk/applications/workeffort/src/org/ofbiz/workeffort/workeffort/ICalConverter.java?rev=789112&r1=789111&r2=789112&view=diff ============================================================================== --- ofbiz/trunk/applications/workeffort/src/org/ofbiz/workeffort/workeffort/ICalConverter.java (original) +++ ofbiz/trunk/applications/workeffort/src/org/ofbiz/workeffort/workeffort/ICalConverter.java Sun Jun 28 15:33:24 2009 @@ -62,6 +62,7 @@ import org.ofbiz.service.ServiceUtil; import org.ofbiz.service.calendar.TemporalExpression; import org.ofbiz.service.calendar.TemporalExpressionWorker; +import static org.ofbiz.workeffort.workeffort.ICalWorker.ResponseProperties; /** iCalendar converter class. This class uses the <a href="http://ical4j.sourceforge.net/index.html"> * iCal4J</a> library. @@ -115,7 +116,7 @@ return organizer; } - protected static void createWorkEffort(Component component, Map<String, Object> context) { + protected static ResponseProperties createWorkEffort(Component component, Map<String, Object> context) { Map<String, Object> serviceMap = FastMap.newInstance(); setWorkEffortServiceMap(component, serviceMap); serviceMap.put("workEffortTypeId", "VTODO".equals(component.getName()) ? "TASK" : "EVENT"); @@ -124,6 +125,9 @@ serviceMap.put("roleTypeId", "CAL_OWNER"); serviceMap.put("statusId", "PRTYASGN_ASSIGNED"); Map<String, Object> serviceResult = invokeService("createWorkEffortAndPartyAssign", serviceMap, context); + if (ServiceUtil.isError(serviceResult)) { + return ICalWorker.createPartialContentResponse(ServiceUtil.getErrorMessage(serviceResult)); + } String workEffortId = (String) serviceResult.get("workEffortId"); if (workEffortId != null) { replaceProperty(component.getProperties(), toXProperty(workEffortIdXPropName, workEffortId)); @@ -134,10 +138,11 @@ serviceMap.put("fromDate", new Timestamp(System.currentTimeMillis())); serviceResult = invokeService("createWorkEffortAssoc", serviceMap, context); if (ServiceUtil.isError(serviceResult)) { - return; + return ICalWorker.createPartialContentResponse(ServiceUtil.getErrorMessage(serviceResult)); } storePartyAssignments(workEffortId, component, context); } + return null; } protected static String fromClazz(PropertyList propertyList) { @@ -348,22 +353,25 @@ * if <code>workEffortId</code> is invalid. * @throws GenericEntityException */ - public static String getICalendar(String workEffortId, Map<String, Object> context) throws GenericEntityException { + public static ResponseProperties getICalendar(String workEffortId, Map<String, Object> context) throws GenericEntityException { GenericDelegator delegator = (GenericDelegator) context.get("delegator"); GenericValue publishProperties = delegator.findOne("WorkEffort", UtilMisc.toMap("workEffortId", workEffortId), false); if (!isCalendarPublished(publishProperties)) { Debug.logInfo("WorkEffort calendar is not published: " + workEffortId, module); - return null; + return ICalWorker.createNotFoundResponse(null); } if (!"WES_PUBLIC".equals(publishProperties.get("scopeEnumId")) && !hasPermission(workEffortId, "VIEW", context)) { - return null; + return ICalWorker.createNotFoundResponse(null); } Calendar calendar = makeCalendar(publishProperties, context); ComponentList components = calendar.getComponents(); List<GenericValue> workEfforts = getRelatedWorkEfforts(publishProperties, context); if (workEfforts != null) { for (GenericValue workEffort : workEfforts) { - toCalendarComponent(components, workEffort, context); + ResponseProperties responseProps = toCalendarComponent(components, workEffort, context); + if (responseProps != null) { + return responseProps; + } } } if (Debug.verboseOn()) { @@ -374,7 +382,7 @@ Debug.logVerbose("iCalendar fails validation: " + e, module); } } - return calendar.toString(); + return ICalWorker.createOkResponse(calendar.toString()); } protected static void getPartyUrl(Property property, GenericValue partyAssign, Map<String, Object> context) { @@ -638,7 +646,7 @@ * @throws GenericServiceException */ @SuppressWarnings("unchecked") - public static void storeCalendar(InputStream is, Map<String, Object> context) throws IOException, ParserException, GenericEntityException, GenericServiceException { + public static ResponseProperties storeCalendar(InputStream is, Map<String, Object> context) throws IOException, ParserException, GenericEntityException, GenericServiceException { CalendarBuilder builder = new CalendarBuilder(); Calendar calendar = null; try { @@ -661,65 +669,74 @@ if (!workEffortId.equals(context.get("workEffortId"))) { Debug.logWarning("Spoof attempt: received calendar workEffortId " + workEffortId + " on URL workEffortId " + context.get("workEffortId"), module); - return; + return ICalWorker.createForbiddenResponse(null); } GenericDelegator delegator = (GenericDelegator) context.get("delegator"); GenericValue publishProperties = delegator.findOne("WorkEffort", UtilMisc.toMap("workEffortId", workEffortId), false); if (!isCalendarPublished(publishProperties)) { Debug.logInfo("WorkEffort calendar is not published: " + workEffortId, module); - return; + return ICalWorker.createNotFoundResponse(null); } if (!hasPermission(workEffortId, "UPDATE", context)) { - return; + return ICalWorker.createNotAuthorizedResponse(null); } boolean hasCreatePermission = hasPermission(workEffortId, "CREATE", context); List<GenericValue> workEfforts = getRelatedWorkEfforts(publishProperties, context); - if (workEfforts == null || workEfforts.size() == 0) { - return; - } - // Security issue: make sure only related work efforts get updated - Set validWorkEfforts = FastSet.newInstance(); - for (GenericValue workEffort : workEfforts) { - validWorkEfforts.add(workEffort.getString("workEffortId")); - } - List<Component> components = calendar.getComponents(); - for (Component component : components) { - if (Component.VEVENT.equals(component.getName()) || Component.VTODO.equals(component.getName())) { - workEffortId = fromXProperty(component.getProperties(), workEffortIdXPropName); - if (workEffortId == null) { - Property uid = component.getProperty(Uid.UID); - if (uid != null) { - GenericValue workEffort = EntityUtil.getFirst(delegator.findByAnd("WorkEffort", UtilMisc.toMap("universalId", uid.getValue()))); - if (workEffort != null) { - workEffortId = workEffort.getString("workEffortId"); + if (workEfforts != null && workEfforts.size() > 0) { + // Security issue: make sure only related work efforts get updated + Set validWorkEfforts = FastSet.newInstance(); + for (GenericValue workEffort : workEfforts) { + validWorkEfforts.add(workEffort.getString("workEffortId")); + } + List<Component> components = calendar.getComponents(); + ResponseProperties responseProps = null; + for (Component component : components) { + if (Component.VEVENT.equals(component.getName()) || Component.VTODO.equals(component.getName())) { + workEffortId = fromXProperty(component.getProperties(), workEffortIdXPropName); + if (workEffortId == null) { + Property uid = component.getProperty(Uid.UID); + if (uid != null) { + GenericValue workEffort = EntityUtil.getFirst(delegator.findByAnd("WorkEffort", UtilMisc.toMap("universalId", uid.getValue()))); + if (workEffort != null) { + workEffortId = workEffort.getString("workEffortId"); + } } } - } - if (workEffortId != null) { - if (validWorkEfforts.contains(workEffortId)) { - replaceProperty(component.getProperties(), toXProperty(workEffortIdXPropName, workEffortId)); - storeWorkEffort(component, context); - } else { - Debug.logWarning("Spoof attempt: unrelated workEffortId " + workEffortId + - " on URL workEffortId " + context.get("workEffortId"), module); - continue; + if (workEffortId != null) { + if (validWorkEfforts.contains(workEffortId)) { + replaceProperty(component.getProperties(), toXProperty(workEffortIdXPropName, workEffortId)); + responseProps = storeWorkEffort(component, context); + } else { + Debug.logWarning("Spoof attempt: unrelated workEffortId " + workEffortId + + " on URL workEffortId " + context.get("workEffortId"), module); + responseProps = ICalWorker.createForbiddenResponse(null); + } + } else if (hasCreatePermission) { + responseProps = createWorkEffort(component, context); + } + if (responseProps != null) { + return responseProps; } - } else if (hasCreatePermission) { - createWorkEffort(component, context); } } } Map<String, ? extends Object> serviceMap = UtilMisc.toMap("workEffortId", context.get("workEffortId"), "icalData", calendar.toString()); GenericValue iCalData = publishProperties.getRelatedOne("WorkEffortIcalData"); + Map<String, Object> serviceResult = null; if (iCalData == null) { - invokeService("createWorkEffortICalData", serviceMap, context); + serviceResult = invokeService("createWorkEffortICalData", serviceMap, context); } else { - invokeService("updateWorkEffortICalData", serviceMap, context); + serviceResult = invokeService("updateWorkEffortICalData", serviceMap, context); + } + if (ServiceUtil.isError(serviceResult)) { + return ICalWorker.createPartialContentResponse(ServiceUtil.getErrorMessage(serviceResult)); } + return ICalWorker.createOkResponse(null); } @SuppressWarnings("unchecked") - protected static void storePartyAssignments(String workEffortId, Component component, Map<String, Object> context) { + protected static ResponseProperties storePartyAssignments(String workEffortId, Component component, Map<String, Object> context) { + ResponseProperties responseProps = null; Map<String, Object> serviceMap = FastMap.newInstance(); List<Property> partyList = FastList.newInstance(); partyList.addAll(component.getProperties("ATTENDEE")); @@ -755,30 +772,33 @@ invokeService("assignPartyToWorkEffort", serviceMap, context); } } catch (GenericEntityException e) { + responseProps = ICalWorker.createPartialContentResponse(e.getMessage()); + break; } } + return responseProps; } - protected static void storeWorkEffort(Component component, Map<String, Object> context) throws GenericEntityException, GenericServiceException { + protected static ResponseProperties storeWorkEffort(Component component, Map<String, Object> context) throws GenericEntityException, GenericServiceException { PropertyList propertyList = component.getProperties(); String workEffortId = fromXProperty(propertyList, workEffortIdXPropName); GenericDelegator delegator = (GenericDelegator) context.get("delegator"); GenericValue workEffort = delegator.findOne("WorkEffort", UtilMisc.toMap("workEffortId", workEffortId), false); if (workEffort == null) { - return; + return ICalWorker.createNotFoundResponse(null); } if (!hasPermission(workEffortId, "UPDATE", context)) { - return; + return ICalWorker.createNotAuthorizedResponse(null); } Map<String, Object> serviceMap = FastMap.newInstance(); serviceMap.put("workEffortId", workEffortId); setWorkEffortServiceMap(component, serviceMap); invokeService("updateWorkEffort", serviceMap, context); - storePartyAssignments(workEffortId, component, context); + return storePartyAssignments(workEffortId, component, context); } @SuppressWarnings("unchecked") - protected static void toCalendarComponent(ComponentList components, GenericValue workEffort, Map<String, Object> context) throws GenericEntityException { + protected static ResponseProperties toCalendarComponent(ComponentList components, GenericValue workEffort, Map<String, Object> context) throws GenericEntityException { GenericDelegator delegator = workEffort.getDelegator(); String workEffortId = workEffort.getString("workEffortId"); String workEffortUid = workEffort.getString("universalId"); @@ -795,7 +815,7 @@ } else if ("EVENT".equals(workEffortTypeId) || (typeValue != null && "EVENT".equals(typeValue.get("parentTypeId")))){ resultList = components.getComponents("VEVENT"); } else { - return; + return null; } Iterator<Component> i = resultList.iterator(); while (i.hasNext()) { @@ -872,6 +892,7 @@ Debug.logVerbose(e, "iCalendar component fails validation: ", module); } } + return null; } protected static Clazz toClazz(String javaObj) { Modified: ofbiz/trunk/applications/workeffort/src/org/ofbiz/workeffort/workeffort/ICalWorker.java URL: http://svn.apache.org/viewvc/ofbiz/trunk/applications/workeffort/src/org/ofbiz/workeffort/workeffort/ICalWorker.java?rev=789112&r1=789111&r2=789112&view=diff ============================================================================== --- ofbiz/trunk/applications/workeffort/src/org/ofbiz/workeffort/workeffort/ICalWorker.java (original) +++ ofbiz/trunk/applications/workeffort/src/org/ofbiz/workeffort/workeffort/ICalWorker.java Sun Jun 28 15:33:24 2009 @@ -61,8 +61,18 @@ * delegates the calendar conversion tasks to <code>ICalConverter</code>. */ public class ICalWorker { + public static final String module = ICalWorker.class.getName(); - + + public static class ResponseProperties { + public final int statusCode; + public final String statusMessage; + public ResponseProperties(int statusCode, String statusMessage) { + this.statusCode = statusCode; + this.statusMessage = statusMessage; + } + } + @SuppressWarnings("unchecked") protected static Map<String, Object> createConversionContext(HttpServletRequest request) { Map<String, Object> context = FastMap.newInstance(); @@ -76,6 +86,26 @@ return context; } + public static ResponseProperties createForbiddenResponse(String statusMessage) { + return new ResponseProperties(HttpServletResponse.SC_FORBIDDEN, statusMessage); + } + + public static ResponseProperties createNotAuthorizedResponse(String statusMessage) { + return new ResponseProperties(HttpServletResponse.SC_UNAUTHORIZED, statusMessage); + } + + public static ResponseProperties createNotFoundResponse(String statusMessage) { + return new ResponseProperties(HttpServletResponse.SC_NOT_FOUND, statusMessage); + } + + public static ResponseProperties createOkResponse(String statusMessage) { + return new ResponseProperties(HttpServletResponse.SC_OK, statusMessage); + } + + public static ResponseProperties createPartialContentResponse(String statusMessage) { + return new ResponseProperties(HttpServletResponse.SC_PARTIAL_CONTENT, statusMessage); + } + protected static Writer getWriter(HttpServletResponse response, ServletContext context) throws IOException { Writer writer = null; if (UtilJ2eeCompat.useOutputStreamNotWriter(context)) { @@ -96,22 +126,18 @@ return; } Debug.logInfo("[handleGetRequest] workEffortId = " + workEffortId, module); + ResponseProperties responseProps = null; try { - String calendar = ICalConverter.getICalendar(workEffortId, createConversionContext(request)); - if (calendar == null) { - response.sendError(HttpServletResponse.SC_NOT_FOUND); - return; - } - response.setContentType("text/calendar"); - response.setStatus(HttpServletResponse.SC_OK); - Writer writer = getWriter(response, context); - writer.write(calendar); - writer.close(); + responseProps = ICalConverter.getICalendar(workEffortId, createConversionContext(request)); } catch (Exception e) { Debug.logError(e, "[handleGetRequest] Error while sending calendar: ", module); response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); return; } + if (responseProps.statusCode == HttpServletResponse.SC_OK) { + response.setContentType("text/calendar"); + } + writeResponse(responseProps, response, context); } public static void handlePropFindRequest(HttpServletRequest request, HttpServletResponse response, ServletContext context) throws ServletException, IOException { @@ -125,9 +151,10 @@ Debug.logInfo("[handlePropFindRequest] workEffortId = " + workEffortId, module); try { Document requestDocument = WebDavUtil.getDocumentFromRequest(request); - ByteArrayOutputStream os = new ByteArrayOutputStream(); - UtilXml.writeXmlDocument(os, requestDocument, "UTF-8", true, true); + ByteArrayOutputStream os = null; if (Debug.verboseOn()) { + os = new ByteArrayOutputStream(); + UtilXml.writeXmlDocument(os, requestDocument, "UTF-8", true, true); Debug.logVerbose("[handlePropFindRequest] PROPFIND body:\r\n" + os.toString(), module); } PropFindHelper helper = new PropFindHelper(requestDocument); @@ -162,9 +189,9 @@ Element rootElement = helper.createMultiStatusElement(); rootElement.appendChild(responseElement); responseDocument.appendChild(rootElement); - os = new ByteArrayOutputStream(); - UtilXml.writeXmlDocument(os, responseDocument, "UTF-8", true, true); if (Debug.verboseOn()) { + os = new ByteArrayOutputStream(); + UtilXml.writeXmlDocument(os, responseDocument, "UTF-8", true, true); Debug.logVerbose("[handlePropFindRequest] PROPFIND response:\r\n" + os.toString(), module); } ResponseHelper.prepareResponse(response, 207, "Multi-Status"); @@ -196,14 +223,15 @@ return; } Debug.logInfo("[handlePutRequest] workEffortId = " + workEffortId, module); + ResponseProperties responseProps = null; try { - ICalConverter.storeCalendar(request.getInputStream(), createConversionContext(request)); + responseProps = ICalConverter.storeCalendar(request.getInputStream(), createConversionContext(request)); } catch (Exception e) { Debug.logError(e, "[handlePutRequest] Error while updating calendar: ", module); response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); return; } - response.setStatus(HttpServletResponse.SC_OK); + writeResponse(responseProps, response, context); } protected static void logInUser(HttpServletRequest request, HttpServletResponse response) throws GenericServiceException, GenericEntityException { @@ -255,4 +283,22 @@ Debug.logError(e, "Error while logging in user: ", module); } } + + protected static void writeResponse(ResponseProperties responseProps, HttpServletResponse response, ServletContext context) throws IOException { + if (Debug.verboseOn()) { + Debug.logVerbose("Returning response: code = " + responseProps.statusCode + + ", message = " + responseProps.statusMessage, module); + } + response.setStatus(responseProps.statusCode); + if (responseProps.statusMessage != null) { + Writer writer = getWriter(response, context); + try { + writer.write(responseProps.statusMessage); + } catch (IOException e) { + throw e; + } finally { + writer.close(); + } + } + } } |
Free forum by Nabble | Edit this page |