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

org.scalajs.linker.PathIRContainer.scala Maven / Gradle / Ivy

/*
 * Scala.js (https://www.scala-js.org/)
 *
 * Copyright EPFL.
 *
 * Licensed under Apache License 2.0
 * (https://www.apache.org/licenses/LICENSE-2.0).
 *
 * See the NOTICE file distributed with this work for
 * additional information regarding copyright ownership.
 */

package org.scalajs.linker

import scala.concurrent._

import java.nio._
import java.nio.file._
import java.nio.file.attribute._
import java.util.EnumSet

import org.scalajs.linker.interface.{IRContainer, IRFile}
import org.scalajs.linker.interface.unstable.IRContainerImpl
import org.scalajs.linker.standard.MemIRFileImpl

import PathIRFile.fileTimeToVersion

object PathIRContainer {
  def fromClasspath(classpath: Seq[Path])(
      implicit ec: ExecutionContext): Future[(Seq[IRContainer], Seq[Path])] = Future {
    val containers = Seq.newBuilder[IRContainer]
    val paths = Seq.newBuilder[Path]

    blocking {
      for (entry <- classpath if Files.exists(entry)) {
        val attrs = Files.readAttributes(entry, classOf[BasicFileAttributes])

        if (attrs.isDirectory()) {
          walkIR(entry) { (path, attrs) =>
            containers += IRContainer.fromIRFile(
                new PathIRFile.PathIRFileImpl(path, attrs.lastModifiedTime()))
            paths += path
          }
        } else if (entry.getFileName().toString().endsWith(".jar")) {
          containers += new JarIRContainer(entry, attrs.lastModifiedTime())
          paths += entry
        } else {
          throw new IllegalArgumentException("Illegal classpath entry " + entry)
        }
      }
    }

    (containers.result(), paths.result())
  }

  private final class JarIRContainer(path: Path, lastModified: FileTime)
      extends IRContainerImpl(path.toString, fileTimeToVersion(lastModified)) {
    def sjsirFiles(implicit ec: ExecutionContext): Future[List[IRFile]] = Future {
      val files = List.newBuilder[IRFile]

      blocking {
        // Open zip/jar file as filesystem.
        val fs = FileSystems.newFileSystem(path,
            // Type ascription is necessary on JDK 13+.
            null: ClassLoader)
        try {
          val i = fs.getRootDirectories().iterator()
          while (i.hasNext()) {
            walkIR(i.next()) { (entry, _) =>
              // We copy the contents of the file, otherwise we'd have to keep
              // the zip file system open (and it's unclear if it would be
              // faster).
              files += new MemIRFileImpl(
                  s"${path.toString}:${entry.toString}", version,
                  Files.readAllBytes(entry))
            }
          }
        } finally {
          fs.close()
        }
      }

      files.result()
    }
  }

  private def walkIR(path: Path)(visit: (Path, BasicFileAttributes) => Unit): Unit = {
    val dirVisitor = new SimpleFileVisitor[Path] {
      override def visitFile(path: Path, attrs: BasicFileAttributes): FileVisitResult = {
        if (path.getFileName().toString().endsWith(".sjsir")) {
          visit(path, attrs)
        }
        super.visitFile(path, attrs)
      }
    }

    Files.walkFileTree(path, EnumSet.of(FileVisitOption.FOLLOW_LINKS), Int.MaxValue, dirVisitor)
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy