/** * {@inheritDoc} * * @see * org.sakaiproject.nakamura.api.personal.PersonalTrackingStore#recordActivity(java.lang.String, * java.lang.String, java.lang.String, java.lang.String, java.util.Date) */ public void recordActivity( String resourceId, String resourceType, String activityType, String userId, Calendar timestamp) { Session session = null; try { session = repository.loginAdministrative(); final ContentManager cm = session.getContentManager(); final String trackingNodePath = "/activity/" + resourceType + "/" + resourceId; Content trackingNode = null; if (cm.exists(trackingNodePath)) { trackingNode = cm.get(trackingNodePath); } else { trackingNode = new Content(trackingNodePath, new HashMap<String, Object>()); } if (!trackingNode.hasProperty("count")) { trackingNode.setProperty("count", BigDecimal.ZERO); } if (!trackingNode.hasProperty("sling:resourceType")) { trackingNode.setProperty("sling:resourceType", "sakai/resource-activity"); } final String generatedNodeName = Base64.encodeBase64URLSafeString(asShorterByteArray(UUID.randomUUID())); final String activityNodePath = trackingNodePath + "/" + generatedNodeName; Content activityNode = null; if (cm.exists(activityNodePath)) { activityNode = cm.get(activityNodePath); } else { activityNode = new Content(activityNodePath, new HashMap<String, Object>()); } BigDecimal activityCount = (BigDecimal) trackingNode.getProperty("count"); activityNode.setProperty("sling:resourceType", "sakai/resource-update"); trackingNode.setProperty("count", activityCount.add(BigDecimal.ONE)); activityNode.setProperty("resourceId", resourceId); activityNode.setProperty("resourcetype", resourceType); activityNode.setProperty("activitytype", activityType); activityNode.setProperty("timestamp", timestamp); activityNode.setProperty("userid", userId); cm.update(activityNode); cm.update(trackingNode); } catch (AccessDeniedException e) { LOG.error(e.getLocalizedMessage(), e); } catch (StorageClientException e) { LOG.error(e.getLocalizedMessage(), e); } finally { if (session != null) { try { session.logout(); } catch (ClientPoolException e) { LOG.error(e.getLocalizedMessage(), e); throw new IllegalStateException(e); } } } }
public static void writeLinkNode( Content content, org.sakaiproject.nakamura.api.lite.Session session, JSONWriter writer, boolean objectInProgress) throws StorageClientException, JSONException { if (!objectInProgress) { writer.object(); } ContentManager contentManager = session.getContentManager(); // Write all the properties. ExtendedJSONWriter.writeNodeContentsToWriter(writer, content); // permissions writePermissions(content, session, writer); // Write the actual file. if (content.hasProperty(SAKAI_LINK)) { String linkPath = (String) content.getProperty(SAKAI_LINK); writer.key("file"); try { Content fileNode = contentManager.get(linkPath); writeFileNode(fileNode, session, writer); } catch (org.sakaiproject.nakamura.api.lite.accesscontrol.AccessDeniedException e) { writer.value(false); } } if (!objectInProgress) { writer.endObject(); } }
private void addDefaultFields(SolrInputDocument doc, RepositorySession repositorySession) throws StorageClientException { Object o = doc.getFieldValue(_DOC_SOURCE_OBJECT); if (o instanceof Content) { Content content = (Content) o; boolean writeReaders = true; Object suppressReadersValue = doc.getFieldValue(FIELD_SUPPRESS_READERS); if (suppressReadersValue instanceof String) { if (FIELD_SUPPRESS_READERS.equals(suppressReadersValue)) { writeReaders = false; doc.removeField(FIELD_SUPPRESS_READERS); } } if (writeReaders) { String[] principals = getReadingPrincipals(repositorySession, Security.ZONE_CONTENT, content.getPath()); for (String principal : principals) { doc.addField(FIELD_READERS, principal); } } else { doc.removeField(FIELD_READERS); } if (content.hasProperty(SLING_RESOURCE_TYPE)) { doc.setField(FIELD_RESOURCE_TYPE, content.getProperty(SLING_RESOURCE_TYPE)); } String path = content.getPath(); // we don't overwrite the id field if it has been provided if (!doc.getFieldNames().contains(FIELD_ID)) { doc.setField(FIELD_ID, path); } while (path != null) { doc.addField(FIELD_PATH, path); String newPath = Utils.getParentPath(path); if (path.equals(newPath)) { break; } path = newPath; } doc.removeField(_DOC_SOURCE_OBJECT); } else { TelemetryCounter.incrementValue("solr", "SparseIndexingServiceImpl", "docMissingSource"); LOGGER.error( "Note to Developer: Indexer must add the _source fields so that the default fields can be set, please correct, SolrDoc was {} ", doc); throw new StorageClientException( _DOC_SOURCE_OBJECT + " fields was missing from Solr Document, please correct the handler implementation"); } }
@SuppressWarnings("unchecked") private <T> T getHandler( RepositorySession repositorySession, String path, Map<String, T> indexers, Map<String, String> ignoreCache) { org.sakaiproject.nakamura.api.lite.Session sparseSession = repositorySession.adaptTo(org.sakaiproject.nakamura.api.lite.Session.class); while (path != null) { if (!ignoreCache.containsKey(path)) { try { if (sparseSession != null) { ContentManager contentManager = sparseSession.getContentManager(); Content c = contentManager.get(path); LOGGER.debug("Checking Content at {} got {} ", path, c); if (c != null) { if (c.hasProperty("sling:resourceType")) { String resourceType = (String) c.getProperty("sling:resourceType"); T handler = indexers.get(resourceType); if (handler != null) { LOGGER.debug( "Handler of type {} found {} for {} from {} ", new Object[] {resourceType, handler, path, indexers}); return handler; } else { LOGGER.debug("Ignoring {}; no handler", path); synchronized (this) { ignoreCache.put(path, path); } } } else { LOGGER.debug("Ignored {} no resource type ", path); } } } } catch (StorageClientException e) { LOGGER.debug(e.getMessage(), e); } catch (AccessDeniedException e) { LOGGER.debug(e.getMessage(), e); } } if (StorageClientUtils.isRoot(path)) { break; } path = Utils.getParentPath(path); } return (T) defaultHandler; }
private IndexingHandler getHandler(RepositorySession repositorySession, String path) { org.sakaiproject.nakamura.api.lite.Session sparseSession = repositorySession.adaptTo(org.sakaiproject.nakamura.api.lite.Session.class); while (path != null) { if (!ignoreCache.containsKey(path)) { try { if (sparseSession != null) { ContentManager contentManager = sparseSession.getContentManager(); Content c = contentManager.get(path); LOGGER.debug("Checking Content at {} got {} ", path, c); if (c != null) { if (c.hasProperty(SLING_RESOURCE_TYPE)) { String resourceType = (String) c.getProperty(SLING_RESOURCE_TYPE); IndexingHandler handler = indexers.get(resourceType); if (handler != null) { LOGGER.debug( "Handler of type {} found {} for {} from {} ", new Object[] {resourceType, handler, path, indexers}); return handler; } else { TelemetryCounter.incrementValue( "solr", "SparseIndexingServiceImpl-ignoredPath", path); LOGGER.debug("Ignored {} no handler for {} ", path, resourceType); ignoreCache.put(path, path); } } else { LOGGER.debug("Ignored {} no resource type ", path); } } } } catch (StorageClientException e) { LOGGER.debug(e.getMessage(), e); } catch (AccessDeniedException e) { LOGGER.debug(e.getMessage(), e); } } if (StorageClientUtils.isRoot(path)) { break; } path = Utils.getParentPath(path); } TelemetryCounter.incrementValue("solr", "SparseIndexingServiceImpl", "useDefaultHandler"); return defaultHandler; }
private void scheduleRetry(int errorCode, Content contentNode) { // All retry-able SMTP errors should have codes starting with 4 if ((errorCode / 100) == 4) { long retryCount = 0; if (contentNode.hasProperty(MessageConstants.PROP_SAKAI_RETRY_COUNT)) { retryCount = StorageClientUtils.toLong( contentNode.getProperty(MessageConstants.PROP_SAKAI_RETRY_COUNT)); } if (retryCount < maxRetries) { Job job = new Job() { public void execute(JobContext jc) { Map<String, Serializable> config = jc.getConfiguration(); Properties eventProps = new Properties(); eventProps.put(NODE_PATH_PROPERTY, config.get(NODE_PATH_PROPERTY)); Event retryEvent = new Event(QUEUE_NAME, eventProps); eventAdmin.postEvent(retryEvent); } }; HashMap<String, Serializable> jobConfig = new HashMap<String, Serializable>(); jobConfig.put(NODE_PATH_PROPERTY, contentNode.getPath()); int retryIntervalMillis = retryInterval * 60000; Date nextTry = new Date(System.currentTimeMillis() + (retryIntervalMillis)); try { scheduler.fireJobAt(null, job, jobConfig, nextTry); } catch (Exception e) { LOGGER.error(e.getMessage(), e); } } else { setError(contentNode, "Unable to send message, exhausted SMTP retries."); } } else { LOGGER.warn("Not scheduling a retry for error code not of the form 4xx."); } }
@Override protected void doGet(SlingHttpServletRequest request, SlingHttpServletResponse response) throws ServletException, IOException { Resource resource = request.getResource(); Node node = resource.adaptTo(Node.class); Content content = resource.adaptTo(Content.class); System.err.println("Node is " + node + " content is " + content); String link = null; try { if (node != null && node.hasProperty(FilesConstants.SAKAI_LINK)) { link = node.getProperty(FilesConstants.SAKAI_LINK).getString(); } else if (content != null && content.hasProperty(FilesConstants.SAKAI_LINK)) { link = (String) content.getProperty(FilesConstants.SAKAI_LINK); } System.err.println("Link is " + link); if (link != null) { String[] linkProps = StringUtils.split(link, ':'); LinkHandler handler = null; String path = null; if (linkProps.length == 2) { handler = fileHandlerTracker.getProcessorByName(linkProps[0]); path = linkProps[1]; } else { if (node != null) { handler = new JcrInternalFileHandler(); } else { handler = new SparseContentInternalFileHandler(); } path = link; } if (handler != null) { handler.handleFile(request, response, path); } } } catch (RepositoryException e) { LOGGER.warn(e.getMessage(), e); response.sendError(500, "Unable to handle linked file."); } }
/** * Writes commentCount of content * * @param node * @param session * @param write * @throws RepositoryException * @throws JSONException */ public static void writeCommentCountProperty( Content content, org.sakaiproject.nakamura.api.lite.Session session, JSONWriter writer, Repository repository) throws StorageClientException, JSONException { int commentCount = 0; String COMMENTCOUNT = "commentCount"; if (content.hasProperty(COMMENTCOUNT)) { commentCount = (Integer) content.getProperty(COMMENTCOUNT); } else { // no commentCount property on Content, then evaluate count and add property Content comments = null; org.sakaiproject.nakamura.api.lite.Session adminSession = null; try { comments = session.getContentManager().get(content.getPath() + "/comments"); if (comments != null) { commentCount = Iterables.size(comments.listChildPaths()); } content.setProperty(COMMENTCOUNT, commentCount); // save property adminSession = repository.loginAdministrative(); ContentManager adminContentManager = adminSession.getContentManager(); adminContentManager.update(content); } catch (org.sakaiproject.nakamura.api.lite.accesscontrol.AccessDeniedException e) { log.error(e.getMessage(), e); } finally { if (adminSession != null) { try { adminSession.logout(); } catch (Exception e) { log.error("Could not logout administrative session."); } } } } writer.key(COMMENTCOUNT); writer.value(commentCount); }
private void addDefaultFields(SolrInputDocument doc, RepositorySession repositorySession) throws StorageClientException { Object o = doc.getFieldValue(_DOC_SOURCE_OBJECT); if (o instanceof Content) { Content content = (Content) o; String[] principals = getReadingPrincipals(repositorySession, Security.ZONE_CONTENT, content.getPath()); for (String principal : principals) { doc.addField(FIELD_READERS, principal); } if (content.hasProperty("sling:resourceType")) { doc.setField(FIELD_RESOURCE_TYPE, content.getProperty("sling:resourceType")); } String path = content.getPath(); // we don't overwrite the id field if it has been provided if (!doc.getFieldNames().contains(FIELD_ID)) { doc.setField(FIELD_ID, path); } while (path != null) { doc.addField(FIELD_PATH, path); String newPath = Utils.getParentPath(path); if (path.equals(newPath)) { break; } path = newPath; } doc.removeField(_DOC_SOURCE_OBJECT); } else { LOGGER.error( "Note to Developer: Indexer must add the _source fields so that the default fields can be set, please correct, SolrDoc was {} ", doc); throw new StorageClientException( _DOC_SOURCE_OBJECT + " fields was missing from Solr Document, please correct the handler implementation"); } }
/** * {@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); } } } } } }
private MultiPartEmail constructMessage( Content contentNode, List<String> recipients, javax.jcr.Session session, org.sakaiproject.nakamura.api.lite.Session sparseSession) throws EmailDeliveryException, StorageClientException, AccessDeniedException, PathNotFoundException, RepositoryException { MultiPartEmail email = new MultiPartEmail(); // TODO: the SAKAI_TO may make no sense in an email context // and there does not appear to be any distinction between Bcc and To in java mail. Set<String> toRecipients = new HashSet<String>(); Set<String> bccRecipients = new HashSet<String>(); for (String r : recipients) { bccRecipients.add(convertToEmail(r.trim(), sparseSession)); } if (contentNode.hasProperty(MessageConstants.PROP_SAKAI_TO)) { String[] tor = StringUtils.split((String) contentNode.getProperty(MessageConstants.PROP_SAKAI_TO), ','); for (String r : tor) { r = convertToEmail(r.trim(), sparseSession); if (bccRecipients.contains(r)) { toRecipients.add(r); bccRecipients.remove(r); } } } for (String r : toRecipients) { try { email.addTo(convertToEmail(r, sparseSession)); } catch (EmailException e) { throw new EmailDeliveryException( "Invalid To Address [" + r + "], message is being dropped :" + e.getMessage(), e); } } for (String r : bccRecipients) { try { email.addBcc(convertToEmail(r, sparseSession)); } catch (EmailException e) { throw new EmailDeliveryException( "Invalid Bcc Address [" + r + "], message is being dropped :" + e.getMessage(), e); } } if (contentNode.hasProperty(MessageConstants.PROP_SAKAI_FROM)) { String from = (String) contentNode.getProperty(MessageConstants.PROP_SAKAI_FROM); try { email.setFrom(convertToEmail(from, sparseSession)); } catch (EmailException e) { throw new EmailDeliveryException( "Invalid From Address [" + from + "], message is being dropped :" + e.getMessage(), e); } } else { throw new EmailDeliveryException("Must provide a 'from' address."); } if (contentNode.hasProperty(MessageConstants.PROP_SAKAI_BODY)) { String messageBody = (String) contentNode.getProperty(MessageConstants.PROP_SAKAI_BODY); // if this message has a template, use it LOGGER.debug( "Checking for sakai:templatePath and sakai:templateParams properties on the outgoing message's node."); if (contentNode.hasProperty(MessageConstants.PROP_TEMPLATE_PATH) && contentNode.hasProperty(MessageConstants.PROP_TEMPLATE_PARAMS)) { Map<String, String> parameters = getTemplateProperties( (String) contentNode.getProperty(MessageConstants.PROP_TEMPLATE_PARAMS)); String templatePath = (String) contentNode.getProperty(MessageConstants.PROP_TEMPLATE_PATH); LOGGER.debug("Got the path '{0}' to the template for this outgoing message.", templatePath); Node templateNode = session.getNode(templatePath); if (templateNode.hasProperty("sakai:template")) { String template = templateNode.getProperty("sakai:template").getString(); LOGGER.debug("Pulled the template body from the template node: {0}", template); messageBody = templateService.evaluateTemplate(parameters, template); LOGGER.debug("Performed parameter substitution in the template: {0}", messageBody); } } else { LOGGER.debug( "Message node '{0}' does not have sakai:templatePath and sakai:templateParams properties", contentNode.getPath()); } try { email.setMsg(messageBody); } catch (EmailException e) { throw new EmailDeliveryException( "Invalid Message Body, message is being dropped :" + e.getMessage(), e); } } if (contentNode.hasProperty(MessageConstants.PROP_SAKAI_SUBJECT)) { email.setSubject((String) contentNode.getProperty(MessageConstants.PROP_SAKAI_SUBJECT)); } ContentManager contentManager = sparseSession.getContentManager(); for (String streamId : contentNode.listStreams()) { String description = null; if (contentNode.hasProperty( StorageClientUtils.getAltField( MessageConstants.PROP_SAKAI_ATTACHMENT_DESCRIPTION, streamId))) { description = (String) contentNode.getProperty( StorageClientUtils.getAltField( MessageConstants.PROP_SAKAI_ATTACHMENT_DESCRIPTION, streamId)); } LiteEmailDataSource ds = new LiteEmailDataSource(contentManager, contentNode, streamId); try { email.attach(ds, streamId, description); } catch (EmailException e) { throw new EmailDeliveryException( "Invalid Attachment [" + streamId + "] message is being dropped :" + e.getMessage(), e); } } return email; }
@SuppressWarnings("unchecked") public void onMessage(Message message) { try { LOGGER.debug("Started handling email jms message."); String nodePath = message.getStringProperty(NODE_PATH_PROPERTY); String contentPath = message.getStringProperty(CONTENT_PATH_PROPERTY); Object objRcpt = message.getObjectProperty(RECIPIENTS); List<String> recipients = null; if (objRcpt instanceof List<?>) { recipients = (List<String>) objRcpt; } else if (objRcpt instanceof String) { recipients = new LinkedList<String>(); String[] rcpts = StringUtils.split((String) objRcpt, ','); for (String rcpt : rcpts) { recipients.add(rcpt); } } if (contentPath != null && contentPath.length() > 0) { javax.jcr.Session adminSession = repository.loginAdministrative(null); org.sakaiproject.nakamura.api.lite.Session sparseSession = StorageClientUtils.adaptToSession(adminSession); try { ContentManager contentManager = sparseSession.getContentManager(); Content messageContent = contentManager.get(contentPath); if (objRcpt != null) { // validate the message if (messageContent != null) { if (messageContent.hasProperty(MessageConstants.PROP_SAKAI_MESSAGEBOX) && (MessageConstants.BOX_OUTBOX.equals( messageContent.getProperty(MessageConstants.PROP_SAKAI_MESSAGEBOX)) || MessageConstants.BOX_PENDING.equals( messageContent.getProperty(MessageConstants.PROP_SAKAI_MESSAGEBOX)))) { if (messageContent.hasProperty(MessageConstants.PROP_SAKAI_MESSAGEERROR)) { // We're retrying this message, so clear the errors messageContent.setProperty( MessageConstants.PROP_SAKAI_MESSAGEERROR, (String) null); } if (messageContent.hasProperty(MessageConstants.PROP_SAKAI_TO) && messageContent.hasProperty(MessageConstants.PROP_SAKAI_FROM)) { // make a commons-email message from the message MultiPartEmail email = null; try { email = constructMessage(messageContent, recipients, adminSession, sparseSession); email.setSmtpPort(smtpPort); email.setHostName(smtpServer); email.send(); } catch (EmailException e) { String exMessage = e.getMessage(); Throwable cause = e.getCause(); setError(messageContent, exMessage); LOGGER.warn("Unable to send email: " + exMessage); // Get the SMTP error code // There has to be a better way to do this boolean rescheduled = false; if (cause != null && cause.getMessage() != null) { String smtpError = cause.getMessage().trim(); try { int errorCode = Integer.parseInt(smtpError.substring(0, 3)); // All retry-able SMTP errors should have codes starting // with 4 scheduleRetry(errorCode, messageContent); rescheduled = true; } catch (NumberFormatException nfe) { // smtpError didn't start with an error code, let's dig for // it String searchFor = "response:"; int rindex = smtpError.indexOf(searchFor); if (rindex > -1 && (rindex + searchFor.length()) < smtpError.length()) { int errorCode = Integer.parseInt( smtpError.substring(searchFor.length(), searchFor.length() + 3)); scheduleRetry(errorCode, messageContent); rescheduled = true; } } } if (rescheduled) { LOGGER.info("Email {} rescheduled for redelivery. ", nodePath); } else { LOGGER.error("Unable to reschedule email for delivery: " + e.getMessage(), e); } } } else { setError(messageContent, "Message must have a to and from set"); } } else { setError(messageContent, "Not an outbox"); } if (!messageContent.hasProperty(MessageConstants.PROP_SAKAI_MESSAGEERROR)) { messageContent.setProperty( MessageConstants.PROP_SAKAI_MESSAGEBOX, MessageConstants.BOX_SENT); } } } else { String retval = "null"; setError( messageContent, "Expected recipients to be String or List<String>. Found " + retval); } } finally { if (adminSession != null) { adminSession.logout(); } } } } catch (PathNotFoundException e) { LOGGER.error(e.getMessage(), e); } catch (RepositoryException e) { LOGGER.error(e.getMessage(), e); } catch (JMSException e) { LOGGER.error(e.getMessage(), e); } catch (EmailDeliveryException e) { LOGGER.error(e.getMessage()); } catch (ClientPoolException e) { LOGGER.error(e.getMessage(), e); } catch (StorageClientException e) { LOGGER.error(e.getMessage(), e); } catch (AccessDeniedException e) { LOGGER.error(e.getMessage(), e); } }
/** * {@inheritDoc} * * @see * org.sakaiproject.nakamura.api.search.solr.SolrSearchBatchResultProcessor#writeResults(org.apache.sling.api.SlingHttpServletRequest, * org.apache.sling.commons.json.io.JSONWriter, java.util.Iterator) */ public void writeResults( SlingHttpServletRequest request, JSONWriter writer, Iterator<Result> iterator) throws JSONException { try { Session session = StorageClientUtils.adaptToSession( request.getResourceResolver().adaptTo(javax.jcr.Session.class)); ContentManager cm = session.getContentManager(); List<String> basePosts = new ArrayList<String>(); Map<String, List<Post>> postChildren = new HashMap<String, List<Post>>(); Map<String, Post> allPosts = new HashMap<String, Post>(); while (iterator.hasNext()) { Result result = iterator.next(); Content content = cm.get(result.getPath()); if (content == null) { continue; } Post p = new Post(content, session); allPosts.put((String) content.getProperty(MessageConstants.PROP_SAKAI_ID), p); if (content.hasProperty(DiscussionConstants.PROP_REPLY_ON)) { // This post is a reply on another post. String replyon = (String) content.getProperty(DiscussionConstants.PROP_REPLY_ON); if (!postChildren.containsKey(replyon)) { postChildren.put(replyon, new ArrayList<Post>()); } postChildren.get(replyon).add(p); } else { // This post is not a reply to another post, thus it is a basepost. basePosts.add(p.getPostId()); } } // Now that we have all the base posts, we can sort the replies properly for (Entry<String, List<Post>> postChild : postChildren.entrySet()) { Post parentPost = allPosts.get(postChild.getKey()); if (parentPost != null) { List<Post> childrenList = parentPost.getChildren(); List<Post> childrenActual = postChild.getValue(); childrenList.addAll(childrenActual); } } // The posts are sorted, now return them as json. for (String basePostId : basePosts) { allPosts .get(basePostId) .outputPostAsJSON( (ExtendedJSONWriter) writer, presenceService, basicUserInfoService, session); } } catch (StorageClientException e) { throw new RuntimeException(e.getMessage(), e); } catch (AccessDeniedException e) { throw new RuntimeException(e.getMessage(), e); } catch (RepositoryException e) { throw new RuntimeException(e.getMessage(), e); } }
public void internalImportContent( ContentManager contentManager, JSONObject json, String path, boolean replaceProperties, AccessControlManager accessControlManager) throws JSONException, StorageClientException, AccessDeniedException { Iterator<String> keys = json.keys(); Map<String, Object> properties = new HashMap<String, Object>(); List<AclModification> modifications = Lists.newArrayList(); while (keys.hasNext()) { String key = keys.next(); if (!key.startsWith("jcr:")) { Object obj = json.get(key); String pathKey = getPathElement(key); Class<?> typeHint = getElementType(key); if (obj instanceof JSONObject) { if (key.endsWith("@grant")) { JSONObject acl = (JSONObject) obj; int bitmap = getPermissionBitMap(acl.getJSONArray("permission")); Operation op = getOperation(acl.getString("operation")); modifications.add(new AclModification(AclModification.grantKey(pathKey), bitmap, op)); } else if (key.endsWith("@deny")) { JSONObject acl = (JSONObject) obj; int bitmap = getPermissionBitMap(acl.getJSONArray("permission")); Operation op = getOperation(acl.getString("operation")); modifications.add(new AclModification(AclModification.denyKey(pathKey), bitmap, op)); } else if (key.endsWith("@Delete")) { StorageClientUtils.deleteTree(contentManager, path); } else { // need to do somethingwith delete here internalImportContent( contentManager, (JSONObject) obj, path + "/" + pathKey, replaceProperties, accessControlManager); } } else if (obj instanceof JSONArray) { if (key.endsWith("@Delete")) { properties.put(pathKey, new RemoveProperty()); } else { // This represents a multivalued property JSONArray arr = (JSONArray) obj; properties.put(pathKey, getArray(arr, typeHint)); } } else { if (key.endsWith("@Delete")) { properties.put(pathKey, new RemoveProperty()); } else { properties.put(pathKey, getObject(obj, typeHint)); } } } } Content content = contentManager.get(path); if (content == null) { contentManager.update(new Content(path, properties)); LOGGER.info("Created Node {} {}", path, properties); } else { for (Entry<String, Object> e : properties.entrySet()) { if (replaceProperties || !content.hasProperty(e.getKey())) { LOGGER.info("Updated Node {} {} {} ", new Object[] {path, e.getKey(), e.getValue()}); content.setProperty(e.getKey(), e.getValue()); } } contentManager.update(content); } if (modifications.size() > 0) { accessControlManager.setAcl( Security.ZONE_CONTENT, path, modifications.toArray(new AclModification[modifications.size()])); } }