001    /*
002     * Copyright 2010 The Apache Software Foundation.
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     */
016    package org.vafer.jdeb.producers;
017    
018    import java.io.File;
019    import java.io.FileInputStream;
020    import java.io.IOException;
021    import java.io.InputStream;
022    
023    import org.apache.tools.ant.DirectoryScanner;
024    import org.apache.tools.tar.TarEntry;
025    import org.vafer.jdeb.DataConsumer;
026    import org.vafer.jdeb.DataProducer;
027    import org.vafer.jdeb.mapping.Mapper;
028    import org.vafer.jdeb.utils.Utils;
029    
030    /**
031     * DataProducer iterating over a directory.
032     * For cross-platform permissions and ownerships you probably want to use a Mapper, too. 
033     * 
034     * @author Torsten Curdt <tcurdt@vafer.org>
035     */
036    public final class DataProducerDirectory extends AbstractDataProducer implements DataProducer {
037    
038        private final DirectoryScanner scanner = new DirectoryScanner();
039        
040        public DataProducerDirectory( final File pDir, final String[] pIncludes, final String[] pExcludes, final Mapper[] pMappers ) {
041            super(pIncludes, pExcludes, pMappers);
042            scanner.setBasedir(pDir);
043            scanner.setIncludes(pIncludes);
044            scanner.setExcludes(pExcludes);
045            scanner.setCaseSensitive(true);
046            scanner.setFollowSymlinks(true);
047        }
048        
049        public void produce( final DataConsumer pReceiver ) throws IOException {
050    
051            scanner.scan();
052    
053            final File baseDir = scanner.getBasedir();
054    
055            final String[] dirs = scanner.getIncludedDirectories();
056            for (int i = 0; i < dirs.length; i++) {
057                final File file = new File(baseDir, dirs[i]);
058                String dirname = getFilename(baseDir, file);
059    
060                if ("".equals(dirname)) {
061                    continue;
062                }
063    
064                if (!isIncluded(dirname)) {
065                    continue;
066                }
067    
068                if ('/' != File.separatorChar) {
069                    dirname = dirname.replace(File.separatorChar, '/');
070                }
071    
072                if (!dirname.endsWith("/")) {
073                    dirname += "/";
074                }
075    
076                TarEntry entry = new TarEntry(dirname);
077                entry.setUserId(0);
078                entry.setUserName("root");
079                entry.setGroupId(0);
080                entry.setGroupName("root");
081                entry.setMode(TarEntry.DEFAULT_DIR_MODE);
082    
083                entry = map(entry);
084    
085                entry.setSize(0);
086    
087                pReceiver.onEachDir(entry.getName(), entry.getLinkName(), entry.getUserName(), entry.getUserId(), entry.getGroupName(), entry.getGroupId(), entry.getMode(), entry.getSize());
088            }
089    
090    
091            final String[] files = scanner.getIncludedFiles();
092    
093            for (int i = 0; i < files.length; i++) {
094                final File file = new File(baseDir, files[i]);
095                String filename = getFilename(baseDir, file);
096    
097                if (!isIncluded(filename)) {
098                    continue;
099                }
100    
101                if ('/' != File.separatorChar) {
102                    filename = filename.replace(File.separatorChar, '/');
103                }
104    
105                TarEntry entry = new TarEntry(filename);
106                entry.setUserId(0);
107                entry.setUserName("root");
108                entry.setGroupId(0);
109                entry.setGroupName("root");
110                entry.setMode(TarEntry.DEFAULT_FILE_MODE);
111    
112                entry = map(entry);
113    
114                entry.setSize(file.length());
115    
116                final InputStream inputStream = new FileInputStream(file);
117                try {
118                    pReceiver.onEachFile(inputStream, entry.getName(), entry.getLinkName(), entry.getUserName(), entry.getUserId(), entry.getGroupName(), entry.getGroupId(), entry.getMode(), entry.getSize());
119                } finally {
120                    inputStream.close();
121                }
122            }
123        }
124    
125        private String getFilename( File root, File file ) {
126            
127            final String relativeFilename = file.getAbsolutePath().substring(root.getAbsolutePath().length());      
128            
129            return Utils.stripLeadingSlash(relativeFilename);
130        }
131    
132    }