/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package org.apache.karaf.tooling;

import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.TreeSet;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.atomic.AtomicLong;
import java.util.jar.Attributes;
import java.util.jar.Manifest;
import java.util.regex.Pattern;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;

import aQute.bnd.osgi.Macro;
import aQute.bnd.osgi.Processor;
import org.apache.felix.resolver.Logger;
import org.apache.felix.resolver.ResolverImpl;
import org.apache.felix.utils.resource.ResourceBuilder;
import org.apache.felix.utils.resource.ResourceImpl;
import org.apache.felix.utils.version.VersionRange;
import org.apache.felix.utils.version.VersionTable;
import org.apache.karaf.features.BundleInfo;
import org.apache.karaf.features.DeploymentEvent;
import org.apache.karaf.features.FeatureEvent;
import org.apache.karaf.features.FeaturesService;
import org.apache.karaf.features.LocationPattern;
import org.apache.karaf.features.internal.download.DownloadCallback;
import org.apache.karaf.features.internal.download.DownloadManager;
import org.apache.karaf.features.internal.download.Downloader;
import org.apache.karaf.features.internal.download.StreamProvider;
import org.apache.karaf.features.internal.model.Conditional;
import org.apache.karaf.features.internal.model.ConfigFile;
import org.apache.karaf.features.internal.model.Feature;
import org.apache.karaf.features.internal.model.Features;
import org.apache.karaf.features.internal.model.JaxbUtil;
import org.apache.karaf.features.internal.resolver.ResourceUtils;
import org.apache.karaf.features.internal.service.Deployer;
import org.apache.karaf.features.internal.service.FeaturesProcessorImpl;
import org.apache.karaf.features.internal.service.FeaturesServiceConfig;
import org.apache.karaf.features.internal.service.State;
import org.apache.karaf.features.internal.service.StaticInstallSupport;
import org.apache.karaf.features.internal.util.MapUtils;
import org.apache.karaf.features.internal.util.MultiException;
import org.apache.karaf.profile.assembly.CustomDownloadManager;
import org.apache.karaf.tooling.utils.MavenUtil;
import org.apache.karaf.tooling.utils.MojoSupport;
import org.apache.karaf.tooling.utils.ReactorMavenResolver;
import org.apache.karaf.util.config.PropertiesLoader;
import org.apache.maven.artifact.Artifact;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugins.annotations.Component;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.plugins.annotations.ResolutionScope;
import org.apache.maven.project.MavenProject;
import org.eclipse.aether.repository.WorkspaceReader;
import org.ops4j.pax.url.mvn.MavenResolver;
import org.ops4j.pax.url.mvn.MavenResolvers;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleException;
import org.osgi.framework.Constants;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.Version;
import org.osgi.framework.namespace.IdentityNamespace;
import org.osgi.framework.startlevel.BundleStartLevel;
import org.osgi.framework.wiring.BundleCapability;
import org.osgi.framework.wiring.BundleRequirement;
import org.osgi.framework.wiring.BundleRevision;
import org.osgi.framework.wiring.BundleWiring;
import org.osgi.resource.Requirement;
import org.osgi.service.resolver.ResolutionException;

import static java.util.jar.JarFile.MANIFEST_NAME;

@Mojo(name = "verify", requiresDependencyResolution = ResolutionScope.COMPILE_PLUS_RUNTIME, threadSafe = true)
public class VerifyMojo extends MojoSupport {

    @Parameter(property = "descriptors")
    protected Set<String> descriptors;

    @Parameter(property = "blacklistedDescriptors")
    protected Set<String> blacklistedDescriptors;

    @Parameter(property = "featureProcessingInstructions")
    protected File featureProcessingInstructions;

    @Parameter(property = "features")
    protected List<String> features;

    @Parameter(property = "framework")
    protected Set<String> framework;

    @Parameter(property = "configuration")
    protected String configuration;

