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

eu.europa.esig.dss.tsl.service.TSLValidationJob Maven / Gradle / Ivy

There is a newer version: 6.0.d4j.2
Show newest version
/**
 * DSS - Digital Signature Services
 * Copyright (C) 2015 European Commission, provided under the CEF programme
 *
 * This file is part of the "DSS - Digital Signature Services" project.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */
package eu.europa.esig.dss.tsl.service;

import java.io.File;
import java.io.FileInputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

import javax.annotation.PostConstruct;

import eu.europa.esig.dss.DSSException;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import eu.europa.esig.dss.DSSUtils;
import eu.europa.esig.dss.client.http.DataLoader;
import eu.europa.esig.dss.tsl.TSLLoaderResult;
import eu.europa.esig.dss.tsl.TSLParserResult;
import eu.europa.esig.dss.tsl.TSLPointer;
import eu.europa.esig.dss.tsl.TSLService;
import eu.europa.esig.dss.tsl.TSLServiceProvider;
import eu.europa.esig.dss.tsl.TSLValidationModel;
import eu.europa.esig.dss.tsl.TSLValidationResult;
import eu.europa.esig.dss.x509.CertificateToken;
import eu.europa.esig.dss.x509.KeyStoreCertificateSource;

/**
 * This class is job class which allows to launch TSL loading/parsing/validation. An instance of this class can be injected in a Spring quartz job.
 */
public class TSLValidationJob {

	private static final Logger logger = LoggerFactory.getLogger(TSLValidationJob.class);

	private ExecutorService executorService = Executors.newCachedThreadPool();

	private DataLoader dataLoader;
	private TSLRepository repository;
	private String lotlCode;
	private String lotlUrl;
	private KeyStoreCertificateSource dssKeyStore;
	private boolean checkLOTLSignature = true;
	private boolean checkTSLSignatures = true;
	private List filterTerritories;

	public void setExecutorService(ExecutorService executorService) {
		this.executorService = executorService;
	}

	public void setDataLoader(DataLoader dataLoader) {
		this.dataLoader = dataLoader;
	}

	public void setRepository(TSLRepository repository) {
		this.repository = repository;
	}

	public void setLotlCode(String lotlCode) {
		this.lotlCode = lotlCode;
	}

	public void setLotlUrl(String lotlUrl) {
		this.lotlUrl = lotlUrl;
	}

	public void setDssKeyStore(KeyStoreCertificateSource dssKeyStore) {
		this.dssKeyStore = dssKeyStore;
	}

	public void setCheckLOTLSignature(boolean checkLOTLSignature) {
		this.checkLOTLSignature = checkLOTLSignature;
	}

	public void setCheckTSLSignatures(boolean checkTSLSignatures) {
		this.checkTSLSignatures = checkTSLSignatures;
	}

	public void setFilterTerritories(List filterTerritories) {
		this.filterTerritories = filterTerritories;
	}

