<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.workspace

import com.thoughtworks.xstream.XStream
import java.io.File
import java.io.IOException
import java.util.{ Random ⇒ JRandom }
import java.util.UUID
import java.util.logging.Level
import java.util.logging.Logger
import org.apache.commons.configuration._
import org.apache.commons.configuration.reloading._
import org.jasypt.util.text._
import org.openmole.misc.tools.service.Random
import org.openmole.misc.tools.service.Random._
import scala.collection.mutable.HashMap
import org.openmole.misc.eventdispatcher.{ EventDispatcher, Event }
import org.openmole.misc.exception._
import org.openmole.misc.replication._
import org.openmole.misc.tools.io.FileUtil._
import org.openmole.misc.osgi

import scala.concurrent.duration.FiniteDuration
import org.openmole.misc.tools.service._
import java.nio.file.{ Paths, Files }

object Workspace {

  case object PasswordRequired extends Event[Workspace]

  val sessionUUID = UUID.randomUUID

  val preferences = "preferences"
  val globalGroup = "Global"
  val tmpLocation = ".tmp"
  val persistentLocation = "persistent"
  val authenticationsLocation = "authentications"
  val pluginLocation = "plugins"
  val uniqueID = new ConfigurationLocation(globalGroup, "UniqueID")

  private val group = "Workspace"
  private val fixedPrefix = "file"
  private val fixedPostfix = ".bin"
  private val fixedDir = "category"

  private val passwordTest = new ConfigurationLocation(group, "passwordTest", true)
  private val passwordTestString = "<PASSWORD>"

  private val configurations = new HashMap[ConfigurationLocation, () ⇒ String]

  val ErrorArraySnipSize = new ConfigurationLocation(group, "ErrorArraySnipSize")

  this += (uniqueID, UUID.randomUUID.toString)
  this += (passwordTest, passwordTestString)
  this += (ErrorArraySnipSize, "10")

  lazy val defaultLocation = DBServerInfo.base //new File(System.getProperty("user.home"), openMoleDir)
  lazy val instance = new Workspace(defaultLocation)

  Runtime.getRuntime.addShutdownHook(new Thread {
    override def run = synchronized {
      instance.clean
    }
  })

  //implicit def objectToInstance(ws: this.type) = instance

  def +=(location: ConfigurationLocation, defaultValue: () ⇒ String) = synchronized {
    configurations(location) = defaultValue
  }

  def +=(location: ConfigurationLocation, defaultValue: String) = synchronized {
    configurations(location) = () ⇒ defaultValue
  }

  def pluginDirLocation = instance.pluginDir

  def location = instance.location

  def tmpDir = instance.tmpDir

  def newDir(prefix: String): File = instance.newDir(prefix)

  def newFile(prefix: String, suffix: String): File = instance.newFile(prefix, suffix)

  def defaultValue(location: ConfigurationLocation): String = instance.defaultValue(location)

  def overridePreference(preference: String, value: String) = instance.overridePreference(preference, value)

  def overridePreference(preference: ConfigurationLocation, value: String) = instance.overridePreference(preference, value)

  def unsetOverridePreference(preference: String) = instance.unsetOverridePreference(preference)

  def rawPreference(location: ConfigurationLocation): String = instance.rawPreference(location)

  def preference(location: ConfigurationLocation): String = instance.preference(location)

  def setPreference(location: ConfigurationLocation, value: String) = instance.setPreference(location, value)

  def removePreference(location: ConfigurationLocation) = instance.removePreference(location)

  def file(name: String): File = instance.file(name)

  def preferenceAsInt(location: ConfigurationLocation): Int = instance.preferenceAsInt(location)

  def preferenceAsDouble(location: ConfigurationLocation): Double = instance.preferenceAsDouble(location)

  def withTmpFile[T](f: File ⇒ T): T = instance.withTmpFile(f)

  def withTmpFile[T](prefix: String, postfix: String)(f: File ⇒ T): T = instance.withTmpFile(prefix, postfix)(f)

  def newFile: File = instance.newFile

  def newDir: File = instance.newDir

  def reset = instance.reset

  def preferenceAsLong(location: ConfigurationLocation): Long = instance.preferenceAsLong(location)

  def setPassword(password: String) = instance.password_=(password)

  def passwordIsCorrect(password: String) = instance.passwordIsCorrect(password)

  def passwordChosen = instance.passwordChosen

  def preferenceAsDuration(location: ConfigurationLocation) = instance.preferenceAsDuration(location)

  def encrypt(s: String) = instance.encrypt(s)

  def persistent(name: String) = instance.persistent(name)

  implicit def authenticationProvider = instance.authenticationProvider

  def authentications = instance.authentications

  def rng = instance.rng

  def newSeed = instance.newSeed

  object NoneTextEncryptor extends TextEncryptor {
    def decrypt(encryptedMessage: String) = encryptedMessage
    def encrypt(message: String) = message
  }

  def textEncryptor(password: String) =
    if (!password.trim.isEmpty) {
      val textEncryptor = new BasicTextEncryptor
      textEncryptor.setPassword(password)
      textEncryptor
    }
    else NoneTextEncryptor

  def decrypt(s: String, password: String = instance.password) =
    if (s.isEmpty) s
    else Workspace.textEncryptor(password).decrypt(s)

  def openMOLELocation = osgi.openMOLELocation
}

class Workspace(val location: File) {

  import Workspace.{ textEncryptor, decrypt, NoneTextEncryptor, persistentLocation, authenticationsLocation, pluginLocation, fixedPrefix, fixedPostfix, fixedDir, passwordTest, passwordTestString, tmpLocation, preferences, configurations, sessionUUID, uniqueID }

  Files.createDirectories(location)

  val tmpDir = Files.createDirectories(Paths.get(location.toString, tmpLocation)).toFile

  val pluginDir = Files.createDirectories(Paths.get(location.toString, pluginLocation)).toFile<commit_msg>An uniq tmp dir should be created for each instance as it is removed on exit.<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.workspace

import com.thoughtworks.xstream.XStream
import java.io.File
import java.io.IOException
import java.util.{ Random ⇒ JRandom }
import java.util.UUID
import java.util.logging.Level
import java.util.logging.Logger
import org.apache.commons.configuration._
import org.apache.commons.configuration.reloading._
import org.jasypt.util.text._
import org.openmole.misc.tools.service.Random
import org.openmole.misc.tools.service.Random._
import scala.collection.mutable.HashMap
import org.openmole.misc.eventdispatcher.{ EventDispatcher, Event }
import org.openmole.misc.exception._
import org.openmole.misc.replication._
import org.openmole.misc.tools.io.FileUtil._
import org.openmole.misc.osgi

import scala.concurrent.duration.FiniteDuration
import org.openmole.misc.tools.service._
import java.nio.file.{ Paths, Files }

object Workspace {

  case object PasswordRequired extends Event[Workspace]

  val sessionUUID = UUID.randomUUID

  val preferences = "preferences"
  val globalGroup = "Global"
  val tmpLocation = ".tmp"
  val persistentLocation = "persistent"
  val authenticationsLocation = "authentications"
  val pluginLocation = "plugins"
  val uniqueID = new ConfigurationLocation(globalGroup, "UniqueID")

  private val group = "Workspace"
  private val fixedPrefix = "file"
  private val fixedPostfix = ".bin"
  private val fixedDir = "category"

  private val passwordTest = new ConfigurationLocation(group, "passwordTest", true)
  private val passwordTestString = "<PASSWORD>"

  private val configurations = new HashMap[ConfigurationLocation, () ⇒ String]

  val ErrorArraySnipSize = new ConfigurationLocation(group, "ErrorArraySnipSize")

  this += (uniqueID, UUID.randomUUID.toString)
  this += (passwordTest, passwordTestString)
  this += (ErrorArraySnipSize, "10")

  lazy val defaultLocation = DBServerInfo.base //new File(System.getProperty("user.home"), openMoleDir)
  lazy val instance = new Workspace(defaultLocation)

  Runtime.getRuntime.addShutdownHook(new Thread {
    override def run = synchronized {
      instance.clean
    }
  })

  //implicit def objectToInstance(ws: this.type) = instance

  def +=(location: ConfigurationLocation, defaultValue: () ⇒ String) = synchronized {
    configurations(location) = defaultValue
  }

  def +=(location: ConfigurationLocation, defaultValue: String) = synchronized {
    configurations(location) = () ⇒ defaultValue
  }

  def pluginDirLocation = instance.pluginDir

  def location = instance.location

  def tmpDir = instance.tmpDir

  def newDir(prefix: String): File = instance.newDir(prefix)

  def newFile(prefix: String, suffix: String): File = instance.newFile(prefix, suffix)

  def defaultValue(location: ConfigurationLocation): String = instance.defaultValue(location)

  def overridePreference(preference: String, value: String) = instance.overridePreference(preference, value)

  def overridePreference(preference: ConfigurationLocation, value: String) = instance.overridePreference(preference, value)

  def unsetOverridePreference(preference: String) = instance.unsetOverridePreference(preference)

  def rawPreference(location: ConfigurationLocation): String = instance.rawPreference(location)

  def preference(location: ConfigurationLocation): String = instance.preference(location)

  def setPreference(location: ConfigurationLocation, value: String) = instance.setPreference(location, value)

  def removePreference(location: ConfigurationLocation) = instance.removePreference(location)

  def file(name: String): File = instance.file(name)

  def preferenceAsInt(location: ConfigurationLocation): Int = instance.preferenceAsInt(location)

  def preferenceAsDouble(location: ConfigurationLocation): Double = instance.preferenceAsDouble(location)

  def withTmpFile[T](f: File ⇒ T): T = instance.withTmpFile(f)

  def withTmpFile[T](prefix: String, postfix: String)(f: File ⇒ T): T = instance.withTmpFile(prefix, postfix)(f)

  def newFile: File = instance.newFile

  def newDir: File = instance.newDir

  def reset = instance.reset

  def preferenceAsLong(location: ConfigurationLocation): Long = instance.preferenceAsLong(location)

  def setPassword(password: String) = instance.password_=(password)

  def passwordIsCorrect(password: String) = instance.passwordIsCorrect(password)

  def passwordChosen = instance.passwordChosen

  def preferenceAsDuration(location: ConfigurationLocation) = instance.preferenceAsDuration(location)

  def encrypt(s: String) = instance.encrypt(s)

  def persistent(name: String) = instance.persistent(name)

  implicit def authenticationProvider = instance.authenticationProvider

  def authentications = instance.authentications

  def rng = instance.rng

  def newSeed = instance.newSeed

  object NoneTextEncryptor extends TextEncryptor {
    def decrypt(encryptedMessage: String) = encryptedMessage
    def encrypt(message: String) = message
  }

  def textEncryptor(password: String) =
    if (!password.trim.isEmpty) {
      val textEncryptor = new BasicTextEncryptor
      textEncryptor.setPassword(password)
      textEncryptor
    }
    else NoneTextEncryptor

  def decrypt(s: String, password: String = instance.password) =
    if (s.isEmpty) s
    else Workspace.textEncryptor(password).decrypt(s)

  def openMOLELocation = osgi.openMOLELocation
}

class Workspace(val location: File) {

  import Workspace.{ textEncryptor, decrypt, NoneTextEncryptor, persistentLocation, authenticationsLocation, pluginLocation, fixedPrefix, fixedPostfix, fixedDir, passwordTest, passwordTestString, tmpLocation, preferences, configurations, sessionUUID, uniqueID }

  Files.createDirectories(location)

  val tmpDir = location.newDir(tmpLocation)

  val pluginDir = Files.createDirectories(Paths.get(location.toString, pluginLocation)).toFile
{'fraction_non_alphanumeric': 0.08871518555058056, 'fraction_numerical': 0.0010624573119830008, 'mean_word_length': 5.248458985301091, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 9, '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': '4447252', 'n_tokens_mistral': 3710, 'n_tokens_neox': 3589, 'n_words': 1017}