/** * Searches up the resource super type hierarchy to create a list of available templates. This * list can have duplicates in it and should respect the app and libs folder. * * @param resource the resource to start getting templates for * @return list of templates that are available for this resource */ private List<String> collectTemplates(final Resource resource) { final List<String> templates = new ArrayList<String>(); if (resource == null) { return templates; } final ResourceResolver resourceResolver = resource.getResourceResolver(); if (resource.getResourceSuperType() != null) { templates.addAll( collectTemplates(resourceResolver.getResource(resource.getResourceSuperType()))); } final Iterator<Resource> childIterator = resource.listChildren(); String templateName; while (childIterator.hasNext()) { templateName = childIterator.next().getName(); if (templateName.matches(TEMPLATE_MASK)) { templates.add(templateName); } } return templates; }
/** Best effort implementation to check on resource type/superType */ @Override public boolean isResourceType(Resource resource, String s) { if (resource == null) { return false; } String resourceType = resource.getResourceType(); if (isEmpty(resourceType) || isEmpty(s)) { return false; } String superType = resource.getResourceSuperType(); if (StringUtils.equals(superType, s)) { return true; } return false; }
/** * {@inheritDoc} This post processor is only interested in posts to messages, so it should iterate * rapidly through all messages. * * @see * org.apache.sling.servlets.post.SlingPostProcessor#process(org.apache.sling.api.SlingHttpServletRequest, * java.util.List) */ public void process(SlingHttpServletRequest request, List<Modification> changes) throws Exception { Resource resource = request.getResource(); ResourceResolver resourceResolver = request.getResourceResolver(); if (SparseContentResource.SPARSE_CONTENT_RT.equals(resource.getResourceSuperType())) { Session session = resource.adaptTo(Session.class); ContentManager contentManager = session.getContentManager(); Map<Content, String> messageMap = new HashMap<Content, String>(); for (Modification m : changes) { try { switch (m.getType()) { case CREATE: case MODIFY: String path = m.getSource(); if (path.lastIndexOf("@") > 0) { path = path.substring(0, path.lastIndexOf("@")); } if (path.endsWith("/" + MessageConstants.PROP_SAKAI_MESSAGEBOX)) { path = path.substring( 0, path.length() - MessageConstants.PROP_SAKAI_MESSAGEBOX.length() - 1); } // The Modification Source is the Resource path, and so we // need to translate that into a Content path. // TODO This is not a cheap operation. We might be better off // if we start including the Content path in our Modification objects. Resource modifiedResource = resourceResolver.getResource(path); if (modifiedResource == null) { return; } Content content = modifiedResource.adaptTo(Content.class); String contentPath = content.getPath(); if (contentManager.exists(contentPath)) { content = contentManager.get(contentPath); if (content.hasProperty(SLING_RESOURCE_TYPE_PROPERTY) && content.hasProperty(PROP_SAKAI_MESSAGEBOX)) { if (SAKAI_MESSAGE_RT.equals(content.getProperty(SLING_RESOURCE_TYPE_PROPERTY)) && BOX_OUTBOX.equals(content.getProperty(PROP_SAKAI_MESSAGEBOX))) { String sendstate; if (content.hasProperty(PROP_SAKAI_SENDSTATE)) { sendstate = (String) content.getProperty(PROP_SAKAI_SENDSTATE); } else { sendstate = STATE_NONE; } messageMap.put(content, sendstate); } } } break; } } catch (StorageClientException ex) { LOGGER.warn("Failed to process on create for {} ", m.getSource(), ex); } catch (AccessDeniedException ex) { LOGGER.warn("Failed to process on create for {} ", m.getSource(), ex); } } List<String> handledNodes = new ArrayList<String>(); // Check if we have any nodes that have a pending state and launch an OSGi // event for (Entry<Content, String> mm : messageMap.entrySet()) { Content content = mm.getKey(); String path = content.getPath(); String state = mm.getValue(); if (!handledNodes.contains(path)) { if (STATE_NONE.equals(state) || STATE_PENDING.equals(state)) { content.setProperty(PROP_SAKAI_SENDSTATE, STATE_NOTIFIED); contentManager.update(content); Dictionary<String, Object> messageDict = new Hashtable<String, Object>(); // WARNING // We can't pass in the node, because the session might expire before the event gets // handled // This does mean that the listener will have to get the node each time, and probably // create a new session for each message // This might be heavy on performance. messageDict.put(EVENT_LOCATION, path); messageDict.put(UserConstants.EVENT_PROP_USERID, request.getRemoteUser()); LOGGER.debug("Launched event for message: {} ", path); Event pendingMessageEvent = new Event(PENDINGMESSAGE_EVENT, messageDict); // KERN-790: Initiate a synchronous event. try { eventAdmin.postEvent(pendingMessageEvent); handledNodes.add(path); } catch (Exception e) { LOGGER.warn("Failed to post message dispatch event, cause {} ", e.getMessage(), e); } } } } } }