private void parseJournaling(
      RepositoryService repositoryService,
      OperationContext context,
      ModelNode model,
      EditableDocument configDoc)
      throws OperationFailedException {
    if (model.hasDefined(ModelKeys.JOURNALING)) {
      EditableDocument journaling = configDoc.getOrCreateDocument(FieldName.JOURNALING);

      // set it temporarily on the repository service because the final location needs to be
      // resolved later
      if (model.hasDefined(ModelKeys.JOURNAL_RELATIVE_TO)) {
        String relativeTo =
            attribute(context, model, ModelAttributes.JOURNAL_RELATIVE_TO).asString();
        repositoryService.setJournalRelativeTo(relativeTo);
      }

      // set it temporarily on the repository service because the final location needs to be
      // resolved later
      if (model.hasDefined(ModelKeys.JOURNAL_PATH)) {
        String path = attribute(context, model, ModelAttributes.JOURNAL_PATH).asString();
        repositoryService.setJournalPath(path);
      }

      int maxDaysToKeepRecords =
          attribute(context, model, ModelAttributes.MAX_DAYS_TO_KEEP_RECORDS).asInt();
      journaling.setNumber(FieldName.MAX_DAYS_TO_KEEP_RECORDS, maxDaysToKeepRecords);

      boolean asyncWrites = attribute(context, model, ModelAttributes.ASYNC_WRITES).asBoolean();
      journaling.setBoolean(FieldName.ASYNC_WRITES_ENABLED, asyncWrites);

      String gcThreadPool =
          attribute(context, model, ModelAttributes.JOURNAL_GC_THREAD_POOL).asString();
      journaling.setString(FieldName.THREAD_POOL, gcThreadPool);

      String gcInitialTime =
          attribute(context, model, ModelAttributes.JOURNAL_GC_INITIAL_TIME).asString();
      journaling.setString(FieldName.INITIAL_TIME, gcInitialTime);
    }
  }
  @Override
  protected void performRuntime(
      final OperationContext context,
      final ModelNode operation,
      final ModelNode model,
      final ServiceVerificationHandler verificationHandler,
      final List<ServiceController<?>> newControllers)
      throws OperationFailedException {

    final ServiceTarget target = context.getServiceTarget();
    final AddressContext addressContext = AddressContext.forOperation(operation);
    final String repositoryName = addressContext.repositoryName();
    final String cacheName = attribute(context, model, ModelAttributes.CACHE_NAME, repositoryName);
    String infinispanConfig = attribute(context, model, ModelAttributes.CACHE_CONFIG, null);
    String configRelativeTo =
        attribute(context, model, ModelAttributes.CONFIG_RELATIVE_TO).asString();
    final boolean enableMonitoring =
        attribute(context, model, ModelAttributes.ENABLE_MONITORING).asBoolean();
    final String gcThreadPool =
        attribute(context, model, ModelAttributes.GARBAGE_COLLECTION_THREAD_POOL, null);
    final String gcInitialTime =
        attribute(context, model, ModelAttributes.GARBAGE_COLLECTION_INITIAL_TIME, null);
    final int gcIntervalInHours =
        attribute(context, model, ModelAttributes.GARBAGE_COLLECTION_INTERVAL).asInt();
    final String optThreadPool =
        attribute(context, model, ModelAttributes.DOCUMENT_OPTIMIZATION_THREAD_POOL, null);
    final String optInitialTime =
        attribute(context, model, ModelAttributes.DOCUMENT_OPTIMIZATION_INITIAL_TIME, null);
    final int optIntervalInHours =
        attribute(context, model, ModelAttributes.DOCUMENT_OPTIMIZATION_INTERVAL).asInt();
    final Integer optTarget =
        intAttribute(
            context, model, ModelAttributes.DOCUMENT_OPTIMIZATION_CHILD_COUNT_TARGET, null);
    final Integer eventBusSize = intAttribute(context, model, ModelAttributes.EVENT_BUS_SIZE, null);
    final Integer optTolerance =
        intAttribute(
            context, model, ModelAttributes.DOCUMENT_OPTIMIZATION_CHILD_COUNT_TOLERANCE, null);

    // Create a document for the repository configuration ...
    EditableDocument configDoc = Schematic.newDocument();
    configDoc.set(FieldName.NAME, repositoryName);

    // Determine the JNDI name ...
    configDoc.set(
        FieldName.JNDI_NAME,
        ""); // always set to empty string, since we'll register in JNDI here ...
    final String jndiName = ModeShapeJndiNames.JNDI_BASE_NAME + repositoryName;
    String jndiAlias = ModeShapeJndiNames.jndiNameFrom(model, repositoryName);
    if (jndiName.equals(jndiAlias)) {
      jndiAlias = null;
    }

    if (eventBusSize != null) {
      configDoc.setNumber(FieldName.EVENT_BUS_SIZE, eventBusSize);
    }

    // Parse the cache configuration
    if (StringUtil.isBlank(infinispanConfig)) {
      infinispanConfig = "modeshape/" + repositoryName + "-cache-config.xml";
    } else {
      // check if it's a system property
      String infinispanConfigSystemProperty = System.getProperty(infinispanConfig);
      if (!StringUtil.isBlank(infinispanConfigSystemProperty)) {
        infinispanConfig = infinispanConfigSystemProperty;
      }
    }
    // Set the storage information (that was set on the repository ModelNode) ...
    setRepositoryStorageConfiguration(infinispanConfig, cacheName, configDoc);

    // Always set whether monitoring is enabled ...
    enableMonitoring(enableMonitoring, configDoc);

    // Initial node-types if configured
    parseCustomNodeTypes(model, configDoc);

    // Workspace information is on the repository model node (unlike the XML) ...
    EditableDocument workspacesDoc = parseWorkspaces(context, model, configDoc);

    // security
    parseSecurity(context, model, configDoc);

    // Now create the repository service that manages the lifecycle of the JcrRepository instance
    // ...
    RepositoryConfiguration repositoryConfig =
        new RepositoryConfiguration(configDoc, repositoryName);
    String configRelativeToSystemProperty = System.getProperty(configRelativeTo);
    if (!StringUtil.isBlank(configRelativeToSystemProperty)) {
      configRelativeTo = configRelativeToSystemProperty;
    }
    if (!configRelativeTo.endsWith("/")) {
      configRelativeTo = configRelativeTo + "/";
    }
    RepositoryService repositoryService =
        new RepositoryService(repositoryConfig, infinispanConfig, configRelativeTo);
    ServiceName repositoryServiceName = ModeShapeServiceNames.repositoryServiceName(repositoryName);

    // Sequencing
    parseSequencing(model, configDoc);

    // Text Extraction
    parseTextExtraction(model, configDoc);

    // Reindexing
    parseReindexing(model, configDoc);

    // Journaling
    parseJournaling(repositoryService, context, model, configDoc);

    // Add the EngineService's dependencies ...
    ServiceBuilder<JcrRepository> repositoryServiceBuilder =
        target.addService(repositoryServiceName, repositoryService);

    // Add dependency to the ModeShape engine service ...
    repositoryServiceBuilder.addDependency(
        ModeShapeServiceNames.ENGINE, ModeShapeEngine.class, repositoryService.getEngineInjector());
    repositoryServiceBuilder.setInitialMode(ServiceController.Mode.ACTIVE);

    // Add garbage collection information ...
    if (gcThreadPool != null) {
      configDoc
          .getOrCreateDocument(FieldName.GARBAGE_COLLECTION)
          .setString(FieldName.THREAD_POOL, gcThreadPool);
    }
    if (gcInitialTime != null) {
      configDoc
          .getOrCreateDocument(FieldName.GARBAGE_COLLECTION)
          .setString(FieldName.INITIAL_TIME, gcInitialTime);
    }
    configDoc
        .getOrCreateDocument(FieldName.GARBAGE_COLLECTION)
        .setNumber(FieldName.INTERVAL_IN_HOURS, gcIntervalInHours);

    // Add document optimization information ...
    if (optTarget != null) {
      EditableDocument docOpt =
          configDoc
              .getOrCreateDocument(FieldName.STORAGE)
              .getOrCreateDocument(FieldName.DOCUMENT_OPTIMIZATION);
      if (optThreadPool != null) {
        docOpt.setString(FieldName.THREAD_POOL, optThreadPool);
      }
      if (optInitialTime != null) {
        docOpt.setString(FieldName.INITIAL_TIME, optInitialTime);
      }
      docOpt.setNumber(FieldName.INTERVAL_IN_HOURS, optIntervalInHours);
      docOpt.setNumber(FieldName.OPTIMIZATION_CHILD_COUNT_TARGET, optTarget.intValue());
      if (optTolerance != null) {
        docOpt.setNumber(FieldName.OPTIMIZATION_CHILD_COUNT_TOLERANCE, optTolerance.intValue());
      }
    }

    // Add the dependency to the Security Manager
    repositoryServiceBuilder.addDependency(
        SecurityManagementService.SERVICE_NAME,
        ISecurityManagement.class,
        repositoryService.getSecurityManagementServiceInjector());

    // Add dependency, if necessary, to the workspaces cache container
    String workspacesInfinispanConfig =
        attribute(context, model, ModelAttributes.WORKSPACES_CACHE_CONTAINER, null);
    if (workspacesInfinispanConfig != null
        && !workspacesInfinispanConfig.toLowerCase().equalsIgnoreCase(infinispanConfig)) {
      workspacesDoc.set(FieldName.WORKSPACE_CACHE_CONFIGURATION, workspacesInfinispanConfig);
    }

    repositoryServiceBuilder.addDependency(
        Services.JBOSS_SERVICE_MODULE_LOADER,
        ModuleLoader.class,
        repositoryService.getModuleLoaderInjector());

    // Set up the JNDI binder service ...
    final ReferenceFactoryService<JcrRepository> referenceFactoryService =
        new ReferenceFactoryService<JcrRepository>();
    ServiceName referenceFactoryServiceName =
        ModeShapeServiceNames.referenceFactoryServiceName(repositoryName);
    final ServiceBuilder<?> referenceBuilder =
        target.addService(referenceFactoryServiceName, referenceFactoryService);
    referenceBuilder.addDependency(
        repositoryServiceName, JcrRepository.class, referenceFactoryService.getInjector());
    referenceBuilder.setInitialMode(ServiceController.Mode.ACTIVE);

    ContextNames.BindInfo bindInfo = ContextNames.bindInfoFor(jndiName);
    BinderService binder = new BinderService(bindInfo.getBindName());
    ServiceBuilder<?> binderBuilder = target.addService(bindInfo.getBinderServiceName(), binder);
    if (jndiAlias != null) {
      ContextNames.BindInfo aliasInfo = ContextNames.bindInfoFor(jndiAlias);
      ServiceName alias = aliasInfo.getBinderServiceName();
      binderBuilder.addAliases(alias);
      LOG.debugv(
          "Binding repository {0} to JNDI name {1} and {2}",
          repositoryName, bindInfo.getAbsoluteJndiName(), aliasInfo.getAbsoluteJndiName());
    } else {
      LOG.debugv(
          "Binding repository {0} to JNDI name {1}",
          repositoryName, bindInfo.getAbsoluteJndiName());
    }
    binderBuilder.addDependency(
        referenceFactoryServiceName,
        ManagedReferenceFactory.class,
        binder.getManagedObjectInjector());
    binderBuilder.addDependency(
        bindInfo.getParentContextServiceName(),
        ServiceBasedNamingStore.class,
        binder.getNamingStoreInjector());
    binderBuilder.setInitialMode(ServiceController.Mode.ACTIVE);

    // Add dependency to the data directory ...
    ServiceName dataDirServiceName = ModeShapeServiceNames.dataDirectoryServiceName(repositoryName);
    ServiceController<String> dataDirServiceController =
        RelativePathService.addService(
            dataDirServiceName,
            "modeshape/" + repositoryName,
            ModeShapeExtension.JBOSS_DATA_DIR_VARIABLE,
            target);
    newControllers.add(dataDirServiceController);
    repositoryServiceBuilder.addDependency(
        dataDirServiceName, String.class, repositoryService.getDataDirectoryPathInjector());

    // Add the default binary storage service which will provide the binary configuration
    BinaryStorageService defaultBinaryService = BinaryStorageService.createDefault();
    ServiceName defaultBinaryStorageServiceName =
        ModeShapeServiceNames.binaryStorageDefaultServiceName(repositoryName);
    ServiceBuilder<BinaryStorage> binaryStorageBuilder =
        target.addService(defaultBinaryStorageServiceName, defaultBinaryService);
    binaryStorageBuilder.setInitialMode(ServiceController.Mode.ACTIVE);
    // Add dependency to the binaries storage service, which captures the properties for the
    // binaries storage
    repositoryServiceBuilder.addDependency(
        defaultBinaryStorageServiceName,
        BinaryStorage.class,
        repositoryService.getBinaryStorageInjector());

    // Add monitor service
    final MonitorService monitorService = new MonitorService();
    final ServiceBuilder<RepositoryMonitor> monitorBuilder =
        target.addService(ModeShapeServiceNames.monitorServiceName(repositoryName), monitorService);
    monitorBuilder.addDependency(
        ModeShapeServiceNames.repositoryServiceName(repositoryName),
        JcrRepository.class,
        monitorService.getJcrRepositoryInjector());
    monitorBuilder.setInitialMode(ServiceController.Mode.ACTIVE);

    // Now add the controller for the RepositoryService ...
    newControllers.add(repositoryServiceBuilder.install());
    newControllers.add(referenceBuilder.install());
    newControllers.add(binderBuilder.install());
    newControllers.add(binaryStorageBuilder.install());
    newControllers.add(monitorBuilder.install());
  }