Index: dna-graph/src/main/java/org/jboss/dna/graph/DnaLexicon.java =================================================================== --- dna-graph/src/main/java/org/jboss/dna/graph/DnaLexicon.java (revision 1125) +++ dna-graph/src/main/java/org/jboss/dna/graph/DnaLexicon.java (working copy) @@ -43,6 +43,8 @@ public static final Name NAMESPACES = new BasicName(Namespace.URI, "namespaces"); public static final Name PROJECTION_RULES = new BasicName(Namespace.URI, "projectionRules"); public static final Name READ_ONLY = new BasicName(Namespace.URI, "readOnly"); + public static final Name RESOURCE = new BasicName(Namespace.URI, "resource"); + public static final Name ROOT = new BasicName(Namespace.URI, "root"); public static final Name TIME_TO_EXPIRE = new BasicName(Namespace.URI, "timeToExpire"); public static final Name NAMESPACE_URI = new BasicName(Namespace.URI, "uri"); Index: dna-integration-tests/src/test/java/org/jboss/dna/test/integration/AbstractRepositoryTckTest.java =================================================================== --- dna-integration-tests/src/test/java/org/jboss/dna/test/integration/AbstractRepositoryTckTest.java (revision 1125) +++ dna-integration-tests/src/test/java/org/jboss/dna/test/integration/AbstractRepositoryTckTest.java (working copy) @@ -53,8 +53,8 @@ public static TestSuite readOnlyRepositorySuite( String name ) { TestSuite suite = new TestSuite("Tests for " + name + "(read-only)"); suite.addTest(new ChangeRepositoryTestCase(name)); - suite.addTest(JcrTckTest.suite()); - suite.addTestSuite(DnaTckTest.class); + suite.addTest(JcrTckTest.readOnlySuite()); + suite.addTest(DnaTckTest.readOnlySuite()); return suite; } Index: dna-integration-tests/src/test/java/org/jboss/dna/test/integration/FileSystemRepositoryTckTest.java =================================================================== --- dna-integration-tests/src/test/java/org/jboss/dna/test/integration/FileSystemRepositoryTckTest.java (revision 0) +++ dna-integration-tests/src/test/java/org/jboss/dna/test/integration/FileSystemRepositoryTckTest.java (revision 0) @@ -0,0 +1,33 @@ +/* + * JBoss DNA (http://www.jboss.org/dna) + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. Some portions may be licensed + * to Red Hat, Inc. under one or more contributor license agreements. + * See the AUTHORS.txt file in the distribution for a full listing of + * individual contributors. + * + * JBoss DNA is free software. Unless otherwise indicated, all code in JBoss DNA + * is licensed to you under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * JBoss DNA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.jboss.dna.test.integration; + +import junit.framework.Test; + +public class FileSystemRepositoryTckTest { + + public static Test suite() { + return AbstractRepositoryTckTest.readOnlyRepositorySuite("filesystem"); + } +} Property changes on: dna-integration-tests\src\test\java\org\jboss\dna\test\integration\FileSystemRepositoryTckTest.java ___________________________________________________________________ Added: svn:keywords + Id Revision Added: svn:eol-style + LF Index: dna-integration-tests/src/test/resources/tck/filesystem/configRepository.xml =================================================================== --- dna-integration-tests/src/test/resources/tck/filesystem/configRepository.xml (revision 0) +++ dna-integration-tests/src/test/resources/tck/filesystem/configRepository.xml (revision 0) @@ -0,0 +1,95 @@ + + + + + + + + + + + + + Standard extension-based MIME type detector + + org.jboss.dna.graph.mimetype.ExtensionBasedMimeTypeDetector + + + + + + + + + + Store + + + + + + + + + + + + Property changes on: dna-integration-tests\src\test\resources\tck\filesystem\configRepository.xml ___________________________________________________________________ Added: svn:keywords + Id Revision Index: dna-integration-tests/src/test/resources/tck/filesystem/repositoryOverlay.properties =================================================================== --- dna-integration-tests/src/test/resources/tck/filesystem/repositoryOverlay.properties (revision 0) +++ dna-integration-tests/src/test/resources/tck/filesystem/repositoryOverlay.properties (revision 0) @@ -0,0 +1,8 @@ +# Placeholder for any overlaid properties for this repo configuration + +javax.jcr.tck.dnaSkipImport=true + + +javax.jcr.tck.nodetype=nt\:file +javax.jcr.tck.nodetype2=nt\:file + Index: dna-jcr/src/main/java/org/jboss/dna/jcr/DnaLexicon.java =================================================================== --- dna-jcr/src/main/java/org/jboss/dna/jcr/DnaLexicon.java (revision 1125) +++ dna-jcr/src/main/java/org/jboss/dna/jcr/DnaLexicon.java (working copy) @@ -35,7 +35,6 @@ public static final Name NAMESPACE = new BasicName(Namespace.URI, "namespace"); public static final Name NODE_TYPES = new BasicName(Namespace.URI, "nodeTypes"); public static final Name REPOSITORIES = new BasicName(Namespace.URI, "repositories"); - public static final Name ROOT = new BasicName(Namespace.URI, "root"); public static final Name SYSTEM = new BasicName(Namespace.URI, "system"); public static final Name URI = new BasicName(Namespace.URI, "uri"); } Index: dna-jcr/src/main/java/org/jboss/dna/jcr/JcrDocumentViewExporter.java =================================================================== --- dna-jcr/src/main/java/org/jboss/dna/jcr/JcrDocumentViewExporter.java (revision 1125) +++ dna-jcr/src/main/java/org/jboss/dna/jcr/JcrDocumentViewExporter.java (working copy) @@ -23,6 +23,7 @@ */ package org.jboss.dna.jcr; +import java.io.IOException; import java.io.OutputStream; import java.text.CharacterIterator; import java.text.StringCharacterIterator; @@ -39,6 +40,7 @@ import net.jcip.annotations.NotThreadSafe; import org.jboss.dna.common.text.TextEncoder; import org.jboss.dna.common.text.XmlNameEncoder; +import org.jboss.dna.common.util.Base64; import org.jboss.dna.graph.ExecutionContext; import org.jboss.dna.graph.property.Name; import org.jboss.dna.graph.property.ValueFactories; @@ -56,6 +58,8 @@ @NotThreadSafe class JcrDocumentViewExporter extends AbstractJcrExporter { + private static final int ENCODE_BUFFER_SIZE = 2 << 15; + private static final TextEncoder VALUE_ENCODER = new JcrDocumentViewExporter.JcrDocumentViewPropertyEncoder(); JcrDocumentViewExporter( JcrSession session ) { @@ -99,14 +103,19 @@ while (properties.hasNext()) { Property prop = properties.nextProperty(); + Name propName = ((AbstractJcrProperty)prop).name(); + + String localPropName = getPrefixedName(propName); + if (skipBinary && PropertyType.BINARY == prop.getType()) { + atts.addAttribute(propName.getNamespaceUri(), + propName.getLocalName(), + localPropName, + PropertyType.nameFromValue(prop.getType()), + ""); continue; } - Name propName = ((AbstractJcrProperty)prop).name(); - - String localPropName = getPrefixedName(propName); - Value value; if (prop instanceof JcrSingleValueProperty) { value = prop.getValue(); @@ -115,11 +124,31 @@ // 6.4.2.5 value = prop.getValues()[0]; } + + String valueAsString; + if (PropertyType.BINARY == prop.getType()) { + StringBuffer buff = new StringBuffer(ENCODE_BUFFER_SIZE); + try { + Base64.InputStream is = new Base64.InputStream(value.getStream(), Base64.ENCODE); + + byte[] bytes = new byte[ENCODE_BUFFER_SIZE]; + int len; + while (-1 != (len = is.read(bytes, 0, ENCODE_BUFFER_SIZE))) { + buff.append(new String(bytes, 0, len)); + } + } catch (IOException ioe) { + throw new RepositoryException(ioe); + } + valueAsString = buff.toString(); + } else { + valueAsString = VALUE_ENCODER.encode(value.getString()); + } + atts.addAttribute(propName.getNamespaceUri(), propName.getLocalName(), localPropName, PropertyType.nameFromValue(prop.getType()), - VALUE_ENCODER.encode(value.getString())); + valueAsString); } Name name; @@ -148,8 +177,10 @@ * Indicates whether the current node is an XML text node as per section 6.4.2.3 of the JCR 1.0 specification. XML text nodes * are nodes that have the name "jcr:xmltext" and only one property (besides the mandatory * "jcr:primaryType"). The property must have a property name of "jcr:xmlcharacters", a type of - * String, and does not have multiple values.

In practice, this is handled in DNA by making XML text nodes - * have a type of "dna:xmltext", which enforces these property characteristics. + * String, and does not have multiple values. + *

+ * In practice, this is handled in DNA by making XML text nodes have a type of "dna:xmltext", which enforces these + * property characteristics. * * @param node the node to test * @return whether this node is a special xml text node @@ -224,6 +255,7 @@ * underscore characters that might otherwise suggest an encoding, as defined in {@link XmlNameEncoder}. */ protected static class JcrDocumentViewPropertyEncoder extends XmlNameEncoder { + private static final Set MAPPED_CHARACTERS; static { Index: dna-jcr/src/main/java/org/jboss/dna/jcr/JcrValue.java =================================================================== --- dna-jcr/src/main/java/org/jboss/dna/jcr/JcrValue.java (revision 1125) +++ dna-jcr/src/main/java/org/jboss/dna/jcr/JcrValue.java (working copy) @@ -56,6 +56,7 @@ private final ValueFactories valueFactories; private final int type; private final Object value; + private InputStream asStream = null; JcrValue( ValueFactories valueFactories, SessionCache sessionCache, @@ -187,10 +188,12 @@ throw new IllegalStateException(JcrI18n.nonInputStreamConsumed.text()); } try { - Binary binary = valueFactories.getBinaryFactory().create(value); - InputStream convertedValue = new SelfClosingInputStream(binary); - state = State.INPUT_STREAM_CONSUMED; - return convertedValue; + if (asStream == null) { + Binary binary = valueFactories.getBinaryFactory().create(value); + asStream = new SelfClosingInputStream(binary); + state = State.INPUT_STREAM_CONSUMED; + } + return asStream; } catch (RuntimeException error) { throw createValueFormatException(InputStream.class); } Index: dna-jcr/src/main/java/org/jboss/dna/jcr/SessionCache.java =================================================================== --- dna-jcr/src/main/java/org/jboss/dna/jcr/SessionCache.java (revision 1125) +++ dna-jcr/src/main/java/org/jboss/dna/jcr/SessionCache.java (working copy) @@ -2067,43 +2067,7 @@ uuidProperty = propertyFactory.create(JcrLexicon.UUID, uuid); } } - if (uuidProperty == null) { - org.jboss.dna.graph.session.GraphSession.PropertyInfo uuidInfo = node.getProperty(JcrLexicon.UUID); - if (uuidInfo != null) { - uuidProperty = uuidInfo.getProperty(); - } - if (uuidProperty != null) { - // Grab the first 'good' UUID value ... - for (Object uuidValue : uuidProperty) { - try { - uuid = factories.getUuidFactory().create(uuidValue); - break; - } catch (ValueFormatException e) { - // Ignore; just continue with the next property value - } - } - } - if (uuid == null) { - // Look for the DNA UUID property ... - uuidInfo = node.getProperty(DnaLexicon.UUID); - if (uuidInfo != null) { - uuidProperty = uuidInfo.getProperty(); - } - if (uuidProperty != null) { - // Grab the first 'good' UUID value ... - for (Object uuidValue : uuidProperty) { - try { - uuid = factories.getUuidFactory().create(uuidValue); - break; - } catch (ValueFormatException e) { - // Ignore; just continue with the next property value - } - } - } - } - } - if (uuid == null) uuid = UUID.randomUUID(); - if (uuidProperty == null) uuidProperty = propertyFactory.create(JcrLexicon.UUID, uuid); + if (uuid != null && uuidProperty == null) uuidProperty = propertyFactory.create(JcrLexicon.UUID, uuid); // Look for the primary type of the node ... Map graphProperties = persistentNode.getPropertiesByName(); Index: dna-jcr/src/main/resources/org/jboss/dna/jcr/dna_builtins.cnd =================================================================== --- dna-jcr/src/main/resources/org/jboss/dna/jcr/dna_builtins.cnd (revision 1125) +++ dna-jcr/src/main/resources/org/jboss/dna/jcr/dna_builtins.cnd (working copy) @@ -53,3 +53,8 @@ + jcr:system (dna:system) = dna:system autocreated mandatory protected ignore + * (nt:base) = nt:unstructured multiple version +[dna:resource] > nt:base +- jcr:data (binary) primary mandatory +- jcr:encoding (string) copy +- jcr:lastModified (date) mandatory ignore +- jcr:mimeType (string) copy mandatory Index: dna-jcr/src/test/java/org/jboss/dna/jcr/DnaRepositoryStub.java =================================================================== --- dna-jcr/src/test/java/org/jboss/dna/jcr/DnaRepositoryStub.java (revision 1125) +++ dna-jcr/src/test/java/org/jboss/dna/jcr/DnaRepositoryStub.java (working copy) @@ -39,6 +39,9 @@ * Concrete implementation of {@link RepositoryStub} based on DNA-specific configuration. */ public class DnaRepositoryStub extends RepositoryStub { + + public static final String DNA_SKIP_IMPORT = "javax.jcr.tck.dnaSkipImport"; + private static final String REPOSITORY_SOURCE_NAME = "Test Repository Source"; private static String currentConfigurationName = "default"; @@ -46,7 +49,6 @@ private Properties configProps; private String repositoryConfigurationName; private JcrRepository repository; - static { @@ -69,7 +71,7 @@ private void configureRepository() { repositoryConfigurationName = currentConfigurationName; - + // Create the in-memory (DNA) repository JcrConfiguration configuration = new JcrConfiguration(); try { @@ -94,7 +96,6 @@ JcrEngine engine = configuration.build(); engine.start(); - // Problems problems = engine.getRepositoryService().getStartupProblems(); Problems problems = engine.getProblems(); // Print all of the problems from the engine configuration ... for (Problem problem : problems) { @@ -110,24 +111,27 @@ try { repository = engine.getRepository(REPOSITORY_SOURCE_NAME); - // Set up some sample nodes in the graph to match the expected test configuration - Graph graph = Graph.create(repository.getRepositorySourceName(), - engine.getRepositoryConnectionFactory(), - executionContext); - Path destinationPath = executionContext.getValueFactories().getPathFactory().createRootPath(); + // This needs to check configProps directly to avoid an infinite loop + String skipImport = (String)configProps.get(DNA_SKIP_IMPORT); + if (!Boolean.valueOf(skipImport)) { - InputStream xmlStream = getClass().getResourceAsStream("/tck/repositoryForTckTests.xml"); - graph.importXmlFrom(xmlStream).into(destinationPath); + // Set up some sample nodes in the graph to match the expected test configuration + Graph graph = Graph.create(repository.getRepositorySourceName(), + engine.getRepositoryConnectionFactory(), + executionContext); + Path destinationPath = executionContext.getValueFactories().getPathFactory().createRootPath(); - graph.createWorkspace().named("otherWorkspace"); + InputStream xmlStream = getClass().getResourceAsStream("/tck/repositoryForTckTests.xml"); + graph.importXmlFrom(xmlStream).into(destinationPath); + graph.createWorkspace().named("otherWorkspace"); + } } catch (Exception ex) { // The TCK tries to quash this exception. Print it out to be more obvious. ex.printStackTrace(); throw new IllegalStateException("Failed to initialize the repository with text content.", ex); } - } public static void setCurrentConfigurationName( String newConfigName ) { Index: dna-jcr/src/test/java/org/jboss/dna/jcr/DnaTckTest.java =================================================================== --- dna-jcr/src/test/java/org/jboss/dna/jcr/DnaTckTest.java (revision 1125) +++ dna-jcr/src/test/java/org/jboss/dna/jcr/DnaTckTest.java (working copy) @@ -13,6 +13,8 @@ import javax.jcr.Session; import javax.jcr.SimpleCredentials; import javax.jcr.nodetype.ConstraintViolationException; +import junit.framework.Test; +import junit.framework.TestSuite; import org.apache.jackrabbit.test.AbstractJCRTest; import org.jboss.dna.jcr.nodetype.NodeTypeTemplate; @@ -23,6 +25,25 @@ Session session; + public DnaTckTest( String testName ) { + super(); + + this.setName(testName); + this.isReadOnly = true; + } + + public static Test readOnlySuite() { + TestSuite suite = new TestSuite("DNA JCR API tests"); + + suite.addTest(new DnaTckTest("testShouldAllowAdminSessionToRead")); + suite.addTest(new DnaTckTest("testShouldAllowReadOnlySessionToRead")); + suite.addTest(new DnaTckTest("testShouldAllowReadWriteSessionToRead")); + suite.addTest(new DnaTckTest("testShouldNotSeeWorkspacesWithoutReadPermission")); + suite.addTest(new DnaTckTest("testShouldMapReadRolesToWorkspacesWhenSpecified")); + + return suite; + } + @Override protected void tearDown() throws Exception { try { @@ -254,11 +275,35 @@ * * @throws Exception */ - public void testShouldMapRolesToWorkspacesWhenSpecified() throws Exception { + public void testShouldMapReadRolesToWorkspacesWhenSpecified() throws Exception { Credentials creds = new SimpleCredentials("defaultonly", "defaultonly".toCharArray()); session = helper.getRepository().login(creds); testRead(session); + + session.logout(); + + session = helper.getRepository().login(creds, "otherWorkspace"); + testRead(session); + try { + testWrite(session); + fail("User 'defaultuser' should not have write access to 'otherWorkspace'"); + } catch (AccessDeniedException expected) { + } + session.logout(); + } + + /** + * User defaultuser is configured to have readwrite in "otherWorkspace" and readonly in the default workspace. This test makes + * sure both work. + * + * @throws Exception + */ + public void testShouldMapWriteRolesToWorkspacesWhenSpecified() throws Exception { + Credentials creds = new SimpleCredentials("defaultonly", "defaultonly".toCharArray()); + session = helper.getRepository().login(creds); + + testRead(session); testWrite(session); session.logout(); Index: dna-jcr/src/test/java/org/jboss/dna/jcr/JcrTckTest.java =================================================================== --- dna-jcr/src/test/java/org/jboss/dna/jcr/JcrTckTest.java (revision 1125) +++ dna-jcr/src/test/java/org/jboss/dna/jcr/JcrTckTest.java (working copy) @@ -107,6 +107,23 @@ } /** + * Wrapper for read-only tests + * + * @return a new instance of {@link JCRTestSuite}. + */ + public static Test readOnlySuite() { + // Uncomment this to execute all tests + // return new JCRTestSuite(); + + // Or uncomment the following lines to execute the different sets/suites of tests ... + TestSuite suite = new TestSuite("JCR 1.0 API tests"); + + suite.addTest(new LevelOneFeatureTests()); + + return suite; + } + + /** * Test suite that includes the Level 1 JCR TCK API tests from the Jackrabbit project. */ private static class LevelOneFeatureTests extends TestSuite { Index: dna-jcr/src/test/resources/security/tck_roles.properties =================================================================== --- dna-jcr/src/test/resources/security/tck_roles.properties (revision 1125) +++ dna-jcr/src/test/resources/security/tck_roles.properties (working copy) @@ -2,6 +2,6 @@ superuser=admin readwrite=readwrite readonly=readonly -# default workspace name is the empty string -defaultonly=readwrite.Store.default,readonly.Store.otherWorkspace +# defaultWorkspace is the default workspace name for the filesystem TCK test +defaultonly=readwrite.Store.default,readonly.Store.otherWorkspace,readwrite.Store.defaultWorkspace noaccess=readonly.Store.otherWorkspace Index: extensions/dna-connector-filesystem/src/main/java/org/jboss/dna/connector/filesystem/FileSystemConnection.java =================================================================== --- extensions/dna-connector-filesystem/src/main/java/org/jboss/dna/connector/filesystem/FileSystemConnection.java (revision 1125) +++ extensions/dna-connector-filesystem/src/main/java/org/jboss/dna/connector/filesystem/FileSystemConnection.java (working copy) @@ -25,7 +25,8 @@ import java.io.File; import java.io.FilenameFilter; -import java.util.Set; +import java.util.Map; +import java.util.UUID; import java.util.concurrent.TimeUnit; import javax.transaction.xa.XAResource; import org.jboss.dna.graph.ExecutionContext; @@ -44,28 +45,35 @@ public class FileSystemConnection implements RepositoryConnection { private final String sourceName; - private final File defaultWorkspace; + private final String defaultWorkspaceName; private final CachePolicy cachePolicy; - private final Set availableWorkspaceNames; + private final Map availableWorkspaces; private final boolean creatingWorkspacesAllowed; private final FilenameFilter filenameFilter; + private final UUID rootNodeUuid; + private final String workspaceRootPath; private final boolean updatesAllowed; FileSystemConnection( String sourceName, - File defaultWorkspace, - Set availableWorkspaceNames, + String defaultWorkspaceName, + Map availableWorkspaces, boolean creatingWorkspacesAllowed, CachePolicy cachePolicy, + UUID rootNodeUuid, + String workspaceRootPath, FilenameFilter filenameFilter, boolean updatesAllowed ) { assert sourceName != null; assert sourceName.trim().length() != 0; - assert availableWorkspaceNames != null; + assert availableWorkspaces != null; + assert rootNodeUuid != null; this.sourceName = sourceName; - this.defaultWorkspace = defaultWorkspace; - this.availableWorkspaceNames = availableWorkspaceNames; + this.defaultWorkspaceName = defaultWorkspaceName; + this.availableWorkspaces = availableWorkspaces; this.creatingWorkspacesAllowed = creatingWorkspacesAllowed; this.cachePolicy = cachePolicy; + this.rootNodeUuid = rootNodeUuid; + this.workspaceRootPath = workspaceRootPath; this.filenameFilter = filenameFilter; this.updatesAllowed = updatesAllowed; } @@ -115,8 +123,9 @@ */ public void execute( ExecutionContext context, Request request ) throws RepositorySourceException { - RequestProcessor proc = new FileSystemRequestProcessor(sourceName, defaultWorkspace, availableWorkspaceNames, - creatingWorkspacesAllowed, context, filenameFilter, updatesAllowed); + RequestProcessor proc = new FileSystemRequestProcessor(sourceName, defaultWorkspaceName, availableWorkspaces, + creatingWorkspacesAllowed, rootNodeUuid, workspaceRootPath, + context, filenameFilter, updatesAllowed); try { proc.process(request); } finally { Index: extensions/dna-connector-filesystem/src/main/java/org/jboss/dna/connector/filesystem/FileSystemI18n.java =================================================================== --- extensions/dna-connector-filesystem/src/main/java/org/jboss/dna/connector/filesystem/FileSystemI18n.java (revision 1125) +++ extensions/dna-connector-filesystem/src/main/java/org/jboss/dna/connector/filesystem/FileSystemI18n.java (working copy) @@ -40,6 +40,9 @@ public static I18n pathForPredefinedWorkspaceDoesNotExist; public static I18n pathForPredefinedWorkspaceIsNotDirectory; public static I18n pathForPredefinedWorkspaceCannotBeRead; + public static I18n pathForWorkspaceRootDoesNotExist; + public static I18n pathForWorkspaceRootIsNotDirectory; + public static I18n pathForWorkspaceRootCannotBeRead; public static I18n propertyIsRequired; public static I18n locationInRequestMustHavePath; public static I18n sameNameSiblingsAreNotAllowed; Index: extensions/dna-connector-filesystem/src/main/java/org/jboss/dna/connector/filesystem/FileSystemRequestProcessor.java =================================================================== --- extensions/dna-connector-filesystem/src/main/java/org/jboss/dna/connector/filesystem/FileSystemRequestProcessor.java (revision 1125) +++ extensions/dna-connector-filesystem/src/main/java/org/jboss/dna/connector/filesystem/FileSystemRequestProcessor.java (working copy) @@ -31,8 +31,11 @@ import java.io.InputStream; import java.util.Collections; import java.util.HashSet; +import java.util.Map; import java.util.Set; +import java.util.UUID; import org.jboss.dna.common.i18n.I18n; +import org.jboss.dna.graph.DnaLexicon; import org.jboss.dna.graph.ExecutionContext; import org.jboss.dna.graph.JcrLexicon; import org.jboss.dna.graph.JcrNtLexicon; @@ -77,43 +80,68 @@ private static final String DEFAULT_MIME_TYPE = "application/octet"; private final String defaultNamespaceUri; - private final Set availableWorkspaceNames; + private final Map availableWorkspaces; private final boolean creatingWorkspacesAllowed; - private final File defaultWorkspace; + private final String defaultWorkspaceName; + private final File workspaceRootPath; private final FilenameFilter filenameFilter; private final boolean updatesAllowed; private final MimeTypeDetector mimeTypeDetector; + private final UUID rootNodeUuid; /** * @param sourceName - * @param defaultWorkspace - * @param availableWorkspaceNames + * @param defaultWorkspaceName + * @param availableWorkspaces * @param creatingWorkspacesAllowed * @param context + * @param rootNodeUuid the UUID for the root node in this workspace; may be null. If not specified, a random UUID will be + * generated each time that the repository is started. + * @param workspaceRootPath the path to the workspace root directory; may be null. If specified, all workspace names will be + * treated as relative paths from this directory. * @param filenameFilter the filename filter to use to restrict the allowable nodes, or null if all files/directories are to * be exposed by this connector * @param updatesAllowed true if this connector supports updating the file system, or false if the connector is readonly */ protected FileSystemRequestProcessor( String sourceName, - File defaultWorkspace, - Set availableWorkspaceNames, + String defaultWorkspaceName, + Map availableWorkspaces, boolean creatingWorkspacesAllowed, + UUID rootNodeUuid, + String workspaceRootPath, ExecutionContext context, FilenameFilter filenameFilter, boolean updatesAllowed ) { super(sourceName, context, null); - assert defaultWorkspace != null; - assert defaultWorkspace.exists(); - assert defaultWorkspace.canRead(); - assert defaultWorkspace.isDirectory(); - assert availableWorkspaceNames != null; - this.availableWorkspaceNames = availableWorkspaceNames; + assert defaultWorkspaceName != null; + assert availableWorkspaces != null; + assert rootNodeUuid != null; + this.availableWorkspaces = availableWorkspaces; this.creatingWorkspacesAllowed = creatingWorkspacesAllowed; this.defaultNamespaceUri = getExecutionContext().getNamespaceRegistry().getDefaultNamespaceUri(); + this.rootNodeUuid = rootNodeUuid; this.filenameFilter = filenameFilter; - this.defaultWorkspace = defaultWorkspace; + this.defaultWorkspaceName = defaultWorkspaceName; this.updatesAllowed = updatesAllowed; this.mimeTypeDetector = context.getMimeTypeDetector(); + + if (workspaceRootPath != null) { + this.workspaceRootPath = new File(workspaceRootPath); + if (!this.workspaceRootPath.exists()) { + throw new IllegalStateException(FileSystemI18n.pathForWorkspaceRootDoesNotExist.text(workspaceRootPath, + sourceName)); + } + if (!this.workspaceRootPath.isDirectory()) { + throw new IllegalStateException(FileSystemI18n.pathForWorkspaceRootIsNotDirectory.text(workspaceRootPath, + sourceName)); + } + if (!this.workspaceRootPath.canRead()) { + throw new IllegalStateException(FileSystemI18n.pathForWorkspaceRootCannotBeRead.text(workspaceRootPath, + sourceName)); + } + } else { + this.workspaceRootPath = null; + } } /** @@ -134,6 +162,11 @@ // Find the existing file for the parent ... Location location = request.of(); Path parentPath = getPathFor(location, request); + + if (parentPath.isRoot()) { + if (!location.hasPath()) location = location.with(parentPath); + } + File parent = getExistingFileFor(workspaceRoot, parentPath, location, request); if (parent == null) { // An error was set on the request @@ -180,13 +213,20 @@ return; } + PropertyFactory factory = getExecutionContext().getPropertyFactory(); + // Find the existing file for the parent ... Location location = request.at(); Path path = getPathFor(location, request); if (path.isRoot()) { - // There are no properties on the root ... + // Root nodes can be requested by UUID, path, or both + if (!location.hasPath()) location = location.with(path); + if (location.getUuid() == null) location = location.with(rootNodeUuid); + + request.addProperty(factory.create(JcrLexicon.PRIMARY_TYPE, DnaLexicon.ROOT)); request.setActualLocationOfNode(location); setCacheableInfo(request); + return; } @@ -197,7 +237,6 @@ return; } // Generate the properties for this File object ... - PropertyFactory factory = getExecutionContext().getPropertyFactory(); DateTimeFactory dateFactory = getExecutionContext().getValueFactories().getDateFactory(); // Note that we don't have 'created' timestamps, just last modified, so we'll have to use them if (file.isDirectory()) { @@ -209,7 +248,9 @@ // It is a file, but ... if (path.getLastSegment().getName().equals(JcrLexicon.CONTENT)) { // The request is to get properties of the "jcr:content" child node ... - request.addProperty(factory.create(JcrLexicon.PRIMARY_TYPE, JcrNtLexicon.RESOURCE)); + // ... use the dna:resource node type. This is the same as nt:resource, but is not referenceable + // since we cannot assume that we control all access to this file and can track its movements + request.addProperty(factory.create(JcrLexicon.PRIMARY_TYPE, DnaLexicon.RESOURCE)); request.addProperty(factory.create(JcrLexicon.LAST_MODIFIED, dateFactory.create(file.lastModified()))); // Don't really know the encoding, either ... // request.addProperty(factory.create(JcrLexicon.ENCODED, stringFactory.create("UTF-8"))); @@ -330,23 +371,19 @@ public void process( VerifyWorkspaceRequest request ) { // If the request contains a null name, then we use the default ... String workspaceName = request.workspaceName(); - if (workspaceName == null) workspaceName = getCanonicalWorkspaceName(defaultWorkspace); + if (workspaceName == null) workspaceName = defaultWorkspaceName; if (!this.creatingWorkspacesAllowed) { // Then the workspace name must be one of the available names ... + boolean found = false; - for (String available : this.availableWorkspaceNames) { + for (String available : this.availableWorkspaces.keySet()) { if (workspaceName.equals(available)) { found = true; break; } - File directory = new File(available); - if (directory.exists() && directory.isDirectory() && directory.canRead() - && getCanonicalWorkspaceName(directory).equals(workspaceName)) { - found = true; - break; - } } + if (!found) { request.setError(new InvalidWorkspaceException(FileSystemI18n.workspaceDoesNotExist.text(workspaceName))); return; @@ -354,9 +391,9 @@ // We know it is an available workspace, so just continue ... } // Verify that there is a directory at the path given by the workspace name ... - File directory = new File(workspaceName); + File directory = availableWorkspaces.get(workspaceName); if (directory.exists() && directory.isDirectory() && directory.canRead()) { - request.setActualWorkspaceName(getCanonicalWorkspaceName(directory)); + request.setActualWorkspaceName(workspaceName); request.setActualRootLocation(Location.create(pathFactory().createRootPath())); } else { request.setError(new InvalidWorkspaceException(FileSystemI18n.workspaceDoesNotExist.text(workspaceName))); @@ -372,12 +409,13 @@ public void process( GetWorkspacesRequest request ) { // Return the set of available workspace names, even if new workspaces can be created ... Set names = new HashSet(); - for (String name : this.availableWorkspaceNames) { - File directory = new File(name); + for (Map.Entry entry : this.availableWorkspaces.entrySet()) { + File directory = entry.getValue(); if (directory.exists() && directory.isDirectory() && directory.canRead()) { - names.add(getCanonicalWorkspaceName(directory)); + names.add(entry.getKey()); } } + request.setAvailableWorkspaceNames(Collections.unmodifiableSet(names)); } @@ -389,6 +427,12 @@ */ protected String getCanonicalWorkspaceName( File directory ) { try { + if (this.workspaceRootPath != null) { + String directoryCanonicalPath = directory.getCanonicalPath(); + String rootCanonicalPath = workspaceRootPath.getCanonicalPath(); + assert directoryCanonicalPath.startsWith(rootCanonicalPath); + return directoryCanonicalPath.substring(rootCanonicalPath.length() + 1); + } return directory.getCanonicalPath(); } catch (IOException e) { return directory.getAbsolutePath(); @@ -424,7 +468,7 @@ if (directory.exists() && directory.isDirectory() && directory.canRead()) { request.setActualWorkspaceName(getCanonicalWorkspaceName(directory)); request.setActualRootLocation(Location.create(pathFactory().createRootPath())); - availableWorkspaceNames.add(workspaceName); + availableWorkspaces.put(workspaceName, directory); recordChange(request); } else { request.setError(new InvalidWorkspaceException(FileSystemI18n.workspaceDoesNotExist.text(workspaceName))); @@ -444,7 +488,7 @@ request.setError(new InvalidRequestException(msg)); } // This doesn't delete the file/directory; rather, it just remove the workspace from the available set ... - if (!this.availableWorkspaceNames.remove(workspaceName)) { + if (this.availableWorkspaces.remove(workspaceName) == null) { request.setError(new InvalidWorkspaceException(FileSystemI18n.workspaceDoesNotExist.text(workspaceName))); } else { request.setActualRootLocation(Location.create(pathFactory().createRootPath())); @@ -470,6 +514,11 @@ protected Path getPathFor( Location location, Request request ) { Path path = location.getPath(); + + if (location.getUuid() != null && rootNodeUuid.equals(location.getUuid())) { + return pathFactory().createRootPath(); + } + if (path == null) { I18n msg = FileSystemI18n.locationInRequestMustHavePath; throw new RepositorySourceException(getSourceName(), msg.text(getSourceName(), request)); @@ -478,13 +527,11 @@ } protected File getWorkspaceDirectory( String workspaceName ) { - File workspace = defaultWorkspace; - if (workspaceName != null) { - File directory = new File(workspaceName); - if (directory.exists() && directory.isDirectory() && directory.canRead()) workspace = directory; - else return null; - } - return workspace; + if (workspaceName == null) workspaceName = defaultWorkspaceName; + + File directory = this.workspaceRootPath == null ? new File(workspaceName) : new File(workspaceRootPath, workspaceName); + if (directory.exists() && directory.isDirectory() && directory.canRead()) return directory; + return null; } /** Index: extensions/dna-connector-filesystem/src/main/java/org/jboss/dna/connector/filesystem/FileSystemSource.java =================================================================== --- extensions/dna-connector-filesystem/src/main/java/org/jboss/dna/connector/filesystem/FileSystemSource.java (revision 1125) +++ extensions/dna-connector-filesystem/src/main/java/org/jboss/dna/connector/filesystem/FileSystemSource.java (working copy) @@ -31,7 +31,8 @@ import java.util.Hashtable; import java.util.List; import java.util.Map; -import java.util.concurrent.CopyOnWriteArraySet; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; import javax.naming.Context; import javax.naming.RefAddr; import javax.naming.Reference; @@ -40,6 +41,7 @@ import net.jcip.annotations.Immutable; import net.jcip.annotations.ThreadSafe; import org.jboss.dna.common.i18n.I18n; +import org.jboss.dna.common.util.CheckArg; import org.jboss.dna.common.util.Logger; import org.jboss.dna.common.util.StringUtil; import org.jboss.dna.graph.cache.CachePolicy; @@ -64,10 +66,16 @@ */ private static final long serialVersionUID = 1L; + /** + * The initial {@link #getDefaultWorkspaceName() name of the default workspace} is "{@value} ", unless otherwise specified. + */ + public static final String DEFAULT_NAME_OF_DEFAULT_WORKSPACE = "default"; + protected static final String SOURCE_NAME = "sourceName"; protected static final String CACHE_TIME_TO_LIVE_IN_MILLISECONDS = "cacheTimeToLiveInMilliseconds"; protected static final String RETRY_LIMIT = "retryLimit"; protected static final String DEFAULT_WORKSPACE = "defaultWorkspace"; + protected static final String WORKSPACE_ROOT = "workspaceRootPath"; protected static final String PREDEFINED_WORKSPACE_NAMES = "predefinedWorkspaceNames"; protected static final String ALLOW_CREATING_WORKSPACES = "allowCreatingWorkspaces"; @@ -84,7 +92,7 @@ */ protected static final boolean DEFAULT_SUPPORTS_CREATING_WORKSPACES = true; /** - * This source does not support udpates by default, but each instance may be configured to be read-only or updateable}. + * This source does not support updates by default, but each instance may be configured to be read-only or updateable}. */ public static final boolean DEFAULT_SUPPORTS_UPDATES = false; @@ -99,8 +107,10 @@ private volatile String name; private volatile int retryLimit = DEFAULT_RETRY_LIMIT; private volatile int cacheTimeToLiveInMilliseconds = DEFAULT_CACHE_TIME_TO_LIVE_IN_SECONDS * 1000; - private volatile String defaultWorkspace; + private volatile String defaultWorkspaceName = DEFAULT_NAME_OF_DEFAULT_WORKSPACE; + private volatile String workspaceRootPath; private volatile String[] predefinedWorkspaces = new String[] {}; + private volatile UUID rootNodeUuid = UUID.randomUUID(); private volatile RepositorySourceCapabilities capabilities = new RepositorySourceCapabilities( SUPPORTS_SAME_NAME_SIBLINGS, DEFAULT_SUPPORTS_UPDATES, @@ -108,7 +118,7 @@ DEFAULT_SUPPORTS_CREATING_WORKSPACES, SUPPORTS_REFERENCES); private transient CachePolicy cachePolicy; - private transient CopyOnWriteArraySet availableWorkspaceNames; + private transient Map availableWorkspaces; /** * @@ -170,30 +180,64 @@ // } /** - * Get the file system path to the existing directory that should be used for the default workspace. If the default is - * specified as a null String or is not a valid and resolvable path, this source will consider the default to be the current - * working directory of this virtual machine, as defined by the new File("."). + * Get the relative root directory for the workspaces. If this property is set, workspaces can be given as relative paths from + * this directory and all workspace paths must be ancestors of this path. * - * @return the file system path to the directory representing the default workspace, or null if the default should be the - * current working directory + * @return the root directory for workspaces */ - public String getDirectoryForDefaultWorkspace() { - return defaultWorkspace; + public String getWorkspaceRootPath() { + return workspaceRootPath; } /** - * Set the file system path to the existing directory that should be used for the default workspace. If the default is - * specified as a null String or is not a valid and resolvable path, this source will consider the default to be the current - * working directory of this virtual machine, as defined by the new File("."). + * Sets the relative root directory for workspaces * - * @param pathToDirectoryForDefaultWorkspace the valid and resolvable file system path to the directory representing the - * default workspace, or null if the current working directory should be used as the default workspace + * @param workspaceRootPath the relative root directory for workspaces. If this value is non-null, all workspace paths will be + * treated as paths relative to this directory */ - public synchronized void setDirectoryForDefaultWorkspace( String pathToDirectoryForDefaultWorkspace ) { - this.defaultWorkspace = pathToDirectoryForDefaultWorkspace; + public synchronized void setWorkspaceRootPath( String workspaceRootPath ) { + this.workspaceRootPath = workspaceRootPath; } /** + * Get the UUID that is used for the root node of each workspace + * + * @return the UUID that is used for the root node of each workspace + */ + public UUID getRootNodeUuid() { + return rootNodeUuid; + } + + /** + * Set the {@code jcr:uuid} property of the root node in each workspace to the given value. + * + * @param rootNodeUuid the UUID to use for the root nodes of all workspaces + */ + public synchronized void setRootNodeUuid( String rootNodeUuid ) { + CheckArg.isNotNull(rootNodeUuid, "rootNodeUuid"); + this.rootNodeUuid = UUID.fromString(rootNodeUuid); + } + + /** + * Get the name of the default workspace. + * + * @return the name of the workspace that should be used by default; never null + */ + public String getDefaultWorkspaceName() { + return defaultWorkspaceName; + } + + /** + * Set the name of the workspace that should be used when clients don't specify a workspace. + * + * @param nameOfDefaultWorkspace the name of the workspace that should be used by default, or null if the + * {@link #DEFAULT_NAME_OF_DEFAULT_WORKSPACE default name} should be used + */ + public synchronized void setDefaultWorkspaceName( String nameOfDefaultWorkspace ) { + this.defaultWorkspaceName = nameOfDefaultWorkspace != null ? nameOfDefaultWorkspace : DEFAULT_NAME_OF_DEFAULT_WORKSPACE; + } + + /** * Gets the names of the workspaces that are available when this source is created. Each workspace name corresponds to a path * to a directory on the file system. * @@ -310,7 +354,7 @@ } ref.add(new StringRefAddr(CACHE_TIME_TO_LIVE_IN_MILLISECONDS, Integer.toString(getCacheTimeToLiveInMilliseconds()))); ref.add(new StringRefAddr(RETRY_LIMIT, Integer.toString(getRetryLimit()))); - ref.add(new StringRefAddr(DEFAULT_WORKSPACE, getDirectoryForDefaultWorkspace())); + ref.add(new StringRefAddr(DEFAULT_WORKSPACE, getDefaultWorkspaceName())); ref.add(new StringRefAddr(ALLOW_CREATING_WORKSPACES, Boolean.toString(isCreatingWorkspacesAllowed()))); String[] workspaceNames = getPredefinedWorkspaceNames(); if (workspaceNames != null && workspaceNames.length != 0) { @@ -356,7 +400,7 @@ if (sourceName != null) source.setName(sourceName); if (cacheTtlInMillis != null) source.setCacheTimeToLiveInMilliseconds(Integer.parseInt(cacheTtlInMillis)); if (retryLimit != null) source.setRetryLimit(Integer.parseInt(retryLimit)); - if (defaultWorkspace != null) source.setDirectoryForDefaultWorkspace(defaultWorkspace); + if (defaultWorkspace != null) source.setDefaultWorkspaceName(defaultWorkspace); if (createWorkspaces != null) source.setCreatingWorkspacesAllowed(Boolean.parseBoolean(createWorkspaces)); if (workspaceNames != null && workspaceNames.length != 0) source.setPredefinedWorkspaceNames(workspaceNames); return source; @@ -364,6 +408,18 @@ return null; } + private String pathFor( String workspaceName ) { + String path = workspaceName; + if (this.workspaceRootPath != null) { + if (this.workspaceRootPath.charAt(workspaceRootPath.length() - 1) == File.separatorChar) { + path = this.workspaceRootPath + workspaceName; + } + path = this.workspaceRootPath + File.separatorChar + workspaceName; + } + + return path; + } + /** * {@inheritDoc} * @@ -376,54 +432,42 @@ throw new RepositorySourceException(getName(), msg.text("name")); } - boolean reportWarnings = false; - if (this.availableWorkspaceNames == null) { + if (this.availableWorkspaces == null) { // Set up the predefined workspace names ... - this.availableWorkspaceNames = new CopyOnWriteArraySet(); + this.availableWorkspaces = new ConcurrentHashMap(); for (String predefined : this.predefinedWorkspaces) { - this.availableWorkspaceNames.add(predefined); - } - - // Report the warnings for non-existant predefined workspaces - reportWarnings = true; - for (String path : this.availableWorkspaceNames) { // Look for the file at this path ... - File file = new File(path); + File file = new File(pathFor(predefined)); if (!file.exists()) { - Logger.getLogger(getClass()).warn(FileSystemI18n.pathForPredefinedWorkspaceDoesNotExist, path, name); + Logger.getLogger(getClass()).warn(FileSystemI18n.pathForPredefinedWorkspaceDoesNotExist, predefined, name); } else if (!file.isDirectory()) { - Logger.getLogger(getClass()).warn(FileSystemI18n.pathForPredefinedWorkspaceIsNotDirectory, path, name); + Logger.getLogger(getClass()).warn(FileSystemI18n.pathForPredefinedWorkspaceIsNotDirectory, predefined, name); } else if (!file.canRead()) { - Logger.getLogger(getClass()).warn(FileSystemI18n.pathForPredefinedWorkspaceCannotBeRead, path, name); + Logger.getLogger(getClass()).warn(FileSystemI18n.pathForPredefinedWorkspaceCannotBeRead, predefined, name); } + + + this.availableWorkspaces.put(predefined, file); } } - FilenameFilter filenameFilter = null; - boolean supportsUpdates = getSupportsUpdates(); - File defaultWorkspace = new File("."); - String path = getDirectoryForDefaultWorkspace(); - if (path != null) { + if (defaultWorkspaceName != null) { // Look for the file at this path ... - File file = new File(path); - I18n warning = null; + File file = new File(pathFor(defaultWorkspaceName)); if (!file.exists()) { - warning = FileSystemI18n.pathForDefaultWorkspaceDoesNotExist; + Logger.getLogger(getClass()).warn(FileSystemI18n.pathForPredefinedWorkspaceDoesNotExist, defaultWorkspaceName, name); } else if (!file.isDirectory()) { - warning = FileSystemI18n.pathForDefaultWorkspaceIsNotDirectory; + Logger.getLogger(getClass()).warn(FileSystemI18n.pathForPredefinedWorkspaceIsNotDirectory, defaultWorkspaceName, name); } else if (!file.canRead()) { - warning = FileSystemI18n.pathForDefaultWorkspaceCannotBeRead; - } else { - // good to use! - defaultWorkspace = file; + Logger.getLogger(getClass()).warn(FileSystemI18n.pathForPredefinedWorkspaceCannotBeRead, defaultWorkspaceName, name); } - if (reportWarnings && warning != null) { - Logger.getLogger(getClass()).warn(warning, path, name); - } + + + this.availableWorkspaces.put(defaultWorkspaceName, file); } - this.availableWorkspaceNames.add(defaultWorkspace.getPath()); - return new FileSystemConnection(name, defaultWorkspace, availableWorkspaceNames, isCreatingWorkspacesAllowed(), - cachePolicy, filenameFilter, supportsUpdates); + + return new FileSystemConnection(name, defaultWorkspaceName, availableWorkspaces, isCreatingWorkspacesAllowed(), + cachePolicy, rootNodeUuid, workspaceRootPath, (FilenameFilter) null, getSupportsUpdates()); } @Immutable Index: extensions/dna-connector-filesystem/src/main/resources/org/jboss/dna/connector/filesystem/FileSystemI18n.properties =================================================================== --- extensions/dna-connector-filesystem/src/main/resources/org/jboss/dna/connector/filesystem/FileSystemI18n.properties (revision 1125) +++ extensions/dna-connector-filesystem/src/main/resources/org/jboss/dna/connector/filesystem/FileSystemI18n.properties (working copy) @@ -29,6 +29,9 @@ pathForPredefinedWorkspaceDoesNotExist = The path "{0}" for the predefined workspace for the file system source "{1}" does not represent an existing directory pathForPredefinedWorkspaceIsNotDirectory = The path "{0}" for the predefined workspace for the file system source "{1}" is actually a path to an existing file pathForPredefinedWorkspaceCannotBeRead = The path "{0}" for the predefined workspace for the file system source "{1}" cannot be read +pathForWorkspaceRootDoesNotExist = The path "{0}" for the predefined workspace for the file system source "{1}" does not represent an existing directory +pathForWorkspaceRootIsNotDirectory = The path "{0}" for the predefined workspace for the file system source "{1}" is actually a path to an existing file +pathForWorkspaceRootCannotBeRead = The path "{0}" for the predefined workspace for the file system source "{1}" cannot be read propertyIsRequired = The {0} property is required but has no value locationInRequestMustHavePath = {0} requires a path in the request: {1} sameNameSiblingsAreNotAllowed = {0} does not allow same name siblings on nodes: {1} Index: extensions/dna-connector-filesystem/src/test/java/org/jboss/dna/connector/filesystem/FileSystemConnectorCreateWorkspacesTest.java =================================================================== --- extensions/dna-connector-filesystem/src/test/java/org/jboss/dna/connector/filesystem/FileSystemConnectorCreateWorkspacesTest.java (revision 1125) +++ extensions/dna-connector-filesystem/src/test/java/org/jboss/dna/connector/filesystem/FileSystemConnectorCreateWorkspacesTest.java (working copy) @@ -25,7 +25,6 @@ import static org.hamcrest.core.Is.is; import static org.junit.Assert.assertThat; -import java.io.File; import java.io.IOException; import java.util.HashSet; import java.util.Set; @@ -56,7 +55,7 @@ FileSystemSource source = new FileSystemSource(); source.setName("Test Repository"); source.setPredefinedWorkspaceNames(predefinedWorkspaceNames); - source.setDirectoryForDefaultWorkspace(predefinedWorkspaceNames[0]); + source.setDefaultWorkspaceName(predefinedWorkspaceNames[0]); source.setCreatingWorkspacesAllowed(true); return source; @@ -101,11 +100,8 @@ workspaceNames.add(workspace.getName()); } // The actual names should be the absolute paths to the directories representing the root ... - String absolutePathToRepositories = new File("./src/test/resources/repositories/").getCanonicalPath(); + String absolutePathToRepositories = "./src/test/resources/repositories/"; - // getCanonicalPath strips the trailing separator character, so we need to re-added it for each case - absolutePathToRepositories += File.separatorChar; - assertThat(workspaceNames.remove(absolutePathToRepositories + "airplanes"), is(true)); assertThat(workspaceNames.remove(absolutePathToRepositories + "cars"), is(true)); assertThat(workspaceNames.isEmpty(), is(true)); Index: extensions/dna-connector-filesystem/src/test/java/org/jboss/dna/connector/filesystem/FileSystemConnectorNoCreateWorkspaceTest.java =================================================================== --- extensions/dna-connector-filesystem/src/test/java/org/jboss/dna/connector/filesystem/FileSystemConnectorNoCreateWorkspaceTest.java (revision 1125) +++ extensions/dna-connector-filesystem/src/test/java/org/jboss/dna/connector/filesystem/FileSystemConnectorNoCreateWorkspaceTest.java (working copy) @@ -49,7 +49,7 @@ FileSystemSource source = new FileSystemSource(); source.setName("Test Repository"); source.setPredefinedWorkspaceNames(predefinedWorkspaceNames); - source.setDirectoryForDefaultWorkspace(predefinedWorkspaceNames[0]); + source.setDefaultWorkspaceName(predefinedWorkspaceNames[0]); source.setCreatingWorkspacesAllowed(false); return source; Index: extensions/dna-connector-filesystem/src/test/java/org/jboss/dna/connector/filesystem/FileSystemConnectorNotWritableTest.java =================================================================== --- extensions/dna-connector-filesystem/src/test/java/org/jboss/dna/connector/filesystem/FileSystemConnectorNotWritableTest.java (revision 1125) +++ extensions/dna-connector-filesystem/src/test/java/org/jboss/dna/connector/filesystem/FileSystemConnectorNotWritableTest.java (working copy) @@ -46,7 +46,7 @@ FileSystemSource source = new FileSystemSource(); source.setName("Test Repository"); source.setPredefinedWorkspaceNames(predefinedWorkspaceNames); - source.setDirectoryForDefaultWorkspace(predefinedWorkspaceNames[0]); + source.setDefaultWorkspaceName(predefinedWorkspaceNames[0]); source.setCreatingWorkspacesAllowed(false); return source; Index: extensions/dna-connector-filesystem/src/test/java/org/jboss/dna/connector/filesystem/FileSystemConnectorReadableTest.java =================================================================== --- extensions/dna-connector-filesystem/src/test/java/org/jboss/dna/connector/filesystem/FileSystemConnectorReadableTest.java (revision 1125) +++ extensions/dna-connector-filesystem/src/test/java/org/jboss/dna/connector/filesystem/FileSystemConnectorReadableTest.java (working copy) @@ -26,7 +26,6 @@ import static org.hamcrest.core.Is.is; import static org.hamcrest.core.IsNull.notNullValue; import static org.junit.Assert.assertThat; -import java.io.File; import java.util.List; import org.jboss.dna.graph.Graph; import org.jboss.dna.graph.JcrLexicon; @@ -50,13 +49,13 @@ @Override protected RepositorySource setUpSource() { // Set the connection properties to be use the content of "./src/test/resources/repositories" as a repository ... - String path = new File(".").getAbsolutePath() + "/src/test/resources/repositories/"; + String path = "./src/test/resources/repositories/"; String[] predefinedWorkspaceNames = new String[] {path + "airplanes", path + "cars"}; FileSystemSource source = new FileSystemSource(); source.setName("Test Repository"); source.setPredefinedWorkspaceNames(predefinedWorkspaceNames); - source.setDirectoryForDefaultWorkspace(predefinedWorkspaceNames[0]); - source.setCreatingWorkspacesAllowed(false); + source.setDefaultWorkspaceName(predefinedWorkspaceNames[0]); + source.setCreatingWorkspacesAllowed(true); return source; }