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

Java tutorial

Introduction

Here is the source code for org.artifactory.repo.service.ArchiveContentRetriever.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.Function;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import org.apache.commons.compress.archivers.ArchiveEntry;
import org.apache.commons.compress.archivers.ArchiveInputStream;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.artifactory.api.context.ContextHelper;
import org.artifactory.api.repo.ArchiveFileContent;
import org.artifactory.common.ConstantValues;
import org.artifactory.mime.NamingUtils;
import org.artifactory.model.common.RepoPathImpl;
import org.artifactory.repo.InternalRepoPathFactory;
import org.artifactory.repo.LocalRepo;
import org.artifactory.repo.RepoPath;
import org.artifactory.sapi.fs.VfsFile;
import org.artifactory.util.PathUtils;
import org.artifactory.util.ZipUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.annotation.Nullable;
import java.io.IOException;
import java.util.List;
import java.util.Set;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;

/**
 * Retrieves a text content from an archive.
 *
 * @author Yossi Shaul
 */
public class ArchiveContentRetriever {
    private static final Logger log = LoggerFactory.getLogger(ArchiveContentRetriever.class);

    public ArchiveFileContent getArchiveFileContent(LocalRepo repo, RepoPath archivePath, String archiveEntryPath)
            throws IOException {
        String content = null;
        String sourceJarPath = null;
        List<String> searchList = null;
        String failureReason = null;
        ZipInputStream jis = null;
        String sourceEntryPath = null;
        try {
            if (archiveEntryPath.endsWith(".class")) {
                sourceEntryPath = NamingUtils.javaSourceNameFromClassName(archiveEntryPath);
                // locate the sources jar and find the source file in it
                String sourceJarName = PathUtils.stripExtension(archivePath.getName()) + "-sources."
                        + PathUtils.getExtension(archivePath.getName());
                String sourcesJarPath = archivePath.getParent().getPath() + "/" + sourceJarName;
                // search in the sources file first
                searchList = Lists.newArrayList(sourcesJarPath, archivePath.getPath());
            } else if (isTextFile(archiveEntryPath)) {
                // read directly from this archive
                searchList = Lists.newArrayList(archivePath.getPath());
                sourceEntryPath = archiveEntryPath;
            } else {
                failureReason = "View source for " + archiveEntryPath + " is not supported";
            }

            if (searchList != null) {
                boolean found = false;
                for (int i = 0; i < searchList.size() && !found; i++) {
                    String sourcesJarPath = searchList.get(i);
                    log.debug("Looking for {} source in {}", sourceEntryPath, sourceJarPath);
                    VfsFile sourceFile = repo.getImmutableFile(new RepoPathImpl(repo.getKey(), sourcesJarPath));
                    if (sourceFile == null) {
                        failureReason = "Source jar not found.";
                    } else if (!ContextHelper.get().getAuthorizationService()
                            .canRead(InternalRepoPathFactory.create(repo.getKey(), sourcesJarPath))) {
                        failureReason = "No read permissions for the source jar.";
                    } else {
                        List<String> alternativeExtensions = null;
                        if ("java".equalsIgnoreCase(PathUtils.getExtension(sourceEntryPath))) {
                            alternativeExtensions = Lists.newArrayList("groovy", "fx");
                        }

                        jis = new ZipInputStream(sourceFile.getStream());
                        ZipEntry zipEntry = ZipUtils.locateEntry(jis, sourceEntryPath, alternativeExtensions);
                        if (zipEntry == null) {
                            failureReason = "Source file not found.";
                        } else {
                            found = true; // source entry was found in the jar
                            int maxAllowedSize = 1024 * 1024;
                            if (zipEntry.getSize() > maxAllowedSize) {
                                failureReason = String.format(
                                        "Source file is too big to render: file size: %s, max size: %s.",
                                        zipEntry.getSize(), maxAllowedSize);

                            } else {
                                // read the current entry (the source entry path)
                                content = IOUtils.toString(jis, "UTF-8");
                                sourceEntryPath = zipEntry.getName();
                                sourceJarPath = sourcesJarPath;
                            }
                        }
                    }
                }
            }
        } finally {
            IOUtils.closeQuietly(jis);
        }

        if (content != null) {
            return new ArchiveFileContent(content, InternalRepoPathFactory.create(repo.getKey(), sourceJarPath),
                    sourceEntryPath);
        } else {
            return ArchiveFileContent.contentNotFound(failureReason);
        }
    }

    public ArchiveFileContent getGenericArchiveFileContent(LocalRepo repo, RepoPath archivePath,
            String archiveEntryPath) throws IOException {
        String content = null;
        String sourceJarPath = null;
        List<String> searchList = null;
        String failureReason = null;
        ArchiveInputStream jis = null;
        String sourceEntryPath = null;
        try {
            if (archiveEntryPath.endsWith(".class")) {
                sourceEntryPath = NamingUtils.javaSourceNameFromClassName(archiveEntryPath);
                // locate the sources jar and find the source file in it
                String sourceJarName = PathUtils.stripExtension(archivePath.getName()) + "-sources."
                        + PathUtils.getExtension(archivePath.getName());
                String sourcesJarPath = archivePath.getParent().getPath() + "/" + sourceJarName;
                // search in the sources file first
                searchList = Lists.newArrayList(sourcesJarPath, archivePath.getPath());
            } else if (isTextFile(archiveEntryPath)) {
                // read directly from this archive
                searchList = Lists.newArrayList(archivePath.getPath());
                sourceEntryPath = archiveEntryPath;
            } else {
                failureReason = "View source for " + archiveEntryPath + " is not supported";
            }

            if (searchList != null) {
                boolean found = false;
                for (int i = 0; i < searchList.size() && !found; i++) {
                    String sourcesJarPath = searchList.get(i);
                    log.debug("Looking for {} source in {}", sourceEntryPath, sourceJarPath);
                    VfsFile sourceFile = repo.getImmutableFile(new RepoPathImpl(repo.getKey(), sourcesJarPath));
                    if (sourceFile == null) {
                        failureReason = "Source jar not found.";
                    } else if (!ContextHelper.get().getAuthorizationService()
                            .canRead(InternalRepoPathFactory.create(repo.getKey(), sourcesJarPath))) {
                        failureReason = "No read permissions for the source jar.";
                    } else {
                        List<String> alternativeExtensions = null;
                        if ("java".equalsIgnoreCase(PathUtils.getExtension(sourceEntryPath))) {
                            alternativeExtensions = Lists.newArrayList("groovy", "fx");
                        }

                        jis = ZipUtils.getArchiveInputStream(sourceFile);
                        ArchiveEntry zipEntry = ZipUtils.locateArchiveEntry(jis, sourceEntryPath,
                                alternativeExtensions);
                        if (zipEntry == null) {
                            failureReason = "Source file not found.";
                        } else {
                            found = true; // source entry was found in the jar
                            int maxAllowedSize = 1024 * 1024;
                            if (zipEntry.getSize() > maxAllowedSize) {
                                failureReason = String.format(
                                        "Source file is too big to render: file size: %s, max size: %s.",
                                        zipEntry.getSize(), maxAllowedSize);

                            } else {
                                // read the current entry (the source entry path)
                                content = IOUtils.toString(jis, "UTF-8");
                                sourceEntryPath = zipEntry.getName();
                                sourceJarPath = sourcesJarPath;
                            }
                        }
                    }
                }
            }
        } finally {
            IOUtils.closeQuietly(jis);
        }

        if (content != null) {
            return new ArchiveFileContent(content, InternalRepoPathFactory.create(repo.getKey(), sourceJarPath),
                    sourceEntryPath);
        } else {
            return ArchiveFileContent.contentNotFound(failureReason);
        }
    }

    private boolean isTextFile(String fileName) {
        return NamingUtils.isViewable(fileName) || isLicenseFile(fileName);
    }

    private boolean isLicenseFile(String fileName) {
        String licenseFileNames = ConstantValues.archiveLicenseFileNames.getString();
        Set<String> possibleLicenseFileNames = Sets.newHashSet(Iterables.transform(
                Sets.newHashSet(StringUtils.split(licenseFileNames, ",")), new Function<String, String>() {
                    @Override
                    public String apply(@Nullable String input) {
                        return StringUtils.isBlank(input) ? input : StringUtils.trim(input);
                    }
                }));
        return possibleLicenseFileNames.contains(PathUtils.getFileName(fileName));
    }
}