static {
   final Set<ChecksumType> availableTypes = checksumProviderFactory.getAvailableTypes();
   final ImmutableList.Builder<ChecksumAlgorithm> builder = ImmutableList.builder();
   for (final ChecksumAlgorithm checksumAlgorithm :
       ChecksumAlgorithmMapper.getAllChecksumAlgorithms()) {
     final ChecksumType checksumType = ChecksumAlgorithmMapper.getChecksumType(checksumAlgorithm);
     if (availableTypes.contains(checksumType)) {
       builder.add(checksumAlgorithm);
     }
   }
   availableChecksumAlgorithms = builder.build();
 }
  public PublicRepositoryI(
      RepositoryDao repositoryDao,
      ChecksumProviderFactory checksumProviderFactory,
      String checksumAlgorithmSupported,
      String pathRules)
      throws ServerError {
    this.repositoryDao = repositoryDao;
    this.checksumProviderFactory = checksumProviderFactory;
    this.repoUuid = null;

    final Builder<ChecksumAlgorithm> checksumAlgorithmsBuilder = ImmutableList.builder();
    for (final String term : checksumAlgorithmSupported.split(",")) {
      if (StringUtils.isNotBlank(term)) {
        checksumAlgorithmsBuilder.add(ChecksumAlgorithmMapper.getChecksumAlgorithm(term.trim()));
      }
    }
    this.checksumAlgorithms = checksumAlgorithmsBuilder.build();
    if (this.checksumAlgorithms.isEmpty()) {
      throw new IllegalArgumentException("a checksum algorithm must be supported");
    }

    final Set<String> terms = new HashSet<String>();
    for (final String term : pathRules.split(",")) {
      if (StringUtils.isNotBlank(term)) {
        terms.add(term.trim());
      }
    }
    final String[] termArray = terms.toArray(new String[terms.size()]);
    try {
      this.filePathRestrictions = FilePathRestrictionInstance.getFilePathRestrictions(termArray);
    } catch (NullPointerException e) {
      throw new ServerError(null, null, "unknown rule set named in: " + pathRules);
    }
  }
  /**
   * Provide initial configuration to the server in order to create the {@link ImportProcessPrx}
   * which will manage state server-side.
   *
   * @param container the import container
   * @return the new import process from the server
   * @throws ServerError if the import process could not be created
   * @throws IOException if the used files' absolute path could not be found
   */
  public ImportProcessPrx createImport(final ImportContainer container)
      throws ServerError, IOException {
    checkManagedRepo();
    String[] usedFiles = container.getUsedFiles();
    File target = container.getFile();
    if (log.isDebugEnabled()) {
      log.debug("Main file: " + target.getAbsolutePath());
      log.debug("Used files before:");
      for (String f : usedFiles) {
        log.debug(f);
      }
    }

    notifyObservers(
        new ImportEvent.FILESET_UPLOAD_PREPARATION(null, 0, usedFiles.length, null, null, null));

    // Copied to ClientPathExclusion
    // TODO: allow looser sanitization according to server configuration
    final FilePathRestrictions portableRequiredRules =
        FilePathRestrictionInstance.getFilePathRestrictions(
            FilePathRestrictionInstance.WINDOWS_REQUIRED,
            FilePathRestrictionInstance.UNIX_REQUIRED);
    final ClientFilePathTransformer sanitizer =
        new ClientFilePathTransformer(new MakePathComponentSafe(portableRequiredRules));

    final ImportSettings settings = new ImportSettings();
    final Fileset fs = new FilesetI();
    container.fillData(settings, fs, sanitizer, transfer);

    String caStr = container.getChecksumAlgorithm();
    if (caStr != null) {
      settings.checksumAlgorithm = ChecksumAlgorithmMapper.getChecksumAlgorithm(caStr);
    } else {
      // check if the container object has ChecksumAlgorithm
      // present and pass it into the settings object
      settings.checksumAlgorithm = repo.suggestChecksumAlgorithm(availableChecksumAlgorithms);
      if (settings.checksumAlgorithm == null) {
        throw new RuntimeException("no supported checksum algorithm negotiated with server");
      }
    }
    return repo.importFileset(fs, settings);
  }
  public String uploadFile(
      final ImportProcessPrx proc,
      final String[] srcFiles,
      final int index,
      final ChecksumProviderFactory cpf,
      TimeEstimator estimator,
      final byte[] buf)
      throws ServerError, IOException {

    final ChecksumProvider cp =
        cpf.getProvider(
            ChecksumAlgorithmMapper.getChecksumType(proc.getImportSettings().checksumAlgorithm));

    final File file = new File(Location.getMappedId(srcFiles[index]));

    try {
      return transfer.transfer(
          new TransferState(file, index, srcFiles.length, proc, this, estimator, cp, buf));
    } catch (Exception e) {
      // Required to bump the error count
      notifyObservers(
          new ErrorHandler.FILE_EXCEPTION(file.getAbsolutePath(), e, srcFiles, "unknown"));
      // The state that we're entering, i.e. exiting upload via error
      notifyObservers(
          new ImportEvent.FILE_UPLOAD_ERROR(
              file.getAbsolutePath(), index, srcFiles.length, null, null, e));
      if (e instanceof RuntimeException) {
        throw (RuntimeException) e;
      } else if (e instanceof ServerError) {
        throw (ServerError) e;
      } else if (e instanceof IOException) {
        throw (IOException) e;
      } else {
        String msg = "Unexpected exception thrown!";
        log.error(msg, e);
        throw new RuntimeException(msg, e);
      }
    }
  }
  /**
   * Method called locally to the repository during {@link #rawAccess()}. Only the remoteable fields
   * should be accessed during this method call since this will be a copy of the object originally
   * called.
   *
   * @param abstractRepositoryI
   * @param servant
   * @param __current
   */
  public void local(
      AbstractRepositoryI abstractRepositoryI, PublicRepositoryI servant, Current __current)
      throws Exception {

    if ("touch".equals(command)) {
      for (String arg : args) {
        final CheckedPath checked = servant.checkPath(parse(arg), null, __current);
        if (!checked.exists()) {
          final CheckedPath parent = checked.parent();
          if (!(parent.isDirectory() || checked.parent().mkdirs())) {
            throw new RepositoryException(null, null, "cannot create directory: " + parent);
          }
          final FileBuffer buffer = checked.getFileBuffer("rw");
          buffer.write(ByteBuffer.allocate(0));
          buffer.close();
        } else if (!checked.markModified()) {
          throw new RepositoryException(null, null, "cannot touch file: " + checked);
        }
      }
    } else if ("mkdir".equals(command)) {
      boolean parents = false;
      for (String arg : args) {
        if ("-p".equals(arg)) {
          parents = true;
          continue;
        }
        final CheckedPath checked = servant.checkPath(parse(arg), null, __current);
        if (parents) {
          checked.mkdirs();
        } else {
          checked.mkdir();
        }
      }
    } else if ("rm".equals(command)) {
      if (args.size() == 1) {
        final CheckedPath checked = servant.checkPath(parse(args.get(0)), null, __current);
        if (!checked.delete()) {
          throw new omero.grid.FileDeleteException(
              null, null, "Delete file failed: " + args.get(0));
        }
      } else {
        throw new omero.ApiUsageException(
            null, null, "Command: " + command + " takes just one argument");
      }
    } else if ("checksum".equals(command)) {
      if (args.size() == 3) {
        final String checksumType = args.get(0);
        final ChecksumAlgorithm algo = ChecksumAlgorithmMapper.getChecksumAlgorithm(checksumType);
        final String expectedHash = args.get(1);
        final CheckedPath checked = servant.checkPath(parse(args.get(2)), algo, __current);
        final String currentHash = checked.hash();
        if (!currentHash.equals(expectedHash)) {
          // TODO: ADD ANNOTATION TO DATABASE HERE!
          throw new omero.ResourceError(
              null,
              null,
              String.format(
                  "Checksum mismatch (%s): expected=%s found=%s",
                  checksumType, expectedHash, currentHash));
        }
      } else {
        throw new omero.ApiUsageException(
            null, null, "'checksum' requires HASHER HASH FILEPATH, not: " + args.toString());
      }
    } else {
      throw new omero.ApiUsageException(null, null, "Unknown command: " + command);
    }
  }