/* * Copyright 2010 Impetus Infotech. * * 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 com.impetus.kundera.classreading; import java.io.BufferedInputStream; import java.io.DataInputStream; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.net.URL; import java.util.ArrayList; import java.util.List; import javassist.bytecode.AnnotationsAttribute; import javassist.bytecode.ClassFile; import javassist.bytecode.annotation.Annotation; /** * Base class-reader. * * @author animesh.kumar */ public abstract class Reader { /** The valid annotations. */ private List<String> validAnnotations = new ArrayList<String>(); /** The annotation discovery listeners. */ private List<AnnotationDiscoveryListener> annotationDiscoveryListeners = new ArrayList<AnnotationDiscoveryListener>(); /** * Instantiates a new reader. */ public Reader() { } /** * Scan class. * * @param bits * the bits * * @throws IOException * Signals that an I/O exception has occurred. */ public void scanClass(InputStream bits) throws IOException { DataInputStream dstream = new DataInputStream(new BufferedInputStream(bits)); ClassFile cf = null; try { cf = new ClassFile(dstream); String className = cf.getName(); List<String> annotations = new ArrayList<String>(); accumulateAnnotations(annotations, (AnnotationsAttribute) cf.getAttribute(AnnotationsAttribute.visibleTag)); accumulateAnnotations(annotations, (AnnotationsAttribute) cf.getAttribute(AnnotationsAttribute.invisibleTag)); // iterate through all valid annotations for (String validAnn : getValidAnnotations()) { // check if the current class has one? if (annotations.contains(validAnn)) { // fire all listeners for (AnnotationDiscoveryListener listener : getAnnotationDiscoveryListeners()) { listener.discovered(className, annotations.toArray(new String[] {})); } } } } finally { dstream.close(); bits.close(); } } // helper method to accumulate annotations. /** * Accumulate annotations. * * @param annotations * the annotations * @param annatt * the annatt */ private void accumulateAnnotations(List<String> annotations, AnnotationsAttribute annatt) { if (null == annatt) { return; } for (Annotation ann : annatt.getAnnotations()) { annotations.add(ann.getTypeName()); } } /** * Gets the resource iterator. * * @param url * the url * @param filter * the filter * * @return the resource iterator * * @throws IOException * Signals that an I/O exception has occurred. */ public ResourceIterator getResourceIterator(URL url, Filter filter) throws IOException { String urlString = url.toString(); if (urlString.endsWith("!/")) { urlString = urlString.substring(4); urlString = urlString.substring(0, urlString.length() - 2); url = new URL(urlString); } if(urlString.endsWith(".class")) { File f = new File(url.getPath()); return new ClassFileIterator(f); } else if (!urlString.endsWith("/")) { return new JarFileIterator(url.openStream(), filter); } else { if (!url.getProtocol().equals("file")) { throw new IOException("Unable to understand protocol: " + url.getProtocol()); } File f = new File(url.getPath()); if (f.isDirectory()) { return new ClassFileIterator(f, filter); } else { return new JarFileIterator(url.openStream(), filter); } } } /** * Gets the valid annotations. * * @return the valid annotations */ public List<String> getValidAnnotations() { return validAnnotations; } /** * Adds the valid annotations. * * @param annotation * the annotation */ public void addValidAnnotations(String annotation) { this.validAnnotations.add(annotation); } /** * Gets the annotation discovery listeners. * * @return the annotation discovery listeners */ public List<AnnotationDiscoveryListener> getAnnotationDiscoveryListeners() { return annotationDiscoveryListeners; } /** * Adds the annotation discovery listeners. * * @param annotationDiscoveryListener * the annotation discovery listener */ public void addAnnotationDiscoveryListeners(AnnotationDiscoveryListener annotationDiscoveryListener) { this.annotationDiscoveryListeners.add(annotationDiscoveryListener); } /** * Read. */ public abstract void read(); /** * Gets the filter. * * @return the filter */ public abstract Filter getFilter(); /** * Find resources. * * @return the uR l[] */ public abstract URL[] findResources(); }