	@PostConstruct
	public void initRepository() {
		logger.info("Initialization of the TSL repository ...");
		int loadedTSL = 0;
		List cachedFiles = repository.getStoredFiles();
		if (CollectionUtils.isNotEmpty(cachedFiles)) {
			List> futureParseResults = new ArrayList>();
			for (File file : cachedFiles) {
				try {
					FileInputStream fis = new FileInputStream(file);
					futureParseResults.add(executorService.submit(new TSLParser(fis)));
				} catch (Exception e) {
					logger.error("Unable to parse file '" + file.getAbsolutePath() + "' : " + e.getMessage(), e);
				}
			}

			for (Future futureParseResult : futureParseResults) {
				try {
					TSLParserResult tslParserResult = futureParseResult.get();
					loadMissingCertificates(tslParserResult);
					repository.addParsedResultFromCacheToMap(tslParserResult);
					loadedTSL++;
				} catch (Exception e) {
					logger.error("Unable to get parsing result : " + e.getMessage(), e);
				}
			}

			TSLValidationModel europeanModel = repository.getByCountry(lotlCode);
			if (checkLOTLSignature && (europeanModel != null)) {
				try {
					TSLValidationResult europeanValidationResult = validateLOTL(europeanModel);
					europeanModel.setValidationResult(europeanValidationResult);
				} catch (Exception e) {
					logger.error("Unable to validate the LOTL : " + e.getMessage(), e);
				}
			}

			if (checkTSLSignatures && ((europeanModel != null) && (europeanModel.getParseResult() != null))) {
				List pointers = europeanModel.getParseResult().getPointers();
				List> futureValidationResults = new ArrayList>();
				Map map = repository.getAllMapTSLValidationModels();
				for (Entry entry : map.entrySet()) {
					String countryCode = entry.getKey();
					if (!lotlCode.equals(countryCode)) {
						TSLValidationModel countryModel = entry.getValue();
						TSLValidator tslValidator = new TSLValidator(new File(countryModel.getFilepath()), countryCode, dssKeyStore, getPotentialSigners(pointers, countryCode));
						futureValidationResults.add(executorService.submit(tslValidator));
					}
				}

				storeValidationResults(futureValidationResults);
			}

			repository.synchronize();
		}
		logger.info(loadedTSL + " loaded TSL from cached files in the repository");
	}

	public void refresh() {
		logger.debug("TSL Validation Job is starting ...");
		TSLLoaderResult resultLoaderLOTL = null;
		Future result = executorService.submit(new TSLLoader(dataLoader, lotlCode, lotlUrl));
		try {
			resultLoaderLOTL = result.get();
		} catch (Exception e) {
			logger.error("Unable to load the LOTL : " + e.getMessage(), e);
			throw new DSSException("Unable to load the LOTL : " + e.getMessage());
		}
		if(resultLoaderLOTL.getContent() == null) {
			logger.error("Unable to load the LOTL: content is empty");
			throw new DSSException("Unable to load the LOTL: content is empty");
		}

		TSLValidationModel europeanModel = null;
		if (!repository.isLastVersion(resultLoaderLOTL)) {
			europeanModel = repository.storeInCache(resultLoaderLOTL);
		} else {
			europeanModel = repository.getByCountry(resultLoaderLOTL.getCountryCode());
		}

		TSLParserResult parseResult = europeanModel.getParseResult();
		if (parseResult == null) {
			try {
				parseResult = parseLOTL(europeanModel);
				europeanModel.setParseResult(parseResult);
			} catch (Exception e) {
				logger.error("Unable to parse the LOTL : " + e.getMessage(), e);
				return;
			}
		}

		if (checkLOTLSignature && (europeanModel.getValidationResult() == null)) {
			try {
				TSLValidationResult validationResult = validateLOTL(europeanModel);
				europeanModel.setValidationResult(validationResult);
			} catch (Exception e) {
				logger.error("Unable to validate the LOTL : " + e.getMessage(), e);
			}
		}

		analyzeCountryPointers(parseResult.getPointers());

		repository.synchronize();

		logger.debug("TSL Validation Job is finishing ...");
	}

