// Path: stecker-plugin-loader/src/main/java/org/meridor/stecker/PluginException.java
// public class PluginException extends Exception {
// 
//     private Optional<DependencyProblem> dependencyProblem = Optional.empty();
// 
//     private Optional<PluginMetadata> pluginMetadata = Optional.empty();
// 
//     public PluginException(Exception e) {
//         super(e);
//     }
// 
//     public PluginException(String message) {
//         super(message);
//     }
// 
//     public PluginException(String message, Exception e) {
//         super(message, e);
//     }
// 
//     public PluginException withDependencyProblem(DependencyProblem dependencyProblem) {
//         this.dependencyProblem = Optional.ofNullable(dependencyProblem);
//         return this;
//     }
// 
//     public PluginException withPlugin(PluginMetadata pluginMetadata) {
//         this.pluginMetadata = Optional.ofNullable(pluginMetadata);
//         return this;
//     }
// 
//     /**
//      * Returns dependency problem if any
//      *
//      * @return dependency problem
//      */
//     public Optional<DependencyProblem> getDependencyProblem() {
//         return dependencyProblem;
//     }
// 
//     /**
//      * Returns plugin affected
//      *
//      * @return plugin metadata
//      */
//     public Optional<PluginMetadata> getPluginMetadata() {
//         return pluginMetadata;
//     }
// 
// }
// 
// Path: stecker-plugin-loader/src/main/java/org/meridor/stecker/interfaces/ClassesScanner.java
// public interface ClassesScanner {
// 
//     /**
//      * Returns a mapping between extension point classes and plugin file classes. E.g. if extension point is
//      * an interface <b>A</b> and some plugin implements it in classes B and C then the mapping will be: A -&gt; (B, C).
//      *
//      * @param pluginFile      plugin file to process
//      * @param extensionPoints a list of extension point classes
//      * @return mapping from extension point to implementations from a plugin
//      * @throws org.meridor.stecker.PluginException when something goes wrong during classes scanning
//      */
//     ScanResult scan(Path pluginFile, List<Class> extensionPoints) throws PluginException;
// 
// }
// 
// Path: stecker-plugin-loader/src/main/java/org/meridor/stecker/interfaces/PluginImplementationsAware.java
// public interface PluginImplementationsAware {
// 
//     /**
//      * Returns a list of present extension points
//      *
//      * @return a list of extension points
//      */
//     List<Class> getExtensionPoints();
// 
//     /**
//      * Returns classes implementing extension point
//      *
//      * @param extensionPoint extension point class
//      * @return a list of implementation classes
//      */
//     List<Class> getImplementations(Class extensionPoint);
// 
// }
// 
// Path: stecker-plugin-loader/src/main/java/org/meridor/stecker/interfaces/ScanResult.java
// public interface ScanResult {
// 
//     ClassLoader getClassLoader();
// 
//     PluginImplementationsAware getContents();
// 
// }


import org.meridor.stecker.PluginException;
import org.meridor.stecker.interfaces.ClassesScanner;
import org.meridor.stecker.interfaces.PluginImplementationsAware;
import org.meridor.stecker.interfaces.ScanResult;
import java.nio.file.Path;
import java.util.List;
package org.meridor.stecker.impl;



public class DefaultClassesScanner implements ClassesScanner {

    private final Path cacheDirectory;

    public DefaultClassesScanner(Path cacheDirectory) {
        this.cacheDirectory = cacheDirectory;
    }