    @Parameter(property = "distribution", defaultValue = "org.apache.karaf:apache-karaf")
    protected String distribution;

    @Parameter(property = "javase")
    protected String javase;

    @Parameter(property = "dist-dir")
    protected String distDir;

    @Parameter(property = "karaf-version")
    protected String karafVersion;

    @Parameter(property = "additional-metadata")
    protected File additionalMetadata;

    @Parameter(property = "ignore-missing-conditions")
    protected boolean ignoreMissingConditions;

    @Parameter(property = "fail")
    protected String fail = "end";

    @Parameter(property = "verify-transitive")
    protected boolean verifyTransitive = false;

    @Parameter(defaultValue = "${project}", readonly = true)
    protected MavenProject project;

    @Component(role = WorkspaceReader.class, hint = "reactor")
    protected WorkspaceReader reactor;

    @Parameter(property = "skip", defaultValue = "${features.verify.skip}")
    protected boolean skip;

    @Parameter(readonly = true, defaultValue = "${project.groupId}")
    protected String selfGroupId;

    @Parameter(readonly = true, defaultValue = "${project.artifactId}")
    protected String selfArtifactId;

    protected MavenResolver resolver;

    @Override
    public void execute() throws MojoExecutionException {
        if (skip) {
            return;
        }

        if (karafVersion == null) {
            karafVersion = org.apache.karaf.util.Version.karafVersion();
        }

        Hashtable<String, String> config = new Hashtable<>();
        String remoteRepositories = MavenUtil.remoteRepositoryList(project.getRemoteProjectRepositories());
        getLog().info("Using repositories: " + remoteRepositories);
        config.put("maven.repositories", remoteRepositories);
        config.put("maven.localRepository", localRepo.getBasedir());

        if (mavenSession.getRequest().getUserSettingsFile().exists()) {
            config.put("maven.settings", mavenSession.getRequest().getUserSettingsFile().toString());
        }

        // TODO: add more configuration bits ?
        resolver = new ReactorMavenResolver(reactor, MavenResolvers.createMavenResolver(config, "maven"));
        doExecute();
    }

    private String getVersion(String id, String def) {
        String v = getVersion(id);
        return v != null ? v : def;
    }

    private String getVersion(String id) {
        Artifact artifact = project.getArtifactMap().get(id);
        if (artifact != null) {
            return artifact.getBaseVersion();
        } else if (id.startsWith("org.apache.karaf")) {
            return karafVersion;
        } else {
            return null;
        }
    }

    private static Object invoke(Object object, String getter) throws MojoExecutionException {
        try {
            return object.getClass().getMethod(getter).invoke(object);
        } catch (Exception e) {
            throw new MojoExecutionException("Unable to build remote repository from " + object.toString(), e);
        }
    }

    private static Object getPolicy(Object object, boolean snapshots) throws MojoExecutionException {
        return invoke(object, "getPolicy", new Class[] { Boolean.TYPE }, new Object[] { snapshots });
    }

    private static Object invoke(Object object, String getter, Class<?>[] types, Object[] params) throws MojoExecutionException {
        try {
            return object.getClass().getMethod(getter, types).invoke(object, params);
        } catch (Exception e) {
            throw new MojoExecutionException("Unable to build remote repository from " + object.toString(), e);
        }
    }

    protected void doExecute() throws MojoExecutionException {
        System.setProperty("karaf.home", "target/karaf");
        System.setProperty("karaf.data", "target/karaf/data");

        Hashtable<String, String> properties = new Hashtable<>();

        if (additionalMetadata != null) {
            try (Reader reader = new FileReader(additionalMetadata)) {
                Properties metadata = new Properties();
                metadata.load(reader);
                for (Enumeration<?> e = metadata.propertyNames(); e.hasMoreElements(); ) {
                    Object key = e.nextElement();
                    Object val = metadata.get(key);
                    properties.put(key.toString(), val.toString());
                }
            } catch (IOException e) {
                throw new MojoExecutionException("Unable to load additional metadata from " + additionalMetadata, e);
            }
        }

        Set<String> allDescriptors = new LinkedHashSet<>();
        if (descriptors == null) {
            if (framework == null) {
                framework = Collections.singleton("framework");
            }
            descriptors = new LinkedHashSet<>();
            if (framework.contains("framework")) {
                allDescriptors.add("mvn:org.apache.karaf.features/framework/" + getVersion("org.apache.karaf.features:framework") + "/xml/features");
            }
            String filePrefix = null;
            if (System.getProperty("os.name").contains("Windows")) {
                filePrefix = "file:/";
            } else {
                filePrefix = "file:";
            }
            allDescriptors.add(filePrefix + project.getBuild().getDirectory() + File.separator 
                               + "feature"
                               + File.separator 
                               + "feature.xml");
        } else {
            allDescriptors.addAll(descriptors);
            if (framework != null && framework.contains("framework")) {
                allDescriptors.add("mvn:org.apache.karaf.features/framework/" + getVersion("org.apache.karaf.features:framework") + "/xml/features");
            }
        }

        // TODO: allow using external configuration ?
        ScheduledExecutorService executor = Executors.newScheduledThreadPool(8);
        DownloadManager manager = new CustomDownloadManager(resolver, executor);
        final Map<String, Features> repositories;
        Map<String, List<Feature>> allFeatures = new HashMap<>();
        try {
            repositories = loadRepositories(manager, allDescriptors);
            for (String repoUri : repositories.keySet()) {
                List<Feature> features = repositories.get(repoUri).getFeature();
                // Ack features to inline configuration files urls
                for (Feature feature : features) {
                    for (org.apache.karaf.features.internal.model.Bundle bi : feature.getBundle()) {
                        String loc = bi.getLocation();
                        String nloc = null;
                        if (loc.contains("file:")) {
                            for (ConfigFile cfi : feature.getConfigfile()) {
                                if (cfi.getFinalname().substring(1)
                                        .equals(loc.substring(loc.indexOf("file:") + "file:".length()))) {
                                    nloc = cfi.getLocation();
                                }
                            }
                        }
                        if (nloc != null) {
                            Field field = bi.getClass().getDeclaredField("location");
                            field.setAccessible(true);
                            field.set(bi, loc.substring(0, loc.indexOf("file:")) + nloc);
                        }
                    }
                }
                allFeatures.put(repoUri, features);
            }
        } catch (Exception e) {
            throw new MojoExecutionException("Unable to load features descriptors", e);
        }

        List<Feature> featuresToTest = new ArrayList<>();
        if (verifyTransitive) {
            for (List<Feature> features : allFeatures.values()) {
                featuresToTest.addAll(features);
            }
        } else {
            for (String uri : descriptors) {
                featuresToTest.addAll(allFeatures.get(uri));
            }
        }
        if (features != null && !features.isEmpty()) {
            Pattern pattern = getPattern(features);
            for (Iterator<Feature> iterator = featuresToTest.iterator(); iterator.hasNext();) {
                Feature feature = iterator.next();
                String id = feature.getName() + "/" + feature.getVersion();
                if (!pattern.matcher(id).matches()) {
                    iterator.remove();
                }
            }
        }

        for (String fmk : framework) {
            properties.put("feature.framework." + fmk, fmk);
        }
        Set<String> successes = new LinkedHashSet<>();
        Set<String> ignored = new LinkedHashSet<>();
        Set<String> skipped = new LinkedHashSet<>();
        Map<String, Exception> failures = new LinkedHashMap<>();
        for (Feature feature : featuresToTest) {
            String id = feature.getId();
            if (feature.isBlacklisted()) {
                skipped.add(id);
                getLog().info("Verification of feature " + id + " skipped");
                continue;
            }
            try {
                verifyResolution(new CustomDownloadManager(resolver, executor),
                                 repositories, Collections.singleton(id), properties);
                successes.add(id);
                getLog().info("Verification of feature " + id + " succeeded");
            } catch (Exception e) {
                if (e.getCause() instanceof ResolutionException || !getLog().isDebugEnabled()) {
                    getLog().warn(e.getMessage() + ": " + id);
                    getLog().warn(e.getCause().getMessage());
                } else {
                    getLog().warn(e);
                }
                failures.put(id, e);
                if ("first".equals(fail)) {
                    throw e;
                }
            }
            for (Conditional cond : feature.getConditional()) {
                Set<String> ids = new LinkedHashSet<>();
                ids.add(feature.getId());
                ids.addAll(cond.getCondition());
                String cid = String.join("+", ids);
                try {
                    verifyResolution(manager, repositories, ids, properties);
                    successes.add(cid);
                    getLog().info("Verification of feature " + cid + " succeeded");
                } catch (Exception e) {
                    if (ignoreMissingConditions && e.getCause() instanceof ResolutionException) {
                        boolean ignore = true;
                        Collection<Requirement> requirements = ((ResolutionException) e.getCause()).getUnresolvedRequirements();
                        for (Requirement req : requirements) {
                            ignore &= (IdentityNamespace.IDENTITY_NAMESPACE.equals(req.getNamespace())
                                    && ResourceUtils.TYPE_FEATURE.equals(req.getAttributes().get("type"))
                                    && cond.getCondition().contains(req.getAttributes().get(IdentityNamespace.IDENTITY_NAMESPACE).toString()));
                        }
                        if (ignore) {
                            ignored.add(cid);
                            getLog().warn("Feature resolution failed for " + cid
                                    + "\nMessage: " + e.getCause().getMessage());
                            continue;
                        }
                    }
                    if (e.getCause() instanceof ResolutionException || !getLog().isDebugEnabled()) {
                        getLog().warn(e.getMessage());
                    } else {
                        getLog().warn(e);
                    }
                    failures.put(cid, e);
                    if ("first".equals(fail)) {
                        throw e;
                    }
                }
            }
        }
        int nb = successes.size() + ignored.size() + failures.size();
        getLog().info("Features verified: " + nb + ", failures: " + failures.size() + ", ignored: " + ignored.size() + ", skipped: " + skipped.size());
        if (!failures.isEmpty()) {
            getLog().info("Failures: " + String.join(", ", failures.keySet()));
        }
        if ("end".equals(fail) && !failures.isEmpty()) {
            throw new MojoExecutionException("Verification failures", new MultiException("Verification failures", new ArrayList<>(failures.values())));
        }
    }

    static Pattern getPattern(List<String> features) {
        StringBuilder sb = new StringBuilder();
        boolean prevIsNeg = false;
        for (String feature : features) {
            if (sb.length() > 0 && !prevIsNeg) {
                sb.append("|");
            }
            sb.append("(");
            feature = feature.trim();
            boolean negative = feature.startsWith("!");
            if (negative) {
                feature = feature.substring("!".length());
                sb.append("(?!");
            }
            String p = feature.replaceAll("\\.", "\\\\.").replaceAll("\\*", ".*");
            sb.append(p);
            if (!feature.contains("/")) {
                sb.append("/.*");
            }
            if (negative) {
                sb.append(")");
            }
            prevIsNeg = negative;
        }
        for (String feature : features) {
            sb.append(")");
        }
        return Pattern.compile(sb.toString());
    }

    private void verifyResolution(DownloadManager manager, final Map<String, Features> repositories, Set<String> features, Hashtable<String, String> properties) throws MojoExecutionException {
        try {
            Bundle systemBundle = getSystemBundle(getMetadata(properties, "metadata#"));
            DummyDeployCallback callback = new DummyDeployCallback(systemBundle, repositories.values());
            Deployer deployer = new Deployer(manager, new ResolverImpl(new MavenResolverLog()), callback);


            // Install framework
            Deployer.DeploymentRequest request = Deployer.DeploymentRequest.defaultDeploymentRequest();

            for (String fmwk : framework) {
                MapUtils.addToMapSet(request.requirements, FeaturesService.ROOT_REGION, fmwk);
            }
            try {
                deployer.deploy(callback.getDeploymentState(), request);
            } catch (Exception e) {
                throw new MojoExecutionException("Unable to resolve framework features", e);
            }

            /*
            boolean resolveOptionalImports = getResolveOptionalImports(properties);

            DeploymentBuilder builder = new DeploymentBuilder(
                    manager,
                    null,
                    repositories.values(),
                    -1 // Disable url handlers
            );
            Map<String, Resource> downloadedResources = builder.download(
                    getPrefixedProperties(properties, "feature."),
                    getPrefixedProperties(properties, "bundle."),
                    getPrefixedProperties(properties, "fab."),
                    getPrefixedProperties(properties, "req."),
                    getPrefixedProperties(properties, "override."),
                    getPrefixedProperties(properties, "optional."),
                    getMetadata(properties, "metadata#")
            );

            for (String uri : getPrefixedProperties(properties, "resources.")) {
                builder.addResourceRepository(new MetadataRepository(new HttpMetadataProvider(uri)));
            }
            */

            // Install features
            for (String feature : features) {
                MapUtils.addToMapSet(request.requirements, FeaturesService.ROOT_REGION, feature);
            }
            try {
                deployer.deployFully(callback.getDeploymentState(), request);

                // TODO: find unused resources ?
            } catch (Exception e) {
                throw new MojoExecutionException("Feature resolution failed for " + features
                        + "\nMessage: " + (e instanceof ResolutionException ? e.getMessage() : e.toString())
                        + "\nRepositories: " + toString(new TreeSet<>(repositories.keySet()))
                        + "\nResources: " + toString(new TreeSet<>(manager.getProviders().keySet())), e);
            }
        } catch (MojoExecutionException e) {
            throw e;
        } catch (Exception e) {
            throw new MojoExecutionException("Error verifying feature " + features + "\nMessage: " + e.getMessage(), e);
        }
    }

    private static String toString(Collection<String> collection) {
        StringBuilder sb = new StringBuilder();
        sb.append("{\n");
        for (String s : collection) {
            sb.append("\t").append(s).append("\n");
        }
        sb.append("}");
        return sb.toString();
    }

    private Bundle getSystemBundle(Map<String, Map<VersionRange, Map<String, String>>> metadata) throws Exception {
        URL configPropURL;
        if (configuration != null) {
            configPropURL = new URL(configuration);
        } else {
            Artifact karafDistro = project.getArtifactMap().get(distribution);
            if (karafDistro != null) {
                String dir = distDir;
                if ("kar".equals(karafDistro.getType()) && dir == null) {
                    dir = "resources";
                }
                if (dir == null) {
                    dir = karafDistro.getArtifactId() + "-" + karafDistro.getBaseVersion();
                }
                configPropURL = new URL("jar:file:" + karafDistro.getFile() + "!/" + dir + "/etc/config.properties");
            } else {
                String version = getVersion(distribution, "RELEASE");
                String[] dist = distribution.split(":");
                File distFile = resolver.resolve(dist[0], dist[1], null, "zip", version);
                String resolvedVersion = distFile.getName().substring(dist[1].length() + 1, distFile.getName().length() - 4);
                String dir = distDir;
                if (dir == null) {
                    dir = dist[1] + "-" + resolvedVersion;
                }
                configPropURL = new URL("jar:file:" + distFile + "!/" + dir + "/etc/config.properties");
            }
        }
        org.apache.felix.utils.properties.Properties configProps = PropertiesLoader.loadPropertiesFile(configPropURL, true);
//        copySystemProperties(configProps);
        if (javase == null) {
            configProps.put("java.specification.version", System.getProperty("java.specification.version"));
        } else {
            configProps.put("java.specification.version", javase);
        }
        configProps.substitute();

        Attributes attributes = new Attributes();
        attributes.putValue(Constants.BUNDLE_MANIFESTVERSION, "2");
        attributes.putValue(Constants.BUNDLE_SYMBOLICNAME, "system.bundle");
        attributes.putValue(Constants.BUNDLE_VERSION, "0.0.0");

        String exportPackages = configProps.getProperty("org.osgi.framework.system.packages");
        if (configProps.containsKey("org.osgi.framework.system.packages.extra")) {
            exportPackages += "," + configProps.getProperty("org.osgi.framework.system.packages.extra");
        }
        exportPackages = exportPackages.replaceAll(",\\s*,", ",");
        attributes.putValue(Constants.EXPORT_PACKAGE, exportPackages);

        String systemCaps = configProps.getProperty("org.osgi.framework.system.capabilities");
        attributes.putValue(Constants.PROVIDE_CAPABILITY, systemCaps);

        // TODO: support metadata overrides on system bundle
//        attributes = DeploymentBuilder.overrideAttributes(attributes, metadata);

        final Hashtable<String, String> headers = new Hashtable<>();
        for (Map.Entry<Object, Object> attr : attributes.entrySet()) {
            headers.put(attr.getKey().toString(), attr.getValue().toString());
        }

        final FakeBundleRevision resource = new FakeBundleRevision(headers, "system-bundle", 0l);
        return resource.getBundle();
    }


    public Map<String, Features> loadRepositories(DownloadManager manager, Set<String> uris) throws Exception {
        final Map<String, Features> loaded = new HashMap<>();
        final Downloader downloader = manager.createDownloader();

        FeaturesServiceConfig config = null;
        if (featureProcessingInstructions != null) {
            config = new FeaturesServiceConfig(featureProcessingInstructions.toURI().toString(), null);
        } else {
            config = new FeaturesServiceConfig();
        }
        FeaturesProcessorImpl processor = new FeaturesProcessorImpl(config);
        if (blacklistedDescriptors != null) {
            blacklistedDescriptors.forEach(lp -> processor.getInstructions().getBlacklistedRepositoryLocationPatterns()
                    .add(new LocationPattern(lp)));
        }
        processor.getInstructions().getBlacklistedRepositoryLocationPatterns()
                .add(new LocationPattern("mvn:" + selfGroupId + "/" + selfArtifactId));

        for (String repository : uris) {
            if (!processor.isRepositoryBlacklisted(repository)) {
                downloader.download(repository, new DownloadCallback() {
                    @Override
                    public void downloaded(final StreamProvider provider) throws Exception {
                        try (InputStream is = provider.open()) {
                            Features featuresModel = JaxbUtil.unmarshal(provider.getUrl(), is, false);
                            processor.process(featuresModel);
                            synchronized (loaded) {
                                loaded.put(provider.getUrl(), featuresModel);
                                for (String innerRepository : featuresModel.getRepository()) {
                                    if (!processor.isRepositoryBlacklisted(innerRepository)) {
                                        downloader.download(innerRepository, this);
                                    }
                                }
                            }
                        }
                    }
                });
            }
        }
        downloader.await();
        return loaded;
    }

    public static Set<String> getPrefixedProperties(Map<String, String> properties, String prefix) {
        Set<String> result = new HashSet<>();
        for (String key : properties.keySet()) {
            if (key.startsWith(prefix)) {
                String url = properties.get(key);
                if (url == null || url.length() == 0) {
                    url = key.substring(prefix.length());
                }
                if (!url.isEmpty()) {
                    result.add(url);
                }
            }
        }
        return result;
    }

