/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package com.tonicsystems.jarjar.classpath;
import com.tonicsystems.jarjar.util.ClassNameUtils;
import com.tonicsystems.jarjar.util.RuntimeIOException;
import java.io.BufferedInputStream;
import java.io.Closeable;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import javax.annotation.Nonnull;
/**
*
* @author shevek
*/
public abstract class ClassPathArchive implements Iterable<ClassPathResource> {
protected final File root;
public ClassPathArchive(@Nonnull File root) {
this.root = root;
}
@Nonnull
public String getArchiveName() {
return root.getPath();
}
public static class ZipArchive extends ClassPathArchive {
public ZipArchive(@Nonnull File root) {
super(root);
}
@Override
public Iterator<ClassPathResource> iterator() {
try {
return new ZipIterator(root);
} catch (IOException e) {
throw new RuntimeIOException(e);
}
}
}
private static class ZipIterator implements Iterator<ClassPathResource>, Closeable {
private final ZipFile zipFile;
private Enumeration<? extends ZipEntry> zipEntries;
ZipIterator(@Nonnull File file) throws IOException {
this.zipFile = new ZipFile(file);
this.zipEntries = zipFile.entries();
}
@Override
public boolean hasNext() {
if (!zipEntries.hasMoreElements()) {
// close();
return false;
} else {
return true;
}
}
@Override
public ClassPathResource next() {
final ZipEntry entry = zipEntries.nextElement();
if (entry == null)
throw new NoSuchElementException();
return new ClassPathResource() {
@Override
public String getArchiveName() {
return zipFile.getName();
}
@Override
public String getName() {
return entry.getName();
}
@Override
public long getLastModifiedTime() {
return entry.getTime();
}
@Override
public InputStream openStream() throws IOException {
return zipFile.getInputStream(entry);
}
};
}
@Override
public void remove() {
throw new UnsupportedOperationException();
}
@Override
public void close() throws IOException {
zipFile.close();
}
}
public static class DirectoryArchive extends ClassPathArchive {
public DirectoryArchive(@Nonnull File root) {
super(root);
}
@Override
public Iterator<ClassPathResource> iterator() {
return new DirectoryIterator(root);
}
}
private static class DirectoryIterator implements Iterator<ClassPathResource> {
@Nonnull
private static void findClassFiles(@Nonnull Collection<? super File> out, @Nonnull File dir) {
for (File file : dir.listFiles()) {
if (file.isDirectory()) {
findClassFiles(out, file);
} else if (file.isFile()) {
if (ClassNameUtils.isClass(file.getName())) {
out.add(file);
}
}
}
}
private final File root;
private final Iterator<File> entries;
DirectoryIterator(@Nonnull File root) {
this.root = root;
List<File> files = new ArrayList<File>();
findClassFiles(files, root);
this.entries = files.iterator();
}
@Override
public boolean hasNext() {
return entries.hasNext();
}
@Override
public ClassPathResource next() {
final File file = entries.next();
return new ClassPathResource() {
@Override
public String getArchiveName() {
return root.getPath();
}
@Override
public String getName() {
return file.getName();
}
@Override
public long getLastModifiedTime() {
return file.lastModified();
}
@Override
public InputStream openStream() throws IOException {
return new BufferedInputStream(new FileInputStream(file));
}
};
}
@Override
public void remove() {
throw new UnsupportedOperationException();
}
}
@Override
public String toString() {
return getClass().getSimpleName() + "(" + root + ")";
}
}