protected void recursiveCreateDocumentFromNode(DocumentModel parent, SourceNode node)
      throws IOException {

    if (getFactory().isTargetDocumentModelFolderish(node)) {
      DocumentModel folder;
      Boolean newThread = false;
      if (skipContainerCreation) {
        folder = parent;
        skipContainerCreation = false;
        newThread = true;
      } else {
        folder = doCreateFolderishNode(parent, node);
        if (folder == null) {
          return;
        }
      }

      // get a new TaskImporter if available to start
      // processing the sub-tree
      GenericThreadedImportTask task = null;
      if (!newThread) {
        task = createNewTaskIfNeeded(folder, node);
      }
      if (task != null) {
        // force comit before starting new thread
        commit(true);
        try {
          GenericMultiThreadedImporter.getExecutor().execute(task);
        } catch (RejectedExecutionException e) {
          log.error("Import task rejected", e);
        }

      } else {
        Stopwatch stopwatch =
            SimonManager.getStopwatch("org.nuxeo.ecm.platform.importer.node_get_children");
        Split split = stopwatch.start();
        List<SourceNode> nodes = node.getChildren();
        split.stop();
        if (nodes != null) {
          for (SourceNode child : nodes) {
            recursiveCreateDocumentFromNode(folder, child);
          }
        }
      }
    } else {
      doCreateLeafNode(parent, node);
    }
  }
 public synchronized void run() {
   TransactionHelper.startTransaction(transactionTimeout);
   synchronized (this) {
     if (isRunning) {
       throw new IllegalStateException("Task already running");
     }
     isRunning = true;
     // versions have no path, target document can be null
     if (rootSource == null) {
       isRunning = false;
       throw new IllegalArgumentException("source node must be specified");
     }
   }
   try {
     session = CoreInstance.openCoreSessionSystem(repositoryName);
     log.info("Starting new import task");
     if (rootDoc != null) {
       // reopen the root to be sure the session is valid
       rootDoc = session.getDocument(rootDoc.getRef());
     }
     recursiveCreateDocumentFromNode(rootDoc, rootSource);
     session.save();
     GenericMultiThreadedImporter.addCreatedDoc(taskId, uploadedFiles);
     TransactionHelper.commitOrRollbackTransaction();
   } catch (Exception e) { // deals with interrupt below
     log.error("Error during import", e);
     ExceptionUtils.checkInterrupt(e);
     notifyImportError();
   } finally {
     log.info("End of task");
     if (session != null) {
       session.close();
       session = null;
     }
     synchronized (this) {
       isRunning = false;
     }
   }
 }