<commit_before>/*
 * Copyright (C) 2010 <NAME>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * 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 Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package org.openmole.misc.fileservice

import com.ice.tar.TarOutputStream
import java.io.File
import java.io.FileOutputStream
import java.util.logging.Logger
import org.openmole.misc.tools.cache.AssociativeCache
import org.openmole.misc.tools.io.FileUtil._
import org.openmole.misc.tools.io.TarArchiver._
import org.openmole.misc.tools.service.Hash
import org.openmole.misc.filecache.FileCacheDeleteOnFinalize
import org.openmole.misc.filecache.IFileCache
import org.openmole.misc.hashservice.HashService
import org.openmole.misc.updater.Updater
import org.openmole.misc.workspace.ConfigurationLocation
import org.openmole.misc.workspace.Workspace

object FileService {
  val GCInterval = new ConfigurationLocation("FileService", "GCInterval")
  Workspace += (GCInterval, "PT5M")

  class CachedArchiveForDir(file: File, val lastModified: Long) extends FileCacheDeleteOnFinalize(file)

  private[fileservice] val hashCache = new AssociativeCache[String, Hash]
  private[fileservice] val archiveCache = new AssociativeCache[String, CachedArchiveForDir]

  Updater.delay(new FileServiceGC, Workspace.preferenceAsDuration(FileService.GCInterval).toMilliSeconds)

  def hash(file: File): Hash =
    if (file.isDirectory) hash(archiveForDir(file).file(false), file)
    else hash(file, file)

  def invalidate(key: Object, file: File) = hashCache.invalidateCache(key, file.getAbsolutePath)

  def archiveForDir(file: File): IFileCache = archiveForDir(file, file)

  def hash(key: Object, file: File): Hash = hashCache.cache(key, file.getAbsolutePath, HashService.computeHash(file))

  def archiveForDir(key: Object, file: File): IFileCache = {
    archiveCache.cache(key, file.getAbsolutePath, {
      val ret = Workspace.newFile("archive", ".tar");
      val os = new TarOutputStream(new FileOutputStream(ret))
      try os.createDirArchiveWithRelativePathNoVariableContent(file)<commit_msg>Fix bug on upload for directories.<commit_after>/*
 * Copyright (C) 2010 <NAME>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * 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 Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package org.openmole.misc.fileservice

import com.ice.tar.TarOutputStream
import java.io.File
import java.io.FileOutputStream
import java.util.logging.Logger
import org.openmole.misc.tools.cache.AssociativeCache
import org.openmole.misc.tools.io.FileUtil._
import org.openmole.misc.tools.io.TarArchiver._
import org.openmole.misc.tools.service.Hash
import org.openmole.misc.filecache.FileCacheDeleteOnFinalize
import org.openmole.misc.filecache.IFileCache
import org.openmole.misc.hashservice.HashService
import org.openmole.misc.updater.Updater
import org.openmole.misc.workspace.ConfigurationLocation
import org.openmole.misc.workspace.Workspace

object FileService {
  val GCInterval = new ConfigurationLocation("FileService", "GCInterval")
  Workspace += (GCInterval, "PT5M")

  class CachedArchiveForDir(file: File, val lastModified: Long) extends FileCacheDeleteOnFinalize(file)

  private[fileservice] val hashCache = new AssociativeCache[String, Hash]
  private[fileservice] val archiveCache = new AssociativeCache[String, CachedArchiveForDir]

  Updater.delay(new FileServiceGC, Workspace.preferenceAsDuration(FileService.GCInterval).toMilliSeconds)

  def hash(file: File): Hash =
    if (file.isDirectory) hash(archiveForDir(file).file(false), file)
    else hash(file, file)

  def invalidate(key: Object, file: File) = hashCache.invalidateCache(key, file.getAbsolutePath)

  def archiveForDir(file: File): IFileCache = archiveForDir(file, file)

  def hash(key: Object, file: File): Hash =
    hashCache.cache(
      key,
      file.getAbsolutePath,
      if (file.isDirectory) hash(archiveForDir(key, file).file(false), file)
      else hash(key, file)
    )

  def archiveForDir(key: Object, file: File): IFileCache = {
    archiveCache.cache(key, file.getAbsolutePath, {
      val ret = Workspace.newFile("archive", ".tar");
      val os = new TarOutputStream(new FileOutputStream(ret))
      try os.createDirArchiveWithRelativePathNoVariableContent(file)
{'fraction_non_alphanumeric': 0.09165885660731021, 'fraction_numerical': 0.0022492970946579195, 'mean_word_length': 5.015783540022548, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2659906', 'n_tokens_mistral': 1590, 'n_tokens_neox': 1539, 'n_words': 456}