org.zclasspath.ZClassPathScanner Maven / Gradle / Ivy
/*
* Copyright 2007 Gerd Ziegler (www.gerdziegler.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. @author
* www.gerdziegler.de
*/
package org.zclasspath;
import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Stack;
import java.util.jar.JarInputStream;
import java.util.jar.Manifest;
import java.util.zip.ZipEntry;
import org.apache.log4j.Logger;
public class ZClassPathScanner {
static Logger log = Logger.getLogger(ZClassPathScanner.class);
private final List classPathItems = new ArrayList();
private final Stack filter = new Stack();
private final Stack visitor = new Stack();
private final Stack errorHandler = new Stack();
public ZClassPathScanner() {
pushFilter(new ZIClassPathFilter() {
public boolean acceptClasspathPart(String name) {
return true;
}
public boolean acceptClass(String name) {
return true;
}
public boolean acceptResource(String resource) {
return true;
}
});
pushVisitor(new ZIClassPathVisitor() {
public void visitResource(ZIClassPathElement element)
throws Exception {
log.debug(element.getName());
}
public void visitClass(ZClassPathClass classPathClass)
throws Exception {
log.debug(classPathClass.getClassName());
}
});
pushErrorHandler(new ZIClassPathErrorHandler() {
public void handleError(String msg, Throwable t) {
log.error(" ******** " + t.getClass() + " ******** ");
if (t instanceof NoClassDefFoundError) {
if (log.isDebugEnabled()) {
log.debug(msg, t);
}
} else {
log.error(msg, t);
}
}
});
}
public void scan()
throws Exception {
List roots;
if (classPathItems.isEmpty()) {
roots = ZJavaClassPath.getItems();
} else {
roots = classPathItems;
}
for (ZIClassPathItem root : roots) {
scanRoot(root);
}
}
private void scanRoot(ZIClassPathItem root)
throws Exception {
if (filter.peek().acceptClasspathPart(root.getName())) {
log.debug(root.getName());
if (root.isDirectory()) {
ZClassPathLocation location = new ZClassPathLocation(root);
scan(location, root);
} else if (isJar(root)) {
log.debug("scanJar " + root.getName());
InputStream in = root.getInputStream();
if (in != null) {
try {
JarInputStream jarIn = new JarInputStream(in);
try {
ZClassPathLocation location = new ZClassPathLocation(root);
scanJar(location, jarIn);
} finally {
jarIn.close();
}
} finally {
in.close();
}
} else {
log.warn("not found: " + root.getName());
}
}
}
}
protected boolean isJar(String name)
throws Exception {
return name.endsWith(".jar") || name.endsWith(".war") || name.endsWith(".ear") || name.endsWith(".sar") || name.endsWith(".rar");
}
protected boolean isJar(ZIClassPathItem root)
throws Exception {
boolean b = root.isFile() && isJar(root.getName());
return b;
}
protected void scan(final ZIClassPathLocation location, ZIClassPathItem file)
throws Exception {
ZIClassPathItem[] list = file.list();
if (list == null) {
return;
}
for (int i = 0; i < list.length; i++) {
if (list[i].isDirectory()) {
log.debug(list[i].getName());
scan(location, list[i]);
} else if (isJar(list[i])) {
log.debug(list[i].getName());
InputStream in = list[i].getInputStream();
try {
JarInputStream jarIn = new JarInputStream(in);
try {
ZClassPathLocation jarLocation = new ZClassPathLocation(location, list[i].getName());
scanJar(jarLocation, jarIn);
} finally {
jarIn.close();
}
} finally {
in.close();
}
} else {
log.debug(list[i].getName());
final ZIClassPathItem crt = list[i];
ZIClassPathElement element = new ZIClassPathElement() {
public InputStream getInputStream()
throws Exception {
return crt.getInputStream();
}
public String getName()
throws Exception {
return crt.getRelativePath(location.getClassPathItem());
}
public ZIClassPathLocation getClassPathLocation()
throws Exception {
return location;
}
public Manifest getManifest()
throws Exception {
return null;
}
};
process(element);
}
}
}
protected void scanJar(final ZIClassPathLocation location, final JarInputStream jarIn)
throws Exception {
for (ZipEntry ze = jarIn.getNextEntry(); ze != null; ze = jarIn.getNextEntry()) {
String crtName = ze.getName();
if (crtName.startsWith("WEB-INF/classes/")) {
crtName = crtName.substring("WEB-INF/classes/".length());
} else if (crtName.startsWith("WEB-INF/lib/")) {
crtName = crtName.substring("WEB-INF/lib/".length());
}
final String name = crtName;
log.debug(name);
ZIClassPathElement element = new ZIClassPathElement() {
public InputStream getInputStream()
throws Exception {
return wrap(jarIn);
}
public String getName() {
return name;
}
public ZIClassPathLocation getClassPathLocation()
throws Exception {
return location;
}
public Manifest getManifest()
throws Exception {
return jarIn.getManifest();
}
};
process(element);
}
}
private static InputStream wrap(final JarInputStream in)
throws Exception {
InputStream ret = new FilterInputStream(in) {
@Override
public void close()
throws IOException {
// do nothing to avoid closing the jarinputstream
}
};
return ret;
// byte[] buff = new byte[2048];
// ByteArrayOutputStream out = new ByteArrayOutputStream();
// for (int c = in.read(buff); c > 0; c = in.read(buff)) {
// out.write(buff, 0, c);
// }
// out.close();
// byte[] bytes = out.toByteArray();
// InputStream ret = new ByteArrayInputStream(bytes);
// return ret;
}
/**
* process
*
* @param name
* String
*/
protected void process(ZIClassPathElement element)
throws Exception {
log.debug(element.getName());
if (isClass(element.getName())) {
processClass(element);
} else if (isJar(element.getName())) {
JarInputStream jarIn = new JarInputStream(element.getInputStream());
try {
ZClassPathLocation jarLocation = new ZClassPathLocation(element.getClassPathLocation(), element.getName());
scanJar(jarLocation, jarIn);
} finally {
jarIn.close();
}
} else {
processResource(element);
}
}
protected boolean isClass(String name) {
return name.endsWith(".class");
}
/**
* processClass
*
* @param name
* String
*/
protected void processClass(ZIClassPathElement element)
throws Exception {
String className = element.getName().replace('/', '.').replace('\\', '.');
className = className.substring(0, className.length() - 6);
ZClassPathClass classPathClass = new ZClassPathClass(className, element);
if (filter.peek().acceptClass(className)) {
try {
getVisitor().visitClass(classPathClass);
} catch (Throwable e) {
if (e instanceof NoClassDefFoundError) {
log.error("Error while processing " + className + " --- " + e);
} else {
log.error("Error while processing " + className, e);
}
}
}
}
/**
* processResource
*
* @param name
* String
*/
protected void processResource(ZIClassPathElement element)
throws Exception {
if (filter.peek().acceptResource(element.getName())) {
try {
getVisitor().visitResource(element);
} catch (Throwable e) {
log.error("Error while processing " + element.getName(), e);
}
}
}
public void setErrorHandler(ZIClassPathErrorHandler errorHandler) {
popErrorHandler();
pushErrorHandler(errorHandler);
}
public ZIClassPathErrorHandler getErrorHandler() {
return errorHandler.peek();
}
public void pushErrorHandler(ZIClassPathErrorHandler errorHandler) {
this.errorHandler.push(errorHandler);
}
public ZIClassPathErrorHandler popErrorHandler() {
return this.errorHandler.pop();
}
public ZIClassPathFilter getFilter() {
return filter.peek();
}
public void setFilter(ZIClassPathFilter filter) {
this.filter.pop();
this.filter.push(filter);
}
public void pushFilter(ZIClassPathFilter filter) {
this.filter.push(filter);
}
public ZIClassPathFilter popFilter() {
return filter.pop();
}
public ZIClassPathVisitor getVisitor() {
return visitor.peek();
}
public void setVisitor(ZIClassPathVisitor visitor) {
popVisitor();
pushVisitor(visitor);
}
public void pushVisitor(ZIClassPathVisitor visitor) {
this.visitor.push(visitor);
}
public ZIClassPathVisitor popVisitor() {
return visitor.pop();
}
public List getClassPathItems() {
return classPathItems;
}
public void setClassPathItems(List classPathItems) {
this.classPathItems.clear();
this.classPathItems.addAll(classPathItems);
}
}