    @Override
    public ScanResult scan(Path pluginFile, List<Class> extensionPoints) throws PluginException {
        try {
            Path unpackedPluginDirectory = PluginUtils.unpackPlugin(pluginFile, cacheDirectory);
            Path pluginImplementationDirectory = PluginUtils.getPluginImplementationDirectory(unpackedPluginDirectory);

            ClassLoader classLoader = getClassLoader(unpackedPluginDirectory, pluginImplementationDirectory);
// Path: stecker-plugin-loader/src/main/java/org/meridor/stecker/PluginException.java
// public class PluginException extends Exception {
// 
//     private Optional<DependencyProblem> dependencyProblem = Optional.empty();
// 
//     private Optional<PluginMetadata> pluginMetadata = Optional.empty();
// 
//     public PluginException(Exception e) {
//         super(e);
//     }
// 
//     public PluginException(String message) {
//         super(message);
//     }
// 
//     public PluginException(String message, Exception e) {
//         super(message, e);
//     }
// 
//     public PluginException withDependencyProblem(DependencyProblem dependencyProblem) {
//         this.dependencyProblem = Optional.ofNullable(dependencyProblem);
//         return this;
//     }
// 
//     public PluginException withPlugin(PluginMetadata pluginMetadata) {
//         this.pluginMetadata = Optional.ofNullable(pluginMetadata);
//         return this;
//     }
// 
//     /**
//      * Returns dependency problem if any
//      *
//      * @return dependency problem
//      */
//     public Optional<DependencyProblem> getDependencyProblem() {
//         return dependencyProblem;
//     }
// 
//     /**
//      * Returns plugin affected
//      *
//      * @return plugin metadata
//      */
//     public Optional<PluginMetadata> getPluginMetadata() {
//         return pluginMetadata;
//     }
// 
// }
// 
// Path: stecker-plugin-loader/src/main/java/org/meridor/stecker/interfaces/ClassesScanner.java
// public interface ClassesScanner {
// 
//     /**
//      * Returns a mapping between extension point classes and plugin file classes. E.g. if extension point is
//      * an interface <b>A</b> and some plugin implements it in classes B and C then the mapping will be: A -&gt; (B, C).
//      *
//      * @param pluginFile      plugin file to process
//      * @param extensionPoints a list of extension point classes
//      * @return mapping from extension point to implementations from a plugin
//      * @throws org.meridor.stecker.PluginException when something goes wrong during classes scanning
//      */
//     ScanResult scan(Path pluginFile, List<Class> extensionPoints) throws PluginException;
// 
// }
// 
// Path: stecker-plugin-loader/src/main/java/org/meridor/stecker/interfaces/PluginImplementationsAware.java
// public interface PluginImplementationsAware {
// 
//     /**
//      * Returns a list of present extension points
//      *
//      * @return a list of extension points
//      */
//     List<Class> getExtensionPoints();
// 
//     /**
//      * Returns classes implementing extension point
//      *
//      * @param extensionPoint extension point class
//      * @return a list of implementation classes
//      */
//     List<Class> getImplementations(Class extensionPoint);
// 
// }
// 
// Path: stecker-plugin-loader/src/main/java/org/meridor/stecker/interfaces/ScanResult.java
// public interface ScanResult {
// 
//     ClassLoader getClassLoader();
// 
//     PluginImplementationsAware getContents();
// 
// }


// Path: stecker-plugin-loader/src/main/java/org/meridor/stecker/impl/DefaultClassesScanner.java
import org.meridor.stecker.PluginException;
import org.meridor.stecker.interfaces.ClassesScanner;
import org.meridor.stecker.interfaces.PluginImplementationsAware;
import org.meridor.stecker.interfaces.ScanResult;
import java.nio.file.Path;
import java.util.List;

package org.meridor.stecker.impl;



public class DefaultClassesScanner implements ClassesScanner {

    private final Path cacheDirectory;

    public DefaultClassesScanner(Path cacheDirectory) {
        this.cacheDirectory = cacheDirectory;
    }

    @Override
    public ScanResult scan(Path pluginFile, List<Class> extensionPoints) throws PluginException {
        try {
            Path unpackedPluginDirectory = PluginUtils.unpackPlugin(pluginFile, cacheDirectory);
            Path pluginImplementationDirectory = PluginUtils.getPluginImplementationDirectory(unpackedPluginDirectory);

            ClassLoader classLoader = getClassLoader(unpackedPluginDirectory, pluginImplementationDirectory);
            PluginImplementationsAware pluginImplementationsAware = PluginUtils.getMatchingClasses(extensionPoints, pluginImplementationDirectory, classLoader);