/**
  * @param repositoryDir
  * @param outputStream
  */
 @Override
 public void exportDirectory(
     RepositoryFile repositoryDir, OutputStream outputStream, String filePath)
     throws ExportException, IOException {
   addToManifest(repositoryDir);
   List<RepositoryFile> children =
       this.unifiedRepository.getChildren(
           new RepositoryRequest(String.valueOf(repositoryDir.getId()), true, 1, null));
   for (RepositoryFile repositoryFile : children) {
     // exclude 'etc' folder - datasources and etc.
     if (!ClientRepositoryPaths.getEtcFolderPath().equals(repositoryFile.getPath())) {
       if (repositoryFile.isFolder()) {
         if (outputStream.getClass().isAssignableFrom(ZipOutputStream.class)) {
           ZipOutputStream zos = (ZipOutputStream) outputStream;
           ZipEntry entry = new ZipEntry(getZipEntryName(repositoryFile, filePath));
           zos.putNextEntry(entry);
         }
         exportDirectory(repositoryFile, outputStream, filePath);
       } else {
         exportFile(repositoryFile, outputStream, filePath);
       }
     }
   }
   createLocales(repositoryDir, filePath, repositoryDir.isFolder(), outputStream);
 }
 public InputStream getInputStream() throws Exception {
   IUnifiedRepository repository = PentahoSystem.get(IUnifiedRepository.class);
   RepositoryFile repositoryFile = repository.getFile(inputFilePath);
   if ((repositoryFile == null) || repositoryFile.isFolder()) {
     throw new FileNotFoundException();
   }
   return new RepositoryFileInputStream(repositoryFile);
 }
 private boolean isValidOutputPath(String path) {
   try {
     RepositoryFile repoFile = repository.getFile(path);
     if (repoFile != null && repoFile.isFolder()) {
       return true;
     }
   } catch (Exception e) {
     logger.warn(e.getMessage(), e);
   }
   return false;
 }
 /**
  * there are certain extensions that get imported with locale maps (incorrectly?) like .png only
  * export locale maps for the list from importexport.xml
  *
  * @param repositoryFile
  * @return true if supported
  */
 private boolean supportedLocaleFileExt(RepositoryFile repositoryFile) {
   boolean ans = true;
   String ext = repositoryFile.getName();
   if (!repositoryFile.isFolder()) {
     int idx = ext.lastIndexOf(".");
     if (idx > 0) {
       ext = ext.substring(idx, ext.length());
     }
     List<String> exportList = getLocaleExportList();
     if (exportList != null) {
       ans = exportList.contains(ext);
     }
   }
   return ans;
 }
  @Test
  public void testGetFolder() throws Exception {
    final MockUnifiedRepository repository =
        new MockUnifiedRepository(new SpringSecurityCurrentUserProvider());
    final RepositoryUtils repositoryUtils = new RepositoryUtils(repository);

    RepositoryFile test = repositoryUtils.getFolder("/public/one/two/three", true, true, null);
    assertNotNull(test);
    assertEquals("The folder name is invalid", "three", test.getName());
    assertEquals("The path is invalid", "/public/one/two/three", test.getPath());
    assertTrue("The folder should be defined as a folder", test.isFolder());

    // Make sure it created the parents
    RepositoryFile one = repositoryUtils.getFolder("/public/one", false, false, null);
    assertNotNull(one);
    RepositoryFile two = repositoryUtils.getFolder("/public/one/two", false, false, null);
    assertNotNull(two);
  }
  /**
   * Take repository file path and local file path and return computed zip entry path
   *
   * @param repositoryFile
   * @param filePath
   * @return
   */
  private String getZipEntryName(RepositoryFile repositoryFile, String filePath) {
    String result = "";

    // if we are at the root, get substring differently
    int filePathLength = 0;

    if (filePath.equals("/")) {
      filePathLength = filePath.length();
    } else {
      filePathLength = filePath.length() + 1;
    }

    result = repositoryFile.getPath().substring(filePathLength);

    // add trailing slash for folders
    if (repositoryFile.isFolder()) {
      result += "/";
    }

    return result;
  }
  @Test
  public void testGetFile() throws Exception {
    final MockUnifiedRepository repository =
        new MockUnifiedRepository(new SpringSecurityCurrentUserProvider());
    final RepositoryUtils repositoryUtils = new RepositoryUtils(repository);

    final SimpleRepositoryFileData data =
        new SimpleRepositoryFileData(
            new ByteArrayInputStream("Test".getBytes()), "UTF-8", "text/plain");
    RepositoryFile test =
        repositoryUtils.getFile("/public/one/two/three.prpt", data, true, true, null);
    assertNotNull(test);
    assertEquals("The filename is invalid", "three.prpt", test.getName());
    assertEquals("The path is invalid", "/public/one/two/three.prpt", test.getPath());
    assertFalse("The file should not be defined as a folder", test.isFolder());

    // Make sure it created the parents
    RepositoryFile one = repositoryUtils.getFolder("/public/one", false, false, null);
    assertNotNull(one);
    RepositoryFile two = repositoryUtils.getFolder("/public/one/two", false, false, null);
    assertNotNull(two);
  }
  /**
   * @param repositoryFile
   * @param outputStream
   * @throws ExportManifestFormatException
   */
  public void exportFile(RepositoryFile repositoryFile, OutputStream outputStream, String filePath)
      throws ExportException, IOException {

    // we need a zip
    ZipOutputStream zos = (ZipOutputStream) outputStream;

    // iterate through handlers to perform export
    for (ExportHandler exportHandler : exportHandlerList) {

      InputStream is = exportHandler.doExport(repositoryFile, filePath);

      // if we don't get a valid input stream back, skip it
      if (is != null) {
        addToManifest(repositoryFile);
        ZipEntry entry = new ZipEntry(getZipEntryName(repositoryFile, filePath));
        zos.putNextEntry(entry);
        IOUtils.copy(is, outputStream);
        zos.closeEntry();
        is.close();
        createLocales(repositoryFile, filePath, repositoryFile.isFolder(), outputStream);
      }
    }
  }
  /**
   * Processes the list of files and performs any processing required to import that data into the
   * repository. If during processing it handles file(s) which should not be handled by downstream
   * import handlers, then it should remove them from the set of files provided.
   *
   * @param importFileSet the set of files to be imported - any files handled to completion by this
   *     Import Handler should remove this files from this list
   * @param comment the import comment provided
   * @param overwrite indicates if the process is authorized to overwrite existing content in the
   *     repository
   * @throws ImportException indicates a significant error during import processing
   */
  @Override
  public void doImport(
      final Iterable<ImportSource.IRepositoryFileBundle> importFileSet,
      final String destinationPath,
      final String comment,
      final boolean overwrite)
      throws ImportException {
    if (null == importFileSet || StringUtils.isEmpty(destinationPath)) {
      throw new IllegalArgumentException();
    }

    // Ensure the destination path is valid
    Assert.notNull(
        getParentId(RepositoryFilenameUtils.normalize(destinationPath + RepositoryFile.SEPARATOR)));

    // Iterate through the file set
    for (Iterator<IRepositoryFileBundle> iterator = importFileSet.iterator();
        iterator.hasNext(); ) {
      final ImportSource.IRepositoryFileBundle bundle =
          (ImportSource.IRepositoryFileBundle) iterator.next();

      // Make sure we don't try to do anything in a system-defined folder
      final String bundlePathName =
          RepositoryFilenameUtils.concat(computeBundlePath(bundle), bundle.getFile().getName());
      if (isSystemPath(bundlePathName)) {
        log.trace("Skipping [" + bundlePathName + "] since it is in admin / system folders");
        continue;
      }
      final String repositoryFilePath =
          RepositoryFilenameUtils.concat(destinationPath, bundlePathName);
      log.trace("Processing [" + bundlePathName + "]");

      // See if the destination already exists in the repository
      final RepositoryFile file = repository.getFile(repositoryFilePath);
      if (file != null) {
        if (file.isFolder() != bundle.getFile().isFolder()) {
          log.warn(
              "Entry already exists in the repository - but it is a "
                  + (file.isFolder() ? "folder" : "file")
                  + " and the entry to be imported is a "
                  + (bundle.getFile().isFolder() ? "folder" : "file"));
        }

        if (!overwrite) {
          log.trace("File already exists in repository and overwrite is false - skipping");
        } else if (file.isFolder()) {
          log.trace("Folder already exists - skip");
        } else {
          // It is a file we can overwrite...
          log.trace("Updating...");
          copyFileToRepository(bundle, bundlePathName, repositoryFilePath, file, comment);
        }
        // We handled this file (even if by doing nothing)
        iterator.remove();
        continue;
      }

      // The file doesn't exist - if it is a folder then this is easy
      if (bundle.getFile().isFolder()) {
        log.trace("Creating folder [" + bundlePathName + "]");
        final Serializable parentId = getParentId(repositoryFilePath);
        if (bundle.getAcl() != null) {
          repository.createFolder(parentId, bundle.getFile(), bundle.getAcl(), comment);
        } else {
          repository.createFolder(parentId, bundle.getFile(), comment);
        }
        iterator.remove();
      } else {
        // It is a file ...
        if (copyFileToRepository(bundle, bundlePathName, repositoryFilePath, null, comment)) {
          iterator.remove();
        }
      }
    }
  }
  /**
   * Performs the export process, returns a zip File object
   *
   * @throws ExportException indicates an error in import processing
   */
  public File performExport(RepositoryFile exportRepositoryFile)
      throws ExportException, IOException {
    File exportFile = null;

    // create temp file
    exportFile = File.createTempFile(EXPORT_TEMP_FILENAME_PREFIX, EXPORT_TEMP_FILENAME_EXT);
    exportFile.deleteOnExit();

    // get the file path
    String filePath = new File(this.path).getParent();
    if (filePath == null) {
      filePath = "/";
    }

    // send a response right away if not found
    if (exportRepositoryFile == null) {
      // todo: add to messages.properties
      throw new FileNotFoundException("JCR file not found: " + this.path);
    }

    ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(exportFile));

    if (exportRepositoryFile.isFolder()) { // Handle recursive export
      exportManifest
          .getManifestInformation()
          .setRootFolder(path.substring(0, path.lastIndexOf("/") + 1));

      // don't zip root folder without name
      if (!ClientRepositoryPaths.getRootFolderPath().equals(exportRepositoryFile.getPath())) {
        zos.putNextEntry(new ZipEntry(getZipEntryName(exportRepositoryFile, filePath)));
      }
      exportDirectory(exportRepositoryFile, zos, filePath);

    } else {
      exportManifest
          .getManifestInformation()
          .setRootFolder(path.substring(0, path.lastIndexOf("/") + 1));
      exportFile(exportRepositoryFile, zos, filePath);
    }

    if (this.withManifest) {
      // write manifest to zip output stream
      ZipEntry entry = new ZipEntry(EXPORT_MANIFEST_FILENAME);
      zos.putNextEntry(entry);

      // pass output stream to manifest class for writing
      try {
        exportManifest.toXml(zos);
      } catch (Exception e) {
        // todo: add to messages.properties
        log.error("Error generating export XML");
      }

      zos.closeEntry();
    }

    zos.close();

    // clean up
    exportManifest = null;
    zos = null;

    return exportFile;
  }