Java tutorial
/** * Copyright 2011 Michael R. Lange <michael.r.lange@langmi.de>. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package de.langmi.spring.batch.examples.readers.file.archive; import de.schlichtherle.truezip.file.TFile; import de.schlichtherle.truezip.file.TFileInputStream; import de.schlichtherle.truezip.fs.FsSyncException; import java.io.FilenameFilter; import java.util.ArrayList; import java.util.Comparator; import java.util.List; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.batch.item.ExecutionContext; import org.springframework.batch.item.ItemStreamException; import org.springframework.batch.item.file.MultiResourceItemReader; import org.springframework.core.io.InputStreamResource; import org.springframework.core.io.Resource; /** * ArchiveMultiResourceItemReader works with TAR, TAR.GZ, ZIP, B2ZIP, WAR, EAR and JAR * Files. Falls back to normal MultiResourceItemReader behaviour if no archive is set. * * @author Michael R. Lange <michael.r.lange@langmi.de> */ public class ArchiveMultiResourceItemReader<T> extends MultiResourceItemReader<T> { private static final Logger LOG = LoggerFactory.getLogger(ArchiveMultiResourceItemReader.class); private Resource[] archives; private TFile[] wrappedArchives; private FilenameFilter filenameFilter = new DefaultArchiveFileNameFilter(); /** * Tries to extract all files in the archives and adds them as resources to * the normal MultiResourceItemReader. Overwrites the Comparator from * the super class to get it working with itemstreams. * * @param executionContext * @throws ItemStreamException */ @Override public void open(ExecutionContext executionContext) throws ItemStreamException { // really used with archives? if (archives != null) { // overwrite the comparator to use description instead of filename this.setComparator(new Comparator<Resource>() { /** Compares resource descriptions. */ @Override public int compare(Resource r1, Resource r2) { return r1.getDescription().compareTo(r2.getDescription()); } }); // get the inputStreams from all files inside the archives wrappedArchives = new TFile[archives.length]; List<Resource> extractedResources = new ArrayList<Resource>(); try { for (int i = 0; i < archives.length; i++) { wrappedArchives[i] = new TFile(archives[i].getFile()); // iterate over each TFile and get the file list // extract only the files, ignore directories List<TFile> fileList = new ArrayList<TFile>(); runNestedDirs(wrappedArchives[i], fileList, filenameFilter); for (TFile tFile : fileList) { extractedResources .add(new InputStreamResource(new TFileInputStream(tFile), tFile.getName())); LOG.info("using extracted file:" + tFile.getName()); } } } catch (Exception ex) { throw new ItemStreamException(ex); } // propagate extracted resources this.setResources(extractedResources.toArray(new Resource[extractedResources.size()])); } super.open(executionContext); } /** * Calls super.close() and tries to unmount all used archive files afterwards. * * @throws ItemStreamException */ @Override public void close() throws ItemStreamException { super.close(); if (wrappedArchives != null) { for (int i = 0; i < wrappedArchives.length; i++) { // release all try { TFile.umount(wrappedArchives[i]); } catch (FsSyncException ex) { throw new ItemStreamException(ex); } } } } /** * Runs recursively through the rootFile.listFiles() and adds each file to the * fileList. Logs each step - even for directories - to show the archive * file contents. * * @param rootFile * @param fileList * @param filenameFilter */ private static void runNestedDirs(TFile rootFile, List<TFile> fileList, FilenameFilter filenameFilter) { TFile files[] = rootFile.listFiles(filenameFilter); if (files != null) { for (int i = 0; i < files.length; i++) { TFile tFile = files[i]; LOG.info("extracting:" + tFile.getAbsolutePath()); if (tFile.isDirectory()) { runNestedDirs(tFile, fileList, filenameFilter); } else { fileList.add(tFile); } } } } /** * Set archive files with normal Spring resources pattern, if not set, the * class will fallback to normal MultiResourceItemReader behaviour. * * @param archives */ public void setArchives(Resource[] archives) { this.archives = archives; } /** * Set a {@link FilenameFilter} to control used files from the archives. * * @param filenameFilter */ public void setFilenameFilter(FilenameFilter filenameFilter) { this.filenameFilter = filenameFilter; } }