gt:                 String currentPath = parentPath + FILE_SEPARATOR + name;
context: /*
   * Copyright (C) 2007-2022 Crafter Software Corporation. All Rights Reserved.
   *
   * This program is free software: you can redistribute it and/or modify
   * it under the terms of the GNU General Public License version 3 as published by
   * the Free Software Foundation.
   *
   * This program 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 General Public License for more details.
   *
   * You should have received a copy of the GNU General Public License
   * along with this program.  If not, see <http://www.gnu.org/licenses/>.
   */
  
  package org.craftercms.studio.impl.v1.service.content;
  
  import org.apache.commons.lang3.StringUtils;
  import org.craftercms.commons.validation.ValidationException;
  import org.craftercms.commons.validation.annotations.param.ValidateParams;
  import org.craftercms.commons.validation.annotations.param.ValidateSecurePathParam;
  import org.craftercms.studio.api.v1.constant.DmConstants;
  import org.craftercms.studio.api.v1.exception.ServiceLayerException;
  import org.craftercms.studio.api.v1.exception.security.UserNotFoundException;
  import org.craftercms.studio.api.v1.log.Logger;
  import org.craftercms.studio.api.v1.log.LoggerFactory;
  import org.craftercms.studio.api.v1.repository.ContentRepository;
  import org.craftercms.studio.api.v1.service.content.ContentService;
  import org.craftercms.studio.api.v1.service.content.ImportService;
  import org.craftercms.studio.api.v1.service.deployment.DmPublishService;
  import org.craftercms.studio.api.v1.service.security.SecurityService;
  import org.craftercms.studio.api.v1.service.site.SiteService;
  import org.craftercms.studio.api.v1.service.workflow.context.MultiChannelPublishingContext;
  import org.craftercms.studio.api.v1.to.ContentItemTO;
  import org.craftercms.studio.api.v2.service.item.internal.ItemServiceInternal;
  import org.craftercms.studio.api.v2.utils.StudioConfiguration;
  import org.craftercms.studio.impl.v1.util.ContentFormatUtils;
  import org.craftercms.studio.impl.v1.util.ContentUtils;
  import org.dom4j.Document;
  import org.dom4j.DocumentException;
  import org.dom4j.Element;
  import org.dom4j.Node;
  
  import java.io.File;
  import java.io.FileInputStream;
  import java.io.FileNotFoundException;
  import java.io.InputStream;
  import java.net.MalformedURLException;
  import java.net.URL;
  import java.util.ArrayList;
  import java.util.HashMap;
  import java.util.HashSet;
  import java.util.List;
  import java.util.Map;
  import java.util.Set;
  
  import static org.craftercms.studio.api.v1.constant.StudioConstants.FILE_SEPARATOR;
  import static org.craftercms.studio.api.v2.dal.ItemState.SAVE_AND_CLOSE_OFF_MASK;
  import static org.craftercms.studio.api.v2.dal.ItemState.SAVE_AND_CLOSE_ON_MASK;
  import static org.craftercms.studio.api.v2.utils.StudioConfiguration.IMPORT_ASSET_CHAIN_NAME;
  import static org.craftercms.studio.api.v2.utils.StudioConfiguration.IMPORT_ASSIGNEE;
  import static org.craftercms.studio.api.v2.utils.StudioConfiguration.IMPORT_XML_CHAIN_NAME;
  
  public class ImportServiceImpl implements ImportService {
  
      private final static Logger logger = LoggerFactory.getLogger(ImportServiceImpl.class);
  
      protected SiteService siteService;
      protected SecurityService securityService;
      protected ContentRepository contentRepository;
      protected ContentService contentService;
      protected DmPublishService dmPublishService;
      protected StudioConfiguration studioConfiguration;
      protected ItemServiceInternal itemServiceInternal;
  
      /**
       * is import in progress?
       */
      private boolean inProgress = false;
  
      /** going to pause import process? **/
      private boolean pauseEanbeld = false;
      /** next pause time **/
      private long nextStop;
      /** import delay interval **/
      private long currentDelayInterval;
      /** import delay time **/
      private long currentDelayLength;
  
      @Override
      @SuppressWarnings("unchecked")
      @ValidateParams
      public void importSite(@ValidateSecurePathParam(name = "configLocation") String configLocation)
              throws ServiceLayerException, ValidationException, UserNotFoundException {
          Document document = loadConfiguration(configLocation);
          if (document != null) {
              Element root = document.getRootElement();
              List<Node> siteNodes = root.selectNodes("site");
              if (siteNodes != null) {
                  for (Node siteNode : siteNodes) {
                      String name = siteNode.valueOf("name");
                      String buildDataLocation = siteNode.valueOf("build-data-location");
                      String publishingChannelGroup = siteNode.valueOf("publish-channel-group");
                      String publishStr = siteNode.valueOf("publish");
                      boolean publish = (!StringUtils.isEmpty(publishStr) && publishStr.equalsIgnoreCase("true"));
                      String publishSize = siteNode.valueOf("publish-chunk-size");
                      int chunkSize = (!StringUtils.isEmpty(publishSize) && StringUtils.isNumeric(publishSize))
                              ? Integer.valueOf(publishSize) : -1;
                      Node foldersNode = siteNode.selectSingleNode("folders");
                      String sourceLocation = buildDataLocation + FILE_SEPARATOR + name;
                      String delayIntervalStr = siteNode.valueOf("delay-interval");
                      int delayInterval = (!StringUtils.isEmpty(delayIntervalStr) && StringUtils.isNumeric(delayIntervalStr))
                              ? Integer.valueOf(delayIntervalStr) : -1;
                      String delayLengthStr = siteNode.valueOf("delay-length");
                      int delayLength = (!StringUtils.isEmpty(delayLengthStr) && StringUtils.isNumeric(delayLengthStr))
                              ? Integer.valueOf(delayLengthStr) : -1;
  
                      importFromConfigNode(name, publishingChannelGroup, foldersNode, sourceLocation, FILE_SEPARATOR,
                              publish, chunkSize, delayInterval, delayLength);
                  }
              }
          }
      }
  
      protected Document loadConfiguration(String configLocation) {
          logger.debug("[IMPORT] loading " + configLocation);
          InputStream in = null;
          try {
              in = new FileInputStream(configLocation);
              if (in != null) {
                  return ContentUtils.convertStreamToXml(in);
              }
          } catch (FileNotFoundException e) {
              logger.error("[IMPORT] failed to load configuration.", e);
  
          } catch (DocumentException e) {
              logger.error("[IMPORT] failed to load configuration.", e);
  
          } finally {
              ContentUtils.release(in);
          }
          return null;
      }
  
      @SuppressWarnings("unchecked")
      private void importFromConfigNode(final String site, String publishChannelGroup, final Node node,
                                        final String fileRoot, final String targetRoot,
                                        boolean publish, int chunkSize, int delayInterval, int delayLength)
              throws ServiceLayerException, ValidationException, UserNotFoundException {
          if (!inProgress) {
              inProgress = true;
              if (delayInterval > 0) pauseEanbeld = true;
              this.currentDelayInterval = delayInterval * 1000;
              this.currentDelayLength = delayLength * 1000;
              final Set<String> importedPaths = new HashSet<String>();
              final List<String> importedFullPaths = new ArrayList<String>();
              logger.info("[IMPORT] started importing in " + site
                      + ", pause enabled: " + pauseEanbeld
                      + ", delay interval: " + this.currentDelayInterval
                      + ", delay length: " + this.currentDelayLength);
  
              boolean overWrite = ContentFormatUtils.getBooleanValue(node.valueOf("@over-write"));
              final List<Node> folderNodes = node.selectNodes("folder");
              if (publish) {
                  String user = securityService.getCurrentUser();
                  logger.debug("[IMPORT] publishing user: " + user);
  
                  this.nextStop = System.currentTimeMillis() + this.currentDelayInterval;
                  createFolders(site, importedPaths, importedFullPaths, folderNodes, fileRoot, targetRoot, "",
                          overWrite, user);
                  logger.info("Starting Publish of Imported Files (Total " + importedFullPaths.size()
                          + " On chunkSize of " + chunkSize + " )");
                  publish(site, publishChannelGroup, targetRoot, importedFullPaths, chunkSize);
              } else {
                  this.nextStop = System.currentTimeMillis() + this.currentDelayInterval;
                  createFolders(site, importedPaths, importedFullPaths, folderNodes, fileRoot, targetRoot, "",
                          overWrite, null);
              }
              inProgress = false;
          } else {
              logger.info("[IMPORT] an import process is currently running.");
          }
      }
  
  
      /**
       * create folders
       *
       * @param site
       *            site name
       * @param importedPaths
       *            a list of imported files
       * @param importedFullPaths
       * @param nodes
       *            nodes representing folders
       * @param fileRoot
       *            the root location of files/folders being imported
       * @param targetRoot
       *            the target location root
       * @param parentPath
       *            the target location to import to
       * @param overWrite
       *            overwrite contents?
       * @param user
       *
       */
      @SuppressWarnings("unchecked")
      private void createFolders(String site, Set<String> importedPaths, List<String> importedFullPaths,
                                 List<Node> nodes, String fileRoot, String targetRoot, String parentPath,
                                 boolean overWrite, String user)
              throws ServiceLayerException, UserNotFoundException {
          logger.info("[IMPORT] createFolders : site[" + site + "] " + "] fileRoot [" + fileRoot + "] targetRoot [ "
                  + targetRoot + "] parentPath [" + parentPath + "] overwrite[" + overWrite + "]");
  
          if (nodes != null) {
              for (Node node : nodes) {
                  String name = node.valueOf("@name");
                  String value = node.valueOf("@over-write");
                  boolean folderOverWrite = (StringUtils.isEmpty(value)) ? overWrite : ContentFormatUtils
                          .getBooleanValue(value);
                  if (!StringUtils.isEmpty(name)) {
                      String currentFilePath = fileRoot + FILE_SEPARATOR + name;
                      String currentPath = parentPath + FILE_SEPARATOR + name;
                      // check if the parent node exists and create the folder if
                      // not
                      boolean folderExists = contentService.contentExists(site, currentPath);
                      if (!folderExists) {
                          contentService.createFolder(site, parentPath, name);
                      }
                      boolean importAll = ContentFormatUtils.getBooleanValue(node.valueOf("@import-all"));
                      if (importAll) {
                          importRootFileList(site, importedPaths, importedFullPaths, fileRoot + FILE_SEPARATOR + name,
                                  targetRoot, currentPath, folderOverWrite, user);
  
                      } else {
                          // create child folders
                          List<Node> childFolders = node.selectNodes("folder");
                          createFolders(site, importedPaths, importedFullPaths, childFolders, currentFilePath,
                                  targetRoot, currentPath, folderOverWrite, user);
                          // create child fiimportedPathsles
                          List<Node> childFiles = node.selectNodes("file");
                          createFiles(site, importedPaths, importedFullPaths, childFiles, currentFilePath,
                                  targetRoot, currentPath, folderOverWrite, user);
                      }
                  }
              }
          }
      }
  
      /**
       * import all files from the given file root
       *
       * @param site
       * @param importedPaths
       * @param importedFullPaths
       * @param fileRoot
       * @param targetRoot
       *            the target location root
       * @param parentPath
       *            the target location to import to
       * @param overWrite
       * @param user
       */
      protected void importRootFileList(String site, Set<String> importedPaths, List<String> importedFullPaths,
                                        String fileRoot, String targetRoot, String parentPath, boolean overWrite,
                                        String user) throws ServiceLayerException, UserNotFoundException {
          URL resourceUrl = getResourceUrl(fileRoot);
          if (resourceUrl != null) {
              String resourcePath = resourceUrl.getFile();
              File file = new File(resourcePath);
              if (file.isDirectory()) {
                  String[] children = file.list();
                  if (children != null && children.length > 0) {
                      for (String childName : children) {
                          File childFile = new File(resourcePath + FILE_SEPARATOR + childName);
                          if (childFile.isDirectory()) {
                              String currentPath = parentPath + FILE_SEPARATOR + childName;
                              boolean folderExists = contentService.contentExists(site, currentPath);
                              if (!folderExists) {
                                  contentService.createFolder(site, parentPath, childName);
                              }
                              logger.info("[IMPORT] Importing " + parentPath + FILE_SEPARATOR + childName);
  
                              importFileList(site, importedPaths, importedFullPaths, fileRoot + FILE_SEPARATOR + childName,
                                      targetRoot, parentPath + FILE_SEPARATOR + childName, overWrite, user);
                              logger.info("[IMPORT] Finished Importing " + parentPath + FILE_SEPARATOR + childName);
                          } else {
                              writeContentInTransaction(site, importedPaths, importedFullPaths, fileRoot,
                                      targetRoot, parentPath, childName, overWrite, user);
                          }
                      }
                  }
  
              }
  
          } else {
              logger.error("[IMPORT] " + fileRoot + " is not found.");
          }
      }
  
      /**
       * get the resource url for import
       *
       * @param filePath
       * @return
       */
      private URL getResourceUrl(String filePath) {
          try {
              return new File(filePath).toURI().toURL();
          } catch (MalformedURLException e) {
              throw new RuntimeException("Not able to find " + filePath);
          }
      }
  
      /**
       * import files and folders at the given fileRoot path
       *
       * @param site
       * @param importedPaths
       * @param importedFullPaths
       * @param fileRoot
       * @param targetRoot
       *            the target location root
       * @param parentPath
       *            the target location to import to
       * @param overWrite
       * @param user
       */
      protected void importFileList(String site, Set<String> importedPaths, List<String> importedFullPaths,
                                    String fileRoot, String targetRoot, String parentPath, boolean overWrite, String user)
              throws ServiceLayerException, UserNotFoundException {
          logger.info("[IMPORT] importFileList: fileRoot [" + fileRoot + "] name [" + targetRoot + "] overwrite["
                  + overWrite + "]");
          URL resourceUrl = getResourceUrl(fileRoot);
          if (resourceUrl != null) {
              String resourcePath = resourceUrl.getFile();
              File file = new File(resourcePath);
              if (file.isDirectory()) {
                  String[] children = file.list();
                  if (children != null && children.length > 0) {
                      for (String childName : children) {
                          File childFile = new File(resourcePath + FILE_SEPARATOR + childName);
                          if (childFile.isDirectory()) {
                              String currentPath = parentPath + FILE_SEPARATOR + childName;
                              boolean folderExists = contentService.contentExists(site, currentPath);
                              if (!folderExists) {
                                  contentService.createFolder(site, parentPath, childName);
                              }
                              importFileList(site, importedPaths, importedFullPaths, fileRoot + FILE_SEPARATOR
                                              + childName, targetRoot, parentPath + FILE_SEPARATOR + childName,
                                      overWrite, user);
                          } else {
                              writeContentInTransaction(site, importedPaths, importedFullPaths, fileRoot,
                                      targetRoot, parentPath, childName, overWrite, user);
                          }
                      }
                  }
              }
          } else {
              logger.error("[IMPORT] " + fileRoot + " is not found.");
          }
      }
  
      /**
       * write content
       *
       * @param site
       * @param importedPaths
       * @param importedFullPaths
       * @param fileRoot
       * @param parentPath
       * @param name
       * @param overWrite
       * @param user
       */
      protected void writeContentInTransaction(final String site, final Set<String> importedPaths,
                                               final List<String> importedFullPaths, final String fileRoot,
                                               final String targetRoot, final String parentPath, final String name,
                                               final boolean overWrite, final String user) {
          long startTimeWrite = System.currentTimeMillis();
          logger.debug("[IMPORT] writing file in transaction: " + parentPath + FILE_SEPARATOR + name);
          writeContent(site, importedPaths, importedFullPaths, fileRoot, targetRoot, parentPath, name,
                          overWrite);
          logger.debug("[IMPORT] done writing file in transaction: " + parentPath + FILE_SEPARATOR + name
                          + ", time: " + (System.currentTimeMillis() - startTimeWrite));
          pause();
      }
  
      /**
       * write content
       *
       * @param site
       * @param importedPaths
       * @param importedFullPaths
       * @param fileRoot
       * @param parentPath
       * @param name
       * @param overWrite
       */
      protected void writeContent(String site, Set<String> importedPaths, List<String> importedFullPaths,
                                  String fileRoot, String targetRoot, String parentPath, String name, boolean overWrite) {
          boolean isXml = true;
          String processChain = getXmlChainName();
          if (!name.endsWith(".xml")) {
              isXml = false;
              processChain = getAssetChainName();
          }
          InputStream in = null;
          String filePath = parentPath + FILE_SEPARATOR + name;
          String fileSystemPath = fileRoot + FILE_SEPARATOR + name;
          logger.info("[IMPORT] writeContent: fileRoot [" + fileRoot + "] fullPath [" + filePath + "] overwrite["
                  + overWrite + "] process chain [ " + processChain + "]");
          long startTimeWrite = System.currentTimeMillis();
          logger.debug("[IMPORT] writing file: " + parentPath + FILE_SEPARATOR + name);
  
          try {
              File file = new File(fileSystemPath);
              if (file.exists()) {
                  in = new FileInputStream(file);
  