protected RepositoryBuilder(
     ReturnType returnObject, Graph.Batch batch, Path path, Name... names) {
   super(returnObject, batch, path, names);
   // Load the current options ...
   try {
     Path optionsPath =
         context.getValueFactories().getPathFactory().create(path, ModeShapeLexicon.OPTIONS);
     Subgraph options = batch.getGraph().getSubgraphOfDepth(2).at(optionsPath);
     for (Location optionChild : options.getRoot().getChildren()) {
       Node option = options.getNode(optionChild);
       Property property = option.getProperty(ModeShapeLexicon.VALUE);
       if (property != null && property.isEmpty()) {
         try {
           Option key =
               Option.findOption(
                   optionChild
                       .getPath()
                       .getLastSegment()
                       .getString(context.getNamespaceRegistry()));
           String value =
               context.getValueFactories().getStringFactory().create(property.getFirstValue());
           optionValues.put(key, value);
         } catch (IllegalArgumentException e) {
           // the key is not valid, so skip it ...
         }
       }
     }
   } catch (PathNotFoundException e) {
     // No current options
   }
 }
Exemple #2
0
  /**
   * {@inheritDoc}
   *
   * @see org.modeshape.repository.ModeShapeEngine#checkConfiguration(org.modeshape.graph.Subgraph)
   */
  @Override
  protected void checkConfiguration(Subgraph configuration) {
    super.checkConfiguration(configuration);

    // Get the list of sources ...
    Set<String> sourceNames = new HashSet<String>();
    for (Location child : configuration.getNode(ModeShapeLexicon.SOURCES)) {
      String name = child.getPath().getLastSegment().getName().getLocalName();
      sourceNames.add(name);
    }
    // Verify all of the repositories reference valid sources ...
    for (Location child : configuration.getNode(ModeShapeLexicon.REPOSITORIES)) {
      String repositoryName = readable(child.getPath().getLastSegment().getName());
      Node repositoryNode = configuration.getNode(child);
      Property property = repositoryNode.getProperty(ModeShapeLexicon.SOURCE_NAME);
      if (property == null) {
        getProblems()
            .addError(JcrI18n.repositoryReferencesNonExistantSource, repositoryName, "null");
      } else {
        String sourceName = string(property.getFirstValue());
        if (!sourceNames.contains(sourceName)) {
          getProblems()
              .addError(JcrI18n.repositoryReferencesNonExistantSource, repositoryName, sourceName);
        }
      }
    }
  }
  @Test
  public void shouldAllowAddingRepositorySourceInstance() {
    UUID rootUuid = UUID.randomUUID();
    CachePolicy cachePolicy = new ImmutableCachePolicy(100);

    // Update the configuration and save it ...
    configuration
        .repositorySource("name")
        .usingClass(InMemoryRepositorySource.class)
        .setRetryLimit(100)
        .setProperty("defaultCachePolicy", cachePolicy)
        .setProperty("defaultWorkspaceName", "default workspace name")
        .setProperty("rootNodeUuid", rootUuid)
        .and()
        .save();

    // Verify that the graph has been updated correctly ...
    ModeShapeConfiguration.ConfigurationDefinition content =
        configuration.getConfigurationDefinition();
    Subgraph subgraph = content.graph().getSubgraphOfDepth(3).at("/");
    assertThat(subgraph.getNode("/mode:sources"), is(notNullValue()));
    assertThat(subgraph.getNode("/mode:sources/name"), is(notNullValue()));
    assertThat(
        subgraph.getNode("/mode:sources/name"), hasProperty(ModeShapeLexicon.RETRY_LIMIT, 100));
    assertThat(
        subgraph.getNode("/mode:sources/name"), hasProperty("defaultCachePolicy", cachePolicy));
    assertThat(
        subgraph.getNode("/mode:sources/name"),
        hasProperty("defaultWorkspaceName", "default workspace name"));
    assertThat(subgraph.getNode("/mode:sources/name"), hasProperty("rootNodeUuid", rootUuid));
  }
  @Test
  public void shouldLoadConfigurationWithCustomAuthenticators() throws Exception {
    File file = new File("src/test/resources/config/configRepositoryWithAuthenticators.xml");
    assertThat(file.exists(), is(true));
    assertThat(file.canRead(), is(true));
    assertThat(file.isFile(), is(true));

    configuration.loadFrom("src/test/resources/config/configRepositoryWithAuthenticators.xml");

    assertThat(configuration.getProblems().isEmpty(), is(true));

    // Verify that the graph has been updated correctly ...
    ModeShapeConfiguration.ConfigurationDefinition content =
        configuration.getConfigurationDefinition();
    Subgraph subgraph = content.graph().getSubgraphOfDepth(6).at("/");

    assertThat(subgraph.getNode("/mode:sources"), is(notNullValue()));
    assertThat(subgraph.getNode("/mode:sources/Stuff"), is(notNullValue()));

    assertThat(
        subgraph.getNode("/mode:repositories").getChildren(), hasChild(segment("My Repository")));
    assertThat(subgraph.getNode("/mode:repositories/My Repository"), is(notNullValue()));
    assertThat(
        subgraph.getNode("/mode:repositories/My Repository"),
        hasProperty(ModeShapeLexicon.SOURCE_NAME, "Stuff"));
    assertThat(
        subgraph.getNode("/mode:repositories/My Repository").getChildren(),
        hasChildren(segment("mode:options"), segment("mode:authenticationProviders")));
    assertThat(
        subgraph.getNode("/mode:repositories/My Repository/mode:options"), is(notNullValue()));
    assertThat(
        subgraph.getNode("/mode:repositories/My Repository/mode:options").getChildren(),
        hasChild(segment("jaasLoginConfigName")));
    assertThat(
        subgraph.getNode("/mode:repositories/My Repository/mode:options/jaasLoginConfigName"),
        is(notNullValue()));
    assertThat(
        subgraph.getNode("/mode:repositories/My Repository/mode:authenticationProviders"),
        is(notNullValue()));
    assertThat(
        subgraph.getNode(
            "/mode:repositories/My Repository/mode:authenticationProviders/CustomProviderA"),
        is(notNullValue()));

    // Initialize PicketBox ...
    JaasTestUtil.initJaas("security/jaas.conf.xml");

    // Create and start the engine ...
    engine = configuration.build();
    engine.start();
    Repository repository = engine.getRepository("My Repository");
    assertThat(repository, is(notNullValue()));

    // Create a session, authenticating using one of the usernames defined by our JAAS policy
    // file(s) ...
    Session session = null;
    try {
      session = repository.login(new SimpleCredentials("superuser", "superuser".toCharArray()));
    } finally {
      if (session != null) session.logout();
    }

    // Create a session, authenticating using a SecurityContextCredentials
    try {
      SecurityContext mockSecurityContext =
          new MockSecurityContext("testuser", Collections.singleton(ModeShapeRoles.READWRITE));
      session = repository.login(new TestSecurityContextCredentials(mockSecurityContext));
    } finally {
      if (session != null) session.logout();
    }
  }
  @Test
  public void shouldAddNodeTypesAndNamespaces() throws Exception {
    File file = new File("src/test/resources/config/configRepository.xml");
    assertThat(file.exists(), is(true));
    assertThat(file.canRead(), is(true));
    assertThat(file.isFile(), is(true));

    configuration.loadFrom("src/test/resources/config/configRepository.xml");
    // Verify that the configration was loaded correctly ...
    assertThat(configuration.repository("Car Repository").getSource(), is("Cars"));
    // ModeShapeConfiguration.ConfigurationDefinition content1 =
    // configuration.getConfigurationDefinition();
    // Subgraph subgraph1 = content1.graph().getSubgraphOfDepth(6).at("/");

    // Load the node types from the CND file, and save the configuration ...
    InputStream nodeTypes = getClass().getResourceAsStream("/tck/tck_test_types.cnd");
    configuration.repository("Car Repository").addNodeTypes(nodeTypes);
    configuration.save();
    // ModeShapeConfiguration.ConfigurationDefinition content2 =
    // configuration.getConfigurationDefinition();
    // Subgraph subgraph2 = content2.graph().getSubgraphOfDepth(6).at("/");

    // Verify there were no problems loading the CND file ...
    assertThat(configuration.getProblems().isEmpty(), is(true));
    assertThat(
        configuration
            .getConfigurationDefinition()
            .getContext()
            .getNamespaceRegistry()
            .isRegisteredNamespaceUri("http://www.modeshape.org/test/1.0"),
        is(true));

    // Verify that the graph has been updated correctly ...
    ModeShapeConfiguration.ConfigurationDefinition content =
        configuration.getConfigurationDefinition();
    Subgraph subgraph = content.graph().getSubgraphOfDepth(6).at("/");

    assertThat(
        subgraph.getNode("/mode:repositories").getChildren(), hasChild(segment("Car Repository")));
    assertThat(subgraph.getNode("/mode:repositories/Car Repository"), is(notNullValue()));
    assertThat(
        subgraph.getNode("/mode:repositories/Car Repository"),
        hasProperty(ModeShapeLexicon.SOURCE_NAME, "Cars"));
    assertThat(
        subgraph.getNode("/mode:repositories/Car Repository").getChildren(),
        hasChild(segment("mode:options")));
    assertThat(
        subgraph.getNode("/mode:repositories/Car Repository/jcr:nodeTypes"), is(notNullValue()));
    // for (Location child : subgraph.getNode("/mode:repositories/Car
    // Repository/mode:nodeTypes").getChildren()) {
    // System.out.println(child.getPath().getLastSegment().getString(context().getNamespaceRegistry()));
    // }
    assertThat(
        subgraph.getNode("/mode:repositories/Car Repository/jcr:nodeTypes").getChildren(),
        hasChildren(
            segment("modetest:noSameNameSibs"),
            segment("modetest:referenceableUnstructured"),
            segment("modetest:nodeWithMandatoryProperty"),
            segment("modetest:nodeWithMandatoryChild"),
            segment("modetest:unorderableUnstructured")));
    assertThat(
        subgraph.getNode("/mode:repositories/Car Repository/mode:namespaces"), is(notNullValue()));

    // Check that the namespace in the CND file was persisted correctly ...
    assertThat(
        subgraph.getNode("/mode:repositories/Car Repository/mode:namespaces").getChildren(),
        hasChild(segment("modetest")));
    assertThat(
        subgraph.getNode("/mode:repositories/Car Repository/mode:namespaces/modetest"),
        hasProperty(ModeShapeLexicon.URI, "http://www.modeshape.org/test/1.0"));

    // Initialize IDTrust and a policy file (which defines the "modeshape-jcr" login config name)
    JaasTestUtil.initJaas("security/jaas.conf.xml");

    // Create and start the engine ...
    engine = configuration.build();
    engine.start();
    Repository repository = engine.getRepository("Car Repository");
    assertThat(repository, is(notNullValue()));

    // Create a session, authenticating using one of the usernames defined by our JAAS policy
    // file(s) ...
    Session session = null;
    try {
      session = repository.login(new SimpleCredentials("superuser", "superuser".toCharArray()));

      // Check that the namespace showed up ...
      assertThat(session.getNamespacePrefix("http://www.modeshape.org/test/1.0"), is("modetest"));

      // Check that some of the node types showed up ...
      NodeTypeManager ntm = session.getWorkspace().getNodeTypeManager();
      assertThat(
          ntm.getNodeType("modetest:noSameNameSibs"), is(notNullValue())); // throws exception
      assertThat(
          ntm.getNodeType("modetest:referenceableUnstructured"),
          is(notNullValue())); // throws exception
      assertThat(
          ntm.getNodeType("modetest:nodeWithMandatoryProperty"),
          is(notNullValue())); // throws exception
      assertThat(
          ntm.getNodeType("modetest:nodeWithMandatoryChild"),
          is(notNullValue())); // throws exception
      assertThat(
          ntm.getNodeType("modetest:unorderableUnstructured"),
          is(notNullValue())); // throws exception
    } finally {
      if (session != null) session.logout();
    }
  }
  @Test
  public void shouldLoadConfigurationFromFilePath() throws Exception {
    File file = new File("src/test/resources/config/configRepository.xml");
    assertThat(file.exists(), is(true));
    assertThat(file.canRead(), is(true));
    assertThat(file.isFile(), is(true));

    configuration.loadFrom("src/test/resources/config/configRepository.xml");

    assertThat(configuration.getProblems().isEmpty(), is(true));

    // Verify that the graph has been updated correctly ...
    ModeShapeConfiguration.ConfigurationDefinition content =
        configuration.getConfigurationDefinition();
    Subgraph subgraph = content.graph().getSubgraphOfDepth(6).at("/");

    assertThat(subgraph.getNode("/mode:sources"), is(notNullValue()));
    assertThat(subgraph.getNode("/mode:sources/Cars"), is(notNullValue()));
    assertThat(
        subgraph.getNode("/mode:sources/Cars"), hasProperty(ModeShapeLexicon.RETRY_LIMIT, "3"));
    assertThat(
        subgraph.getNode("/mode:sources/Cars"),
        hasProperty(ModeShapeLexicon.CLASSNAME, InMemoryRepositorySource.class.getName()));
    assertThat(subgraph.getNode("/mode:sources/Aircraft"), is(notNullValue()));
    assertThat(
        subgraph.getNode("/mode:sources/Aircraft"), hasProperty("defaultWorkspaceName", "default"));
    assertThat(
        subgraph.getNode("/mode:sources/Aircraft"),
        hasProperty(ModeShapeLexicon.CLASSNAME, InMemoryRepositorySource.class.getName()));
    assertThat(subgraph.getNode("/mode:sources/Cache"), is(notNullValue()));
    assertThat(
        subgraph.getNode("/mode:sources/Cache"),
        hasProperty(ModeShapeLexicon.CLASSNAME, InMemoryRepositorySource.class.getName()));

    assertThat(
        subgraph.getNode("/mode:mimeTypeDetectors").getChildren(), hasChild(segment("Detector")));
    assertThat(subgraph.getNode("/mode:mimeTypeDetectors/Detector"), is(notNullValue()));
    assertThat(
        subgraph.getNode("/mode:mimeTypeDetectors/Detector"),
        hasProperty(ModeShapeLexicon.DESCRIPTION, "Standard extension-based MIME type detector"));
    assertThat(
        subgraph.getNode("/mode:mimeTypeDetectors/Detector"),
        hasProperty(ModeShapeLexicon.CLASSNAME, ExtensionBasedMimeTypeDetector.class.getName()));

    assertThat(
        subgraph.getNode("/mode:repositories").getChildren(), hasChild(segment("Car Repository")));
    assertThat(subgraph.getNode("/mode:repositories/Car Repository"), is(notNullValue()));
    assertThat(
        subgraph.getNode("/mode:repositories/Car Repository"),
        hasProperty(ModeShapeLexicon.SOURCE_NAME, "Cars"));
    assertThat(
        subgraph.getNode("/mode:repositories/Car Repository").getChildren(),
        hasChild(segment("mode:options")));
    assertThat(
        subgraph.getNode("/mode:repositories/Car Repository/mode:options"), is(notNullValue()));
    assertThat(
        subgraph.getNode("/mode:repositories/Car Repository/mode:options").getChildren(),
        hasChild(segment("jaasLoginConfigName")));
    assertThat(
        subgraph.getNode("/mode:repositories/Car Repository/mode:options/jaasLoginConfigName"),
        is(notNullValue()));
    assertThat(
        subgraph.getNode(
            "/mode:repositories/Car Repository/mode:descriptors/query.xpath.doc.order"),
        is(notNullValue()));
    assertThat(
        subgraph.getNode("/mode:repositories/Car Repository/mode:descriptors/myDescriptor"),
        is(notNullValue()));

    // Initialize PicketBox ...
    JaasTestUtil.initJaas("security/jaas.conf.xml");

    // Create and start the engine ...
    engine = configuration.build();
    engine.start();
    Repository repository = engine.getRepository("Car Repository");
    assertThat(repository, is(notNullValue()));
    assertThat(repository.getDescriptor("query.xpath.doc.order"), is("false"));
    assertThat(repository.getDescriptor("myDescriptor"), is("foo"));

    // Create a session, authenticating using one of the usernames defined by our JAAS policy
    // file(s) ...
    Session session = null;
    try {
      session = repository.login(new SimpleCredentials("superuser", "superuser".toCharArray()));
    } finally {
      if (session != null) session.logout();
    }
  }
  @SuppressWarnings("deprecation")
  @Test
  public void shouldAllowSpecifyingOptions() throws Exception {
    configuration
        .repositorySource("Source2")
        .usingClass(InMemoryRepositorySource.class.getName())
        .loadedFromClasspath()
        .setDescription("description")
        .and()
        .repository("JCR Repository")
        .setSource("Source2")
        .setOption(Option.JAAS_LOGIN_CONFIG_NAME, "test");

    engine = configuration.build();
    engine.start();

    // Verify that the graph has been updated correctly ...
    Graph config = engine.getGraph(JcrConfiguration.DEFAULT_CONFIGURATION_SOURCE_NAME);
    Subgraph subgraph = config.getSubgraphOfDepth(6).at("/");
    assertThat(subgraph.getNode("/mode:sources"), is(notNullValue()));
    assertThat(subgraph.getNode("/mode:sources/Source2"), is(notNullValue()));
    assertThat(
        subgraph.getNode("/mode:sources/Source2"),
        hasProperty(ModeShapeLexicon.CLASSNAME, InMemoryRepositorySource.class.getName()));
    assertThat(subgraph.getNode("/mode:repositories"), is(notNullValue()));
    assertThat(subgraph.getNode("/mode:repositories/JCR Repository"), is(notNullValue()));
    assertThat(
        subgraph.getNode("/mode:repositories/JCR Repository"),
        hasProperty(ModeShapeLexicon.SOURCE_NAME, "Source2"));
    assertThat(
        subgraph.getNode("/mode:repositories/JCR Repository/mode:options"), is(notNullValue()));
    assertThat(
        subgraph.getNode("/mode:repositories/JCR Repository/mode:options/JAAS_LOGIN_CONFIG_NAME"),
        hasProperty(ModeShapeLexicon.VALUE, "test"));

    JcrRepository repository = engine.getRepository("JCR Repository");

    Map<Option, String> options = new HashMap<Option, String>();
    options.put(Option.JAAS_LOGIN_CONFIG_NAME, "test");
    options.put(Option.PROJECT_NODE_TYPES, DefaultOption.PROJECT_NODE_TYPES);
    options.put(Option.READ_DEPTH, DefaultOption.READ_DEPTH);
    options.put(Option.INDEX_READ_DEPTH, DefaultOption.INDEX_READ_DEPTH);
    options.put(Option.ANONYMOUS_USER_ROLES, DefaultOption.ANONYMOUS_USER_ROLES);
    options.put(
        Option.TABLES_INCLUDE_COLUMNS_FOR_INHERITED_PROPERTIES,
        DefaultOption.TABLES_INCLUDE_COLUMNS_FOR_INHERITED_PROPERTIES);
    options.put(Option.QUERY_EXECUTION_ENABLED, DefaultOption.QUERY_EXECUTION_ENABLED);
    options.put(Option.QUERY_INDEX_DIRECTORY, DefaultOption.QUERY_INDEX_DIRECTORY);
    options.put(
        Option.QUERY_INDEXES_UPDATED_SYNCHRONOUSLY,
        DefaultOption.QUERY_INDEXES_UPDATED_SYNCHRONOUSLY);
    options.put(
        Option.PERFORM_REFERENTIAL_INTEGRITY_CHECKS,
        DefaultOption.PERFORM_REFERENTIAL_INTEGRITY_CHECKS);
    options.put(
        Option.EXPOSE_WORKSPACE_NAMES_IN_DESCRIPTOR,
        DefaultOption.EXPOSE_WORKSPACE_NAMES_IN_DESCRIPTOR);
    options.put(Option.VERSION_HISTORY_STRUCTURE, DefaultOption.VERSION_HISTORY_STRUCTURE);
    options.put(Option.REPOSITORY_JNDI_LOCATION, DefaultOption.REPOSITORY_JNDI_LOCATION);
    options.put(
        Option.USE_ANONYMOUS_ACCESS_ON_FAILED_LOGIN,
        DefaultOption.USE_ANONYMOUS_ACCESS_ON_FAILED_LOGIN);
    options.put(
        Option.REBUILD_QUERY_INDEX_ON_STARTUP, DefaultOption.REBUILD_QUERY_INDEX_ON_STARTUP);
    options.put(
        Option.QUERY_INDEXES_REBUILT_SYNCHRONOUSLY,
        DefaultOption.QUERY_INDEXES_REBUILT_SYNCHRONOUSLY);
    String defaultRemoveDerivedValue = DefaultOption.REMOVE_DERIVED_CONTENT_WITH_ORIGINAL;
    if (engine.getSequencingService().getSequencers().isEmpty()) {
      defaultRemoveDerivedValue = Boolean.FALSE.toString();
    }
    options.put(Option.REMOVE_DERIVED_CONTENT_WITH_ORIGINAL, defaultRemoveDerivedValue);
    options.put(
        Option.USE_SECURITY_CONTEXT_CREDENTIALS, DefaultOption.USE_SECURITY_CONTEXT_CREDENTIALS);
    assertThat(repository.getOptions(), is(options));
  }
Exemple #8
0
  protected JcrRepository doCreateJcrRepository(String repositoryName)
      throws RepositoryException, PathNotFoundException {
    RepositoryConnectionFactory connectionFactory = getRepositoryConnectionFactory();
    Map<String, String> descriptors = new HashMap<String, String>();
    Map<Option, String> options = new HashMap<Option, String>();

    // Read the subgraph that represents the repository ...
    PathFactory pathFactory = getExecutionContext().getValueFactories().getPathFactory();
    Path repositoriesPath =
        pathFactory.create(configuration.getPath(), ModeShapeLexicon.REPOSITORIES);
    Path repositoryPath = pathFactory.create(repositoriesPath, repositoryName);
    Name repoName =
        getExecutionContext().getValueFactories().getNameFactory().create(repositoryName);
    Graph configuration = null;
    Subgraph subgraph = getConfigurationSubgraph(false);

    // Read the options ...
    Path optionsPath =
        pathFactory.createRelativePath(
            ModeShapeLexicon.REPOSITORIES, repoName, ModeShapeLexicon.OPTIONS);
    Node optionsNode = subgraph.getNode(optionsPath);
    if (optionsNode != null) {
      for (Location optionLocation : optionsNode.getChildren()) {
        Node optionNode = subgraph.getNode(optionLocation);
        Path.Segment segment = optionLocation.getPath().getLastSegment();
        Property valueProperty = optionNode.getProperty(ModeShapeLexicon.VALUE);
        if (valueProperty == null) {
          log.warn(JcrI18n.noOptionValueProvided, segment.getName().getLocalName());
          continue;
        }
        Option option = Option.findOption(segment.getName().getLocalName());
        if (option == null) {
          log.warn(JcrI18n.invalidOptionProvided, segment.getName().getLocalName());
          continue;
        }
        options.put(option, valueProperty.getFirstValue().toString());
      }
    }

    // Disable the derived content removal option if not explicitly set and no sequencers ...
    if (!options.containsKey(Option.REMOVE_DERIVED_CONTENT_WITH_ORIGINAL)
        && getSequencingService().getSequencers().isEmpty()) {
      options.put(Option.REMOVE_DERIVED_CONTENT_WITH_ORIGINAL, Boolean.FALSE.toString());
    }

    // Read the descriptors ...
    Path descriptorsPath =
        pathFactory.createRelativePath(
            ModeShapeLexicon.REPOSITORIES, repoName, ModeShapeLexicon.DESCRIPTORS);
    Node descriptorsNode = subgraph.getNode(descriptorsPath);
    if (descriptorsNode != null) {
      for (Location descriptorLocation : descriptorsNode.getChildren()) {
        Node optionNode = subgraph.getNode(descriptorLocation);
        Path.Segment segment = descriptorLocation.getPath().getLastSegment();
        Property valueProperty = optionNode.getProperty(ModeShapeLexicon.VALUE);
        if (valueProperty == null) continue;
        descriptors.put(segment.getName().getLocalName(), valueProperty.getFirstValue().toString());
      }
    }

    // Read the namespaces ...
    ExecutionContext context = getExecutionContext();
    Path namespacesPath =
        pathFactory.createRelativePath(
            ModeShapeLexicon.REPOSITORIES, repoName, ModeShapeLexicon.NAMESPACES);
    Node namespacesNode = subgraph.getNode(namespacesPath);
    descriptors.put(org.modeshape.jcr.api.Repository.REPOSITORY_NAME, repositoryName);
    if (namespacesNode != null) {
      configuration = getConfigurationGraph();
      GraphNamespaceRegistry registry =
          new GraphNamespaceRegistry(
              configuration,
              namespacesNode.getLocation().getPath(),
              ModeShapeLexicon.URI,
              ModeShapeLexicon.GENERATED);
      context = context.with(registry);
    }

    // Get the name of the source ...
    Path repoPath = pathFactory.createRelativePath(ModeShapeLexicon.REPOSITORIES, repoName);
    Node repoNode = subgraph.getNode(repoPath);
    if (repoNode == null) {
      // There is no repository with the supplied name ...
      throw new PathNotFoundException(
          Location.create(repoPath),
          repositoriesPath,
          JcrI18n.repositoryDoesNotExist.text(readable(repoName)));
    }
    Property property = repoNode.getProperty(ModeShapeLexicon.SOURCE_NAME);
    if (property == null || property.isEmpty()) {
      if (configuration == null) configuration = getConfigurationGraph();
      String readableName = readable(ModeShapeLexicon.SOURCE_NAME);
      String readablePath = readable(subgraph.getLocation());
      String msg =
          JcrI18n.propertyNotFoundOnNode.text(
              readableName, readablePath, configuration.getCurrentWorkspaceName());
      throw new RepositoryException(msg);
    }
    String sourceName =
        context.getValueFactories().getStringFactory().create(property.getFirstValue());

    // Verify the sourc exists ...
    RepositorySource source = getRepositorySource(sourceName);
    if (source == null) {
      throw new RepositoryException(
          JcrI18n.repositoryReferencesNonExistantSource.text(repositoryName, sourceName));
    }

    // Read the initial content ...
    String initialContentForNewWorkspaces = null;
    for (Location initialContentLocation : repoNode.getChildren(ModeShapeLexicon.INITIAL_CONTENT)) {
      Node initialContent = subgraph.getNode(initialContentLocation);
      if (initialContent == null) continue;

      // Determine where to load the initial content from ...
      Property contentReference = initialContent.getProperty(ModeShapeLexicon.CONTENT);
      if (contentReference == null || contentReference.isEmpty()) {
        if (configuration == null) configuration = getConfigurationGraph();
        String readableName = readable(ModeShapeLexicon.CONTENT);
        String readablePath = readable(initialContentLocation);
        String msg =
            JcrI18n.propertyNotFoundOnNode.text(
                readableName, readablePath, configuration.getCurrentWorkspaceName());
        throw new RepositoryException(msg);
      }
      String contentRef = string(contentReference.getFirstValue());

      // Determine which workspaces this should apply to ...
      Property workspaces = initialContent.getProperty(ModeShapeLexicon.WORKSPACES);
      if (workspaces == null || workspaces.isEmpty()) {
        if (configuration == null) configuration = getConfigurationGraph();
        String readableName = readable(ModeShapeLexicon.WORKSPACES);
        String readablePath = readable(initialContentLocation);
        String msg =
            JcrI18n.propertyNotFoundOnNode.text(
                readableName, readablePath, configuration.getCurrentWorkspaceName());
        throw new RepositoryException(msg);
      }

      // Load the initial content into a transient source ...
      XmlFileRepositorySource initialContentSource = new XmlFileRepositorySource();
      initialContentSource.setName("Initial content for " + repositoryName);
      initialContentSource.setContentLocation(contentRef);
      Graph initialContentGraph = Graph.create(initialContentSource, context);
      Graph sourceGraph = Graph.create(sourceName, connectionFactory, context);

      // And initialize the source with the content (if not already there) ...
      for (Object value : workspaces) {
        String workspaceName = string(value);
        if (workspaceName != null && workspaceName.trim().length() != 0) {
          // Load the content into the workspace with this name ...
          sourceGraph.useWorkspace(workspaceName);
          try {
            sourceGraph.merge(initialContentGraph);
          } catch (RuntimeException e) {
            throw new RepositoryException(
                JcrI18n.unableToImportInitialContent.text(readable(repoName), contentRef), e);
          }
        }
      }

      // Determine if this initial content should apply to new workspaces ...
      Property applyToNewWorkspaces =
          initialContent.getProperty(ModeShapeLexicon.APPLY_TO_NEW_WORKSPACES);
      if (applyToNewWorkspaces != null
          && !applyToNewWorkspaces.isEmpty()
          && isTrue(applyToNewWorkspaces.getFirstValue())) {
        initialContentForNewWorkspaces =
            contentRef; // may overwrite the value if seen more than once!
      }
    }

    // Find the capabilities ...
    RepositorySourceCapabilities capabilities = source.getCapabilities();
    // Create the repository ...
    JcrRepository repository =
        new JcrRepository(
            context,
            connectionFactory,
            sourceName,
            getRepositoryService().getRepositoryLibrary(),
            capabilities,
            descriptors,
            options,
            initialContentForNewWorkspaces);

    // Register all the the node types ...
    Path nodeTypesPath =
        pathFactory.createRelativePath(
            ModeShapeLexicon.REPOSITORIES, repoName, JcrLexicon.NODE_TYPES);
    Node nodeTypesNode = subgraph.getNode(nodeTypesPath);
    if (nodeTypesNode != null) {
      boolean needToRefreshSubgraph = false;
      if (configuration == null) configuration = getConfigurationGraph();

      // Expand any references to a CND file
      Property resourceProperty = nodeTypesNode.getProperty(ModeShapeLexicon.RESOURCE);
      if (resourceProperty != null) {
        ClassLoader classLoader = this.context.getClassLoader();
        for (Object resourceValue : resourceProperty) {
          String resources =
              this.context.getValueFactories().getStringFactory().create(resourceValue);

          for (String resource : resources.split("\\s*,\\s*")) {
            Graph.Batch batch = configuration.batch();
            GraphBatchDestination destination = new GraphBatchDestination(batch);

            Path nodeTypesAbsPath = pathFactory.create(repositoryPath, JcrLexicon.NODE_TYPES);
            CndImporter importer = new CndImporter(destination, nodeTypesAbsPath, true, false);
            InputStream is = IoUtil.getResourceAsStream(resource, classLoader, getClass());
            Problems cndProblems = new SimpleProblems();
            if (is == null) {
              String msg =
                  JcrI18n.unableToFindNodeTypeDefinitionsOnClasspathOrFileOrUrl.text(resource);
              throw new RepositoryException(msg);
            }
            try {
              importer.importFrom(is, cndProblems, resource);
              batch.execute();
              needToRefreshSubgraph = true;
            } catch (IOException ioe) {
              String msg = JcrI18n.errorLoadingNodeTypeDefintions.text(resource, ioe.getMessage());
              throw new RepositoryException(msg, ioe);
            }
            if (!cndProblems.isEmpty()) {
              // Add any warnings or information to this engine's list ...
              getProblems().addAll(cndProblems);
              if (cndProblems.hasErrors()) {
                String msg = null;
                Throwable cause = null;
                for (Problem problem : cndProblems) {
                  if (problem.getStatus() == Status.ERROR) {
                    msg = problem.getMessageString();
                    cause = problem.getThrowable();
                    break;
                  }
                }
                throw new RepositoryException(
                    JcrI18n.errorLoadingNodeTypeDefintions.text(resource, msg), cause);
              }
            }
          }
        }
      }

      // Load any namespaces from the configuration into the repository's context ...
      NamespaceRegistry repoRegistry = repository.getExecutionContext().getNamespaceRegistry();
      repoRegistry.register(configuration.getContext().getNamespaceRegistry().getNamespaces());

      // Re-read the subgraph, in case any new nodes were added
      Subgraph nodeTypesSubgraph = subgraph;
      if (needToRefreshSubgraph) {
        nodeTypesSubgraph =
            configuration.getSubgraphOfDepth(4).at(nodeTypesNode.getLocation().getPath());
      }

      repository
          .getRepositoryTypeManager()
          .registerNodeTypes(nodeTypesSubgraph, nodeTypesNode.getLocation(), false);
    }

    return repository;
  }