Exemple #1
0
  /** Dump given node in JSON, optionally recursing into its child nodes */
  protected void dump(Node node, JSONWriter w, int currentRecursionLevel, int maxRecursionLevels)
      throws RepositoryException, JSONException {

    w.object();
    PropertyIterator props = node.getProperties();

    // the node's actual properties
    while (props.hasNext()) {
      Property prop = props.nextProperty();

      if (propertyNamesToIgnore != null && propertyNamesToIgnore.contains(prop.getName())) {
        continue;
      }

      writeProperty(w, prop);
    }

    // the child nodes
    if (recursionLevelActive(currentRecursionLevel, maxRecursionLevels)) {
      final NodeIterator children = node.getNodes();
      while (children.hasNext()) {
        final Node n = children.nextNode();
        dumpSingleNode(n, w, currentRecursionLevel, maxRecursionLevels);
      }
    }

    w.endObject();
  }
Exemple #2
0
  @Override
  public int performAction(Resource res) throws RepositoryException {
    // get value map and node
    ValueMap vm = res.adaptTo(ValueMap.class);
    Node node = res.adaptTo(Node.class);

    int propsModified = 0;

    PropertyIterator pIter = node.getProperties();
    while (pIter.hasNext()) {
      Property prop = pIter.nextProperty();

      if (isModifiable(prop)) {
        boolean modified = doModifications(prop);
        if (modified) {
          // increase our modification count
          propsModified++;
        }
      } else {
        // move on to next property
      }
    }

    return propsModified;
  }
 /**
  * {@inheritDoc}
  *
  * @see
  *     org.modeshape.graph.request.processor.RequestProcessor#process(org.modeshape.graph.request.ReadAllPropertiesRequest)
  */
 @Override
 public void process(ReadAllPropertiesRequest request) {
   if (request == null) return;
   try {
     Workspace workspace = workspaceFor(request.inWorkspace());
     Node node = workspace.node(request.at());
     Location actualLocation = workspace.locationFor(node);
     request.setActualLocationOfNode(actualLocation);
     // Read the properties ...
     for (PropertyIterator iter = node.getProperties(); iter.hasNext(); ) {
       request.addProperty(workspace.propertyFor(iter.nextProperty()));
     }
     // Add in the 'jcr:uuid' property ...
     if (actualLocation.hasIdProperties()) {
       request.addProperty(workspace.propertyFor(ModeShapeLexicon.UUID, actualLocation.getUuid()));
     }
     // Get the number of children ...
     NodeIterator childIter = node.getNodes();
     int numChildren = (int) childIter.getSize();
     if (numChildren == -1) {
       numChildren = 0;
       while (childIter.hasNext()) {
         childIter.nextNode();
         ++numChildren;
       }
     }
     request.setNumberOfChildren(numChildren);
     setCacheableInfo(request);
   } catch (Throwable e) {
     request.setError(e);
   }
 }
  /** Recursively outputs the contents of the given node. */
  private static void dump(Node node) throws RepositoryException {
    // First output the node path
    System.out.println(node.getPath());
    // Skip the virtual (and large!) jcr:system subtree
    if (node.getName().equals("jcr:system")) {
      return;
    }

    // Then output the properties
    PropertyIterator properties = node.getProperties();
    while (properties.hasNext()) {
      Property property = properties.nextProperty();
      if (property.getDefinition().isMultiple()) {
        // A multi-valued property, print all values
        Value[] values = property.getValues();
        for (int i = 0; i < values.length; i++) {
          System.out.println(property.getPath() + " = " + values[i].getString());
        }
      } else {
        // A single-valued property
        System.out.println(property.getPath() + " = " + property.getString());
      }
    }

    // Finally output all the child nodes recursively
    NodeIterator nodes = node.getNodes();
    while (nodes.hasNext()) {
      dump(nodes.nextNode());
    }
  }
 /**
  * {@inheritDoc}
  *
  * @see
  *     org.modeshape.graph.request.processor.RequestProcessor#process(org.modeshape.graph.request.ReadNodeRequest)
  */
 @Override
 public void process(ReadNodeRequest request) {
   if (request == null) return;
   try {
     Workspace workspace = workspaceFor(request.inWorkspace());
     Node node = workspace.node(request.at());
     Location actualLocation = workspace.locationFor(node);
     request.setActualLocationOfNode(actualLocation);
     // Read the children ...
     for (NodeIterator iter = node.getNodes(); iter.hasNext(); ) {
       request.addChild(workspace.locationFor(iter.nextNode()));
     }
     // Read the properties ...
     for (PropertyIterator iter = node.getProperties(); iter.hasNext(); ) {
       request.addProperty(workspace.propertyFor(iter.nextProperty()));
     }
     // Add in the 'jcr:uuid' property ...
     if (actualLocation.hasIdProperties()) {
       request.addProperty(workspace.propertyFor(ModeShapeLexicon.UUID, actualLocation.getUuid()));
     }
     setCacheableInfo(request);
   } catch (Throwable e) {
     request.setError(e);
   }
 }
 @Override
 public String run(Application app, Request req, Response resp) {
   ContentModel cm = (ContentModel) req.attr(ContentModel.KEY);
   try {
     List<Map<String, String>> labelList = new ArrayList<Map<String, String>>();
     Node labelsNode = cm.getAppsConfigNode(LabelsExtension.NODE_NAME, true).getNode();
     PropertyIterator it = labelsNode.getProperties();
     while (it.hasNext()) {
       Property p = it.nextProperty();
       String name = p.getName();
       if (name.startsWith("label.")) {
         Map<String, String> label = new HashMap<String, String>();
         label.put("name", name.substring(6));
         label.put("value", p.getString());
         labelList.add(label);
       }
     }
     Collections.sort(
         labelList,
         new Comparator<Map<String, String>>() {
           @Override
           public int compare(Map<String, String> o1, Map<String, String> o2) {
             return o1.get("name").compareTo(o2.get("name"));
           }
         });
     Map<String, Object> params = new HashMap<String, Object>();
     params.put("labels", labelList);
     params.put("node", cm.getAppsConfigNode(LabelsExtension.NODE_NAME));
     return resp.formatTemplate("admin/labels.html", params);
   } catch (RepositoryException e) {
     log.error("Error while getting labels", e);
   }
   return null;
 }
  /**
   * Load properties from the query node, request and property provider.<br>
   * Overwrite order: query node &lt; request &lt; property provider<br>
   * This ordering allows the query node to set defaults, the request to override those defaults but
   * the property provider to have the final say in what value is set.
   *
   * @param request
   * @param propertyProviderName
   * @return
   * @throws RepositoryException
   */
  private Map<String, String> loadProperties(
      SlingHttpServletRequest request, String propertyProviderName, Node node)
      throws RepositoryException {
    Map<String, String> propertiesMap = new HashMap<String, String>();

    // 0. load authorizable (user) information
    String userId = request.getRemoteUser();
    String userPrivatePath = ClientUtils.escapeQueryChars(LitePersonalUtils.getPrivatePath(userId));
    propertiesMap.put("_userPrivatePath", userPrivatePath);
    propertiesMap.put("_userId", ClientUtils.escapeQueryChars(userId));

    // 1. load in properties from the query template node so defaults can be set
    PropertyIterator props = node.getProperties();
    while (props.hasNext()) {
      javax.jcr.Property prop = props.nextProperty();
      if (!propertiesMap.containsKey(prop.getName()) && !prop.isMultiple()) {
        propertiesMap.put(prop.getName(), prop.getString());
      }
    }

    // 2. load in properties from the request
    RequestParameterMap params = request.getRequestParameterMap();
    for (Entry<String, RequestParameter[]> entry : params.entrySet()) {
      String key = entry.getKey();
      RequestParameter[] vals = entry.getValue();
      String requestValue = vals[0].getString();

      // blank values aren't cool
      if (StringUtils.isBlank(requestValue)) {
        continue;
      }

      // KERN-1601 Wildcard searches have to be manually lowercased for case insensitive
      // matching as Solr bypasses the analyzer when dealing with a wildcard or fuzzy
      // search.
      if (StringUtils.contains(requestValue, '*') || StringUtils.contains(requestValue, '~')) {
        requestValue = requestValue.toLowerCase();
      }
      // KERN-1703 Escape just :
      requestValue = StringUtils.replace(requestValue, ":", "\\:");
      propertiesMap.put(entry.getKey(), requestValue);
    }

    // 3. load properties from a property provider
    if (propertyProviderName != null) {
      LOGGER.debug("Trying Provider Name {} ", propertyProviderName);
      SolrSearchPropertyProvider provider = propertyProvider.get(propertyProviderName);
      if (provider != null) {
        LOGGER.debug("Trying Provider {} ", provider);
        provider.loadUserProperties(request, propertiesMap);
      } else {
        LOGGER.warn("No properties provider found for {} ", propertyProviderName);
      }
    } else {
      LOGGER.debug("No Provider ");
    }

    return propertiesMap;
  }
 /**
  * Fill's in the values for the search properties.
  *
  * @param searchProperties
  * @param vals
  * @param request
  * @throws RepositoryException
  */
 protected void handleProperties(
     Map<String, Object> searchProperties, Node node, SlingHttpServletRequest request)
     throws RepositoryException {
   PropertyIterator props = node.getProperties("sakai:search-prop-*");
   while (props.hasNext()) {
     Property p = props.nextProperty();
     handleProperty(searchProperties, p, request);
   }
 }
 private Map<Value, String> binaryPropertyPaths(Node node) throws RepositoryException {
   Map<Value, String> result = new HashMap<Value, String>();
   for (PropertyIterator propertyIterator = node.getProperties(); propertyIterator.hasNext(); ) {
     Property property = propertyIterator.nextProperty();
     if (property.getType() == PropertyType.BINARY) {
       result.put(property.getValue(), property.getPath());
     }
   }
   return result;
 }
 /**
  * Reads properties of the given node.
  *
  * @param node the node instance
  * @return list of node's properties.
  * @throws RepositoryException
  */
 private Collection<JcrProperty> getProperties(Node node) throws RepositoryException {
   ArrayList<JcrProperty> list = new ArrayList();
   PropertyIterator it = node.getProperties();
   while (it.hasNext()) {
     Property p = it.nextProperty();
     JcrProperty property =
         new JcrProperty(p.getName(), PropertyType.nameFromValue(p.getType()), values(p));
     property.setProtected(p.getDefinition().isProtected());
     property.setProtected(p.getDefinition().isMultiple());
     list.add(property);
   }
   return list;
 }
  /** Sets up the fixture for this test. */
  protected void setUp() throws Exception {
    isReadOnly = true;
    super.setUp();

    session = getHelper().getReadOnlySession();
    testRootNode = session.getRootNode().getNode(testPath);

    PropertyIterator properties = testRootNode.getProperties();
    try {
      property = properties.nextProperty();
    } catch (NoSuchElementException e) {
      fail("Any node must have at least one property set: jcr:primaryType");
    }
  }
  public static void writeNodeContentsToWriter(JSONWriter write, Node node)
      throws RepositoryException, JSONException {
    // Since removal of bigstore we add in jcr:path and jcr:name
    write.key("jcr:path");
    write.value(PathUtils.translateAuthorizablePath(node.getPath()));
    write.key("jcr:name");
    write.value(node.getName());

    PropertyIterator properties = node.getProperties();
    while (properties.hasNext()) {
      Property prop = properties.nextProperty();
      String name = prop.getName();
      write.key(name);
      PropertyDefinition propertyDefinition = prop.getDefinition();
      int propertyType = prop.getType();
      if (PropertyType.BINARY == propertyType) {
        if (propertyDefinition.isMultiple()) {
          write.array();
          for (long l : prop.getLengths()) {
            write.value("binary-length:" + String.valueOf(l));
          }
          write.endArray();
        } else {
          write.value("binary-length:" + String.valueOf(prop.getLength()));
        }
      } else {
        if (propertyDefinition.isMultiple()) {
          Value[] values = prop.getValues();
          write.array();
          for (Value value : values) {
            Object ovalue = stringValue(value);
            if (isUserPath(name, ovalue)) {
              write.value(PathUtils.translateAuthorizablePath(ovalue));
            } else {
              write.value(ovalue);
            }
          }
          write.endArray();
        } else {
          Object value = stringValue(prop.getValue());
          if (isUserPath(name, value)) {
            write.value(PathUtils.translateAuthorizablePath(value));
          } else {
            write.value(value);
          }
        }
      }
    }
  }
  @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();
  }
 /**
  * Writes the mail attributes from the <code>jamesattr:*</code> property.
  *
  * @param node mail node
  * @param mail mail message
  * @throws RepositoryException if a repository error occurs
  * @throws IOException if an IO error occurs
  */
 private void getAttributes(Node node, Mail mail) throws RepositoryException, IOException {
   PropertyIterator iterator = node.getProperties("jamesattr:*");
   while (iterator.hasNext()) {
     Property property = iterator.nextProperty();
     String name =
         Text.unescapeIllegalJcrChars(property.getName().substring("jamesattr:".length()));
     if (property.getType() == PropertyType.BINARY) {
       @SuppressWarnings("deprecation")
       InputStream input = property.getStream();
       try {
         ObjectInputStream stream = new ObjectInputStream(input);
         mail.setAttribute(name, (Serializable) stream.readObject());
       } catch (ClassNotFoundException e) {
         throw new IOException(e.getMessage());
       } finally {
         input.close();
       }
     } else {
       mail.setAttribute(name, property.getString());
     }
   }
 }
  protected void simpleResultCountCheck(SearchResultProcessor processor)
      throws RepositoryException, JSONException {
    int itemCount = 12;
    QueryResult queryResult = createMock(QueryResult.class);
    RowIterator results = createMock(RowIterator.class);
    expect(queryResult.getRows()).andReturn(results);
    expect(results.getSize()).andReturn(500L).anyTimes();
    Row dummyRow = createMock(Row.class);
    Value val = createMock(Value.class);
    expect(val.getString()).andReturn("").times(itemCount);
    expect(dummyRow.getValue("jcr:path")).andReturn(val).times(itemCount);
    expect(results.hasNext()).andReturn(true).anyTimes();
    expect(results.nextRow()).andReturn(dummyRow).times(itemCount);
    SlingHttpServletRequest request = createMock(SlingHttpServletRequest.class);
    ResourceResolver resourceResolver = createMock(ResourceResolver.class);
    Session session = createMock(Session.class);
    Node resultNode = createMock(Node.class);
    expect(resultNode.getPath()).andReturn("/path/to/node").anyTimes();
    expect(resultNode.getName()).andReturn("node").anyTimes();
    expect(request.getResourceResolver()).andReturn(resourceResolver).times(itemCount);
    expect(resourceResolver.adaptTo(Session.class)).andReturn(session).times(itemCount);
    expect(session.getItem("")).andReturn(resultNode).times(itemCount);
    PropertyIterator propIterator = createMock(PropertyIterator.class);
    expect(propIterator.hasNext()).andReturn(false).anyTimes();
    expect(resultNode.getProperties()).andReturn(propIterator).anyTimes();

    replay();
    JSONWriter write = new JSONWriter(new PrintWriter(new ByteArrayOutputStream()));
    write.array();
    RowIterator iterator = queryResult.getRows();
    int i = 0;
    while (iterator.hasNext() && i < itemCount) {
      processor.writeNode(request, write, null, iterator.nextRow());
      i++;
    }
    write.endArray();
    verify();
  }
  @Override
  public List<Mail> getCategorizedMails(String token, String categoryId)
      throws RepositoryException, DatabaseException {
    log.debug("getCategorizedMails({}, {})", token, categoryId);
    List<Mail> mails = new ArrayList<Mail>();
    Session session = null;

    try {
      if (token == null) {
        session = JCRUtils.getSession();
      } else {
        session = JcrSessionManager.getInstance().get(token);
      }

      Node category = session.getNodeByUUID(categoryId);

      for (PropertyIterator it = category.getReferences(); it.hasNext(); ) {
        Property refProp = it.nextProperty();

        if (com.openkm.bean.Property.CATEGORIES.equals(refProp.getName())) {
          Node node = refProp.getParent();

          if (node.isNodeType(Mail.TYPE)) {
            Mail mail = BaseMailModule.getProperties(session, node);
            mails.add(mail);
          }
        }
      }
    } catch (javax.jcr.RepositoryException e) {
      log.error(e.getMessage(), e);
      throw new RepositoryException(e.getMessage(), e);
    } finally {
      if (token == null) JCRUtils.logout(session);
    }

    log.debug("getCategorizedMails: {}", mails);
    return mails;
  }
 /**
  * @param queryNode
  * @param queryOptions
  * @return
  * @throws RepositoryException
  * @throws ValueFormatException
  * @throws PathNotFoundException
  * @throws JSONException
  */
 private JSONObject accumulateQueryOptions(Node queryNode)
     throws RepositoryException, ValueFormatException, PathNotFoundException, JSONException {
   JSONObject queryOptions = null;
   if (queryNode.hasProperty(SAKAI_QUERY_TEMPLATE_OPTIONS)) {
     // process the options as JSON string
     String optionsProp = queryNode.getProperty(SAKAI_QUERY_TEMPLATE_OPTIONS).getString();
     queryOptions = new JSONObject(optionsProp);
   } else if (queryNode.hasNode(SAKAI_QUERY_TEMPLATE_OPTIONS)) {
     // process the options as a sub-node
     Node optionsNode = queryNode.getNode(SAKAI_QUERY_TEMPLATE_OPTIONS);
     if (optionsNode.hasProperties()) {
       queryOptions = new JSONObject();
       PropertyIterator props = optionsNode.getProperties();
       while (props.hasNext()) {
         javax.jcr.Property prop = props.nextProperty();
         if (!prop.getName().startsWith("jcr:")) {
           queryOptions.put(prop.getName(), prop.getString());
         }
       }
     }
   }
   return queryOptions;
 }
  private ModelResource createModelResource(Node node) throws RepositoryException {
    ModelResource resource =
        new ModelResource(
            ModelId.fromPath(node.getParent().getPath()),
            ModelType.valueOf(node.getProperty("vorto:type").getString()));
    resource.setDescription(node.getProperty("vorto:description").getString());
    resource.setDisplayName(node.getProperty("vorto:displayname").getString());
    resource.setCreationDate(node.getProperty("jcr:created").getDate().getTime());
    if (node.hasProperty("vorto:author")) {
      resource.setAuthor(node.getProperty("vorto:author").getString());
    }

    if (node.hasProperty("vorto:references")) {
      Value[] referenceValues = node.getProperty("vorto:references").getValues();
      if (referenceValues != null) {
        ModelReferencesHelper referenceHelper = new ModelReferencesHelper();
        for (Value referValue : referenceValues) {
          String nodeUuid = referValue.getString();
          Node referencedNode = session.getNodeByIdentifier(nodeUuid);
          referenceHelper.addModelReference(
              ModelId.fromPath(referencedNode.getParent().getPath()).getPrettyFormat());
        }
        resource.setReferences(referenceHelper.getReferences());
      }
    }

    PropertyIterator propIter = node.getReferences();
    while (propIter.hasNext()) {
      Property prop = propIter.nextProperty();
      Node referencedByFileNode = prop.getParent();
      final ModelId referencedById = ModelId.fromPath(referencedByFileNode.getParent().getPath());
      resource.getReferencedBy().add(referencedById);
    }

    return resource;
  }
  /** {@inheritDoc} */
  public void permanentlyDeleteFile(
      final Session session,
      final PentahoJcrConstants pentahoJcrConstants,
      final Serializable fileId)
      throws RepositoryException {
    Assert.notNull(fileId);
    Node fileNode = session.getNodeByIdentifier(fileId.toString());
    // guard against using a file retrieved from a more lenient session inside a more strict session
    Assert.notNull(fileNode);

    // see if anything is referencing this node; if yes, then we cannot delete it as a
    // ReferentialIntegrityException
    // will result
    Set<RepositoryFile> referrers = new HashSet<RepositoryFile>();
    PropertyIterator refIter = fileNode.getReferences();
    if (refIter.hasNext()) {
      while (refIter.hasNext()) {
        // for each referrer property, march up the tree until we find the file node to which the
        // property belongs
        RepositoryFile referrer =
            getReferrerFile(session, pentahoJcrConstants, refIter.nextProperty());
        if (referrer != null) {
          referrers.add(referrer);
        }
      }
      if (!referrers.isEmpty()) {
        RepositoryFile referee =
            JcrRepositoryFileUtils.nodeToFile(
                session, pentahoJcrConstants, pathConversionHelper, lockHelper, fileNode);
        throw new RepositoryFileDaoReferentialIntegrityException(referee, referrers);
      }
    }

    // technically, the node can be deleted while it is locked; however, we want to avoid an
    // orphaned lock token;
    // delete
    // it first
    if (fileNode.isLocked()) {
      Lock lock = session.getWorkspace().getLockManager().getLock(fileNode.getPath());
      // don't need lock token anymore
      lockHelper.removeLockToken(session, pentahoJcrConstants, lock);
    }

    // if this file was non-permanently deleted, delete its containing folder too
    IPentahoSession pentahoSession = PentahoSessionHolder.getSession();
    String tenantId = (String) pentahoSession.getAttribute(IPentahoSession.TENANT_ID_KEY);
    String trashFolder =
        ServerRepositoryPaths.getUserHomeFolderPath(
                new Tenant(tenantId, true), PentahoSessionHolder.getSession().getName())
            + RepositoryFile.SEPARATOR
            + FOLDER_NAME_TRASH;
    Node parent = fileNode.getParent();

    purgeHistory(fileNode, session, pentahoJcrConstants);

    if (fileNode.getPath().startsWith(trashFolder)) {
      // Remove the file and then the wrapper foler
      fileNode.remove();
      parent.remove();
    } else {
      fileNode.remove();
    }
  }
Exemple #20
0
  @Test
  public void shouldRetrieveReferenceProperties() throws Exception {
    Node referenceableNode = session.getRootNode().addNode("referenceable");
    referenceableNode.addMixin(JcrMixLexicon.REFERENCEABLE.toString());

    Node node1 = session.getRootNode().addNode("node1");
    Property prop1 =
        node1.setProperty("prop1", session.getValueFactory().createValue(referenceableNode, false));
    Property prop2 =
        node1.setProperty("prop2", session.getValueFactory().createValue(referenceableNode, true));

    Node node2 = session.getRootNode().addNode("node2");
    Property prop3 =
        node2.setProperty("prop3", session.getValueFactory().createValue(referenceableNode, false));
    Property prop4 =
        node2.setProperty("prop4", session.getValueFactory().createValue(referenceableNode, true));

    session.save();

    // check all strong references
    PropertyIterator propertyIterator = referenceableNode.getReferences();
    assertEquals(2, propertyIterator.getSize());
    Set<String> propertyNames = new HashSet<String>(2);
    while (propertyIterator.hasNext()) {
      propertyNames.add(propertyIterator.nextProperty().getName());
    }
    assertTrue(propertyNames.contains(prop1.getName()) && propertyNames.contains(prop3.getName()));

    propertyIterator = referenceableNode.getReferences("prop1");
    assertEquals(1, propertyIterator.getSize());
    assertEquals(prop1.getName(), propertyIterator.nextProperty().getName());

    propertyIterator = referenceableNode.getReferences("unknown");
    assertEquals(0, propertyIterator.getSize());

    // check all weak references
    propertyIterator = referenceableNode.getWeakReferences();
    assertEquals(2, propertyIterator.getSize());
    propertyNames = new HashSet<String>(2);
    while (propertyIterator.hasNext()) {
      propertyNames.add(propertyIterator.nextProperty().getName());
    }
    assertTrue(propertyNames.contains(prop2.getName()) && propertyNames.contains(prop4.getName()));

    propertyIterator = referenceableNode.getWeakReferences("prop4");
    assertEquals(1, propertyIterator.getSize());
    assertEquals(prop4.getName(), propertyIterator.nextProperty().getName());

    propertyIterator = referenceableNode.getWeakReferences("unknown");
    assertEquals(0, propertyIterator.getSize());
  }
  /**
   * Exports <code>node</code> (or the subtree rooted at <code>node</code>) into an XML document by
   * invoking SAX events on <code>contentHandler</code>.
   *
   * @param node the node which should be exported. If <code>noRecursion</code> was set to <code>
   *     false</code> in the constructor, the entire subtree rooted at <code>node</code> will be
   *     exported.
   * @param contentHandler the SAX content handler for which SAX events will be invoked as the XML
   *     document is created.
   * @param skipBinary if <code>true</code>, indicates that binary properties should not be exported
   * @param noRecurse if<code>true</code>, indicates that only the given node should be exported,
   *     otherwise a recursive export and not any of its child nodes.
   * @param isRoot true if the supplied node is the root node (supplied as an efficiency)
   * @throws SAXException if an exception occurs during generation of the XML document
   * @throws RepositoryException if an exception occurs accessing the content repository
   */
  protected void exportNode(
      Node node,
      ContentHandler contentHandler,
      boolean skipBinary,
      boolean noRecurse,
      boolean isRoot)
      throws RepositoryException, SAXException {

    // start the sv:node element for this JCR node
    AttributesImpl atts = new AttributesImpl();
    String nodeName = node.getName();
    if (isRoot && node.getDepth() == 0) {
      // This is the root node ...
      nodeName = "jcr:root";
    }
    atts.addAttribute(
        JcrSvLexicon.NAME.getNamespaceUri(),
        JcrSvLexicon.NAME.getLocalName(),
        getPrefixedName(JcrSvLexicon.NAME),
        PropertyType.nameFromValue(PropertyType.STRING),
        nodeName);

    startElement(contentHandler, JcrSvLexicon.NODE, atts);

    if (node instanceof JcrSharedNode) {
      // This is a shared node, and per Section 14.7 of the JCR 2.0 specification, they have to be
      // written out
      // in a special way ...

      // jcr:primaryType = nt:share ...
      emitProperty(
          JcrLexicon.PRIMARY_TYPE,
          PropertyType.NAME,
          JcrNtLexicon.SHARE,
          contentHandler,
          skipBinary);

      // jcr:uuid = UUID of shared node ...
      emitProperty(
          JcrLexicon.UUID, PropertyType.STRING, node.getIdentifier(), contentHandler, skipBinary);
    } else {

      // Output any special properties first (see Javadoc for SPECIAL_PROPERTY_NAMES for more
      // context)
      for (Name specialPropertyName : SPECIAL_PROPERTY_NAMES) {
        Property specialProperty = ((AbstractJcrNode) node).getProperty(specialPropertyName);

        if (specialProperty != null) {
          emitProperty(specialProperty, contentHandler, skipBinary);
        }
      }

      PropertyIterator properties = node.getProperties();
      while (properties.hasNext()) {
        exportProperty(properties.nextProperty(), contentHandler, skipBinary);
      }

      if (!noRecurse) {
        NodeIterator nodes = node.getNodes();
        while (nodes.hasNext()) {
          exportNode(nodes.nextNode(), contentHandler, skipBinary, noRecurse, false);
        }
      }
    }

    endElement(contentHandler, JcrSvLexicon.NODE);
  }
  protected void dump(Node node, JSONWriter w, int currentRecursionLevel, int maxRecursionLevels)
      throws RepositoryException, JSONException {

    // check for array
    boolean isArray = true;
    NodeIterator children = node.getNodes();
    if (!children.hasNext()) { // has no children
      isArray = false;
    }
    while (children.hasNext()) {
      final Node n = children.nextNode();
      if (!n.getName().matches("\\d+")) {
        isArray = false;
        break;
      }
    }
    PropertyIterator props = node.getProperties();
    if (isArray && props.hasNext()) {
      // array should not have properties
      while (props.hasNext()) {
        Property prop = props.nextProperty();
        // ignore any jcr:* properties
        if (!prop.getName().matches("jcr:.+")) {
          isArray = false;
          break;
        }
      }
    }

    if (isArray) {
      w.array();
      // the child nodes
      if (recursionLevelActive(currentRecursionLevel, maxRecursionLevels)) {
        children = node.getNodes();
        while (children.hasNext()) {
          final Node n = children.nextNode();
          dump(n, w, currentRecursionLevel + 1, maxRecursionLevels);
        }
      }
      w.endArray();
    } else {
      w.object();
      props = node.getProperties();
      // the node's actual properties
      while (props.hasNext()) {
        Property prop = props.nextProperty();
        if (prop.getName().matches("jcr:.+")) { // ignore any jcr:* properties
          continue;
        }
        if (prop.getName().matches("cq:.+")) { // ignore any cq:* properties
          continue;
        }
        writeProperty(w, prop);
      }

      // the child nodes
      if (recursionLevelActive(currentRecursionLevel, maxRecursionLevels)) {
        children = node.getNodes();
        while (children.hasNext()) {
          final Node n = children.nextNode();
          dumpSingleNode(n, w, currentRecursionLevel, maxRecursionLevels);
        }
      }
      w.endObject();
    }
  }
  /**
   * {@inheritDoc}
   *
   * @see
   *     org.modeshape.graph.request.processor.RequestProcessor#process(org.modeshape.graph.request.UpdatePropertiesRequest)
   */
  @Override
  public void process(UpdatePropertiesRequest request) {
    if (request == null) return;
    try {
      Workspace workspace = workspaceFor(request.inWorkspace());
      Node node = workspace.node(request.on());
      Set<Name> newProperties = new HashSet<Name>();
      for (Map.Entry<Name, Property> entry : request.properties().entrySet()) {
        Name propertyName = entry.getKey();
        String name = workspace.stringFor(propertyName);
        Property property = entry.getValue();

        // We need to remove the existing property (if there is one) in case the
        // old property has a different cardinality than the new property ...
        javax.jcr.Property existing = node.hasProperty(name) ? node.getProperty(name) : null;
        if (existing != null
            && (property == null || existing.getDefinition().isMultiple() == property.isSingle())) {
          // Remove the property ...
          if (!existing.getDefinition().isProtected()) {
            existing.remove();
          }
        }
        if (property != null) {
          if (property.size() == 1) {
            // Try setting as a single-valued property ...
            try {
              workspace.setProperty(node, property, false);
            } catch (ValueFormatException e) {
              workspace.setProperty(node, property, true);
            }
          } else {
            // Set as a multi-valued property ...
            workspace.setProperty(node, property, true);
          }
          if (existing == null) newProperties.add(propertyName);
        }
      }

      if (request.removeOtherProperties()) {
        Set<String> stringNames = new HashSet<String>();
        for (Name name : request.properties().keySet()) {
          stringNames.add(workspace.stringFor(name));
        }
        stringNames.add(workspace.stringFor(JcrLexicon.PRIMARY_TYPE));
        stringNames.add(workspace.stringFor(JcrLexicon.MIXIN_TYPES));
        PropertyIterator propertyIter = node.getProperties();
        while (propertyIter.hasNext()) {
          javax.jcr.Property property = propertyIter.nextProperty();
          if (!stringNames.contains(property.getName())
              && !property.getDefinition().isProtected()) {
            property.remove();
          }
        }
      }

      // Set up the actual results on the request ...
      request.setActualLocationOfNode(workspace.locationFor(node));
      request.setNewProperties(newProperties);
    } catch (Throwable e) {
      request.setError(e);
    }
  }