Package org.gradle.api.internal.plugins

Source Code of org.gradle.api.internal.plugins.DefaultPluginRegistry$PluginIdLookupCacheKey

/*
* Copyright 2010 the original author or authors.
*
* Licensed 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.gradle.api.internal.plugins;

import com.google.common.base.Optional;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.google.common.util.concurrent.UncheckedExecutionException;
import org.gradle.api.internal.initialization.ClassLoaderScope;
import org.gradle.api.plugins.InvalidPluginException;
import org.gradle.api.plugins.PluginInstantiationException;
import org.gradle.internal.Factories;
import org.gradle.internal.Factory;
import org.gradle.internal.UncheckedException;
import org.gradle.plugin.internal.PluginId;
import org.gradle.util.GUtil;

import java.util.concurrent.ExecutionException;

public class DefaultPluginRegistry implements PluginRegistry {

    private final PluginRegistry parent;
    private final PluginInspector pluginInspector;
    private final Factory<? extends ClassLoader> classLoaderFactory;

    private final LoadingCache<Class<?>, PotentialPlugin> classMappings;
    private final LoadingCache<PluginIdLookupCacheKey, Optional<PotentialPluginWithId>> idMappings;

    public DefaultPluginRegistry(PluginInspector pluginInspector, ClassLoader classLoader) {
        this(null, pluginInspector, Factories.constant(classLoader));
    }

    private DefaultPluginRegistry(PluginRegistry parent, PluginInspector pluginInspector, final Factory<? extends ClassLoader> classLoaderFactory) {
        this.parent = parent;
        this.pluginInspector = pluginInspector;
        this.classLoaderFactory = classLoaderFactory;
        this.classMappings = CacheBuilder.newBuilder().build(new PotentialPluginCacheLoader(pluginInspector));
        this.idMappings = CacheBuilder.newBuilder().build(new CacheLoader<PluginIdLookupCacheKey, Optional<PotentialPluginWithId>>() {
            @Override
            public Optional<PotentialPluginWithId> load(@SuppressWarnings("NullableProblems") PluginIdLookupCacheKey key) throws Exception {
                String pluginId = key.getId();
                ClassLoader classLoader = key.getClassLoader();

                PluginDescriptorLocator locator = new ClassloaderBackedPluginDescriptorLocator(classLoader);

                PluginDescriptor pluginDescriptor = locator.findPluginDescriptor(pluginId);
                if (pluginDescriptor == null) {
                    return Optional.absent();
                }

                String implClassName = pluginDescriptor.getImplementationClassName();
                if (!GUtil.isTrue(implClassName)) {
                    throw new PluginInstantiationException(String.format("No implementation class specified for plugin '%s' in %s.", pluginId, pluginDescriptor));
                }

                Class<?> implClass;
                try {
                    implClass = classLoader.loadClass(implClassName);
                } catch (ClassNotFoundException e) {
                    throw new InvalidPluginException(String.format(
                            "Could not find implementation class '%s' for plugin '%s' specified in %s.", implClassName, pluginId,
                            pluginDescriptor), e);
                }

                PotentialPlugin potentialPlugin = inspect(implClass);
                return Optional.of(new PotentialPluginWithId(PluginId.unvalidated(pluginId), potentialPlugin));
            }
        });
    }

    public PluginRegistry createChild(final ClassLoaderScope lookupScope) {
        return new DefaultPluginRegistry(this, pluginInspector, new Factory<ClassLoader>() {
            public ClassLoader create() {
                return lookupScope.getLocalClassLoader();
            }
        });
    }

    public PotentialPlugin inspect(Class<?> clazz) {
        // Don't go up the parent chain.
        // Don't want to risk classes crossing “scope” boundaries and being non collectible.
        return uncheckedGet(classMappings, clazz);
    }

    public PotentialPluginWithId lookup(String idOrName) {
        PotentialPluginWithId lookup;
        if (parent != null) {
            lookup = parent.lookup(idOrName);
            if (lookup == null) {
                String qualified = PluginManager.maybeQualify(idOrName);
                if (qualified != null) {
                    lookup = lookup(qualified);
                }
            }

            if (lookup != null) {
                return lookup;
            }
        }

        return lookup(idOrName, classLoaderFactory.create());
    }

    public PotentialPluginWithId lookup(String idOrName, ClassLoader classLoader) {
        // Don't go up the parent chain.
        // Don't want to risk classes crossing “scope” boundaries and being non collectible.
        PotentialPluginWithId lookup = uncheckedGet(idMappings, new PluginIdLookupCacheKey(idOrName, classLoader)).orNull();
        if (lookup == null) {
            String qualified = PluginManager.maybeQualify(idOrName);
            if (qualified != null) {
                lookup = uncheckedGet(idMappings, new PluginIdLookupCacheKey(qualified, classLoader)).orNull();
            }
        }

        return lookup;
    }

    private static <K, V> V uncheckedGet(LoadingCache<K, V> cache, K key) {
        try {
            return cache.get(key);
        } catch (ExecutionException e) {
            throw UncheckedException.throwAsUncheckedException(e.getCause());
        } catch (UncheckedExecutionException e) {
            throw UncheckedException.throwAsUncheckedException(e.getCause());
        }
    }

    static class PluginIdLookupCacheKey {

        private final ClassLoader classLoader;
        private final String id;

        PluginIdLookupCacheKey(String id, ClassLoader classLoader) {
            this.classLoader = classLoader;
            this.id = id;
        }

        public String getId() {
            return id;
        }

        public ClassLoader getClassLoader() {
            return classLoader;
        }

        @Override
        public boolean equals(Object o) {
            if (this == o) {
                return true;
            }
            if (o == null || getClass() != o.getClass()) {
                return false;
            }

            PluginIdLookupCacheKey that = (PluginIdLookupCacheKey) o;

            return classLoader.equals(that.classLoader) && id.equals(that.id);
        }

        @Override
        public int hashCode() {
            int result = classLoader.hashCode();
            result = 31 * result + id.hashCode();
            return result;
        }
    }

    private static class PotentialPluginCacheLoader extends CacheLoader<Class<?>, PotentialPlugin> {
        private final PluginInspector pluginInspector;

        public PotentialPluginCacheLoader(PluginInspector pluginInspector) {
            this.pluginInspector = pluginInspector;
        }

        @Override
        public PotentialPlugin load(@SuppressWarnings("NullableProblems") Class<?> key) throws Exception {
            return pluginInspector.inspect(key);
        }
    }

}
TOP

Related Classes of org.gradle.api.internal.plugins.DefaultPluginRegistry$PluginIdLookupCacheKey

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.
ew');