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}