// Path: cicomponents-test/src/main/java/com/cicomponents/test/ContainerConfiguration.java
// public class ContainerConfiguration {
// 
//     @SuppressWarnings("unused")
//     public static final MavenUrlReference karafStandardRepo =
//             maven()
//                     .groupId("org.apache.karaf.features")
//                     .artifactId("standard")
//                     .version("4.0.8")
//                     .classifier("features")
//                     .type("xml");
// 
// 
//     @Configuration
//     public static Option[] withDefaultConfig(final Option ...options) {
//         Option[] defaultOptions = {
//                 keepCaches(),
//                 karafDistributionConfiguration()
//                 .frameworkUrl(maven().groupId("org.apache.karaf").artifactId("apache-karaf-minimal").type("zip")
//                                      .version("4.0.8"))
//                 .karafVersion("4.0.8")
//                 .unpackDirectory(new File("target/exam")),
//                 keepRuntimeFolder(),
//                 logLevel(WARN),
//                 features(maven().groupId("org.cicomponents").artifactId("cicomponents").type("xml")
//                        .classifier("features").version("0.2.0-SNAPSHOT"), "cicomponents"),
//                 junitBundles(),
//                 features(karafStandardRepo),
//                 bundle("wrap:mvn:com.google.guava/guava-testlib/19.0"),
//                 configureConsole().ignoreLocalConsole().ignoreRemoteShell()
//         };
//         return Stream.concat(Arrays.stream(defaultOptions), Arrays.stream(options)).collect(Collectors.toList())
//                      .toArray(defaultOptions);
//     }
// 
// 
// 
// }
// 
// Path: cicomponents-api/src/main/java/org/cicomponents/ResourceEmitter.java
// public interface ResourceEmitter<T extends Resource> {
//     void addResourceListener(ResourceListener<T> listener);
//     void removeResourceListener(ResourceListener<T> listener);
// }
// 
// Path: cicomponents-api/src/main/java/org/cicomponents/ResourceHolder.java
// public interface ResourceHolder<T extends Resource> {
//     T acquire();
// }
// 
// Path: cicomponents-api/src/main/java/org/cicomponents/ResourceListener.java
// @FunctionalInterface
// public interface ResourceListener<T extends Resource> {
//     void onEmittedResource(ResourceHolder<T> holder,
//                            ResourceEmitter<T> emitter);
// 
//     default boolean isMatchingListener(Class klass) {
//         for (Type type : getClass().getGenericInterfaces()) {
//             if (type instanceof ParameterizedType &&
//                     ((ParameterizedType) type).getRawType() == ResourceListener.class) {
//                 ParameterizedType parameterizedType = (ParameterizedType) type;
//                 Type target = parameterizedType.getActualTypeArguments()[0];
//                 if (target == klass) {
//                     return true;
//                 }
//             }
//         }
//         return false;
//     }
// }
// 
// Path: cicomponents-fs-api/src/main/java/org/cicomponents/fs/WorkingDirectory.java
// public interface WorkingDirectory extends Resource {
//     String getDirectory();
// }
// 
// Path: cicomponents-fs-api/src/main/java/org/cicomponents/fs/WorkingDirectoryProvider.java
// public interface WorkingDirectoryProvider {
//     WorkingDirectory getDirectory();
// }
// 
// Path: cicomponents-git-api/src/main/java/org/cicomponents/git/GitRevision.java
// public interface GitRevision extends File, Resource {
//     Git getRepository();
//     ObjectId getRef();
// }
// 
// Path: cicomponents-git-api/src/main/java/org/cicomponents/git/GitRevisionEmitter.java
// public interface GitRevisionEmitter extends ResourceEmitter<GitRevision> {
// }


import com.cicomponents.test.ContainerConfiguration;
import lombok.Getter;
import lombok.SneakyThrows;
import org.cicomponents.ResourceEmitter;
import org.cicomponents.ResourceHolder;
import org.cicomponents.ResourceListener;
import org.cicomponents.fs.WorkingDirectory;
import org.cicomponents.fs.WorkingDirectoryProvider;
import org.cicomponents.git.GitRevision;
import org.cicomponents.git.GitRevisionEmitter;
import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.revwalk.RevCommit;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.ops4j.pax.exam.Configuration;
import org.ops4j.pax.exam.Option;
import org.ops4j.pax.exam.junit.PaxExam;
import org.ops4j.pax.exam.spi.reactors.ExamReactorStrategy;
import org.ops4j.pax.exam.spi.reactors.PerMethod;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
import org.osgi.framework.ServiceRegistration;
import javax.inject.Inject;
import java.io.File;
import java.util.Collection;
import java.util.Hashtable;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import static junit.framework.TestCase.assertFalse;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
        public void onEmittedResource(ResourceHolder<GitRevision> holder, ResourceEmitter<GitRevision> emitter) {
            try (GitRevision resource = holder.acquire()) {
                future.complete(resource.getRef());
            }
        }

        void reset() {
            future = new CompletableFuture<>();
        }
    }

    @Inject
    private WorkingDirectoryProvider workingDirectoryProvider;

    @Test
    @SneakyThrows
    public void listenerDiscovery() {
        try (WorkingDirectory directory = workingDirectoryProvider.getDirectory()) {
            Git git = Git.init().setDirectory(new File(directory.getDirectory())).call();
            RevCommit commit = git.commit().setAllowEmpty(true).setMessage("Test").call();

            Hashtable<String, Object> properties = new Hashtable<>();
            properties.put("repository","file://" + git.getRepository().getDirectory().getAbsolutePath());
            properties.put("type", "latest");
            Listener listener = new Listener();
            ServiceRegistration<ResourceListener> registration = bundleContext
                    .registerService(ResourceListener.class, listener, properties);


            Collection<ServiceReference<GitRevisionEmitter>> references = bundleContext
// Path: cicomponents-test/src/main/java/com/cicomponents/test/ContainerConfiguration.java
// public class ContainerConfiguration {
// 
//     @SuppressWarnings("unused")
//     public static final MavenUrlReference karafStandardRepo =
//             maven()
//                     .groupId("org.apache.karaf.features")
//                     .artifactId("standard")
//                     .version("4.0.8")
//                     .classifier("features")
//                     .type("xml");
// 
// 
//     @Configuration
//     public static Option[] withDefaultConfig(final Option ...options) {
//         Option[] defaultOptions = {
//                 keepCaches(),
//                 karafDistributionConfiguration()
//                 .frameworkUrl(maven().groupId("org.apache.karaf").artifactId("apache-karaf-minimal").type("zip")
//                                      .version("4.0.8"))
//                 .karafVersion("4.0.8")
//                 .unpackDirectory(new File("target/exam")),
//                 keepRuntimeFolder(),
//                 logLevel(WARN),
//                 features(maven().groupId("org.cicomponents").artifactId("cicomponents").type("xml")
//                        .classifier("features").version("0.2.0-SNAPSHOT"), "cicomponents"),
//                 junitBundles(),
//                 features(karafStandardRepo),
//                 bundle("wrap:mvn:com.google.guava/guava-testlib/19.0"),
//                 configureConsole().ignoreLocalConsole().ignoreRemoteShell()
//         };
//         return Stream.concat(Arrays.stream(defaultOptions), Arrays.stream(options)).collect(Collectors.toList())
//                      .toArray(defaultOptions);
//     }
// 
// 
// 
// }
// 
// Path: cicomponents-api/src/main/java/org/cicomponents/ResourceEmitter.java
// public interface ResourceEmitter<T extends Resource> {
//     void addResourceListener(ResourceListener<T> listener);
//     void removeResourceListener(ResourceListener<T> listener);
// }
// 
// Path: cicomponents-api/src/main/java/org/cicomponents/ResourceHolder.java
// public interface ResourceHolder<T extends Resource> {
//     T acquire();
// }
// 
// Path: cicomponents-api/src/main/java/org/cicomponents/ResourceListener.java
// @FunctionalInterface
// public interface ResourceListener<T extends Resource> {
//     void onEmittedResource(ResourceHolder<T> holder,
//                            ResourceEmitter<T> emitter);
// 
//     default boolean isMatchingListener(Class klass) {
//         for (Type type : getClass().getGenericInterfaces()) {
//             if (type instanceof ParameterizedType &&
//                     ((ParameterizedType) type).getRawType() == ResourceListener.class) {
//                 ParameterizedType parameterizedType = (ParameterizedType) type;
//                 Type target = parameterizedType.getActualTypeArguments()[0];
//                 if (target == klass) {
//                     return true;
//                 }
//             }
//         }
//         return false;
//     }
// }
// 
// Path: cicomponents-fs-api/src/main/java/org/cicomponents/fs/WorkingDirectory.java
// public interface WorkingDirectory extends Resource {
//     String getDirectory();
// }
// 
// Path: cicomponents-fs-api/src/main/java/org/cicomponents/fs/WorkingDirectoryProvider.java
// public interface WorkingDirectoryProvider {
//     WorkingDirectory getDirectory();
// }
// 
// Path: cicomponents-git-api/src/main/java/org/cicomponents/git/GitRevision.java
// public interface GitRevision extends File, Resource {
//     Git getRepository();
//     ObjectId getRef();
// }
// 
// Path: cicomponents-git-api/src/main/java/org/cicomponents/git/GitRevisionEmitter.java
// public interface GitRevisionEmitter extends ResourceEmitter<GitRevision> {
// }


// Path: cicomponents-test/src/test/java/org/cicomponents/test/GitEmitterTest.java
import com.cicomponents.test.ContainerConfiguration;
import lombok.Getter;
import lombok.SneakyThrows;
import org.cicomponents.ResourceEmitter;
import org.cicomponents.ResourceHolder;
import org.cicomponents.ResourceListener;
import org.cicomponents.fs.WorkingDirectory;
import org.cicomponents.fs.WorkingDirectoryProvider;
import org.cicomponents.git.GitRevision;
import org.cicomponents.git.GitRevisionEmitter;
import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.revwalk.RevCommit;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.ops4j.pax.exam.Configuration;
import org.ops4j.pax.exam.Option;
import org.ops4j.pax.exam.junit.PaxExam;
import org.ops4j.pax.exam.spi.reactors.ExamReactorStrategy;
import org.ops4j.pax.exam.spi.reactors.PerMethod;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
import org.osgi.framework.ServiceRegistration;
import javax.inject.Inject;
import java.io.File;
import java.util.Collection;
import java.util.Hashtable;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import static junit.framework.TestCase.assertFalse;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

        public void onEmittedResource(ResourceHolder<GitRevision> holder, ResourceEmitter<GitRevision> emitter) {
            try (GitRevision resource = holder.acquire()) {
                future.complete(resource.getRef());
            }
        }

        void reset() {
            future = new CompletableFuture<>();
        }
    }

    @Inject
    private WorkingDirectoryProvider workingDirectoryProvider;

    @Test
    @SneakyThrows
    public void listenerDiscovery() {
        try (WorkingDirectory directory = workingDirectoryProvider.getDirectory()) {
            Git git = Git.init().setDirectory(new File(directory.getDirectory())).call();
            RevCommit commit = git.commit().setAllowEmpty(true).setMessage("Test").call();

            Hashtable<String, Object> properties = new Hashtable<>();
            properties.put("repository","file://" + git.getRepository().getDirectory().getAbsolutePath());
            properties.put("type", "latest");
            Listener listener = new Listener();
            ServiceRegistration<ResourceListener> registration = bundleContext
                    .registerService(ResourceListener.class, listener, properties);


            Collection<ServiceReference<GitRevisionEmitter>> references = bundleContext
                    .getServiceReferences(GitRevisionEmitter.class,