@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);
   if (node != null) {
     try {
       Session jcrSession = request.getResourceResolver().adaptTo(Session.class);
       JSONWriter write = new JSONWriter(response.getWriter());
       FileUtils.writeLinkNode(node, jcrSession, write);
     } catch (JSONException e) {
       response.sendError(500, "Unable to parse JSON.");
     } catch (RepositoryException e) {
       LOGGER.warn("Unable to get file info for link.");
       response.sendError(500, "Unable get file info.");
     }
   } else {
     try {
       org.sakaiproject.nakamura.api.lite.Session session =
           resource.adaptTo(org.sakaiproject.nakamura.api.lite.Session.class);
       JSONWriter write = new JSONWriter(response.getWriter());
       FileUtils.writeLinkNode(content, session, write);
     } catch (StorageClientException e) {
       LOGGER.warn("Unable to get file info for link.");
       response.sendError(500, "Unable get file info.");
     } catch (JSONException e) {
       response.sendError(500, "Unable to parse JSON.");
     }
   }
 }
  @Override
  protected void doGet(SlingHttpServletRequest request, SlingHttpServletResponse response)
      throws ServletException, IOException {

    // setup SSE headers
    response.setContentType("text/event-stream");
    response.setCharacterEncoding("UTF-8");
    response.setHeader("Cache-Control", "no-cache");
    response.setHeader("Connection", "keep-alive");
    // needed to allow the JavaScript EventSource API to make a call from author to this server and
    // listen for the events
    response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin"));
    response.setHeader("Access-Control-Allow-Credentials", "true");

    String agentName =
        request.getResource().getParent().getParent().adaptTo(ReplicationAgent.class).getName();
    PrintWriter writer = response.getWriter();
    while (true) {
      try {
        synchronized (cachedEvents) {
          cachedEvents.wait();
          Collection<String> eventsForAgent = cachedEvents.get(agentName);
          if (eventsForAgent != null) {
            for (String event : eventsForAgent) {
              writeEvent(writer, agentName + "-queue-event", event);
            }
          }
        }
      } catch (InterruptedException e) {
        log.error("error during SSE", e);
        throw new ServletException(e);
      }
    }
  }
 @Before
 public void setup() throws IOException {
   when(response.getWriter()).thenReturn(new PrintWriter(new StringWriter()));
   when(request.getResource()).thenReturn(resource);
   servlet = new SiteDeleteServlet();
   servlet.bindSiteService(siteService);
 }
示例#4
0
  @Test
  public void testProperPoolId()
      throws ItemNotFoundException, RepositoryException, NoSuchAlgorithmException,
          UnsupportedEncodingException {
    SlingHttpServletRequest request = mock(SlingHttpServletRequest.class);
    HtmlResponse response = new HtmlResponse();

    ResourceResolver resolver = mock(ResourceResolver.class);

    String poolId = "foobarbaz";
    Resource resource = mock(Resource.class);

    // The tagnode
    Node tagNode = new MockNode("/path/to/tag");
    tagNode.setProperty(SLING_RESOURCE_TYPE_PROPERTY, FilesConstants.RT_SAKAI_TAG);
    tagNode.setProperty(FilesConstants.SAKAI_TAG_NAME, "urban");

    // The file we want to tag.
    Node fileNode = mock(Node.class);
    when(fileNode.getPath()).thenReturn("/path/to/file");
    NodeType type = mock(NodeType.class);
    when(type.getName()).thenReturn("foo");
    when(fileNode.getMixinNodeTypes()).thenReturn(new NodeType[] {type});
    Property tagsProp = mock(Property.class);
    MockPropertyDefinition tagsPropDef = new MockPropertyDefinition(false);
    Value v = new MockValue("uuid-to-other-tag");
    when(tagsProp.getDefinition()).thenReturn(tagsPropDef);
    when(tagsProp.getValue()).thenReturn(v);
    when(fileNode.getProperty(FilesConstants.SAKAI_TAGS)).thenReturn(tagsProp);
    when(fileNode.hasProperty(FilesConstants.SAKAI_TAGS)).thenReturn(true);

    // Stuff to check if this is a correct request
    when(session.getNode(CreateContentPoolServlet.hash(poolId))).thenReturn(tagNode);
    RequestParameter poolIdParam = mock(RequestParameter.class);
    when(resolver.adaptTo(Session.class)).thenReturn(session);
    when(resource.adaptTo(Node.class)).thenReturn(fileNode);
    when(poolIdParam.getString()).thenReturn(poolId);
    when(request.getResource()).thenReturn(resource);
    when(request.getResourceResolver()).thenReturn(resolver);
    when(request.getRequestParameter("key")).thenReturn(poolIdParam);
    when(request.getRemoteUser()).thenReturn("john");

    // Actual tagging procedure
    Session adminSession = mock(Session.class);
    when(adminSession.getItem(fileNode.getPath())).thenReturn(fileNode);
    ValueFactory valueFactory = mock(ValueFactory.class);
    Value newValue = new MockValue("uuid-of-tag");
    when(valueFactory.createValue(Mockito.anyString(), Mockito.anyInt()))
        .thenReturn(newValue)
        .thenReturn(newValue);
    when(adminSession.getValueFactory()).thenReturn(valueFactory).thenReturn(valueFactory);
    when(slingRepo.loginAdministrative(null)).thenReturn(adminSession);

    when(adminSession.hasPendingChanges()).thenReturn(true);
    operation.doRun(request, response, null);

    assertEquals(200, response.getStatusCode());
    verify(adminSession).save();
    verify(adminSession).logout();
  }
示例#5
0
 @Override
 protected void doPost(SlingHttpServletRequest request, SlingHttpServletResponse response)
     throws ServletException, IOException {
   String paramUser = request.getParameter(SiteService.SiteEvent.USER);
   logger.info("Request to add user " + paramUser);
   String paramGroup = "";
   try {
     Node requestedNode = request.getResource().adaptTo(Node.class);
     Value[] authorizables = requestedNode.getProperty("sakai:authorizables").getValues();
     paramGroup = authorizables[1].getString();
     request.setAttribute(JoinRequestConstants.PARAM_SITENODE, requestedNode);
     Session session = slingRepository.loginAdministrative(null);
     UserManager userManager = AccessControlUtil.getUserManager(session);
     Authorizable userAuth = userManager.getAuthorizable(paramUser);
     Group groupAuth = (Group) userManager.getAuthorizable(paramGroup);
     if (siteJoinIsAuthorized(request)) {
       groupAuth.addMember(userAuth);
       logger.info(paramUser + " added as member of group " + paramGroup);
     } else {
       response.sendError(403, "Not authorized to add member to site.");
     }
     if (session.hasPendingChanges()) {
       session.save();
     }
   } catch (Exception e) {
     response.sendError(500, e.getMessage());
   }
 }
  /** {@inheritDoc} */
  public void doPost(SlingHttpServletRequest request, SlingHttpServletResponse response)
      throws ServletException, IOException {
    try {
      Resource resource = request.getResource();
      Node node = resource.adaptTo(Node.class);
      if (node == null) {
        response.sendError(HttpServletResponse.SC_NOT_FOUND);
        return;
      }
      Version version = versionService.saveNode(node, request.getRemoteUser());

      response.setContentType("application/json");
      response.setCharacterEncoding("UTF-8");

      ExtendedJSONWriter write = new ExtendedJSONWriter(response.getWriter());
      write.object();
      write.key("versionName");
      write.value(version.getName());
      ExtendedJSONWriter.writeNodeContentsToWriter(write, version);
      write.endObject();
    } catch (RepositoryException e) {
      LOGGER.info("Failed to save version ", e);
      response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e.getMessage());
      return;
    } catch (JSONException e) {
      LOGGER.info("Failed to save version ", e);
      response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e.getMessage());
      return;
    }
  }
 @Override
 protected void doGet(final SlingHttpServletRequest req, final SlingHttpServletResponse resp)
     throws ServletException, IOException {
   final Resource resource = req.getResource();
   resp.getOutputStream().println(resource.toString());
   resp.getOutputStream().println("This content is generated by the SimpleServlet");
 }
示例#8
0
 public ForumSearchImpl(final SlingHttpServletRequest request) {
   this.request = request;
   resolver = request.getResourceResolver();
   properties = ResourceUtil.getValueMap(request.getResource());
   searchPaths = properties.get(PN_SEARCHPATHS, new String[0]);
   query = getParameter(REQUEST_PARAM_QUERY);
   scopeProps = request.getParameterValues(REQUEST_PARAM_QUERY_SCOPE);
   request.setAttribute(ATTRIBUTE_NAME_SEARCH, this);
 }
  @Override
  protected void doGet(SlingHttpServletRequest request, SlingHttpServletResponse response)
      throws ServletException, IOException {

    Resource resource = request.getResource();
    Node node = (Node) resource.adaptTo(Node.class);

    String filename = null;
    try {
      if (node.hasNode(JcrConstants.JCR_CONTENT)) {
        Node content = node.getNode(JcrConstants.JCR_CONTENT);
        response.setHeader(
            "Content-Type", content.getProperty(JcrConstants.JCR_MIMETYPE).getString());
        response.setHeader(
            "Content-Length", "" + content.getProperty(JcrConstants.JCR_DATA).getLength());
      }
      if (node.hasProperty(FilesConstants.SAKAI_FILENAME)) {
        filename = node.getProperty(FilesConstants.SAKAI_FILENAME).getString();
      }

      // If we provided a filename and we haven't changed the name in a previous request.
      if (filename != null && !response.containsHeader("Content-Disposition")) {
        response.setHeader("Content-Disposition", "filename=\"" + filename + "\"");
      }

      response.setStatus(HttpServletResponse.SC_OK);
      InputStream in = (InputStream) request.getResource().adaptTo(InputStream.class);
      OutputStream out = response.getOutputStream();

      IOUtils.stream(in, out);
    } catch (RepositoryException e) {
      logger.warn("Unable to download file due to repositoryexception!");
      e.printStackTrace();
      response.sendError(500);
    }
  }
  protected void dumpRequestAsProperties(
      SlingHttpServletRequest request, SlingHttpServletResponse response) throws IOException {
    final Properties props = new Properties();
    response.setContentType("text/plain");
    props.put("servlet.class.name", getClass().getName());

    final Resource r = request.getResource();
    props.put("sling.resource.path", r == null ? "" : r.getPath());
    props.put("sling.resource.type", r == null ? "" : r.getResourceType());
    props.put("http.request.method", request.getMethod());

    props.store(
        response.getOutputStream(),
        "Data created by " + getClass().getName() + " at " + new Date());
    response.getOutputStream().flush();
  }
  @Test
  public void testGet()
      throws VersionException, UnsupportedRepositoryOperationException, InvalidItemStateException,
          LockException, RepositoryException, IOException, ServletException {
    SlingHttpServletRequest request = createNiceMock(SlingHttpServletRequest.class);
    SlingHttpServletResponse response = createNiceMock(SlingHttpServletResponse.class);
    Resource resource = createNiceMock(Resource.class);
    Node node = createNiceMock(Node.class);
    Version version = createNiceMock(Version.class);
    PropertyIterator propertyIterator = createNiceMock(PropertyIterator.class);
    VersionHistory versionHistory = createNiceMock(VersionHistory.class);
    VersionIterator versionIterator = createNiceMock(VersionIterator.class);
    Node versionNode = createNiceMock(Node.class);
    Session session = createNiceMock(Session.class);
    Workspace workspace = createNiceMock(Workspace.class);
    VersionManager versionManager = createNiceMock(VersionManager.class);

    EasyMock.expect(request.getResource()).andReturn(resource).anyTimes();
    EasyMock.expect(resource.adaptTo(Node.class)).andReturn(node).anyTimes();
    PrintWriter pw = new PrintWriter(new ByteArrayOutputStream());
    EasyMock.expect(response.getWriter()).andReturn(pw).anyTimes();

    EasyMock.expect(node.getSession()).andReturn(session);
    EasyMock.expect(session.getWorkspace()).andReturn(workspace);
    EasyMock.expect(workspace.getVersionManager()).andReturn(versionManager);
    EasyMock.expect(versionManager.getVersionHistory("/foo")).andReturn(versionHistory);
    EasyMock.expect(node.getPath()).andReturn("/foo").anyTimes();
    EasyMock.expect(versionHistory.getAllVersions()).andReturn(versionIterator);
    EasyMock.expect(versionIterator.getSize()).andReturn(2L);
    EasyMock.expect(versionIterator.hasNext()).andReturn(true);
    EasyMock.expect(versionIterator.nextVersion()).andReturn(version);
    EasyMock.expect(versionIterator.hasNext()).andReturn(true);
    EasyMock.expect(versionIterator.nextVersion()).andReturn(version);

    EasyMock.expect(version.getName()).andReturn("NameVersioNode").anyTimes();
    EasyMock.expect(version.getNode(JcrConstants.JCR_FROZENNODE)).andReturn(versionNode).anyTimes();
    EasyMock.expect(version.getProperties()).andReturn(propertyIterator).anyTimes();
    EasyMock.expect(propertyIterator.hasNext()).andReturn(false).anyTimes();

    replay();

    listVersionsServlet.doGet(request, response);
    verify();
  }
示例#12
0
  @Test
  public void testMissingResource() throws RepositoryException {
    // This shouldn't really happen, but hey!
    SlingHttpServletRequest request = mock(SlingHttpServletRequest.class);
    HtmlResponse response = new HtmlResponse();

    ResourceResolver resolver = mock(ResourceResolver.class);
    when(resolver.adaptTo(Session.class)).thenReturn(session);

    Resource resource = mock(Resource.class);
    when(resource.adaptTo(Node.class)).thenReturn(null);
    when(request.getResource()).thenReturn(resource);
    when(request.getResourceResolver()).thenReturn(resolver);
    when(request.getRemoteUser()).thenReturn("john");

    operation.doRun(request, response, null);

    assertEquals(400, response.getStatusCode());
  }
示例#13
0
  @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.");
    }
  }
示例#14
0
  @Test
  public void testMissingParams() throws RepositoryException {
    SlingHttpServletRequest request = mock(SlingHttpServletRequest.class);
    HtmlResponse response = new HtmlResponse();

    ResourceResolver resolver = mock(ResourceResolver.class);
    when(resolver.adaptTo(Session.class)).thenReturn(session);

    Resource resource = mock(Resource.class);
    Node node = new MockNode("/bla/bla");
    when(resource.adaptTo(Node.class)).thenReturn(node);

    when(request.getResource()).thenReturn(resource);
    when(request.getResourceResolver()).thenReturn(resolver);
    when(request.getRequestParameter("key")).thenReturn(null);
    when(request.getRemoteUser()).thenReturn("john");

    operation.doRun(request, response, null);

    assertEquals(400, response.getStatusCode());
  }
示例#15
0
  @Override
  protected void doGet(SlingHttpServletRequest request, SlingHttpServletResponse response)
      throws ServletException, IOException {
    String resourceType = request.getResource().getResourceType();

    Resource resource = null;
    if (UserConstants.GROUP_HOME_RESOURCE_TYPE.equals(resourceType)) {
      resource = request.getResourceResolver().getResource(groupHome);
    } else if (UserConstants.USER_HOME_RESOURCE_TYPE.equals(resourceType)) {
      resource = request.getResourceResolver().getResource(userHome);
    }

    if (resource == null) {
      response.sendError(
          500, "Somehow didn't get a user or group home resource [" + resourceType + "]");
    } else {
      response.setContentType("text/html");
      response.setCharacterEncoding("UTF-8");
      response.setStatus(HttpServletResponse.SC_OK);
      IOUtils.stream(resource.adaptTo(InputStream.class), response.getOutputStream());
    }
  }
  @Override
  protected void doGet(SlingHttpServletRequest request, SlingHttpServletResponse response)
      throws ServletException, IOException {
    String path = request.getResource().getPath();

    // check path is a valid DAM root folder path for asset service
    if (!damPathHandler.isAllowedDataVersionPath(path)) {
      log.debug("Path not allowed to get data version {}", path);
      response.sendError(HttpServletResponse.SC_NOT_FOUND);
      return;
    }

    // return data version as JSON
    try {
      JSONObject jsonResponse = new JSONObject();
      jsonResponse.put("dataVersion", damPathHandler.getDataVersion());

      response.setContentType(ContentType.JSON);
      response.setCharacterEncoding(CharEncoding.UTF_8);
      response.getWriter().write(jsonResponse.toString());
    } catch (JSONException ex) {
      throw new ServletException("Unable to generate JSON.", ex);
    }
  }
  protected void dispatch(
      SlingHttpServletRequest request, SlingHttpServletResponse response, boolean userInputStream)
      throws ServletException, IOException {
    try {

      Resource resource = request.getResource();
      if (!resource.getPath().startsWith(PROXY_PATH_PREFIX)) {
        response.sendError(
            HttpServletResponse.SC_FORBIDDEN,
            "Proxying templates may only be stored in " + PROXY_PATH_PREFIX);
        return;
      }
      Node node = resource.adaptTo(Node.class);
      if (!userInputStream) {
        Value[] v = JcrUtils.getValues(node, SAKAI_REQUEST_STREAM_BODY);
        if (v != null && v.length > 0) {
          userInputStream = Boolean.parseBoolean(v[0].getString());
        }
      }
      Map<String, String> headers = new ConcurrentHashMap<String, String>();
      for (Enumeration<?> enames = request.getHeaderNames(); enames.hasMoreElements(); ) {

        String name = (String) enames.nextElement();
        if (!headerBacklist.contains(name)) {
          headers.put(name, request.getHeader(name));
        }
      }
      // search for special headers.
      if (headers.containsKey(BASIC_USER)) {
        String user = headers.get(BASIC_USER);
        String password = headers.get(BASIC_PASSWORD);
        Base64 base64 = new Base64();
        String passwordDigest =
            new String(base64.encode((user + ":" + password).getBytes("UTF-8")));
        String digest = BASIC + passwordDigest.trim();
        headers.put(AUTHORIZATION, digest);
      }

      for (Entry<String, String> e : headers.entrySet()) {
        if (e.getKey().startsWith(":")) {
          headers.remove(e.getKey());
        }
      }

      // collect the parameters and store into a mutable map.
      RequestParameterMap parameterMap = request.getRequestParameterMap();
      Map<String, Object> templateParams = new ConcurrentHashMap<String, Object>(parameterMap);

      // search for special parameters.
      if (parameterMap.containsKey(BASIC_USER)) {
        String user = parameterMap.getValue(BASIC_USER).getString();
        String password = parameterMap.getValue(BASIC_PASSWORD).getString();
        Base64 base64 = new Base64();
        String passwordDigest =
            new String(base64.encode((user + ":" + password).getBytes("UTF-8")));
        String digest = BASIC + passwordDigest.trim();
        headers.put(AUTHORIZATION, digest);
      }

      // we might want to pre-process the headers
      if (node.hasProperty(ProxyPreProcessor.SAKAI_PREPROCESSOR)) {
        String preprocessorName =
            node.getProperty(ProxyPreProcessor.SAKAI_PREPROCESSOR).getString();
        ProxyPreProcessor preprocessor = preProcessors.get(preprocessorName);
        if (preprocessor != null) {
          preprocessor.preProcessRequest(request, headers, templateParams);
        } else {
          LOGGER.warn(
              "Unable to find pre processor of name {} for node {} ",
              preprocessorName,
              node.getPath());
        }
      }
      ProxyPostProcessor postProcessor = defaultPostProcessor;
      // we might want to post-process the headers
      if (node.hasProperty(ProxyPostProcessor.SAKAI_POSTPROCESSOR)) {
        String postProcessorName =
            node.getProperty(ProxyPostProcessor.SAKAI_POSTPROCESSOR).getString();
        if (postProcessors.containsKey(postProcessorName)) {
          postProcessor = postProcessors.get(postProcessorName);
        }
        if (postProcessor == null) {
          LOGGER.warn(
              "Unable to find post processor of name {} for node {} ",
              postProcessorName,
              node.getPath());
          postProcessor = defaultPostProcessor;
        }
      }

      ProxyResponse proxyResponse =
          proxyClientService.executeCall(node, headers, templateParams, null, -1, null);
      try {
        postProcessor.process(templateParams, response, proxyResponse);
      } finally {
        proxyResponse.close();
      }
    } catch (IOException e) {
      throw e;
    } catch (ProxyClientException e) {
      response.sendError(500, e.getMessage());
    } catch (RepositoryException e) {
      response.sendError(500, e.getMessage());
    }
  }
 public boolean accepts(SlingHttpServletRequest request) {
   LOGGER.info("Checing accepts ");
   return !(request.getResource() instanceof SparseContentResource);
 }
  /**
   * Manipulate the member list for this file.
   *
   * <p>{@inheritDoc}
   *
   * @see
   *     org.apache.sling.api.servlets.SlingAllMethodsServlet#doPost(org.apache.sling.api.SlingHttpServletRequest,
   *     org.apache.sling.api.SlingHttpServletResponse)
   */
  @SuppressWarnings("unchecked")
  @Override
  protected void doPost(SlingHttpServletRequest request, SlingHttpServletResponse response)
      throws ServletException, IOException {
    // fail if anonymous
    String remoteUser = request.getRemoteUser();
    if (User.ANON_USER.equals(remoteUser)) {
      response.sendError(SC_FORBIDDEN, "Anonymous users cannot update content members.");
      return;
    }
    Session session = null;
    boolean releaseSession = false;
    try {
      Resource resource = request.getResource();
      session = resource.adaptTo(Session.class);
      Content pooledContent = resource.adaptTo(Content.class);
      AccessControlManager accessControlManager = session.getAccessControlManager();
      AuthorizableManager authorizableManager = session.getAuthorizableManager();
      User thisUser = authorizableManager.getUser();
      if (!accessControlManager.can(
          thisUser, Security.ZONE_CONTENT, pooledContent.getPath(), Permissions.CAN_READ)) {
        response.sendError(SC_FORBIDDEN, "Insufficient permission to read this content.");
      }

      Map<String, Object> properties = pooledContent.getProperties();
      String[] managers =
          StorageClientUtils.nonNullStringArray(
              (String[]) properties.get(POOLED_CONTENT_USER_MANAGER));
      String[] editors =
          StorageClientUtils.nonNullStringArray(
              (String[]) properties.get(POOLED_CONTENT_USER_EDITOR));
      String[] viewers =
          StorageClientUtils.nonNullStringArray(
              (String[]) properties.get(POOLED_CONTENT_USER_VIEWER));

      Set<String> managerSet = Sets.newHashSet(managers);
      Set<String> editorSet = Sets.newHashSet(editors);
      Set<String> viewerSet = Sets.newHashSet(viewers);

      List<String> removeViewers =
          Arrays.asList(
              StorageClientUtils.nonNullStringArray(request.getParameterValues(":viewer@Delete")));
      List<String> removeManagers =
          Arrays.asList(
              StorageClientUtils.nonNullStringArray(request.getParameterValues(":manager@Delete")));
      List<String> removeEditors =
          Arrays.asList(
              StorageClientUtils.nonNullStringArray(request.getParameterValues(":editor@Delete")));
      List<String> addViewers =
          Arrays.asList(
              StorageClientUtils.nonNullStringArray(request.getParameterValues(":viewer")));
      List<String> addManagers =
          Arrays.asList(
              StorageClientUtils.nonNullStringArray(request.getParameterValues(":manager")));
      List<String> addEditors =
          Arrays.asList(
              StorageClientUtils.nonNullStringArray(request.getParameterValues(":editor")));

      if (!accessControlManager.can(
          thisUser, Security.ZONE_CONTENT, pooledContent.getPath(), Permissions.CAN_WRITE)) {
        if (!addManagers.isEmpty()) {
          response.sendError(SC_FORBIDDEN, "Non-managers may not add managers to content.");
          return;
        }

        for (String name : removeManagers) {
          // asking to remove managers who don't exist is harmless
          if (managerSet.contains(name)) {
            response.sendError(SC_FORBIDDEN, "Non-managers may not remove managers from content.");
            return;
          }
        }

        if (addViewers.contains(User.ANON_USER) || addViewers.contains(Group.EVERYONE)) {
          response.sendError(
              SC_FORBIDDEN, "Non-managers may not add 'anonymous' or 'everyone' as viewers.");
          return;
        }

        if (addEditors.contains(User.ANON_USER) || addEditors.contains(Group.EVERYONE)) {
          response.sendError(
              SC_FORBIDDEN, "Non-managers may not add 'anonymous' or 'everyone' as editors.");
          return;
        }

        for (String name : removeViewers) {
          if (!thisUser.getId().equals(name)) {
            Authorizable viewer = authorizableManager.findAuthorizable(name);
            if (viewer != null
                && !accessControlManager.can(
                    thisUser, Security.ZONE_AUTHORIZABLES, name, Permissions.CAN_WRITE)) {
              response.sendError(
                  SC_FORBIDDEN,
                  "Non-managers may not remove any viewer other than themselves or a group which they manage.");
            }
          }
        }

        // the request has passed all the rules that govern non-manager users
        // so we'll grant an administrative session
        session = session.getRepository().loginAdministrative();
        releaseSession = true;
      }
      List<AclModification> aclModifications = Lists.newArrayList();

      for (String addManager : addManagers) {
        if ((addManager.length() > 0) && !managerSet.contains(addManager)) {
          managerSet.add(addManager);
          AclModification.addAcl(true, Permissions.CAN_MANAGE, addManager, aclModifications);
        }
      }

      for (String removeManager : removeManagers) {
        if ((removeManager.length() > 0) && managerSet.contains(removeManager)) {
          managerSet.remove(removeManager);
          AclModification.removeAcl(true, Permissions.CAN_MANAGE, removeManager, aclModifications);
        }
      }

      for (String addEditor : addEditors) {
        if ((addEditor.length() > 0) && !editorSet.contains(addEditor)) {
          editorSet.add(addEditor);
          AclModification.addAcl(true, PERMISSION_EDITOR, addEditor, aclModifications);
        }
      }

      for (String removeEditor : removeEditors) {
        if ((removeEditor.length() > 0) && editorSet.contains(removeEditor)) {
          editorSet.remove(removeEditor);
          AclModification.removeAcl(true, PERMISSION_EDITOR, removeEditor, aclModifications);
        }
      }

      for (String addViewer : addViewers) {
        if ((addViewer.length() > 0) && !viewerSet.contains(addViewer)) {
          viewerSet.add(addViewer);
          AclModification.addAcl(true, Permissions.CAN_READ, addViewer, aclModifications);
        }
      }

      for (String removeViewer : removeViewers) {
        removeViewer = removeViewer.trim();
        if ((removeViewer.length() > 0) && viewerSet.contains(removeViewer)) {
          viewerSet.remove(removeViewer);
          if (!managerSet.contains(removeViewer)) {
            AclModification.removeAcl(true, Permissions.CAN_READ, removeViewer, aclModifications);
          }
        }
      }

      updateContentMembers(session, pooledContent, viewerSet, managerSet, editorSet);
      updateContentAccess(session, pooledContent, aclModifications);

      this.authorizableCountChanger.notify(
          UserConstants.CONTENT_ITEMS_PROP,
          addViewers,
          addEditors,
          addManagers,
          removeViewers,
          removeEditors,
          removeManagers);

      response.setStatus(SC_OK);

    } catch (StorageClientException e) {
      LOGGER.error(e.getMessage());
      response.sendError(
          SC_INTERNAL_SERVER_ERROR, "StorageClientException: " + e.getLocalizedMessage());
    } catch (AccessDeniedException e) {
      response.sendError(
          SC_FORBIDDEN,
          "Insufficient permission to update content members at " + request.getRequestURI());
    } finally {
      if (session != null && releaseSession) {
        try {
          session.logout();
        } catch (ClientPoolException e) {
          LOGGER.error(e.getMessage());
        }
      }
    }
  }
  /**
   * {@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);
            }
          }
        }
      }
    }
  }
示例#21
0
  @Override
  protected void doGet(SlingHttpServletRequest request, SlingHttpServletResponse response)
      throws ServletException, IOException {
    try {
      Resource resource = request.getResource();
      if (!resource.getPath().startsWith(SEARCH_PATH_PREFIX)) {
        response.sendError(
            HttpServletResponse.SC_FORBIDDEN,
            "Search templates can only be executed if they are located under "
                + SEARCH_PATH_PREFIX);
        return;
      }

      Node node = resource.adaptTo(Node.class);
      if (node != null && node.hasProperty(SAKAI_QUERY_TEMPLATE)) {
        // TODO: we might want to use this ?
        @SuppressWarnings("unused")
        boolean limitResults = true;
        if (node.hasProperty(SAKAI_LIMIT_RESULTS)) {
          limitResults = node.getProperty(SAKAI_LIMIT_RESULTS).getBoolean();
        }

        // KERN-1147 Respond better when all parameters haven't been provided for a query
        Query query = null;
        try {
          query = processQuery(request, node);
        } catch (MissingParameterException e) {
          response.sendError(HttpServletResponse.SC_BAD_REQUEST, e.getMessage());
          return;
        }

        long nitems =
            SolrSearchUtil.longRequestParameter(
                request, PARAMS_ITEMS_PER_PAGE, DEFAULT_PAGED_ITEMS);
        long page = SolrSearchUtil.longRequestParameter(request, PARAMS_PAGE, 0);

        // allow number of items to be specified in sakai:query-template-options
        if (query.getOptions().containsKey(PARAMS_ITEMS_PER_PAGE)) {
          nitems = Long.valueOf(query.getOptions().get(PARAMS_ITEMS_PER_PAGE));
        } else {
          // add this to the options so that all queries are constrained to a limited
          // number of returns per page.
          query.getOptions().put(PARAMS_ITEMS_PER_PAGE, Long.toString(nitems));
        }

        if (query.getOptions().containsKey(PARAMS_PAGE)) {
          page = Long.valueOf(query.getOptions().get(PARAMS_PAGE));
        } else {
          // add this to the options so that all queries are constrained to a limited
          // number of returns per page.
          query.getOptions().put(PARAMS_PAGE, Long.toString(page));
        }

        boolean useBatch = false;
        // Get the
        SolrSearchBatchResultProcessor searchBatchProcessor = defaultSearchBatchProcessor;
        if (node.hasProperty(SAKAI_BATCHRESULTPROCESSOR)) {
          searchBatchProcessor =
              batchProcessors.get(node.getProperty(SAKAI_BATCHRESULTPROCESSOR).getString());
          useBatch = true;
          if (searchBatchProcessor == null) {
            searchBatchProcessor = defaultSearchBatchProcessor;
          }
        }

        SolrSearchResultProcessor searchProcessor = defaultSearchProcessor;
        if (node.hasProperty(SAKAI_RESULTPROCESSOR)) {
          searchProcessor = processors.get(node.getProperty(SAKAI_RESULTPROCESSOR).getString());
          if (searchProcessor == null) {
            searchProcessor = defaultSearchProcessor;
          }
        }

        SolrSearchResultSet rs = null;
        try {
          // Prepare the result set.
          // This allows a processor to do other queries and manipulate the results.
          if (useBatch) {
            rs = searchBatchProcessor.getSearchResultSet(request, query);
          } else {
            rs = searchProcessor.getSearchResultSet(request, query);
          }
        } catch (SolrSearchException e) {
          response.sendError(e.getCode(), e.getMessage());
          return;
        }

        response.setContentType("application/json");
        response.setCharacterEncoding("UTF-8");

        ExtendedJSONWriter write = new ExtendedJSONWriter(response.getWriter());
        write.setTidy(isTidy(request));

        write.object();
        write.key(PARAMS_ITEMS_PER_PAGE);
        write.value(nitems);
        write.key(JSON_RESULTS);

        write.array();

        Iterator<Result> iterator = rs.getResultSetIterator();
        if (useBatch) {
          LOGGER.info("Using batch processor for results");
          searchBatchProcessor.writeResults(request, write, iterator);
        } else {
          LOGGER.info("Using regular processor for results");
          // We don't skip any rows ourselves here.
          // We expect a rowIterator coming from a resultset to be at the right place.
          for (long i = 0; i < nitems && iterator.hasNext(); i++) {
            // Get the next row.
            Result result = iterator.next();

            // Write the result for this row.
            searchProcessor.writeResult(request, write, result);
          }
        }
        write.endArray();

        // write the total out after processing the list to give the underlying iterator
        // a chance to walk the results then report how many there were.
        write.key(TOTAL);
        write.value(rs.getSize());

        write.endObject();
      }
    } catch (RepositoryException e) {
      LOGGER.error(e.getMessage(), e);
      response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e.getMessage());
    } catch (JSONException e) {
      LOGGER.error(e.getMessage(), e);
      response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e.getMessage());
    }
  }
  /**
   * {@inheritDoc}
   *
   * @see
   *     org.apache.sling.api.servlets.SlingSafeMethodsServlet#doGet(org.apache.sling.api.SlingHttpServletRequest,
   *     org.apache.sling.api.SlingHttpServletResponse)
   */
  @Override
  protected void doGet(SlingHttpServletRequest request, SlingHttpServletResponse response)
      throws ServletException, IOException {
    Authorizable authorizable = null;
    Resource resource = request.getResource();
    if (resource != null) {
      authorizable = resource.adaptTo(Authorizable.class);
    }

    if (authorizable == null || !authorizable.isGroup()) {
      response.sendError(HttpServletResponse.SC_NO_CONTENT, "Couldn't find group");
      return;
    }

    Group group = (Group) authorizable;

    List<String> selectors = Arrays.asList(request.getRequestPathInfo().getSelectors());
    ExtendedJSONWriter writer = new ExtendedJSONWriter(response.getWriter());
    writer.setTidy(selectors.contains("tidy"));

    // Get the sorting order, default is ascending or the natural sorting order (which is
    // null for a TreeMap.)
    Comparator<String> comparator = null;
    String order = "ascending";
    if (request.getRequestParameter("sortOrder") != null) {
      order = request.getRequestParameter("sortOrder").getString();
      if (order.equals("descending")) {
        comparator = Collections.reverseOrder();
      }
    }

    try {
      response.setContentType("application/json");
      TreeMap<String, Authorizable> map = null;
      if (selectors.contains("managers")) {
        map = getManagers(request, group, comparator);
      } else {
        // Members is the default.
        map = getMembers(request, group, comparator);
      }

      // Do some paging.
      long items =
          (request.getParameter(ITEMS) != null) ? Long.parseLong(request.getParameter(ITEMS)) : 25;
      long page =
          (request.getParameter(PAGE) != null) ? Long.parseLong(request.getParameter(PAGE)) : 0;
      if (page < 0) {
        page = 0;
      }
      if (items < 0) {
        items = 25;
      }
      Iterator<Entry<String, Authorizable>> iterator =
          getInPlaceIterator(request, map, items, page);

      // Write the whole lot out.
      Session session = request.getResourceResolver().adaptTo(Session.class);
      writer.array();
      int i = 0;
      while (iterator.hasNext() && i < items) {
        Entry<String, Authorizable> entry = iterator.next();
        Authorizable au = entry.getValue();
        ValueMap profile;
        if (selectors.contains("detailed")) {
          profile = profileService.getProfileMap(au, session);
        } else {
          profile = profileService.getCompactProfileMap(au, session);
        }
        if (profile != null) {
          writer.valueMap(profile);
          i++;
        } else {
          // profile wasn't found.  safe to ignore and not include the group
          logger.info("Profile not found for " + au.getID());
        }
      }
      writer.endArray();

    } catch (RepositoryException e) {
      response.sendError(
          HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Failed to retrieve members/managers.");
      return;
    } catch (JSONException e) {
      response.sendError(
          HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Failed to build a proper JSON output.");
      return;
    }
  }
示例#23
0
  @SuppressWarnings("unchecked")
  @Test
  public void test()
      throws ServletException, IOException, UnsupportedRepositoryOperationException,
          RepositoryException {
    SlingHttpServletRequest request = createNiceMock(SlingHttpServletRequest.class);
    SlingHttpServletResponse response = createNiceMock(SlingHttpServletResponse.class);
    RequestPathInfo requestPathInfo = createNiceMock(RequestPathInfo.class);
    Resource resource = createNiceMock(Resource.class);
    Node node = createNiceMock(Node.class);
    VersionHistory versionHistory = createNiceMock(VersionHistory.class);
    Version version = createNiceMock(Version.class);
    Node frozenNode = createNiceMock(Node.class);
    Property resourceTypeProperty = createNiceMock(Property.class);
    Capture<Resource> capturedResource = new Capture<Resource>();
    RequestDispatcher requestDispatcher = createNiceMock(RequestDispatcher.class);
    Capture<ServletRequest> capturedRequest = new Capture<ServletRequest>();
    Capture<ServletResponse> capturedResponse = new Capture<ServletResponse>();
    VersionManager versionManager = createNiceMock(VersionManager.class);
    Session session = createNiceMock(Session.class);
    Workspace workspace = createNiceMock(Workspace.class);

    EasyMock.expect(request.getRequestPathInfo()).andReturn(requestPathInfo);
    EasyMock.expect(requestPathInfo.getSelectorString()).andReturn("version.,1.1,.tidy.json");
    EasyMock.expect(request.getResource()).andReturn(resource);
    EasyMock.expect(resource.adaptTo(Node.class)).andReturn(node);
    EasyMock.expect(node.getPath()).andReturn("/foo");
    EasyMock.expect(node.getSession()).andReturn(session);
    EasyMock.expect(session.getWorkspace()).andReturn(workspace);
    EasyMock.expect(workspace.getVersionManager()).andReturn(versionManager);
    EasyMock.expect(versionManager.getVersionHistory("/foo")).andReturn(versionHistory);
    EasyMock.expect(versionHistory.getVersion("1.1")).andReturn(version);
    EasyMock.expect(version.getNode(JcrConstants.JCR_FROZENNODE)).andReturn(frozenNode);
    EasyMock.expect(frozenNode.getPath()).andReturn("/testnode");
    EasyMock.expect(frozenNode.hasProperty(JcrResourceConstants.SLING_RESOURCE_TYPE_PROPERTY))
        .andReturn(true);
    EasyMock.expect(frozenNode.getProperty(JcrResourceConstants.SLING_RESOURCE_TYPE_PROPERTY))
        .andReturn(resourceTypeProperty);
    EasyMock.expect(resourceTypeProperty.getString()).andReturn("sakai/testing");
    EasyMock.expect(frozenNode.hasProperty(JcrResourceConstants.SLING_RESOURCE_SUPER_TYPE_PROPERTY))
        .andReturn(true);
    EasyMock.expect(frozenNode.getProperty(JcrResourceConstants.SLING_RESOURCE_SUPER_TYPE_PROPERTY))
        .andReturn(resourceTypeProperty);
    EasyMock.expect(resourceTypeProperty.getString()).andReturn("sakai/super-type-testing");
    EasyMock.expect(request.getRequestDispatcher(EasyMock.capture(capturedResource)))
        .andReturn(requestDispatcher);
    requestDispatcher.forward(
        EasyMock.capture(capturedRequest), EasyMock.capture(capturedResponse));
    EasyMock.expectLastCall();

    replay();
    getVersionServlet.doGet(request, response);

    Assert.assertTrue(capturedRequest.hasCaptured());
    Assert.assertTrue(capturedResource.hasCaptured());
    Assert.assertTrue(capturedResponse.hasCaptured());

    Resource cresource = capturedResource.getValue();

    Node capturedNode = cresource.adaptTo(Node.class);
    Assert.assertEquals(capturedNode, frozenNode);

    Map<String, String> map = cresource.adaptTo(Map.class);
    Assert.assertNotNull(map);

    verify();
  }
 public BlogPagination(SlingHttpServletRequest request) {
   this.request = request;
   ValueMap properties = request.getResource().adaptTo(ValueMap.class);
   pageSize = properties.get(PAGE_SIZE_PROPERTY, Integer.class);
 }
  /**
   * {@inheritDoc}
   *
   * @see
   *     org.apache.sling.api.servlets.SlingSafeMethodsServlet#doGet(org.apache.sling.api.SlingHttpServletRequest,
   *     org.apache.sling.api.SlingHttpServletResponse)
   */
  @Override
  protected void doGet(SlingHttpServletRequest request, SlingHttpServletResponse response)
      throws ServletException, IOException {
    try {
      // Grab the search node.
      Node node = request.getResource().adaptTo(Node.class);

      // Grab the node that holds the repository information.
      Node proxyNode = DocProxyUtils.getProxyNode(node);

      // Grab the correct processor
      String type = proxyNode.getProperty(REPOSITORY_PROCESSOR).getString();
      ExternalRepositoryProcessor processor = tracker.getProcessorByType(type);
      if (processor == null) {
        LOGGER.warn("No processor found for type - {}", type);
        response.sendError(
            HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Could not handle this repository type.");
        return;
      }

      // Handle properties.
      Map<String, Object> searchProperties = new HashMap<String, Object>();
      handleProperties(searchProperties, node, request);

      // Process search
      Iterator<ExternalDocumentResult> results = processor.search(proxyNode, searchProperties);

      // Do the default search paging.
      long toSkip = SearchUtil.getPaging(request, -1);
      while (toSkip > 0) {
        if (results.hasNext()) {
          results.next();
          toSkip--;
        } else {
          throw new NoSuchElementException();
        }
      }

      response.setContentType("application/json");
      response.setCharacterEncoding("UTF-8");

      ExtendedJSONWriter write = new ExtendedJSONWriter(response.getWriter());
      write.array();
      long nitems =
          SearchUtil.longRequestParameter(
              request, SearchConstants.PARAMS_ITEMS_PER_PAGE, SearchConstants.DEFAULT_PAGED_ITEMS);
      for (long i = 0; i < nitems && results.hasNext(); i++) {
        ExternalDocumentResult result = results.next();
        DocProxyUtils.writeMetaData(write, result);
      }
      write.endArray();

    } catch (RepositoryException e) {
      LOGGER.error("Got a repository exception when trying to grab search node information.", e);
      response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Failed to perform search.");
    } catch (JSONException e) {
      LOGGER.error("Got a JSON exception when trying to grab search node information.", e);
      response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Failed to perform search.");
    } catch (DocProxyException e) {
      LOGGER.error("Got a DocProxy exception when trying to grab search node information.", e);
      response.sendError(e.getCode(), e.getMessage());
    }
  }
  /**
   * Retrieves the list of members.
   *
   * <p>{@inheritDoc}
   *
   * @see
   *     org.apache.sling.api.servlets.SlingSafeMethodsServlet#doGet(org.apache.sling.api.SlingHttpServletRequest,
   *     org.apache.sling.api.SlingHttpServletResponse)
   */
  @Override
  protected void doGet(SlingHttpServletRequest request, SlingHttpServletResponse response)
      throws ServletException, IOException {
    try {
      // Get hold of the actual file.
      Resource resource = request.getResource();
      javax.jcr.Session jcrSession = request.getResourceResolver().adaptTo(javax.jcr.Session.class);
      Session session = resource.adaptTo(Session.class);

      AuthorizableManager am = session.getAuthorizableManager();
      AccessControlManager acm = session.getAccessControlManager();
      Content node = resource.adaptTo(Content.class);
      Authorizable thisUser = am.findAuthorizable(session.getUserId());

      if (!acm.can(thisUser, Security.ZONE_CONTENT, resource.getPath(), Permissions.CAN_READ)) {
        response.sendError(HttpServletResponse.SC_NOT_FOUND);
        return;
      }

      Map<String, Object> properties = node.getProperties();
      String[] managers = (String[]) properties.get(POOLED_CONTENT_USER_MANAGER);
      String[] editors = (String[]) properties.get(POOLED_CONTENT_USER_EDITOR);
      String[] viewers = (String[]) properties.get(POOLED_CONTENT_USER_VIEWER);

      boolean detailed = false;
      boolean tidy = false;
      for (String selector : request.getRequestPathInfo().getSelectors()) {
        if ("detailed".equals(selector)) {
          detailed = true;
        } else if ("tidy".equals(selector)) {
          tidy = true;
        }
      }

      // Loop over the sets and output it.
      ExtendedJSONWriter writer = new ExtendedJSONWriter(response.getWriter());
      writer.setTidy(tidy);
      writer.object();
      writer.key("managers");
      writer.array();
      for (String manager : StorageClientUtils.nonNullStringArray(managers)) {
        try {
          writeProfileMap(jcrSession, am, writer, manager, detailed);
        } catch (AccessDeniedException e) {
          LOGGER.debug("Skipping private manager [{}]", manager);
        }
      }
      writer.endArray();
      writer.key("editors");
      writer.array();
      for (String editor : StorageClientUtils.nonNullStringArray(editors)) {
        try {
          writeProfileMap(jcrSession, am, writer, editor, detailed);
        } catch (AccessDeniedException e) {
          LOGGER.debug("Skipping private editor [{}]", editor);
        }
      }
      writer.endArray();
      writer.key("viewers");
      writer.array();
      for (String viewer : StorageClientUtils.nonNullStringArray(viewers)) {
        try {
          writeProfileMap(jcrSession, am, writer, viewer, detailed);
        } catch (AccessDeniedException e) {
          LOGGER.debug("Skipping private viewer [{}]", viewer);
        }
      }
      writer.endArray();
      writer.endObject();
    } catch (JSONException e) {
      response.sendError(SC_INTERNAL_SERVER_ERROR, "Failed to generate proper JSON.");
      LOGGER.error(e.getMessage(), e);
    } catch (StorageClientException e) {
      response.sendError(SC_INTERNAL_SERVER_ERROR, "Failed to generate proper JSON.");
      LOGGER.error(e.getMessage(), e);
    } catch (AccessDeniedException e) {
      response.sendError(SC_INTERNAL_SERVER_ERROR, "Failed to generate proper JSON.");
      LOGGER.error(e.getMessage(), e);
    } catch (RepositoryException e) {
      response.sendError(SC_INTERNAL_SERVER_ERROR, "Failed to generate proper JSON.");
      LOGGER.error(e.getMessage(), e);
    }
  }