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

org.opalj.br.reader.package.scala Maven / Gradle / Ivy

The newest version!
/* BSD 2-Clause License - see OPAL/LICENSE for details. */
package org.opalj
package br

import scala.util.control.ControlThrowable
import java.io.File
import java.net.URL
import org.opalj.log.LogContext
import org.opalj.log.OPALLogger
import org.opalj.log.GlobalLogContext
import org.opalj.bytecode.JRELibraryFolder
import org.opalj.bytecode.RTJar

import scala.collection.parallel.CollectionConverters.IterableIsParallelizable

/**
 * Defines convenience methods related to reading in class files.
 *
 * @author Michael Eichberg
 */
package object reader {

    final val ConfigKeyPrefix = org.opalj.br.ConfigKeyPrefix+"reader."

    type Source = AnyRef

    /**
     * Reads in all class files found in the jar files or jar and class files in the
     * folders specified by `args`. The class files are read in using the specified
     * class file reader. This enables, e.g., to use this method to only read in
     * the public interface of a class file or to read in complete class files.
     *
     * @param args An `Iterable` of file and folder names that refer to jar files
     *      or folders in which jar and class files are found.
     * @param classFilesReader A function that – given a file (jar, folder, class file) – 
     *      loads the respective class files and returns an `Iterable`. The second
     *      parameter of the function is a function that should be called back by the
     *      reader whenever the processing of given file fails with an exception.
     *      This design was chosen to enable a reader of jar file to continue processing
     *      class files even if the processing of a class file failed.
     */
    def read(
        args:             Iterable[String],
        classFilesReader: (File, (Source, Throwable) => Unit) => Iterable[(ClassFile, URL)]
    ): (Iterable[(ClassFile, URL)], List[Throwable]) = {
        readClassFiles(args.view.map(new File(_)), classFilesReader)
    }

    def readClassFiles(
        files:            Iterable[File],
        classFilesReader: (File, (Source, Throwable) => Unit) => Iterable[(ClassFile, URL)],
        perFile:          File => Unit                                                      = (f: File) => { /*do nothing*/ }
    ): (Iterable[(ClassFile, URL)], List[Throwable]) = {
        val exceptionsMutex = new Object
        var exceptions: List[Throwable] = Nil
        def handleException(source: Source, t: Throwable): Unit = {
            val e = new RuntimeException(s"exception while processing: $source", t)
            exceptionsMutex.synchronized { exceptions ::= e }
        }

        val allClassFiles = for (file <- files.par) yield {
            try {
                perFile(file)
                classFilesReader(file, handleException)
            } catch {
                case ct: ControlThrowable => throw ct
                case t: Throwable         => handleException(file, t); Iterable.empty
            }
        }
        (allClassFiles.flatten.seq, exceptions)
    }

    /**
     * Loads class files from JRE .jars found in the boot classpath.
     *
     * @return List of class files ready to be passed to a `IndexBasedProject`.
     */
    def readJREClassFiles(
        cache: BytecodeInstructionsCache = new BytecodeInstructionsCache
    )(
        implicit
        reader:     ClassFileBinding = new Java11FrameworkWithCaching(cache),
        logContext: LogContext       = GlobalLogContext
    ): Seq[(ClassFile, URL)] = {
        val classFiles = reader.ClassFiles(JRELibraryFolder)
        if (classFiles.isEmpty) {
            OPALLogger.error("project setup", s"loading the JRE ($JRELibraryFolder) failed")
        }

        classFiles
    }

    def readRTJarClassFiles(
        cache: BytecodeInstructionsCache = new BytecodeInstructionsCache
    )(
        implicit
        reader:     ClassFileBinding = new Java11FrameworkWithCaching(cache),
        logContext: LogContext       = GlobalLogContext
    ): Iterable[(ClassFile, URL)] = {
        val classFiles = reader.ClassFiles(RTJar)
        if (classFiles.isEmpty) {
            OPALLogger.error("project setup", s"loading the JRE ($JRELibraryFolder) failed")
        }
        classFiles
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy