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

org.gradle.plugin.use.resolve.service.internal.PersistentCachingPluginResolutionServiceClient Maven / Gradle / Ivy

There is a newer version: 8.11.1
Show newest version
/*
 * Copyright 2013 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.plugin.use.resolve.service.internal;

import com.google.common.base.Objects;
import org.gradle.api.specs.Spec;
import org.gradle.api.specs.Specs;
import org.gradle.cache.PersistentCache;
import org.gradle.cache.PersistentIndexedCache;
import org.gradle.cache.PersistentIndexedCacheParameters;
import org.gradle.internal.Factory;
import org.gradle.internal.concurrent.CompositeStoppable;
import org.gradle.internal.serialize.AbstractSerializer;
import org.gradle.internal.serialize.Decoder;
import org.gradle.internal.serialize.Encoder;
import org.gradle.internal.serialize.Serializer;
import org.gradle.plugin.management.internal.PluginRequestInternal;

import java.io.IOException;

public class PersistentCachingPluginResolutionServiceClient implements PluginResolutionServiceClient {

    public static final String PLUGIN_USE_METADATA_CACHE_NAME = "plugin-use-metadata";
    public static final String CLIENT_STATUS_CACHE_NAME = "client-status";

    private final PluginResolutionServiceClient delegate;
    private final PersistentCache cacheAccess;
    private final PersistentIndexedCache> pluginUseMetadataCache;
    private final PersistentIndexedCache> clientStatusCache;

    public PersistentCachingPluginResolutionServiceClient(PluginResolutionServiceClient delegate, PersistentCache persistentCache) {
        this.delegate = delegate;
        this.cacheAccess = persistentCache;
        this.pluginUseMetadataCache = persistentCache.createCache(PersistentIndexedCacheParameters.of(
                        PLUGIN_USE_METADATA_CACHE_NAME, new PluginRequestKey.Serializer(), ResponseSerializer.of(new PluginUseMetaData.Serializer()))
        );
        this.clientStatusCache = persistentCache.createCache(PersistentIndexedCacheParameters.of(
                        CLIENT_STATUS_CACHE_NAME, new ClientStatusKey.Serializer(), ResponseSerializer.of(new ClientStatus.Serializer()))
        );
    }

    public Response queryPluginMetadata(final String portalUrl, final boolean shouldValidate, final PluginRequestInternal pluginRequest) {
        PluginRequestKey key = PluginRequestKey.of(portalUrl, pluginRequest);
        Factory> factory = new Factory>() {
            public Response create() {
                return delegate.queryPluginMetadata(portalUrl, shouldValidate, pluginRequest);
            }
        };

        if (shouldValidate) {
            return fetch(pluginUseMetadataCache, key, factory);
        } else {
            return maybeFetch(pluginUseMetadataCache, key, factory);
        }
    }

    public Response queryClientStatus(final String portalUrl, final boolean shouldValidate, final String checksum) {
        ClientStatusKey key = new ClientStatusKey(portalUrl);
        Factory> factory = new Factory>() {
            public Response create() {
                return delegate.queryClientStatus(portalUrl, shouldValidate, checksum);
            }
        };

        if (shouldValidate) {
            return fetch(clientStatusCache, key, factory);
        } else {
            return maybeFetch(clientStatusCache, key, factory, new Spec>() {
                public boolean isSatisfiedBy(Response element) {
                    return !element.getClientStatusChecksum().equals(checksum);
                }
            });
        }
    }

    private > V maybeFetch(final PersistentIndexedCache cache, final K key, Factory factory) {
        return maybeFetch(cache, key, factory, Specs.SATISFIES_NONE);
    }

    private > V maybeFetch(final PersistentIndexedCache cache, final K key, Factory factory, Spec shouldFetch) {
        V cachedValue = cacheAccess.useCache(new Factory() {
            public V create() {
                return cache.get(key);
            }
        });

        boolean fetch = cachedValue == null || shouldFetch.isSatisfiedBy(cachedValue);
        if (fetch) {
            return fetch(cache, key, factory);
        } else {
            return cachedValue;
        }
    }

    private > V fetch(final PersistentIndexedCache cache, final K key, Factory factory) {
        final V value = factory.create();
        if (value.isError()) {
            return value;
        }

        cacheAccess.useCache(new Runnable() {
            public void run() {
                cache.put(key, value);
            }
        });
        return value;
    }

    public void close() throws IOException {
        CompositeStoppable.stoppable(delegate, cacheAccess).stop();
    }

    private static class ResponseSerializer extends AbstractSerializer> {

        private final Serializer payloadSerializer;

        private static  ResponseSerializer of(Serializer payloadSerializer) {
            return new ResponseSerializer(payloadSerializer);
        }

        private ResponseSerializer(Serializer payloadSerializer) {
            this.payloadSerializer = payloadSerializer;
        }

        public Response read(Decoder decoder) throws Exception {
            return new SuccessResponse(
                    payloadSerializer.read(decoder),
                    decoder.readSmallInt(),
                    decoder.readString(),
                    decoder.readNullableString()
            );
        }

        public void write(Encoder encoder, Response value) throws Exception {
            T response = value.getResponse();
            payloadSerializer.write(encoder, response);
            encoder.writeSmallInt(value.getStatusCode());
            encoder.writeString(value.getUrl());
            encoder.writeNullableString(value.getClientStatusChecksum());
        }

        @Override
        public boolean equals(Object obj) {
            if (!super.equals(obj)) {
                return false;
            }

            ResponseSerializer rhs = (ResponseSerializer) obj;
            return Objects.equal(payloadSerializer, rhs.payloadSerializer);
        }

        @Override
        public int hashCode() {
            return Objects.hashCode(super.hashCode(), payloadSerializer);
        }
    }

    static class PluginRequestKey {
        private final String id;
        private final String version;

        private final String url;

        private static PluginRequestKey of(String url, PluginRequestInternal pluginRequest) {
            return new PluginRequestKey(pluginRequest.getId().toString(), pluginRequest.getVersion(), url);
        }

        private PluginRequestKey(String id, String version, String url) {
            this.id = id;
            this.version = version;
            this.url = url;
        }

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

            PluginRequestKey key = (PluginRequestKey) o;

            return id.equals(key.id) && url.equals(key.url) && version.equals(key.version);
        }

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

        private static class Serializer extends AbstractSerializer {

            public PluginRequestKey read(Decoder decoder) throws Exception {
                return new PluginRequestKey(decoder.readString(), decoder.readString(), decoder.readString());
            }

            public void write(Encoder encoder, PluginRequestKey value) throws Exception {
                encoder.writeString(value.id);
                encoder.writeString(value.version);
                encoder.writeString(value.url);
            }
        }

    }

    public static class ClientStatusKey {

        private final String portalUrl;

        public ClientStatusKey(String portalUrl) {
            this.portalUrl = portalUrl;
        }

        public static class Serializer extends AbstractSerializer {
            public ClientStatusKey read(Decoder decoder) throws Exception {
                return new ClientStatusKey(decoder.readString());
            }

            public void write(Encoder encoder, ClientStatusKey value) throws Exception {
                encoder.writeString(value.portalUrl);
            }
        }

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

            ClientStatusKey that = (ClientStatusKey) o;

            return portalUrl.equals(that.portalUrl);
        }

        @Override
        public int hashCode() {
            return portalUrl.hashCode();
        }
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy