/* * Copyright 2016 DiffPlug * * 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 com.diffplug.spotless; import java.io.File; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.util.HashMap; import java.util.Map; import java.util.function.Consumer; import java.util.function.Supplier; import org.gradle.api.Project; import org.gradle.api.artifacts.Configuration; import org.gradle.api.artifacts.Dependency; import org.gradle.api.artifacts.ResolveException; import org.gradle.api.artifacts.dsl.RepositoryHandler; import org.gradle.testfixtures.ProjectBuilder; import com.diffplug.common.base.Box; import com.diffplug.common.base.Errors; import com.diffplug.common.base.StandardSystemProperty; import com.diffplug.common.base.Suppliers; import com.diffplug.common.collect.ImmutableSet; import com.diffplug.common.io.Files; public class TestProvisioner { /** * Creates a Provisioner for the given repositories. * * The first time a project is created, there are ~7 seconds of configuration * which will go away for all subsequent runs. * * Every call to resolve will take about 1 second, even when all artifacts are resolved. */ private static Supplier<Provisioner> createLazyWithRepositories(Consumer<RepositoryHandler> repoConfig) { // Running this takes ~3 seconds the first time it is called. Probably because of classloading. return Suppliers.memoize(() -> { Project project = ProjectBuilder.builder().build(); repoConfig.accept(project.getRepositories()); return mavenCoords -> { Dependency[] deps = mavenCoords.stream() .map(project.getDependencies()::create) .toArray(Dependency[]::new); Configuration config = project.getConfigurations().detachedConfiguration(deps); config.setDescription(mavenCoords.toString()); try { return config.resolve(); } catch (ResolveException e) { /* Provide Maven coordinates in exception message instead of static string 'detachedConfiguration' */ throw new ResolveException(config.getDescription(), e); } }; }); } /** Creates a Provisioner which will cache the result of previous calls. */ @SuppressWarnings("unchecked") private static Provisioner caching(String name, Supplier<Provisioner> input) { File spotlessDir = new File(StandardSystemProperty.USER_DIR.value()).getParentFile(); File testlib = new File(spotlessDir, "testlib"); File cacheFile = new File(testlib, "build/tmp/testprovisioner." + name + ".cache"); Map<ImmutableSet<String>, ImmutableSet<File>> cached; if (cacheFile.exists()) { try (ObjectInputStream inputStream = new ObjectInputStream(Files.asByteSource(cacheFile).openBufferedStream())) { cached = (Map<ImmutableSet<String>, ImmutableSet<File>>) inputStream.readObject(); } catch (IOException | ClassNotFoundException e) { throw Errors.asRuntime(e); } } else { cached = new HashMap<>(); } return mavenCoords -> { Box<Boolean> wasChanged = Box.of(false); ImmutableSet<File> result = cached.computeIfAbsent(ImmutableSet.copyOf(mavenCoords), coords -> { wasChanged.set(true); return ImmutableSet.copyOf(input.get().provisionWithDependencies(coords)); }); if (wasChanged.get()) { try (ObjectOutputStream outputStream = new ObjectOutputStream(Files.asByteSink(cacheFile).openBufferedStream())) { outputStream.writeObject(cached); } catch (IOException e) { throw Errors.asRuntime(e); } } return result; }; } /** Creates a Provisioner for the jcenter repo. */ public static Provisioner jcenter() { return jcenter.get(); } private static final Supplier<Provisioner> jcenter = Suppliers.memoize(() -> { return caching("jcenter", createLazyWithRepositories(repo -> repo.jcenter())); }); /** Creates a Provisioner for the mavenCentral repo. */ public static Provisioner mavenCentral() { return mavenCentral.get(); } private static final Supplier<Provisioner> mavenCentral = Suppliers.memoize(() -> { return caching("mavenCentral", createLazyWithRepositories(repo -> repo.mavenCentral())); }); /** Creates a Provisioner for the local maven repo for development purpose. */ public static Provisioner mavenLocal() { return mavenLocal.get(); } private static final Supplier<Provisioner> mavenLocal = createLazyWithRepositories(repo -> repo.mavenLocal()); /** Creates a Provisioner for the Sonatype snapshots maven repo for development purpose. */ public static Provisioner snapshots() { return snapshots.get(); } private static final Supplier<Provisioner> snapshots = createLazyWithRepositories(repo -> { repo.maven(setup -> { setup.setUrl("https://oss.sonatype.org/content/repositories/snapshots"); }); }); }