
org.apache.ivy.osgi.repo.AbstractFSManifestIterable Maven / Gradle / Ivy
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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 org.apache.ivy.osgi.repo;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.Stack;
import java.util.jar.JarInputStream;
import java.util.jar.Manifest;
import org.apache.ivy.util.Message;
// T is the type of the resource "path"
public abstract class AbstractFSManifestIterable implements Iterable {
private final T root;
public AbstractFSManifestIterable(T root) {
this.root = root;
}
public Iterator iterator() {
return new FSManifestIterator();
}
protected abstract List listBundleFiles(T dir) throws IOException;
protected abstract List listDirs(T dir) throws IOException;
protected abstract InputStream getInputStream(T f) throws IOException;
protected abstract URI buildBundleURI(T location) throws IOException;
class FSManifestIterator implements Iterator {
private ManifestAndLocation next = null;
/**
* Stack of list of directories. An iterator in the stack represents the current directory
* being lookup. The first element in the stack is the root directory. The next element in
* the stack is an iterator on the children on the root. The last iterator in the stack
* points to {@link #currentDir}.
*/
private Stack> dirs = new Stack<>();
/**
* The bundles files being lookup.
*/
private Iterator bundleCandidates = null;
private T currentDir = null;
FSManifestIterator() {
dirs.add(Collections.singleton(root).iterator());
}
/**
* Deep first tree lookup for the directories and the bundles are searched on each found
* directory.
*/
public boolean hasNext() {
while (next == null) {
// no current directory
if (currentDir == null) {
// so get the next one
if (dirs.peek().hasNext()) {
currentDir = dirs.peek().next();
try {
bundleCandidates = listBundleFiles(currentDir).iterator();
} catch (IOException e) {
Message.warn("Unlistable dir: " + currentDir, e);
currentDir = null;
}
} else if (dirs.size() <= 1) {
// no next directory, but we are at the root: finished
return false;
} else {
// remove the top of the stack and continue with a sibling.
dirs.pop();
}
} else if (bundleCandidates.hasNext()) {
T bundleCandidate = bundleCandidates.next();
JarInputStream in = null;
try {
in = new JarInputStream(getInputStream(bundleCandidate));
Manifest manifest = in.getManifest();
if (manifest != null) {
next = new ManifestAndLocation(manifest,
buildBundleURI(bundleCandidate), null);
} else {
Message.debug("No manifest in jar: " + bundleCandidate);
}
} catch (FileNotFoundException e) {
Message.debug("Jar file just removed: " + bundleCandidate, e);
} catch (IOException e) {
Message.warn("Unreadable jar: " + bundleCandidate, e);
} finally {
if (in != null) {
try {
in.close();
} catch (IOException e) {
// Don't care
}
}
}
} else {
// no more candidate on the current directory
// so lookup in the children directories
try {
dirs.add(listDirs(currentDir).iterator());
} catch (IOException e) {
Message.warn("Unlistable dir: " + currentDir + " (" + e + ")");
dirs.add(Collections. emptyList().iterator());
}
currentDir = null;
}
}
return true;
}
public ManifestAndLocation next() {
if (!hasNext()) {
throw new NoSuchElementException();
}
ManifestAndLocation manifest = next;
next = null;
return manifest;
}
public void remove() {
throw new UnsupportedOperationException();
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy