Author: rhauch
Date: 2008-09-17 11:08:00 -0400 (Wed, 17 Sep 2008)
New Revision: 523
Modified:
trunk/docs/examples/gettingstarted/repositories/src/main/config/run.sh
trunk/docs/examples/gettingstarted/repositories/src/main/java/org/jboss/example/dna/repository/ConsoleInput.java
trunk/docs/examples/gettingstarted/repositories/src/main/java/org/jboss/example/dna/repository/RepositoryClient.java
trunk/docs/examples/gettingstarted/repositories/src/main/java/org/jboss/example/dna/repository/UserInterface.java
trunk/docs/examples/gettingstarted/repositories/src/test/java/org/jboss/example/dna/repository/RepositoryClientTest.java
trunk/extensions/dna-connector-inmemory/src/main/java/org/jboss/dna/connector/inmemory/InMemoryRepository.java
Log:
DNA-222 - Create Getting Started example application for repositories
http://jira.jboss.com/jira/browse/DNA-222
Additional changes after more testing. Mostly working now, except for DNA-225.
Modified: trunk/docs/examples/gettingstarted/repositories/src/main/config/run.sh
===================================================================
--- trunk/docs/examples/gettingstarted/repositories/src/main/config/run.sh 2008-09-16
20:26:44 UTC (rev 522)
+++ trunk/docs/examples/gettingstarted/repositories/src/main/config/run.sh 2008-09-17
15:08:00 UTC (rev 523)
@@ -1,3 +1,3 @@
#!/bin/sh
-java -Djava.ext.dirs=`pwd`/lib -cp .:dna-example-sequencers-0.1-SNAPSHOT.jar
org.jboss.example.dna.repository.RepositoryClient $1
\ No newline at end of file
+java -Djava.ext.dirs=`pwd`/lib -cp .:dna-example-repositories-0.1-SNAPSHOT.jar
org.jboss.example.dna.repository.RepositoryClient $1
\ No newline at end of file
Modified:
trunk/docs/examples/gettingstarted/repositories/src/main/java/org/jboss/example/dna/repository/ConsoleInput.java
===================================================================
---
trunk/docs/examples/gettingstarted/repositories/src/main/java/org/jboss/example/dna/repository/ConsoleInput.java 2008-09-16
20:26:44 UTC (rev 522)
+++
trunk/docs/examples/gettingstarted/repositories/src/main/java/org/jboss/example/dna/repository/ConsoleInput.java 2008-09-17
15:08:00 UTC (rev 523)
@@ -29,7 +29,9 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import javax.security.auth.callback.CallbackHandler;
import org.jboss.dna.common.util.StringUtil;
+import com.sun.security.auth.callback.TextCallbackHandler;
/**
* @author Randall Hauch
@@ -41,17 +43,37 @@
private final RepositoryClient repositoryClient;
private final Map<Integer, String> selectionToSourceName = new
HashMap<Integer, String>();
+ /**
+ * Construct the console input and prompt for user input to interact with the
RepositoryClient.
+ *
+ * @param client the client that should be used; may not be null
+ * @param args the command-line arguments; may not be null but may be empty
+ */
public ConsoleInput( final RepositoryClient client,
final String[] args ) {
+ assert client != null;
this.repositoryClient = client;
+ for (String arg : args) {
+ arg = arg.trim().toLowerCase();
+ if (arg.equals("--help")) {
+ System.out.println();
+ System.out.println("Usage: run.sh [options]");
+ System.out.println();
+ System.out.println("Options:");
+ System.out.println(" --api=value Specify which API should be
used to obtain the content.");
+ System.out.println(" The 'value' must be
either 'jcr' or 'dna', and defaults");
+ System.out.println(" to 'jcr'.");
+ System.out.println(" --jaas Specify that JAAS should be
used to authenticate the user.");
+ System.out.println(" --jaas=name With no 'name', use
JAAS with an application context");
+ System.out.println(" named \"" +
RepositoryClient.JAAS_LOGIN_CONTEXT_NAME + "\".");
+ System.out.println(" If another application context
is to be used, then specify");
+ System.out.println(" the name.");
+ System.out.println(" --help Print these instructions and
exit.");
+ System.out.println();
+ return;
+ }
+ }
try {
- System.out.println();
- System.out.print("Starting repositories ... ");
- client.startRepositories();
- System.out.println("done.");
- System.out.println();
-
- System.out.println(getMenu());
Thread eventThread = new Thread(new Runnable() {
private boolean quit = false;
@@ -59,34 +81,30 @@
@SuppressWarnings( "synthetic-access" )
public void run() {
try {
+ System.out.println();
+ System.out.print("Starting repositories ... ");
+ client.startRepositories();
+ System.out.println("done.");
+ System.out.println();
+ displayMainMenu();
+
while (!quit) {
System.out.print(">");
try {
- String input = in.readLine();
- if (input.length() != 1) {
- System.out.println("Please enter a valid
option.");
- continue;
+ String input = in.readLine().trim();
+ if ("?".equals(input) ||
"h".equals(input)) displayMainMenu();
+ else if ("q".equals(input)) quit = true;
+ else {
+ try {
+ int selection = Integer.parseInt(input);
+ String sourceName =
selectionToSourceName.get(selection);
+ displayNavigationMenu(sourceName);
+ displayMainMenu();
+ } catch (NumberFormatException e) {
+ System.out.println("Invalid option.");
+ displayMainMenu();
+ }
}
-
- char option = input.charAt(0);
- switch (option) {
- case '?':
- case 'h':
- System.out.println(getMenu());
- break;
- case 'q':
- quit = true;
- break;
- default:
- try {
- int selection = Integer.parseInt(""
+ option);
- String sourceName =
selectionToSourceName.get(selection);
- navigate(sourceName);
- } catch (NumberFormatException e) {
- System.out.println("Invalid
option.");
- break;
- }
- }
} catch (NumberFormatException e) {
System.out.println("Invalid integer " +
e.getMessage());
} catch (IllegalArgumentException e) {
@@ -97,6 +115,9 @@
e.printStackTrace();
}
}
+ } catch (Exception err) {
+ System.out.println("Error: " +
err.getLocalizedMessage());
+ err.printStackTrace(System.err);
} finally {
try {
// Terminate ...
@@ -122,72 +143,98 @@
}
}
- protected String getMenu() {
+ /**
+ * Generate the main menu for the console-based application.
+ */
+ protected void displayMainMenu() {
selectionToSourceName.clear();
- StringBuilder buffer = new StringBuilder();
- buffer.append("-----------------------------------\n");
- buffer.append("Menu:\n");
- buffer.append("\n");
- buffer.append(" Select a repository to view:\n");
+ System.out.println("-----------------------------------");
+ System.out.println("Menu:");
+ System.out.println();
+ System.out.println("Select a repository to view:");
int selection = 1;
- for (String sourceName : this.repositoryClient.getNamesOfRepositories()) {
+ for (String sourceName : repositoryClient.getNamesOfRepositories()) {
selectionToSourceName.put(selection, sourceName);
- buffer.append(" " + selection + ") " + sourceName +
"\n");
+ System.out.println(StringUtil.justifyRight("" + selection++, 3,
' ') + ") " + sourceName);
}
- buffer.append(" or\n");
- buffer.append(" ?) Show this menu\n");
- buffer.append(" q) Quit");
- return buffer.toString();
+ System.out.println("or");
+ System.out.println(" ?) Show this menu");
+ System.out.println(" q) Quit");
}
- protected void navigate( String sourceName ) {
+ /**
+ * Display the menu for navigating the source with the supplied name. This method
returns as soon as the user exits the
+ * source.
+ *
+ * @param sourceName the source to be navigated; may not be null
+ */
+ protected void displayNavigationMenu( String sourceName ) {
+ assert sourceName != null;
String currentPath = "/";
+ System.out.println();
+ System.out.println("Entering the \"" + sourceName + "\"
repository.");
+ displayNavigationHelp();
while (true) {
-
- // Ask for the command ...
- System.out.print("> ");
try {
+ // Print the prompt and read the input command ...
+ System.out.print(sourceName + "> ");
String input = in.readLine().trim();
- if (input.length() == 0) {
- continue;
- }
+ // Process the command ...
+ if (input.length() == 0) continue;
if ("?".equals(input) || "help".equals(input) ||
"h".equals(input)) {
- System.out.println(" Enter a command:");
- System.out.println(" pwd print the current
node's path");
- System.out.println(" ls [path] to list the details of
the node at the specified absolute or relative path");
- System.out.println(" (or the current path if
none is supplied)");
- System.out.println(" cd path to change to the node at
the specified absolute or relative path");
- System.out.println(" exit to exit this repository
and return to the main menu");
- System.out.println(" and press return:");
+ displayNavigationHelp();
} else if ("pwd".equals(input)) {
- System.out.println(" " + currentPath);
+ System.out.println(currentPath);
} else if ("exit".equals(input)) {
return;
- } else if (input.startsWith("ls")) {
- input = input.substring("ls".length()).trim();
- String path = currentPath;
- if (input.length() != 0) path = input;
+ } else if (input.startsWith("ls") ||
input.startsWith("ll")) {
+ input = input.substring(2).trim();
+ String path = repositoryClient.buildPath(currentPath, input);
displayNode(sourceName, path);
} else if (input.startsWith("cd ")) {
input = input.substring("cd ".length()).trim();
if (input.length() == 0) continue;
- // Check to see if the new path exists ...
- if (!repositoryClient.getNodeInfo(sourceName, input, null, null)) {
- System.out.println(" \"" + input + "\"
does not exist");
+ // Change the current path to the new location
+ String oldPath = currentPath;
+ currentPath = repositoryClient.buildPath(currentPath, input);
+ // If the current path does not exist, then go back to the previous
path ...
+ if (!repositoryClient.getNodeInfo(sourceName, currentPath, null,
null)) {
+ System.out.println("\"" + currentPath +
"\" does not exist");
+ currentPath = oldPath;
} else {
- currentPath = input;
+ System.out.println(currentPath);
}
}
} catch (Throwable e) {
displayError(" processing your command", e);
}
}
+ }
+ protected void displayNavigationHelp() {
+ System.out.println();
+ System.out.println("Enter one of the following commands followed by
RETURN:");
+ System.out.println(" pwd print the current node's
path");
+ System.out.println(" ls [path] to list the details of the node at
the specified absolute or relative path");
+ System.out.println(" (or the current path if none is
supplied)");
+ System.out.println(" cd path to change to the node at the
specified absolute or relative path");
+ System.out.println(" exit to exit this repository and return to
the main menu");
+ System.out.println();
}
+ /**
+ * Display the node with the given path found in the supplied source.
+ *
+ * @param sourceName the name of the source; may not be null
+ * @param path the path to the node; may not be null
+ */
protected void displayNode( String sourceName,
String path ) {
+ assert sourceName != null;
+ assert path != null;
+
+ // Retrieve the node information from the client ...
Map<String, Object[]> properties = new HashMap<String, Object[]>();
List<String> children = new ArrayList<String>();
try {
@@ -196,29 +243,39 @@
displayError(" displaying node \"" + path +
"\"", t);
}
- System.out.println(" Path:" + path);
- System.out.println(" Properties:");
- int maxLength = 0;
+ // Print the './' and '../' options ...
+ System.out.println(" ./");
+ System.out.println(" ../");
+
+ // Display the children ...
+ for (String childName : children) {
+ System.out.println(" " + childName + "/");
+ }
+ // Determine the maximum length of the properties so that we can left-justify the
values
+ int maxLength = 5;
for (String propertyName : properties.keySet()) {
maxLength = Math.max(maxLength, propertyName.length());
}
+ // Display the properties ...
for (Map.Entry<String, Object[]> property : properties.entrySet()) {
- String name = property.getKey();
- name = StringUtil.justifyLeft(name, maxLength, ' ');
+ String name = StringUtil.justifyLeft(property.getKey(), maxLength, '
');
Object[] values = property.getValue();
String valueStr = StringUtil.readableString(values);
- if (values.length == 1) StringUtil.readableString(values[0]);
- System.out.println(" " + name + " = " + valueStr);
+ if (values.length == 1) valueStr = StringUtil.readableString(values[0]);
+ System.out.println(" " + name + " = " + valueStr);
}
- System.out.println(" Children:");
- for (String childName : children) {
- System.out.println(" " + childName);
- }
- System.out.println();
}
+ /**
+ * Display the supplied error that happened during the activity.
+ *
+ * @param activity the activity; may not be null but may be empty
+ * @param t the exception; may not be null
+ */
protected void displayError( String activity,
Throwable t ) {
+ assert activity != null;
+ assert t != null;
System.err.println();
System.err.println("There has been an error" + activity);
System.err.println(" " + t.getMessage());
@@ -240,4 +297,14 @@
public String getLocationOfRepositoryFiles() {
return new File("").getAbsolutePath();
}
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.example.dna.repository.UserInterface#getCallbackHandler()
+ */
+ public CallbackHandler getCallbackHandler() {
+ return new TextCallbackHandler();
+ }
+
}
Modified:
trunk/docs/examples/gettingstarted/repositories/src/main/java/org/jboss/example/dna/repository/RepositoryClient.java
===================================================================
---
trunk/docs/examples/gettingstarted/repositories/src/main/java/org/jboss/example/dna/repository/RepositoryClient.java 2008-09-16
20:26:44 UTC (rev 522)
+++
trunk/docs/examples/gettingstarted/repositories/src/main/java/org/jboss/example/dna/repository/RepositoryClient.java 2008-09-17
15:08:00 UTC (rev 523)
@@ -22,7 +22,8 @@
package org.jboss.example.dna.repository;
import java.io.IOException;
-import java.util.Collection;
+import java.util.ArrayList;
+import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
@@ -31,11 +32,14 @@
import javax.jcr.NodeIterator;
import javax.jcr.PropertyIterator;
import javax.jcr.Session;
-import javax.jcr.SimpleCredentials;
import javax.naming.NamingException;
-import javax.security.auth.callback.PasswordCallback;
+import javax.security.auth.login.LoginContext;
+import javax.security.auth.login.LoginException;
+import net.jcip.annotations.Immutable;
import org.jboss.dna.common.component.ClassLoaderFactory;
import org.jboss.dna.common.component.StandardClassLoaderFactory;
+import org.jboss.dna.common.text.NoOpEncoder;
+import org.jboss.dna.common.util.ArgCheck;
import org.jboss.dna.connector.inmemory.InMemoryRepositorySource;
import org.jboss.dna.jcr.JcrRepository;
import org.jboss.dna.repository.RepositoryImporter;
@@ -68,7 +72,8 @@
arg = arg.trim();
if (arg.equals("--api=jcr")) client.setApi(Api.JCR);
if (arg.equals("--api=dna")) client.setApi(Api.DNA);
- if (arg.startsWith("--user=") && arg.length() > 7)
client.setUsername(arg.substring(7).trim());
+ if (arg.equals("--jaas"))
client.setJaasContextName(JAAS_LOGIN_CONTEXT_NAME);
+ if (arg.startsWith("--jaas=") && arg.length() > 7)
client.setJaasContextName(arg.substring(7).trim());
}
client.setUserInterface(new ConsoleInput(client, args));
}
@@ -82,10 +87,11 @@
private RepositoryLibrary sources;
private ExecutionContextFactory contextFactory;
private RepositoryService repositoryService;
- private Api api = Api.DNA;
- private String username = null;
- private char[] password = null;
+ private Api api = Api.JCR;
+ private String jaasContextName;
private UserInterface userInterface;
+ private LoginContext loginContext;
+ private ExecutionContext context;
/**
* @param userInterface Sets userInterface to the specified value.
@@ -104,37 +110,15 @@
}
/**
- * Set the username that this client should use.
+ * Set the JAAS context name that should be used. If null (which is the default),
then no authentication will be used.
*
- * @param username the new username, or null if no username should be used.
+ * @param jaasContextName the JAAS context name, or null if no authentication should
be performed
*/
- public void setUsername( String username ) {
- this.username = username;
- this.password = null;
+ public void setJaasContextName( String jaasContextName ) {
+ this.jaasContextName = jaasContextName;
}
/**
- * Clear any cached password.
- */
- public void clearPassword() {
- password = null;
- }
-
- /**
- * Method used internally to obtain the password, which is obtained from the user
(only once per process) if needed
- *
- * @return the user's password, or null if no username is known
- */
- private char[] getPassword() {
- if (username == null) return null;
- if (password == null) {
- PasswordCallback callback = new PasswordCallback("Password:",
false);
- password = callback.getPassword();
- }
- return password;
- }
-
- /**
* Start up the repositories. This method creates the necessary components and
services, and initializes the in-memory
* repositories.
*
@@ -152,7 +136,7 @@
// Create the execution context that we'll use for the services. If we'd
want to use JAAS, we'd create the context
// by supply LoginContext, AccessControlContext, or even Subject with
CallbackHandlers. But no JAAS in this example.
- ExecutionContext context = contextFactory.create();
+ context = contextFactory.create();
// Create the library for the RepositorySource instances ...
sources = new RepositoryLibrary(contextFactory);
@@ -183,16 +167,20 @@
*
* @return the repository names
*/
- public Collection<String> getNamesOfRepositories() {
- return sources.getSourceNames();
+ public List<String> getNamesOfRepositories() {
+ List<String> names = new
ArrayList<String>(sources.getSourceNames());
+ Collections.sort(names);
+ return names;
}
/**
* Shut down the components and services and blocking until all resources have been
released.
*
* @throws InterruptedException if the thread was interrupted before completing the
shutdown.
+ * @throws LoginException
*/
- public void shutdown() throws InterruptedException {
+ public void shutdown() throws InterruptedException, LoginException {
+ logout();
if (repositoryService == null) return;
try {
// Shut down the various services ...
@@ -208,6 +196,37 @@
}
/**
+ * Get the current JAAS LoginContext (if there is one).
+ *
+ * @return the current login context, or null if no JAAS authentication is to be
used.
+ * @throws LoginException if authentication was attempted but failed
+ */
+ protected LoginContext getLoginContext() throws LoginException {
+ if (loginContext == null) {
+ if (jaasContextName != null) {
+ loginContext = new LoginContext(jaasContextName,
this.userInterface.getCallbackHandler());
+ loginContext.login();
+ }
+ }
+ return loginContext;
+ }
+
+ /**
+ * Calling this will lose the context
+ *
+ * @throws LoginException
+ */
+ public void logout() throws LoginException {
+ if (loginContext != null) {
+ try {
+ loginContext.logout();
+ } finally {
+ loginContext = null;
+ }
+ }
+ }
+
+ /**
* Get the information about a node, using the {@link #setApi(Api) API} method.
*
* @param sourceName the name of the repository source
@@ -223,17 +242,20 @@
String pathToNode,
Map<String, Object[]> properties,
List<String> children ) throws Throwable {
+ LoginContext loginContext = getLoginContext(); // will ask user to authenticate
if needed
switch (api) {
case JCR: {
JcrRepository jcrRepository = new JcrRepository(contextFactory,
sources);
Session session = null;
- if (username != null) {
- Credentials credentials = new SimpleCredentials(username,
getPassword());
+ if (loginContext != null) {
+ Credentials credentials = new JaasCredentials(loginContext);
session = jcrRepository.login(credentials, sourceName);
} else {
session = jcrRepository.login(sourceName);
}
try {
+ // Make the path relative to the root by removing the leading
slash(es) ...
+ pathToNode = pathToNode.replaceAll("^/+", "");
// Get the node by path ...
Node root = session.getRootNode();
Node node = root.getNode(pathToNode);
@@ -242,7 +264,8 @@
if (properties != null) {
for (PropertyIterator iter = node.getProperties();
iter.hasNext();) {
javax.jcr.Property property = iter.nextProperty();
- properties.put(property.getName(), property.getValues());
+ Object[] values = property.getDefinition().isMultiple() ?
property.getValues() : new Object[] {property.getValue()};
+ properties.put(property.getName(), values);
}
}
if (children != null) {
@@ -259,12 +282,7 @@
break;
}
case DNA: {
- ExecutionContext context = null;
- if (username != null) {
- context = contextFactory.create(JAAS_LOGIN_CONTEXT_NAME);
- } else {
- context = contextFactory.create();
- }
+ ExecutionContext context = loginContext != null ?
contextFactory.create(loginContext) : contextFactory.create();
PathFactory pathFactory = context.getValueFactories().getPathFactory();
// Get the node submitting a graph command to a repository connection.
@@ -303,4 +321,53 @@
}
return true;
}
+
+ /**
+ * Utility to build a path given the current path and the input path as string, where
the input path could be an absolute path
+ * or relative to the current and where the input may use "." and
"..".
+ *
+ * @param current the current path
+ * @param input the input path
+ * @return the resulting full and normalized path
+ */
+ protected String buildPath( String current,
+ String input ) {
+ if (current == null) current = "/";
+ if (input == null || input.length() == 0) return current;
+ PathFactory factory = context.getValueFactories().getPathFactory();
+ Path inputPath = factory.create(input);
+ if (inputPath.isAbsolute()) {
+ return
inputPath.getNormalizedPath().getString(context.getNamespaceRegistry(),
NoOpEncoder.getInstance());
+ }
+ Path currentPath = factory.create(current);
+ currentPath = factory.create(currentPath, inputPath);
+ currentPath = currentPath.getNormalizedPath();
+ return currentPath.getString(context.getNamespaceRegistry(),
NoOpEncoder.getInstance());
+ }
+
+ /**
+ * A class that represents JCR Credentials containing the JAAS LoginContext.
+ *
+ * @author Randall Hauch
+ */
+ @Immutable
+ protected static class JaasCredentials implements Credentials {
+ private static final long serialVersionUID = 1L;
+ private final LoginContext context;
+
+ public JaasCredentials( LoginContext context ) {
+ ArgCheck.isNotNull(context, "context");
+ this.context = context;
+ }
+
+ /**
+ * JBoss DNA's JCR implementation will reflectively look for and call this
method to get the JAAS LoginContext.
+ *
+ * @return the current LoginContext
+ */
+ public LoginContext getLoginContext() {
+ return context;
+ }
+
+ }
}
Modified:
trunk/docs/examples/gettingstarted/repositories/src/main/java/org/jboss/example/dna/repository/UserInterface.java
===================================================================
---
trunk/docs/examples/gettingstarted/repositories/src/main/java/org/jboss/example/dna/repository/UserInterface.java 2008-09-16
20:26:44 UTC (rev 522)
+++
trunk/docs/examples/gettingstarted/repositories/src/main/java/org/jboss/example/dna/repository/UserInterface.java 2008-09-17
15:08:00 UTC (rev 523)
@@ -21,6 +21,8 @@
*/
package org.jboss.example.dna.repository;
+import javax.security.auth.callback.CallbackHandler;
+
/**
* @author Randall Hauch
*/
@@ -28,4 +30,6 @@
String getLocationOfRepositoryFiles();
+ CallbackHandler getCallbackHandler();
+
}
Modified:
trunk/docs/examples/gettingstarted/repositories/src/test/java/org/jboss/example/dna/repository/RepositoryClientTest.java
===================================================================
---
trunk/docs/examples/gettingstarted/repositories/src/test/java/org/jboss/example/dna/repository/RepositoryClientTest.java 2008-09-16
20:26:44 UTC (rev 522)
+++
trunk/docs/examples/gettingstarted/repositories/src/test/java/org/jboss/example/dna/repository/RepositoryClientTest.java 2008-09-17
15:08:00 UTC (rev 523)
@@ -32,6 +32,7 @@
import java.util.Map;
import org.junit.After;
import org.junit.Before;
+import org.junit.Ignore;
import org.junit.Test;
import org.mockito.MockitoAnnotations;
import org.mockito.MockitoAnnotations.Mock;
@@ -190,9 +191,17 @@
assertThat(properties.size(), is(8));
}
+ @Ignore
@Test
public void shouldLoadVehiclesRepository() throws Throwable {
client.startRepositories();
+ assertThat(client.getNodeInfo("Vehicles", "/", properties,
children), is(true));
+ assertThat(children, hasItems("Vehicles"));
+ assertThat(properties.containsKey("dna:uuid"), is(true));
+ assertThat(properties.size(), is(1));
+
+ properties.clear();
+ children.clear();
assertThat(client.getNodeInfo("Vehicles", "/Vehicles",
properties, children), is(true));
assertThat(children, hasItems("Cars", "Aircraft"));
assertThat(properties.containsKey("jcr:primaryType"), is(false));
@@ -201,6 +210,13 @@
properties.clear();
children.clear();
+ assertThat(client.getNodeInfo("Vehicles", "/", properties,
children), is(true));
+ assertThat(children, hasItems("Vehicles"));
+ assertThat(properties.containsKey("dna:uuid"), is(true));
+ assertThat(properties.size(), is(1));
+
+ properties.clear();
+ children.clear();
assertThat(client.getNodeInfo("Vehicles",
"/Vehicles/Cars/Hybrid", properties, children), is(true));
assertThat(children, hasItems("Toyota Prius", "Toyota
Highlander", "Nissan Altima"));
assertThat(properties.containsKey("jcr:primaryType"), is(true));
Modified:
trunk/extensions/dna-connector-inmemory/src/main/java/org/jboss/dna/connector/inmemory/InMemoryRepository.java
===================================================================
---
trunk/extensions/dna-connector-inmemory/src/main/java/org/jboss/dna/connector/inmemory/InMemoryRepository.java 2008-09-16
20:26:44 UTC (rev 522)
+++
trunk/extensions/dna-connector-inmemory/src/main/java/org/jboss/dna/connector/inmemory/InMemoryRepository.java 2008-09-17
15:08:00 UTC (rev 523)
@@ -345,24 +345,26 @@
@Override
public void execute( CreateNodeCommand command ) {
Path path = command.getPath();
- Node parentNode = null;
+ Node node = null;
if (!path.isRoot()) {
Path parent = path.getParent();
// Look up the parent node, which must exist ...
- parentNode = getNode(parent);
+ Node parentNode = getNode(parent);
if (parentNode == null) {
Path lowestExisting = getLowestExistingPath(parent);
throw new PathNotFoundException(path, lowestExisting,
InMemoryConnectorI18n.nodeDoesNotExist.text(parent));
}
- }
- UUID uuid = null;
- for (Property property : command.getProperties()) {
- if (property.getName().equals(uuidPropertyName)) {
- uuid =
getExecutionContext().getValueFactories().getUuidFactory().create(property.getValues().next());
- break;
+ UUID uuid = null;
+ for (Property property : command.getProperties()) {
+ if (property.getName().equals(uuidPropertyName)) {
+ uuid =
getExecutionContext().getValueFactories().getUuidFactory().create(property.getValues().next());
+ break;
+ }
}
+ node = createNode(getExecutionContext(), parentNode,
path.getLastSegment().getName(), uuid);
+ } else {
+ node = getRoot();
}
- Node node = createNode(getExecutionContext(), parentNode,
path.getLastSegment().getName(), uuid);
// Now add the properties to the supplied node ...
for (Property property : command.getProperties()) {
Name propName = property.getName();