	private void analyzeCountryPointers(List pointers) {
		List> futureLoaderResults = new ArrayList>();
		for (TSLPointer tslPointer : pointers) {
			if (CollectionUtils.isEmpty(filterTerritories) || filterTerritories.contains(tslPointer.getTerritory())) {
				TSLLoader tslLoader = new TSLLoader(dataLoader, tslPointer.getTerritory(), tslPointer.getUrl());
				futureLoaderResults.add(executorService.submit(tslLoader));
			}
		}

		List> futureParseResults = new ArrayList>();
		List> futureValidationResults = new ArrayList>();
		for (Future futureLoaderResult : futureLoaderResults) {
			try {
				TSLLoaderResult loaderResult = futureLoaderResult.get();
				if(loaderResult.getContent() == null || loaderResult.getContent().length == 0) {
					logger.error("Failed to load TSl for country '" + loaderResult.getCountryCode() + "' from '" + loaderResult.getUrl() + "'");
					continue;
				}
				TSLValidationModel countryModel = null;
				if (!repository.isLastVersion(loaderResult)) {
					countryModel = repository.storeInCache(loaderResult);
				} else {
					countryModel = repository.getByCountry(loaderResult.getCountryCode());
				}

				TSLParserResult countryParseResult = countryModel.getParseResult();
				if (countryParseResult == null) {
					FileInputStream fis = new FileInputStream(countryModel.getFilepath());
					futureParseResults.add(executorService.submit(new TSLParser(fis)));
				}

				if (checkTSLSignatures && (countryModel.getValidationResult() == null)) {
					TSLValidator tslValidator = new TSLValidator(new File(countryModel.getFilepath()), loaderResult.getCountryCode(), dssKeyStore, getPotentialSigners(pointers,
							loaderResult.getCountryCode()));
					futureValidationResults.add(executorService.submit(tslValidator));
				}
			} catch (Exception e) {
				logger.error("Unable to load/parse TSL : " + e.getMessage(), e);
			}
		}

		for (Future futureParseResult : futureParseResults) {
			try {
				TSLParserResult tslParserResult = futureParseResult.get();
				loadMissingCertificates(tslParserResult);
				repository.updateParseResult(tslParserResult);
			} catch (Exception e) {
				logger.error("Unable to get parsing result : " + e.getMessage(), e);
			}
		}

		storeValidationResults(futureValidationResults);
	}

	private void storeValidationResults(List> futureValidationResults) {
		for (Future futureValidationResult : futureValidationResults) {
			try {
				TSLValidationResult tslValidationResult = futureValidationResult.get();
				repository.updateValidationResult(tslValidationResult);
			} catch (Exception e) {
				logger.error("Unable to get validation result : " + e.getMessage(), e);
			}
		}
	}

	/**
	 * The spanish TSL contains some urls with certificates to download
	 */
	private void loadMissingCertificates(TSLParserResult tslParserResult) {
		if ("ES".equals(tslParserResult.getTerritory())) {
			List serviceProviders = tslParserResult.getServiceProviders();
			if (CollectionUtils.isNotEmpty(serviceProviders)) {
				for (TSLServiceProvider tslServiceProvider : serviceProviders) {
					List services = tslServiceProvider.getServices();
					if (CollectionUtils.isNotEmpty(services)) {
						for (TSLService tslService : services) {
							List certificateUrls = tslService.getCertificateUrls();
							if (CollectionUtils.isNotEmpty(certificateUrls)) {
								for (String url : certificateUrls) {
									try {
										byte[] byteArray = dataLoader.get(url);
										CertificateToken certificate = DSSUtils.loadCertificate(byteArray);
										if (certificate != null) {
											tslService.getCertificates().add(certificate);
										}
									} catch (Exception e) {
										logger.warn("Cannot load certificate from url '" + url + "' : " + e.getMessage());
									}
								}
							}
						}
					}
				}
			}
		}
	}

	private List getPotentialSigners(List pointers, String countryCode) {
		if (CollectionUtils.isNotEmpty(pointers)) {
			for (TSLPointer tslPointer : pointers) {
				if (StringUtils.equals(countryCode, tslPointer.getTerritory())) {
					return tslPointer.getPotentialSigners();
				}
			}
		}
		return Collections.emptyList();
	}

	private TSLValidationResult validateLOTL(TSLValidationModel validationModel) throws Exception {
		TSLValidator tslValidator = new TSLValidator(new File(validationModel.getFilepath()), lotlCode, dssKeyStore);
		Future future = executorService.submit(tslValidator);
		return future.get();
	}

	private TSLParserResult parseLOTL(TSLValidationModel validationModel) throws Exception {
		FileInputStream fis = new FileInputStream(validationModel.getFilepath());
		Future future = executorService.submit(new TSLParser(fis));
		return future.get();
	}

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy