/* * Copyright 2011 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.tooling.internal.provider; import org.gradle.api.JavaVersion; import org.gradle.api.Nullable; import org.gradle.initialization.BuildCancellationToken; import org.gradle.initialization.BuildLayoutParameters; import org.gradle.initialization.DefaultBuildCancellationToken; import org.gradle.internal.concurrent.CompositeStoppable; import org.gradle.internal.jvm.UnsupportedJavaRuntimeException; import org.gradle.internal.logging.services.LoggingServiceRegistry; import org.gradle.internal.nativeintegration.services.NativeServices; import org.gradle.internal.service.ServiceRegistry; import org.gradle.internal.service.ServiceRegistryBuilder; import org.gradle.tooling.UnsupportedVersionException; import org.gradle.tooling.internal.adapter.ProtocolToModelAdapter; import org.gradle.tooling.internal.protocol.BuildActionRunner; import org.gradle.tooling.internal.protocol.BuildExceptionVersion1; import org.gradle.tooling.internal.protocol.BuildOperationParametersVersion1; import org.gradle.tooling.internal.protocol.BuildParameters; import org.gradle.tooling.internal.protocol.BuildParametersVersion1; import org.gradle.tooling.internal.protocol.BuildResult; import org.gradle.tooling.internal.protocol.ConfigurableConnection; import org.gradle.tooling.internal.protocol.ConnectionMetaDataVersion1; import org.gradle.tooling.internal.protocol.ConnectionParameters; import org.gradle.tooling.internal.protocol.ConnectionVersion4; import org.gradle.tooling.internal.protocol.InternalBuildAction; import org.gradle.tooling.internal.protocol.InternalBuildActionExecutor; import org.gradle.tooling.internal.protocol.InternalCancellableConnection; import org.gradle.tooling.internal.protocol.InternalCancellationToken; import org.gradle.tooling.internal.protocol.InternalConnection; import org.gradle.tooling.internal.protocol.InternalUnsupportedModelException; import org.gradle.tooling.internal.protocol.ModelBuilder; import org.gradle.tooling.internal.protocol.ModelIdentifier; import org.gradle.tooling.internal.protocol.ProjectVersion3; import org.gradle.tooling.internal.protocol.ShutdownParameters; import org.gradle.tooling.internal.protocol.StoppableConnection; import org.gradle.tooling.internal.protocol.exceptions.InternalUnsupportedBuildArgumentException; import org.gradle.tooling.internal.protocol.test.InternalTestExecutionConnection; import org.gradle.tooling.internal.protocol.test.InternalTestExecutionRequest; import org.gradle.tooling.internal.provider.connection.BuildLogLevelMixIn; import org.gradle.tooling.internal.provider.connection.ProviderBuildResult; import org.gradle.tooling.internal.provider.connection.ProviderConnectionParameters; import org.gradle.tooling.internal.provider.connection.ProviderOperationParameters; import org.gradle.tooling.internal.provider.test.ProviderInternalTestExecutionRequest; import org.gradle.util.GradleVersion; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.File; public class DefaultConnection implements ConnectionVersion4, InternalConnection, BuildActionRunner, ConfigurableConnection, ModelBuilder, InternalBuildActionExecutor, InternalCancellableConnection, StoppableConnection, InternalTestExecutionConnection { private static final Logger LOGGER = LoggerFactory.getLogger(DefaultConnection.class); private static final GradleVersion MIN_CLIENT_VERSION = GradleVersion.version("2.0"); private ProtocolToModelAdapter adapter; private ServiceRegistry services; private ProviderConnection connection; private boolean supportedConsumerVersion; @Nullable // not provided by older client versions private GradleVersion consumerVersion; /** * This is used by consumers 1.0-milestone-3 and later */ public DefaultConnection() { LOGGER.debug("Tooling API provider {} created.", GradleVersion.current().getVersion()); } /** * This is used by consumers 1.2-rc-1 and later. */ public void configure(ConnectionParameters parameters) { UnsupportedJavaRuntimeException.assertUsingVersion("Gradle", JavaVersion.VERSION_1_7); ProviderConnectionParameters providerConnectionParameters = new ProtocolToModelAdapter().adapt(ProviderConnectionParameters.class, parameters); File gradleUserHomeDir = providerConnectionParameters.getGradleUserHomeDir(null); if (gradleUserHomeDir == null) { gradleUserHomeDir = new BuildLayoutParameters().getGradleUserHomeDir(); } initializeServices(gradleUserHomeDir); connection.configure(providerConnectionParameters); consumerVersion = GradleVersion.version(providerConnectionParameters.getConsumerVersion()); supportedConsumerVersion = consumerVersion.compareTo(MIN_CLIENT_VERSION) >= 0; } private void initializeServices(File gradleUserHomeDir) { NativeServices.initialize(gradleUserHomeDir); LoggingServiceRegistry loggingServices = LoggingServiceRegistry.newEmbeddableLogging(); services = ServiceRegistryBuilder.builder() .displayName("Connection services") .parent(loggingServices) .parent(NativeServices.getInstance()) .provider(new ConnectionScopeServices(loggingServices)).build(); adapter = services.get(ProtocolToModelAdapter.class); connection = services.get(ProviderConnection.class); } /** * This method was used by consumers 1.0-rc-1 through to 1.1. Later consumers use {@link #configure(ConnectionParameters)} instead. */ public void configureLogging(final boolean verboseLogging) { // Ignore - we don't support these consumer versions any more } /** * This is used by consumers 1.0-milestone-3 and later */ public ConnectionMetaDataVersion1 getMetaData() { return new DefaultConnectionMetaData(); } /** * This is used by consumers 1.0-milestone-3 and later */ @Deprecated public void stop() { // We don't do anything here, as older consumers call this method when the project connection is closed but then later attempt to reuse the connection } /** * This is used by consumers 2.2-rc-1 and later */ public void shutdown(ShutdownParameters parameters) { CompositeStoppable.stoppable(services).stop(); } /** * This is used by consumers 1.0-milestone-3 to 1.1. */ @Deprecated public void executeBuild(BuildParametersVersion1 buildParameters, BuildOperationParametersVersion1 operationParameters) { throw unsupportedConnectionException(); } /** * This is used by consumers 1.0-milestone-3 to 1.0-milestone-7 */ @Deprecated public ProjectVersion3 getModel(Class<? extends ProjectVersion3> type, BuildOperationParametersVersion1 parameters) { throw unsupportedConnectionException(); } /** * This is used by consumers 1.0-milestone-8 to 1.1 */ @Deprecated public <T> T getTheModel(Class<T> type, BuildOperationParametersVersion1 parameters) { throw unsupportedConnectionException(); } /** * This is used by consumers 1.2-rc-1 to 1.5 */ @Deprecated public <T> BuildResult<T> run(Class<T> type, BuildParameters buildParameters) throws UnsupportedOperationException, IllegalStateException { throw unsupportedConnectionException(); } /** * This is used by consumers 1.6-rc-1 to 2.0 */ public BuildResult<?> getModel(ModelIdentifier modelIdentifier, BuildParameters operationParameters) throws UnsupportedOperationException, IllegalStateException { ProviderOperationParameters providerParameters = validateAndConvert(operationParameters); Object result = connection.run(modelIdentifier.getName(), new DefaultBuildCancellationToken(), providerParameters); return new ProviderBuildResult<Object>(result); } /** * This is used by consumers 2.1-rc-1 and later */ public BuildResult<?> getModel(ModelIdentifier modelIdentifier, InternalCancellationToken cancellationToken, BuildParameters operationParameters) throws BuildExceptionVersion1, InternalUnsupportedModelException, InternalUnsupportedBuildArgumentException, IllegalStateException { ProviderOperationParameters providerParameters = validateAndConvert(operationParameters); BuildCancellationToken buildCancellationToken = new InternalCancellationTokenAdapter(cancellationToken); Object result = connection.run(modelIdentifier.getName(), buildCancellationToken, providerParameters); return new ProviderBuildResult<Object>(result); } /** * This is used by consumers 1.8-rc-1 to 2.0 */ public <T> BuildResult<T> run(InternalBuildAction<T> action, BuildParameters operationParameters) throws BuildExceptionVersion1, InternalUnsupportedBuildArgumentException, IllegalStateException { ProviderOperationParameters providerParameters = validateAndConvert(operationParameters); Object results = connection.run(action, new DefaultBuildCancellationToken(), providerParameters); return new ProviderBuildResult<T>((T) results); } /** * This is used by consumers 2.1-rc-1 and later. */ public <T> BuildResult<T> run(InternalBuildAction<T> action, InternalCancellationToken cancellationToken, BuildParameters operationParameters) throws BuildExceptionVersion1, InternalUnsupportedBuildArgumentException, IllegalStateException { ProviderOperationParameters providerParameters = validateAndConvert(operationParameters); BuildCancellationToken buildCancellationToken = new InternalCancellationTokenAdapter(cancellationToken); Object results = connection.run(action, buildCancellationToken, providerParameters); return new ProviderBuildResult<T>((T) results); } /** * This is used by consumers 2.6-rc-1 and later */ public BuildResult<?> runTests(InternalTestExecutionRequest testExecutionRequest, InternalCancellationToken cancellationToken, BuildParameters operationParameters) throws BuildExceptionVersion1, InternalUnsupportedBuildArgumentException, IllegalStateException { ProviderOperationParameters providerParameters = validateAndConvert(operationParameters); ProviderInternalTestExecutionRequest testExecutionRequestVersion2 = adapter.adapt(ProviderInternalTestExecutionRequest.class, testExecutionRequest); BuildCancellationToken buildCancellationToken = new InternalCancellationTokenAdapter(cancellationToken); Object results = connection.runTests(testExecutionRequestVersion2, buildCancellationToken, providerParameters); return new ProviderBuildResult<Object>(results); } private UnsupportedVersionException unsupportedConnectionException() { StringBuilder message = new StringBuilder("Support for clients using a tooling API version older than 2.0 was removed in Gradle 3.0. "); if (consumerVersion != null) { // Consumer version is provided by client 1.2 and later message.append("You are currently using tooling API version "); message.append(consumerVersion.getVersion()); message.append(". "); } message.append("You should upgrade your tooling API client to version 2.0 or later."); return new UnsupportedVersionException(message.toString()); } private ProviderOperationParameters validateAndConvert(BuildParameters buildParameters) { LOGGER.info("Tooling API is using target Gradle version: {}.", GradleVersion.current().getVersion()); UnsupportedJavaRuntimeException.assertUsingVersion("Gradle", JavaVersion.VERSION_1_7); if (!supportedConsumerVersion) { throw unsupportedConnectionException(); } return adapter.builder(ProviderOperationParameters.class).mixInTo(ProviderOperationParameters.class, BuildLogLevelMixIn.class).build(buildParameters); } }