    public static Map<String, Map<VersionRange, Map<String, String>>> getMetadata(Map<String, String> properties, String prefix) {
        Map<String, Map<VersionRange, Map<String, String>>> result = new HashMap<>();
        for (String key : properties.keySet()) {
            if (key.startsWith(prefix)) {
                String val = properties.get(key);
                key = key.substring(prefix.length());
                String[] parts = key.split("#");
                if (parts.length == 3) {
                    Map<VersionRange, Map<String, String>> ranges =
                            result.computeIfAbsent(parts[0], k -> new HashMap<>());
                    String version = parts[1];
                    if (!version.startsWith("[") && !version.startsWith("(")) {
                        Processor processor = new Processor();
                        processor.setProperty("@", VersionTable.getVersion(version).toString());
                        Macro macro = new Macro(processor);
                        version = macro.process("${range;[==,=+)}");
                    }
                    VersionRange range = new VersionRange(version);
                    ranges.computeIfAbsent(range, k -> new HashMap<>()).put(parts[2], val);
                }
            }
        }
        return result;
    }

    public static class FakeBundleRevision extends ResourceImpl implements BundleRevision, BundleStartLevel {

        private final Bundle bundle;
        private int startLevel;

        public FakeBundleRevision(final Hashtable<String, String> headers, final String location, final long bundleId) throws BundleException {
            ResourceBuilder.build(this, location, headers);
            this.bundle = (Bundle) Proxy.newProxyInstance(
                    getClass().getClassLoader(),
                    new Class[] { Bundle.class },
                    new InvocationHandler() {
                        @Override
                        public Object invoke(Object proxy, Method method, Object[] args) {
                            if (method.getName().equals("hashCode")) {
                                return FakeBundleRevision.this.hashCode();
                            } else if (method.getName().equals("equals")) {
                                return proxy == args[0];
                            } else if (method.getName().equals("toString")) {
                                return bundle.getSymbolicName() + "/" + bundle.getVersion();
                            } else if (method.getName().equals("adapt")) {
                                if (args.length == 1 && args[0] == BundleRevision.class) {
                                    return FakeBundleRevision.this;
                                } else if (args.length == 1 && args[0] == BundleStartLevel.class) {
                                    return FakeBundleRevision.this;
                                }
                            } else if (method.getName().equals("getHeaders")) {
                                return headers;
                            } else if (method.getName().equals("getBundleId")) {
                                return bundleId;
                            } else if (method.getName().equals("getLocation")) {
                                return location;
                            } else if (method.getName().equals("getSymbolicName")) {
                                String name = headers.get(Constants.BUNDLE_SYMBOLICNAME);
                                int idx = name.indexOf(';');
                                if (idx > 0) {
                                    name = name.substring(0, idx).trim();
                                }
                                return name;
                            } else if (method.getName().equals("getVersion")) {
                                return new Version(headers.get(Constants.BUNDLE_VERSION));
                            } else if (method.getName().equals("getState")) {
                                return Bundle.ACTIVE;
                            } else if (method.getName().equals("getLastModified")) {
                                return 0l;
                            }
                            return null;
                        }
                    });
        }

        @Override
        public int getStartLevel() {
            return startLevel;
        }

        @Override
        public void setStartLevel(int startLevel) {
            this.startLevel = startLevel;
        }

        @Override
        public boolean isPersistentlyStarted() {
            return true;
        }

        @Override
        public boolean isActivationPolicyUsed() {
            return false;
        }

        @Override
        public String getSymbolicName() {
            return bundle.getSymbolicName();
        }

        @Override
        public Version getVersion() {
            return bundle.getVersion();
        }

        @Override
        public List<BundleCapability> getDeclaredCapabilities(String namespace) {
            throw new UnsupportedOperationException();
        }

        @Override
        public List<BundleRequirement> getDeclaredRequirements(String namespace) {
            throw new UnsupportedOperationException();
        }

        @Override
        public int getTypes() {
            throw new UnsupportedOperationException();
        }

