001/*
002 * Copyright 2007-2018 The jdeb developers.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *      http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016package org.vafer.jdeb.producers;
017
018import java.io.File;
019import java.io.FileInputStream;
020import java.io.IOException;
021import java.io.InputStream;
022
023import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
024import org.apache.commons.compress.archivers.tar.TarConstants;
025import org.apache.tools.ant.DirectoryScanner;
026import org.apache.tools.ant.taskdefs.Tar;
027import org.apache.tools.ant.types.FileSet;
028import org.apache.tools.tar.TarEntry;
029import org.vafer.jdeb.DataConsumer;
030import org.vafer.jdeb.DataProducer;
031import org.vafer.jdeb.utils.SymlinkUtils;
032
033/**
034 * DataProducer providing data from an Ant fileset. TarFileSets are also
035 * supported with their permissions.
036 */
037public final class DataProducerFileSet implements DataProducer {
038
039    private final FileSet fileset;
040
041    public DataProducerFileSet( final FileSet fileset ) {
042        this.fileset = fileset;
043    }
044
045    public void produce( final DataConsumer pReceiver ) throws IOException {
046        String user = Producers.ROOT_NAME;
047        int uid = Producers.ROOT_UID;
048        String group = Producers.ROOT_NAME;
049        int gid = Producers.ROOT_UID;
050        int filemode = TarEntry.DEFAULT_FILE_MODE;
051        int dirmode = TarEntry.DEFAULT_DIR_MODE;
052        String prefix = "";
053        String fullpath = "";
054
055        if (fileset instanceof Tar.TarFileSet) {
056            Tar.TarFileSet tarfileset = (Tar.TarFileSet) fileset;
057            user = tarfileset.getUserName();
058            uid = tarfileset.getUid();
059            group = tarfileset.getGroup();
060            gid = tarfileset.getGid();
061            filemode = tarfileset.getMode();
062            dirmode = tarfileset.getDirMode(tarfileset.getProject());
063            prefix = tarfileset.getPrefix(tarfileset.getProject());
064            fullpath = tarfileset.getFullpath();
065        }
066
067        final DirectoryScanner scanner = fileset.getDirectoryScanner(fileset.getProject());
068        scanner.scan();
069
070        final File basedir = scanner.getBasedir();
071
072        if (scanner.getIncludedFilesCount() != 1 || scanner.getIncludedDirsCount() != 0) {
073            // the full path attribute only have sense in this context
074            // if it's a single-file fileset, we ignore it otherwise
075            fullpath = "";
076        }
077
078        for (String directory : scanner.getIncludedDirectories()) {
079            String name = directory.replace('\\', '/');
080
081            final TarArchiveEntry entry = new TarArchiveEntry(prefix + "/" + name);
082            entry.setUserName(user);
083            entry.setUserId(uid);
084            entry.setGroupName(group);
085            entry.setGroupId(gid);
086            entry.setMode(dirmode);
087
088            pReceiver.onEachDir(entry);
089        }
090
091        for (String filename : scanner.getIncludedFiles()) {
092            final String name = filename.replace('\\', '/');
093            final File file = new File(basedir, name);
094
095            final InputStream inputStream = new FileInputStream(file);
096            try {
097                final String entryName = "".equals(fullpath) ? prefix + "/" + name : fullpath;
098
099                final File entryPath = new File(entryName);
100
101                final boolean symbolicLink = SymlinkUtils.isSymbolicLink(entryPath);
102                final TarArchiveEntry e;
103                if (symbolicLink) {
104                    e = new TarArchiveEntry(entryName, TarConstants.LF_SYMLINK);
105                    e.setLinkName(SymlinkUtils.readSymbolicLink(entryPath));
106                } else {
107                    e = new TarArchiveEntry(entryName, true);
108                }
109
110                e.setUserId(uid);
111                e.setGroupId(gid);
112                e.setUserName(user);
113                e.setGroupName(group);
114                e.setMode(filemode);
115                e.setSize(file.length());
116
117                pReceiver.onEachFile(inputStream, e);
118            } finally {
119                inputStream.close();
120            }
121        }
122    }
123}