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

de.mklinger.qetcher.liferay.client.impl.QetcherClientServiceImpl Maven / Gradle / Ivy

The newest version!
package de.mklinger.qetcher.liferay.client.impl;

import java.io.File;
import java.io.InputStream;
import java.nio.file.Path;
import java.security.KeyStore;
import java.util.Map;
import java.util.function.Supplier;

import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.ConfigurationPolicy;
import org.osgi.service.component.annotations.Deactivate;
import org.osgi.service.component.annotations.Modified;
import org.osgi.service.component.annotations.Reference;
import org.osgi.service.component.annotations.ReferencePolicy;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.liferay.portal.configuration.metatype.bnd.util.ConfigurableUtil;
import com.liferay.portal.kernel.util.PropsKeys;
import com.liferay.portal.kernel.util.PropsUtil;

import de.mklinger.micro.annotations.VisibleForTesting;
import de.mklinger.micro.keystores.KeyStores;
import de.mklinger.qetcher.client.InputConversionFile;
import de.mklinger.qetcher.client.InputJob;
import de.mklinger.qetcher.client.QetcherClient;
import de.mklinger.qetcher.client.QetcherClient.Builder;
import de.mklinger.qetcher.client.QetcherClientBuilders;
import de.mklinger.qetcher.client.QetcherClientException;
import de.mklinger.qetcher.client.QetcherClientVersion;
import de.mklinger.qetcher.client.httpclient.BodyProviders;
import de.mklinger.qetcher.liferay.client.QetcherClientService;

/**
 * @author Marc Klinger - mklinger[at]mklinger[dot]de
 */
@Component(configurationPid = QetcherConfiguration.ID, configurationPolicy = ConfigurationPolicy.REQUIRE)
public class QetcherClientServiceImpl implements QetcherClientService {
	private static final Logger LOG = LoggerFactory.getLogger(QetcherClientServiceImpl.class);

	private QetcherTrustStoreSupplier trustStoreSupplier;
	private Map configurationProperties;
	private QetcherClient client;

	@Reference(policy = ReferencePolicy.DYNAMIC)
	public synchronized void setTrustStoreSupplier(final QetcherTrustStoreSupplier trustStoreSupplier) {
		LOG.info("Trust store supplier was set");
		this.trustStoreSupplier = trustStoreSupplier;
		resetClient();
	}

	// Called by OSGi framework by naming convention
	public synchronized void unsetTrustStoreSupplier(final QetcherTrustStoreSupplier trustStoreSupplier) {
		LOG.info("Trust store supplier was unset");
		this.trustStoreSupplier = null;
		resetClient();
	}

	// Called by OSGi framework by naming convention
	public synchronized void updatedTrustStoreSupplier(final QetcherTrustStoreSupplier trustStoreSupplier) {
		LOG.info("Trust store supplier was updated");
		this.trustStoreSupplier = trustStoreSupplier;
		resetClient();
	}

	@Activate
	@Modified
	public synchronized void activate(final Map properties) {
		LOG.info("Configuration was set");
		this.configurationProperties = properties;
		resetClient();
	}

	private synchronized void resetClient() {
		closeClient();

		if (configurationProperties == null) {
			LOG.error("Could not create Qetcher client as no configuration is available");
			client = new DefunctQetcherClient("Qetcher client is not functional. No configuration available");
			return;
		}

		if (trustStoreSupplier == null) {
			LOG.error("Could not create Qetcher client as no trust store supplier is available");
			client = new DefunctQetcherClient("Qetcher client is not functional. No trust store supplier available");
			return;
		}

		QetcherConfiguration configuration;
		try {
			configuration = ConfigurableUtil.createConfigurable(QetcherConfiguration.class, configurationProperties);
		} catch (final Exception e) {
			final String causeMessages = getCauseMessages(e);
			LOG.error("Error creating Qetcher configuration: {}", causeMessages);
			client = new DefunctQetcherClient("Qetcher client is not functional. There was an error creating Qetcher configuration: " + causeMessages);
			return;
		}

		try {
			client = newClient(configuration);
			LOG.info("Successfully created new Qetcher client");
		} catch (final Exception e) {
			final String causeMessages = getCauseMessages(e);
			LOG.error("Error creating Qetcher client: {}", causeMessages, e);
			client = new DefunctQetcherClient("Qetcher client is not functional. There was an error creating Qetcher client instance: " + causeMessages);
			return;
		}
	}

	private static String getCauseMessages(final Throwable e) {
		return getCauseMessages(e, ": ");
	}

	private static String getCauseMessages(final Throwable e, final String separator) {
		final StringBuilder sb = new StringBuilder();
		Throwable cause = e;
		while (cause != null) {
			final String message = cause.getMessage();
			if (message != null) {
				if (sb.length() > 0) {
					sb.append(separator);
				}
				sb.append(message);
			}
			cause = cause.getCause();
		}
		return sb.toString();
	}

	@Deactivate
	public synchronized void closeClient() {
		try {
			if (client != null) {
				final QetcherClient oldClient = client;
				client = null;
				if (oldClient instanceof NonClosingQetcherClient) {
					((NonClosingQetcherClient) oldClient).reallyClose();
				} else {
					oldClient.close();
				}
			}
		} catch (final Exception e) {
			LOG.warn("Error closing Qetcher client", e);
		}
	}

	private NonClosingQetcherClient newClient(final QetcherConfiguration configuration) {
		final String[] serviceAddresses = configuration.serviceAddresses();
		if (serviceAddresses == null || serviceAddresses.length == 0) {
			throw new QetcherClientException("No Qetcher service addresses configured");
		}

		final KeyStore keyStore = loadKeyStore(configuration);
		final String keyPassword = emptyToNull(configuration.keyPassword());
		final KeyStore trustStore = trustStoreSupplier.get();

		final QetcherClient qetcherClient = newClientBuilder()
				.serviceAddresses(serviceAddresses)
				.keyStore(keyStore, keyPassword)
				.trustStore(trustStore)
				.build();

		LOG.info("Initialized new Qetcher client, version {}", QetcherClientVersion.getVersion());
		LOG.info("Using Qetcher service addresses: {}", (Object)configuration.serviceAddresses());
		new QetcherClientCertificateInfo(keyStore).log();

		return new NonClosingQetcherClient(qetcherClient);
	}

	@VisibleForTesting
	protected Builder newClientBuilder() {
		return QetcherClientBuilders.client();
	}

	private KeyStore loadKeyStore(final QetcherConfiguration configuration) {
		final String keyStoreLocation = getKeyStoreLocation(configuration);
		final String keyStorePassword = emptyToNull(configuration.keyStorePassword());
		final String keyStoreType = emptyToNull(configuration.keyStoreType());

		return KeyStores.load(
				keyStoreLocation,
				keyStorePassword,
				keyStoreType);
	}

	private String getKeyStoreLocation(final QetcherConfiguration configuration) {
		String keyStoreLocation = configuration.keyStoreLocation();
		if (keyStoreLocation == null || keyStoreLocation.isEmpty()) {
			keyStoreLocation = PropsUtil.get(PropsKeys.LIFERAY_HOME) + "/data/qetcher/qetcher-key.p12";
			LOG.info("No Qetcher key store location configured. Using default location: {}", keyStoreLocation);
		}
		return keyStoreLocation;
	}

	private String emptyToNull(final String s) {
		if (s != null && s.trim().isEmpty()) {
			return null;
		}
		return s;
	}

	@Override
	public synchronized QetcherClient client() {
		if (client == null) {
			throw new QetcherClientException("Qetcher client is not initialized. Check configuration and previous log.");
		}
		return client;
	}

	@Override
	public InputConversionFile.Builder inputFileFor(final File inputFile) {
		return QetcherClientBuilders.inputFileFor(inputFile);
	}

	@Override
	public InputConversionFile.Builder inputFileFor(final Path inputFile) {
		return QetcherClientBuilders.inputFileFor(inputFile);
	}

	@Override
	public InputConversionFile.Builder inputFileFor(final Supplier inputStreamSupplier) {
		return QetcherClientBuilders.inputFile()
				.bodyProvider(BodyProviders.fromInputStream(inputStreamSupplier));
	}

	@Override
	public InputJob.Builder job() {
		return QetcherClientBuilders.job();
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy