org.artifactory.repo.service.DeployServiceImpl.java Source code

Java tutorial

Introduction

Here is the source code for org.artifactory.repo.service.DeployServiceImpl.java

Source

/*
 * Artifactory is a binaries repository manager.
 * Copyright (C) 2012 JFrog Ltd.
 *
 * Artifactory 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 3 of the License, or
 * (at your option) any later version.
 *
 * Artifactory 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 Artifactory.  If not, see <http://www.gnu.org/licenses/>.
 */

package org.artifactory.repo.service;

import com.google.common.base.Charsets;
import com.google.common.collect.Lists;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.io.filefilter.AbstractFileFilter;
import org.apache.commons.io.filefilter.DirectoryFileFilter;
import org.apache.commons.io.filefilter.IOFileFilter;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.time.DurationFormatUtils;
import org.artifactory.api.artifact.ArtifactInfo;
import org.artifactory.api.artifact.UnitInfo;
import org.artifactory.api.common.BasicStatusHolder;
import org.artifactory.api.context.ContextHelper;
import org.artifactory.api.maven.MavenArtifactInfo;
import org.artifactory.api.maven.MavenService;
import org.artifactory.api.module.ModuleInfo;
import org.artifactory.api.repo.DeployService;
import org.artifactory.api.repo.exception.RepoRejectException;
import org.artifactory.api.request.UploadService;
import org.artifactory.descriptor.repo.RealRepoDescriptor;
import org.artifactory.descriptor.repo.RepoDescriptor;
import org.artifactory.md.Properties;
import org.artifactory.mime.MavenNaming;
import org.artifactory.mime.NamingUtils;
import org.artifactory.repo.InternalRepoPathFactory;
import org.artifactory.repo.LocalRepo;
import org.artifactory.repo.Repo;
import org.artifactory.repo.RepoPath;
import org.artifactory.request.InternalArtifactoryResponse;
import org.artifactory.sapi.common.RepositoryRuntimeException;
import org.artifactory.spring.InternalContextHelper;
import org.artifactory.util.GlobalExcludes;
import org.artifactory.util.PathUtils;
import org.artifactory.util.ZipUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.File;
import java.io.IOException;
import java.util.Collections;
import java.util.List;

/**
 * Provides artifacts deploy services from the UI.
 *
 * @author Yossi Shaul
 */
@Service
public class DeployServiceImpl implements DeployService {
    private static final Logger log = LoggerFactory.getLogger(DeployServiceImpl.class);

    @Autowired
    private InternalRepositoryService repositoryService;

    @Autowired
    private UploadService uploadService;

    @Autowired
    private MavenService mavenService;

    @Override
    public void deploy(RepoDescriptor targetRepo, UnitInfo artifactInfo, File file, Properties properties)
            throws RepoRejectException {
        String pomString = mavenService.getPomModelString(file);
        deploy(targetRepo, artifactInfo, file, pomString, false, false, properties);
    }

    @Override
    public void deploy(RepoDescriptor targetRepo, UnitInfo artifactInfo, File fileToDeploy, String pomString,
            boolean forceDeployPom, boolean partOfBundleDeploy, Properties properties) throws RepoRejectException {
        String path = artifactInfo.getPath();
        if (!artifactInfo.isValid()) {
            throw new IllegalArgumentException("Invalid unit info for '" + path + "'.");
        }

        //Sanity check
        if (targetRepo == null) {
            throw new IllegalArgumentException("No target repository selected for deployment.");
        }
        final LocalRepo localRepo = repositoryService.localRepositoryByKey(targetRepo.getKey());
        if (localRepo == null) {
            throw new IllegalArgumentException("No target repository found for deployment.");
        }

        RepoPath repoPath = InternalRepoPathFactory.create(targetRepo.getKey(), path);

        // upload the main file
        try {
            ArtifactoryDeployRequest request = new ArtifactoryDeployRequestBuilder(repoPath)
                    .fileToDeploy(fileToDeploy).properties(properties).build();
            request.setSkipJarIndexing(partOfBundleDeploy);
            InternalArtifactoryResponse response = new InternalArtifactoryResponse();
            uploadService.upload(request, response);
            assertNotFailedRequest(fileToDeploy.getName(), response);
        } catch (IOException e) {
            String msg = "Cannot deploy file " + fileToDeploy.getName() + ". Cause: " + e.getMessage();
            log.debug(msg, e);
            throw new RepositoryRuntimeException(msg, e);
        }

        //Handle extra pom deployment - add the metadata with the generated pom file to the artifact
        if (forceDeployPom && artifactInfo.isMavenArtifact() && StringUtils.isNotBlank(pomString)) {
            MavenArtifactInfo mavenArtifactInfo = (MavenArtifactInfo) artifactInfo;
            RepoPath pomPath = InternalRepoPathFactory.create(repoPath.getParent(),
                    mavenArtifactInfo.getArtifactId() + "-" + mavenArtifactInfo.getVersion() + ".pom");
            RepoPath uploadPomPath = InternalRepoPathFactory.create(targetRepo.getKey(), pomPath.getPath());
            try {
                ArtifactoryDeployRequest pomRequest = new ArtifactoryDeployRequestBuilder(uploadPomPath)
                        .inputStream(IOUtils.toInputStream(pomString, Charsets.UTF_8.name()))
                        .contentLength(pomString.getBytes().length).lastModified(fileToDeploy.lastModified())
                        .properties(properties).build();
                InternalArtifactoryResponse pomResponse = new InternalArtifactoryResponse();
                // upload the POM if needed
                uploadService.upload(pomRequest, pomResponse);
                assertNotFailedRequest(fileToDeploy.getName(), pomResponse);
            } catch (IOException e) {
                String msg = "Cannot deploy file " + pomPath.getName() + ". Cause: " + e.getMessage();
                log.debug(msg, e);
                throw new RepositoryRuntimeException(msg, e);
            }
        }
    }

    private void assertNotFailedRequest(String deployedFileName, InternalArtifactoryResponse response)
            throws RepoRejectException {
        if (!response.isSuccessful()) {
            StringBuilder errorMessageBuilder = new StringBuilder("Cannot deploy file '").append(deployedFileName)
                    .append("'. ");
            String statusMessage = response.getStatusMessage();
            if (StringUtils.isNotBlank(statusMessage)) {
                errorMessageBuilder.append(statusMessage);
                if (!StringUtils.endsWith(statusMessage, ".")) {
                    errorMessageBuilder.append(".");
                }
            } else {
                errorMessageBuilder.append("Please view the logs for further information.");
            }
            throw new RepoRejectException(errorMessageBuilder.toString());
        }
    }

    @Override
    public void deployBundle(File bundle, RealRepoDescriptor targetRepo, BasicStatusHolder status,
            boolean failFast) {
        deployBundle(bundle, targetRepo, status, failFast, "", null);
    }

    @Override
    public void deployBundle(File bundle, RealRepoDescriptor targetRepo, final BasicStatusHolder status,
            boolean failFast, String prefix, Properties properties) {
        long start = System.currentTimeMillis();
        if (!bundle.exists()) {
            String message = "Specified location '" + bundle + "' does not exist. Deployment aborted.";
            status.error(message, log);
            return;
        }
        File extractFolder;
        try {
            extractFolder = extractArchive(status, bundle);
        } catch (Exception e) {
            status.error(e.getLocalizedMessage(), e, log);
            return;
        }
        if (extractFolder == null) {
            //We have errors
            return;
        }
        try {
            IOFileFilter deployableFilesFilter = new AbstractFileFilter() {
                @Override
                public boolean accept(File file) {
                    if (NamingUtils.isSystem(file.getAbsolutePath()) || GlobalExcludes.isInGlobalExcludes(file)
                            || file.getName().contains(MavenNaming.MAVEN_METADATA_NAME)) {
                        status.debug("Excluding '" + file.getAbsolutePath() + "' from bundle deployment.", log);
                        return false;
                    }

                    return true;
                }
            };
            List<File> archiveContent = Lists.newArrayList(
                    FileUtils.listFiles(extractFolder, deployableFilesFilter, DirectoryFileFilter.DIRECTORY));
            Collections.sort(archiveContent);

            Repo repo = repositoryService.repositoryByKey(targetRepo.getKey());
            for (File file : archiveContent) {
                String parentPath = extractFolder.getAbsolutePath();
                String filePath = file.getAbsolutePath();
                String relPath = PathUtils
                        .trimSlashes(prefix + "/" + PathUtils.getRelativePath(parentPath, filePath)).toString();

                ModuleInfo moduleInfo = repo.getItemModuleInfo(relPath);
                if (MavenNaming.isPom(file.getName())) {
                    try {
                        mavenService.validatePomFile(file, relPath, moduleInfo,
                                targetRepo.isSuppressPomConsistencyChecks());
                    } catch (Exception e) {
                        String msg = "The pom: " + file.getName()
                                + " could not be validated, and thus was not deployed.";
                        status.error(msg, e, log);
                        if (failFast) {
                            return;
                        }
                        continue;
                    }
                }

                try {
                    getTransactionalMe().deploy(targetRepo, new ArtifactInfo(relPath), file, null, false, true,
                            properties);
                } catch (IllegalArgumentException iae) {
                    status.error(iae.getMessage(), iae, log);
                    if (failFast) {
                        return;
                    }
                } catch (Exception e) {
                    // Fail fast
                    status.error("Error during deployment: " + e.getMessage(), e, log);
                    if (failFast) {
                        return;
                    }
                }
            }

            String bundleName = bundle.getName();
            String timeTaken = DurationFormatUtils.formatPeriod(start, System.currentTimeMillis(), "s");
            int archiveContentSize = archiveContent.size();

            status.status("Successfully deployed " + archiveContentSize + " artifacts from archive: " + bundleName
                    + " (" + timeTaken + " seconds).", log);
        } catch (Exception e) {
            status.error(e.getMessage(), e, log);
        } finally {
            FileUtils.deleteQuietly(extractFolder);
        }
    }

    private File extractArchive(BasicStatusHolder status, File archive) throws Exception {
        String archiveName = archive.getName();
        String fixedArchiveName = new String(archiveName.getBytes(Charsets.UTF_8.name()), Charsets.UTF_8);
        File fixedArchive = new File(archive.getParentFile(), fixedArchiveName);
        try {
            if (!fixedArchive.exists()) {
                FileUtils.moveFile(archive, fixedArchive);
            }
        } catch (IOException e) {
            throw new Exception("Could not encode archive name to UTF-8.", e);
        }
        File extractFolder = new File(ContextHelper.get().getArtifactoryHome().getTempUploadDir(),
                fixedArchive.getName() + "_extracted_" + System.currentTimeMillis());
        if (extractFolder.exists()) {
            //Clean up any existing folder
            try {
                FileUtils.deleteDirectory(extractFolder);
            } catch (IOException e) {
                status.error("Could not delete existing extracted archive folder: "
                        + extractFolder.getAbsolutePath() + ".", e, log);
                return null;
            }
        }
        try {
            FileUtils.forceMkdir(extractFolder);
        } catch (IOException e) {
            log.error("Could not created the extracted archive folder: " + extractFolder.getAbsolutePath() + ".",
                    log);
            return null;
        }

        try {
            ZipUtils.extract(fixedArchive, extractFolder);
        } catch (Exception e) {
            FileUtils.deleteQuietly(extractFolder);
            if (e.getMessage() == null) {
                String errorMessage;
                if (e instanceof IllegalArgumentException) {
                    errorMessage = "Please make sure the textual values in the archive are encoded in UTF-8.";
                } else {
                    errorMessage = "Please ensure the integrity of the selected archive";
                }
                throw new Exception(errorMessage, e);
            }
            throw e;
        }
        return extractFolder;
    }

    private static DeployService getTransactionalMe() {
        return InternalContextHelper.get().beanForType(DeployService.class);
    }
}