        @Override
        public BundleWiring getWiring() {
            throw new UnsupportedOperationException();
        }

        @Override
        public Bundle getBundle() {
            return bundle;
        }
    }

    public static class DummyDeployCallback extends StaticInstallSupport implements Deployer.DeployCallback {

        private final Bundle systemBundle;
        private final Deployer.DeploymentState dstate;
        private final AtomicLong nextBundleId = new AtomicLong(0);

        public DummyDeployCallback(Bundle sysBundle, Collection<Features> repositories) {
            systemBundle = sysBundle;
            dstate = new Deployer.DeploymentState();
            dstate.bundles = new HashMap<>();
            dstate.bundlesPerRegion = new HashMap<>();
            dstate.filtersPerRegion = new HashMap<>();
            dstate.state = new State();

            MapUtils.addToMapSet(dstate.bundlesPerRegion, FeaturesService.ROOT_REGION, 0l);
            dstate.bundles.put(0l, systemBundle);

            Collection<org.apache.karaf.features.Feature> features = new LinkedList<>();
            for (Features repo : repositories) {
                if (repo.isBlacklisted()) {
                    continue;
                }
                for (Feature f : repo.getFeature()) {
                    if (!f.isBlacklisted()) {
                        features.add(f);
                    }
                }
            }
            dstate.partitionFeatures(features);
        }

        public Deployer.DeploymentState getDeploymentState() {
            return dstate;
        }

        @Override
        public void saveState(State state) {
            dstate.state.replace(state);
        }

        @Override
        public void persistResolveRequest(Deployer.DeploymentRequest request) {
        }

        @Override
        public void installConfigs(org.apache.karaf.features.Feature feature) {
        }

        @Override
        public void deleteConfigs(org.apache.karaf.features.Feature feature) throws IOException, InvalidSyntaxException {
        }

        @Override
        public void installLibraries(org.apache.karaf.features.Feature feature) {
        }

        @Override
        public void callListeners(FeatureEvent featureEvent) {
        }

        @Override
        public void callListeners(DeploymentEvent deployEvent) {
        }

        @Override
        public Bundle installBundle(String region, String uri, InputStream is) throws BundleException {
            try {
                Hashtable<String, String> headers = new Hashtable<>();
                ZipInputStream zis = new ZipInputStream(is);
                ZipEntry entry;
                while ((entry = zis.getNextEntry()) != null) {
                    if (MANIFEST_NAME.equals(entry.getName())) {
                        Attributes attributes = new Manifest(zis).getMainAttributes();
                        for (Map.Entry<Object, Object> attr : attributes.entrySet()) {
                            headers.put(attr.getKey().toString(), attr.getValue().toString());
                        }
                    }
                }
                BundleRevision revision = new FakeBundleRevision(headers, uri, nextBundleId.incrementAndGet());
                Bundle bundle = revision.getBundle();
                MapUtils.addToMapSet(dstate.bundlesPerRegion, region, bundle.getBundleId());
                dstate.bundles.put(bundle.getBundleId(), bundle);
                return bundle;
            } catch (IOException e) {
                throw new BundleException("Unable to install bundle", e);
            }
        }

        @Override
        public void bundleBlacklisted(BundleInfo bundleInfo) {

        }

    }

    public class MavenResolverLog extends org.apache.felix.resolver.Logger {

        public MavenResolverLog() {
            super(Logger.LOG_DEBUG);
        }

        @Override
        protected void doLog(int level, String msg, Throwable throwable) {
            switch (level) {
            case LOG_DEBUG:
                getLog().debug(msg, throwable);
                break;
            case LOG_INFO:
                getLog().info(msg, throwable);
                break;
            case LOG_WARNING:
                getLog().warn(msg, throwable);
                break;
            case LOG_ERROR:
                getLog().error(msg, throwable);
                break;
            }
        }
    }
}
