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

org.openl.rules.ruleservice.deployer.RulesDeployerService Maven / Gradle / Ivy

There is a newer version: 5.27.9
Show newest version
package org.openl.rules.ruleservice.deployer;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.Closeable;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;

import org.openl.rules.repository.RepositoryInstatiator;
import org.openl.rules.repository.api.ChangesetType;
import org.openl.rules.repository.api.FileData;
import org.openl.rules.repository.api.FolderRepository;
import org.openl.rules.repository.api.Repository;
import org.openl.rules.repository.folder.FileChangesFromZip;
import org.openl.util.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * This class allows to deploy a zip-based project to a production repository.
 *
 * @author Vladyslav Pikus
 */
public class RulesDeployerService implements Closeable {

    private static final String DEFAULT_DEPLOYMENT_NAME = "openl_rules_";
    private static final String DEFAULT_AUTHOR_NAME = "OpenL_Deployer";

    private final Logger log = LoggerFactory.getLogger(getClass());

    private final Repository deployRepo;
    private final String deployPath;

    public RulesDeployerService(Repository repository, String deployPath) {
        this.deployRepo = repository;
        this.deployPath = deployPath.isEmpty() || deployPath.endsWith("/") ? deployPath : deployPath + "/";
    }

    /**
     * Initializes repository using target properties
     * @param properties repository settings
     */
    public RulesDeployerService(Properties properties) {
        String deployPath = properties.getProperty("production-repository.base.path");
        this.deployPath = deployPath.isEmpty() || deployPath.endsWith("/") ? deployPath : deployPath + "/";

        Map params = new HashMap<>();
        params.put("uri", properties.getProperty("production-repository.uri"));
        params.put("login", properties.getProperty("production-repository.login"));
        params.put("password", properties.getProperty("production-repository.password"));
        // AWS S3 specific
        params.put("bucketName",properties.getProperty("production-repository.bucket-name"));
        params.put("regionName",properties.getProperty("production-repository.region-name"));
        params.put("accessKey",properties.getProperty("production-repository.access-key"));
        params.put("secretKey",properties.getProperty("production-repository.secret-key"));
        // Git specific
        params.put("localRepositoryPath",properties.getProperty("production-repository.local-repository-path"));
        params.put("branch",properties.getProperty("production-repository.branch"));
        params.put("tagPrefix",properties.getProperty("production-repository.tag-prefix"));
        params.put("commentTemplate",properties.getProperty("production-repository.comment-template"));
        // AWS S3 and Git specific
        params.put("listener-timer-period",properties.getProperty("production-repository.listener-timer-period"));

        this.deployRepo = RepositoryInstatiator
                .newRepository(properties.getProperty("production-repository.factory"), params);
    }

    /**
     * Deploys or redeploys target zip input stream
     *
     * @param name original ZIP file name
     * @param in zip input stream
     * @param overridable if deployment was exist before and overridable is false, it will not be deployed, if true, it will be overridden.
     */
    public void deploy(String name, InputStream in, boolean overridable) throws Exception {
        deployInternal(name, in, overridable);
    }

    public void deploy(InputStream in, boolean overridable) throws Exception {
        deployInternal(null, in, overridable);
    }

    private void deployInternal(String originalName, InputStream in, boolean overridable) throws Exception {
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        IOUtils.copyAndClose(in, outputStream);
        String name = originalName != null ? originalName : DEFAULT_DEPLOYMENT_NAME + System.currentTimeMillis();

        if (outputStream.size() == 0) {
            throw new RuntimeException("Zip file input stream is empty");
        }

        DeploymentDTO deployment = new DeploymentDTO(name,
            new ByteArrayInputStream(outputStream.toByteArray()),
            outputStream.size());

        deployInternal(deployment, overridable);
    }

    private void deployInternal(DeploymentDTO deployment, boolean overridable) throws Exception {
        ZipInputStream zipStream = null;
        try {
            String projectName = deployment.getName();
            String apiVersion = null;

            zipStream = new ZipInputStream(deployment.getInputStream());
            ZipEntry zipEntry;
            boolean doesNotContainZippedFiles = true;
            while ((zipEntry = zipStream.getNextEntry()) != null) {
                InputStream fileStream = new ZippedFileInputStream(zipStream);
                if (!zipEntry.isDirectory()) {
                    String zippedFileName = DeploymentUtils.getFileName(zipEntry.getName());
                    if ("rules.xml".equals(zippedFileName)) {
                        String name = DeploymentUtils.getProjectName(fileStream);
                        if (name != null && !name.isEmpty()) {
                            projectName = name;
                        }
                    } else if ("rules-deploy.xml".equals(zippedFileName)) {
                        apiVersion = DeploymentUtils.getApiVersion(fileStream);
                    }
                    doesNotContainZippedFiles = false;
                }
                fileStream.close();
            }

            if (doesNotContainZippedFiles) {
                throw new RuntimeException("Target zip file doesn't contain entries");
            }

            String deploymentName = projectName;
            if (apiVersion != null && !apiVersion.isEmpty()) {
                deploymentName += DeploymentUtils.API_VERSION_SEPARATOR + apiVersion;
            }

            if (!overridable && isRulesDeployed(deploymentName)) {
                log.info("Module '{}' is skipped for deploy because it has been already deployed.", deploymentName);
                return;
            }

            InputStream inputStream = deployment.getInputStream();
            inputStream.reset();
            doDeploy(deployPath + deploymentName + '/' + projectName,
                deployment.getContentSize(),
                inputStream);
        } finally {
            IOUtils.closeQuietly(zipStream);
        }
    }

    private void doDeploy(String name, Integer contentSize, InputStream inputStream) throws IOException {
        FileData dest = new FileData();
        dest.setName(name);
        dest.setAuthor(DEFAULT_AUTHOR_NAME);

        if (deployRepo.supports().folders()) {
            ((FolderRepository) deployRepo).save(dest, new FileChangesFromZip(new ZipInputStream(inputStream), name),
                    ChangesetType.FULL);
        } else {
            dest.setSize(contentSize);
            deployRepo.save(dest, inputStream);
        }
    }

    private boolean isRulesDeployed(String deploymentName) throws IOException {
        List deployments = deployRepo.list(deployPath + deploymentName + "/");
        return !deployments.isEmpty();
    }

    @Override
    public void close() {
        if (deployRepo instanceof Closeable) {
            // Close repo connection after validation
            IOUtils.closeQuietly((Closeable) deployRepo);
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy