Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import org.gradle.test.fixtures.file.TestNameTestDirectoryProvider
import org.gradle.tooling.GradleConnector
import org.gradle.tooling.ProjectConnection
import org.gradle.tooling.internal.consumer.Distribution
import org.gradle.tooling.internal.consumer.ConsumerProgressListener
import org.gradle.tooling.model.GradleProject
import org.gradle.tooling.model.idea.IdeaProject
import org.junit.Rule
Expand Down Expand Up @@ -273,12 +274,12 @@ project.description = text
return 'mock'
}

ClassPath getToolingImplementationClasspath(ProgressLoggerFactory progressLoggerFactory, File userHomeDir, BuildCancellationToken cancellationToken) {
ClassPath getToolingImplementationClasspath(ProgressLoggerFactory progressLoggerFactory, ConsumerProgressListener progressListener, File userHomeDir, BuildCancellationToken cancellationToken) {
def o = progressLoggerFactory.newOperation("mock")
operation(o)
o.started()
o.completed()
return delegate.getToolingImplementationClasspath(progressLoggerFactory, userHomeDir, cancellationToken)
return delegate.getToolingImplementationClasspath(progressLoggerFactory, progressListener, userHomeDir, cancellationToken)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
package org.gradle.integtests.tooling

import org.gradle.integtests.fixtures.AbstractIntegrationSpec
import org.gradle.integtests.tooling.fixture.ProgressEvents
import org.gradle.integtests.tooling.fixture.ToolingApi
import org.gradle.test.fixtures.file.LeaksFileHandles
import org.gradle.test.fixtures.server.http.HttpServer
Expand All @@ -25,6 +26,7 @@ import org.gradle.tooling.BuildLauncher
import org.gradle.tooling.CancellationTokenSource
import org.gradle.tooling.GradleConnector
import org.gradle.tooling.ProjectConnection
import org.gradle.tooling.events.StatusEvent
import org.gradle.tooling.internal.consumer.DefaultCancellationTokenSource
import org.gradle.util.GradleVersion
import org.junit.Rule
Expand Down Expand Up @@ -77,6 +79,39 @@ class ToolingApiRemoteIntegrationTest extends AbstractIntegrationSpec {
toolingApi.gradleUserHomeDir.file("wrapper/dists/custom-dist").assertIsDir().listFiles().size() == 1
}

def "receives distribution download progress events"() {
assert distribution.binDistribution.exists() : "bin distribution must exist to run this test, you need to run the :binZip task"

given:
settingsFile << "";
buildFile << ""

and:
server.expectGet("/custom-dist.zip", distribution.binDistribution)

and:
def distUri = URI.create("http://localhost:${server.port}/custom-dist.zip")
toolingApi.withConnector { GradleConnector connector ->
connector.useDistribution(distUri)
}

when:
def events = new ProgressEvents()
toolingApi.withConnection { ProjectConnection connection ->
connection.newBuild()
.forTasks("help")
.addProgressListener(events)
.run()
}

then:
def lastProgressEvent = events.all.findAll { it instanceof StatusEvent }.last() as StatusEvent
lastProgressEvent.displayName == "Downloading " + distUri
lastProgressEvent.total == distribution.binDistribution.length()
lastProgressEvent.progress <= distribution.binDistribution.length()
toolingApi.gradleUserHomeDir.file("wrapper/dists/custom-dist").assertIsDir().listFiles().size() == 1
}

def "can cancel distribution download"() {
assert distribution.binDistribution.exists() : "bin distribution must exist to run this test, you need to run the :binZip task"
def userHomeDir = file("user-home-dir")
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/*
* Copyright 2017 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.events;

/**
* An event that informs about an interim results of the operation.
*/
public interface StatusEvent extends ProgressEvent {
/**
* The amount of work already performed by the build operation.
*
* @return The amount of performed work
*/
long getProgress();

/**
* The total amount of work that the build operation is in the progress of performing, or -1 if not known.
*
* @return The total amount of work, or -1 if not known.
*/
long getTotal();

/**
* The measure used to express the amount of work.
*
* @return The measure used to express the amount of work.
*/
String getUnit();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/*
* Copyright 2017 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.events.internal;

import org.gradle.tooling.events.OperationDescriptor;
import org.gradle.tooling.events.StatusEvent;

/**
* Base implementation of the {@code StatusEvent} interface.
*/
public class DefaultStatusEvent extends BaseProgressEvent implements StatusEvent {

private final long total;
private final long progress;
private final String unit;

public DefaultStatusEvent(long eventTime, String displayName, OperationDescriptor descriptor, long total, long progress, String unit) {
super(eventTime, displayName, descriptor);
this.total = total;
this.progress = progress;
this.unit = unit;
}

@Override
public long getProgress() {
return progress;
}

@Override
public long getTotal() {
return total;
}

@Override
public String getUnit() {
return unit;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/*
* Copyright 2017 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.consumer;

import org.gradle.wrapper.DownloadProgressListener;
import org.gradle.wrapper.IDownload;

public interface ConsumerProgressListener extends IDownload, DownloadProgressListener {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/*
* Copyright 2017 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.consumer;

import org.gradle.internal.logging.events.OperationIdentifier;
import org.gradle.internal.logging.progress.ProgressLogger;
import org.gradle.internal.logging.progress.ProgressLoggerFactory;
import org.gradle.internal.time.TimeProvider;
import org.gradle.internal.time.TrueTimeProvider;
import org.gradle.tooling.events.OperationDescriptor;
import org.gradle.tooling.events.StatusEvent;
import org.gradle.tooling.events.internal.DefaultOperationDescriptor;
import org.gradle.tooling.events.internal.DefaultStatusEvent;
import org.gradle.tooling.internal.protocol.InternalBuildProgressListener;
import org.gradle.util.GradleVersion;
import org.gradle.wrapper.Download;
import org.gradle.wrapper.Logger;

import java.io.File;
import java.net.URI;

public class DefaultConsumerProgressListener implements ConsumerProgressListener {
private static final String APP_NAME = "Gradle Tooling API";
private final ProgressLoggerFactory progressLoggerFactory;
private final InternalBuildProgressListener buildProgressListener;
private final TimeProvider timeProvider;

public DefaultConsumerProgressListener(ProgressLoggerFactory progressLoggerFactory, InternalBuildProgressListener buildProgressListener) {
this.progressLoggerFactory = progressLoggerFactory;
this.buildProgressListener = buildProgressListener;
this.timeProvider = new TrueTimeProvider();
}

@Override
public void download(URI address, File destination) throws Exception {
ProgressLogger progressLogger = progressLoggerFactory.newOperation(DefaultConsumerProgressListener.class);
progressLogger.setDescription("Download " + address);
progressLogger.started();
try {
new Download(new Logger(false), this, APP_NAME, GradleVersion.current().getVersion()).download(address, destination);
} finally {
progressLogger.completed();
}
}

@Override
public void downloadStatusChanged(URI address, long contentLength, long downloaded) {
String displayName = "Downloading " + address;
OperationIdentifier id = new OperationIdentifier(0);
org.gradle.tooling.internal.provider.events.DefaultOperationDescriptor internalDescriptor =
new org.gradle.tooling.internal.provider.events.DefaultOperationDescriptor(id, displayName, displayName, null);
OperationDescriptor descriptor = new DefaultOperationDescriptor(internalDescriptor, null);
StatusEvent statusEvent = new DefaultStatusEvent(timeProvider.getCurrentTime(), displayName, descriptor, contentLength, downloaded, "bytes");
buildProgressListener.onEvent(statusEvent);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,5 +25,5 @@ public interface Distribution {
String getDisplayName();

ClassPath getToolingImplementationClasspath(
ProgressLoggerFactory progressLoggerFactory, File userHomeDir, BuildCancellationToken cancellationToken);
ProgressLoggerFactory progressLoggerFactory, ConsumerProgressListener progressListener, File userHomeDir, BuildCancellationToken cancellationToken);
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,7 @@
import org.gradle.tooling.GradleConnectionException;
import org.gradle.util.DistributionLocator;
import org.gradle.util.GradleVersion;
import org.gradle.wrapper.Download;
import org.gradle.wrapper.GradleUserHomeLookup;
import org.gradle.wrapper.IDownload;
import org.gradle.wrapper.Install;
import org.gradle.wrapper.Logger;
import org.gradle.wrapper.PathAssembler;
Expand Down Expand Up @@ -128,14 +126,14 @@ public String getDisplayName() {
return "Gradle distribution '" + wrapperConfiguration.getDistribution() + "'";
}

public ClassPath getToolingImplementationClasspath(final ProgressLoggerFactory progressLoggerFactory, final File userHomeDir, BuildCancellationToken cancellationToken) {
public ClassPath getToolingImplementationClasspath(ProgressLoggerFactory progressLoggerFactory, final ConsumerProgressListener progressListener, final File userHomeDir, BuildCancellationToken cancellationToken) {
if (installedDistribution == null) {
Callable<File> installDistroTask = new Callable<File>() {
public File call() throws Exception {
File installDir;
try {
File realUserHomeDir = determineRealUserHomeDir(userHomeDir);
Install install = new Install(new Logger(false), new ProgressReportingDownload(progressLoggerFactory), new PathAssembler(realUserHomeDir));
Install install = new Install(new Logger(false), progressListener, new PathAssembler(realUserHomeDir));
installDir = install.createDist(wrapperConfiguration);
} catch (FileNotFoundException e) {
throw new IllegalArgumentException(String.format("The specified %s does not exist.", getDisplayName()), e);
Expand Down Expand Up @@ -175,7 +173,7 @@ public void run() {
}
installedDistribution = new InstalledDistribution(installDir, getDisplayName(), getDisplayName());
}
return installedDistribution.getToolingImplementationClasspath(progressLoggerFactory, userHomeDir, cancellationToken);
return installedDistribution.getToolingImplementationClasspath(progressLoggerFactory, progressListener, userHomeDir, cancellationToken);
}

private File determineRealUserHomeDir(final File userHomeDir) {
Expand All @@ -187,25 +185,6 @@ private File determineRealUserHomeDir(final File userHomeDir) {
}
}

private static class ProgressReportingDownload implements IDownload {
private final ProgressLoggerFactory progressLoggerFactory;

private ProgressReportingDownload(ProgressLoggerFactory progressLoggerFactory) {
this.progressLoggerFactory = progressLoggerFactory;
}

public void download(URI address, File destination) throws Exception {
ProgressLogger progressLogger = progressLoggerFactory.newOperation(DistributionFactory.class);
progressLogger.setDescription("Download " + address);
progressLogger.started();
try {
new Download(new Logger(false), "Gradle Tooling API", GradleVersion.current().getVersion()).download(address, destination);
} finally {
progressLogger.completed();
}
}
}

private static class InstalledDistribution implements Distribution {
private final File gradleHomeDir;
private final String displayName;
Expand All @@ -221,7 +200,7 @@ public String getDisplayName() {
return displayName;
}

public ClassPath getToolingImplementationClasspath(ProgressLoggerFactory progressLoggerFactory, File userHomeDir, BuildCancellationToken cancellationToken) {
public ClassPath getToolingImplementationClasspath(ProgressLoggerFactory progressLoggerFactory, ConsumerProgressListener progressListener, File userHomeDir, BuildCancellationToken cancellationToken) {
ProgressLogger progressLogger = progressLoggerFactory.newOperation(DistributionFactory.class);
progressLogger.setDescription("Validate distribution");
progressLogger.started();
Expand Down Expand Up @@ -258,7 +237,7 @@ public String getDisplayName() {
return "Gradle classpath distribution";
}

public ClassPath getToolingImplementationClasspath(ProgressLoggerFactory progressLoggerFactory, File userHomeDir, BuildCancellationToken cancellationToken) {
public ClassPath getToolingImplementationClasspath(ProgressLoggerFactory progressLoggerFactory, ConsumerProgressListener progressListener, File userHomeDir, BuildCancellationToken cancellationToken) {
ClassPath classpath = new DefaultClassPath();
DefaultModuleRegistry registry = new DefaultModuleRegistry(null);
for (Module module : registry.getModule("gradle-launcher").getAllRequiredModules()) {
Expand Down
Loading