All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.ensime.vfs.EnsimeVFS.scala Maven / Gradle / Ivy

There is a newer version: 2.0.2
Show newest version
// Copyright: 2010 - 2016 https://github.com/ensime/ensime-server/graphs
// Licence: http://www.gnu.org/licenses/gpl-3.0.en.html
package org.ensime.vfs

import java.io.File
import java.util.zip.ZipFile

import org.apache.commons.vfs2._
import org.apache.commons.vfs2.impl._
import org.apache.commons.vfs2.provider.zip.ZipFileSystem

abstract class ExtSelector extends FileSelector {
  def includeFile(f: FileObject): Boolean = include(f.getName.getExtension)
  def includeFile(info: FileSelectInfo): Boolean = includeFile(info.getFile)
  def includeFile(f: File): Boolean = include.exists(f.getName.endsWith(_))
  def traverseDescendents(info: FileSelectInfo) = true
  def include: Set[String]
}

// intended to be used when watching a single jar file
object JarSelector extends ExtSelector {
  val include = Set("jar")
  override def traverseDescendents(info: FileSelectInfo) = false
}

object ClassfileSelector extends ExtSelector {
  val include = Set("class")
}

object SourceSelector extends ExtSelector {
  val include = Set("scala", "java")
}

object EnsimeVFS {
  def apply(): EnsimeVFS = {
    val vfsInst = new StandardFileSystemManager()
    vfsInst.init()
    vfsInst
  }
}

object `package` {
  type EnsimeVFS = DefaultFileSystemManager

  // the alternative is a monkey patch, count yourself lucky
  private val zipFileField = classOf[ZipFileSystem].getDeclaredField("zipFile")
  zipFileField.setAccessible(true)

  object URLParamEncoder {
    def encode(input: String): String = {
      var ofs = 0
      val resultStr = new StringBuilder()
      while (ofs < input.length) {
        val ch = input.charAt(ofs)
        if ((ch == '+') || (ch == '%'))
          resultStr.append("%%%02x".format(ch.toShort))
        else
          resultStr.append(ch)
        ofs += 1
      }
      resultStr.toString
    }
  }

  implicit class RichVFS(val vfs: DefaultFileSystemManager) extends AnyVal {
    implicit def toFileObject(f: File): FileObject = vfile(f)

    private def withContext[T](msg: String)(t: => T): T = try { t } catch {
      case e: FileSystemException => throw new FileSystemException(e.getMessage + " in " + msg, e)
    }

    def vfile(name: String) = withContext(s"$name =>")(
      vfs.resolveFile(name.intern)
    )
    def vfile(file: File) = withContext(s"$file =>")(
      vfs.toFileObject(file)
    )
    def vres(path: String) = withContext(s"$path =>")(
      vfs.resolveFile(asUri("res", path).intern)
    )
    def vjar(jar: File) = withContext(s"$jar =>") {
      vfs.resolveFile(asUri("jar", jar.getAbsolutePath).intern)
    }
    def vjar(jar: FileObject) = withContext(s"$jar =>")(
      vfs.resolveFile(("jar:" + jar.getName.getURI).intern)
    )

    private def asUri(scheme: String, path: String): String = {
      s"${scheme}:${URLParamEncoder.encode(path)}"
    }

    // WORKAROUND https://issues.apache.org/jira/browse/VFS-594
    def nuke(jar: FileObject) = {
      jar.close()

      val fs = jar.getFileSystem

      // clearing an entry from the cache doesn't close it
      val zip = zipFileField.get(fs)
      if (zip != null)
        zip.asInstanceOf[ZipFile].close()

      vfs.getFilesCache.clear(fs)
      vfs.closeFileSystem(fs)
    }
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy