/*
* Copyright (c) MuleSoft, Inc. All rights reserved. http://www.mulesoft.com
* The software in this package is published under the terms of the CPAL v1.0
* license, a copy of which has been included with this distribution in the
* LICENSE.txt file.
*/
package org.mule.runtime.module.tooling.internal;
import static com.google.common.base.Throwables.getCausalChain;
import static org.mule.runtime.api.connection.ConnectionValidationResult.failure;
import static org.mule.runtime.api.util.Preconditions.checkArgument;
import static org.mule.runtime.core.util.FileUtils.deleteTree;
import org.mule.runtime.api.component.location.Location;
import org.mule.runtime.api.connection.ConnectionException;
import org.mule.runtime.api.connection.ConnectionValidationResult;
import org.mule.runtime.api.exception.MuleRuntimeException;
import org.mule.runtime.core.api.connectivity.ConnectivityTestingService;
import org.mule.runtime.deployment.model.api.DeploymentStartException;
import org.mule.runtime.deployment.model.api.application.Application;
import org.mule.runtime.module.repository.api.BundleNotFoundException;
import org.eclipse.aether.resolution.ArtifactResolutionException;
import org.eclipse.aether.transfer.ArtifactNotFoundException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* {@link ConnectivityTestingService} for a temporary artifact.
* <p/>
* This class will take care of the artifact initialization as part of the connection service invocation and deal with any thrown
* exception by the startup of the artifact.
*/
public class TemporaryArtifactConnectivityTestingService implements ConnectivityTestingService {
private static final Logger LOGGER = LoggerFactory.getLogger(TemporaryArtifactConnectivityTestingService.class);
private final ApplicationSupplier applicationSupplier;
private Application application;
/**
* Creates a {@code DefaultConnectivityTestingService}.
*
* @param applicationSupplier supplier of the application that will be used to do connectivity testing.
*/
public TemporaryArtifactConnectivityTestingService(ApplicationSupplier applicationSupplier) {
this.applicationSupplier = applicationSupplier;
}
/**
* {@inheritDoc}
*
* @throws MuleRuntimeException
*/
@Override
public ConnectionValidationResult testConnection(Location location) {
checkArgument(location != null, "identifier cannot be null");
try {
application = applicationSupplier.get();
} catch (Exception e) {
throw getCausalChain(e).stream()
.filter(exception -> exception.getClass().equals(ArtifactNotFoundException.class)
|| exception.getClass().equals(ArtifactResolutionException.class))
.findFirst().map(exception -> (RuntimeException) new BundleNotFoundException(exception))
.orElse(new MuleRuntimeException(e));
}
try {
try {
this.application.install();
this.application.init();
this.application.start();
} catch (DeploymentStartException e) {
return failure(e.getMessage(), e);
} catch (Exception e) {
return getCausalChain(e).stream()
.filter(exception -> exception.getClass().equals(ConnectionException.class)
&& ((ConnectionException) exception).getErrorType().isPresent())
.map(exception -> failure(exception.getMessage(), ((ConnectionException) exception).getErrorType().get(),
(Exception) exception))
.findFirst()
.orElse(failure(e.getMessage(), e));
}
return application.getConnectivityTestingService().testConnection(location);
} finally {
if (application != null) {
doWithoutFail(() -> application.stop());
doWithoutFail(() -> application.dispose());
doWithoutFail(() -> deleteTree(application.getLocation()));
}
}
}
public void doWithoutFail(Runnable runnable) {
try {
runnable.run();
} catch (Exception e) {
LOGGER.warn(e.getMessage());
if (LOGGER.isDebugEnabled()) {
LOGGER.debug(e.getMessage(), e);
}
}
}
@FunctionalInterface
public interface ApplicationSupplier {
Application get() throws Exception;
}
}