001/* 002 * (C) Copyright 2006-2011 Nuxeo SA (http://nuxeo.com/) and others. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 * 016 * Contributors: 017 * bstefanescu 018 */ 019package org.nuxeo.ecm.webengine.jaxrs.scan; 020 021import java.io.IOException; 022import java.io.InputStream; 023import java.net.URL; 024import java.util.ArrayList; 025import java.util.Collection; 026import java.util.Enumeration; 027import java.util.HashMap; 028import java.util.HashSet; 029import java.util.Map; 030import java.util.Set; 031 032import org.objectweb.asm.ClassReader; 033import org.osgi.framework.Bundle; 034 035/** 036 * @author <a href="mailto:bs@nuxeo.com">Bogdan Stefanescu</a> 037 */ 038public class Scanner { 039 040 public final static String PATH_ANNO = "Ljavax/ws/rs/Path;"; 041 042 public final static String PROVIDER_ANNO = "Ljavax/ws/rs/ext/Provider;"; 043 044 protected Bundle bundle; 045 046 protected String packageBase; 047 048 protected Map<String, Collection<Class<?>>> collectors; 049 050 public Scanner(Bundle bundle, String packageBase) { 051 this(bundle, packageBase, PATH_ANNO, PROVIDER_ANNO); 052 } 053 054 public Scanner(Bundle bundle, String packageBase, String... annotations) { 055 this.bundle = bundle; 056 this.packageBase = packageBase == null ? "/" : packageBase; 057 this.collectors = new HashMap<String, Collection<Class<?>>>(); 058 for (String annotation : annotations) { 059 addCollector(annotation); 060 } 061 } 062 063 public void addCollector(String annotation) { 064 collectors.put(annotation, new ArrayList<Class<?>>()); 065 } 066 067 public void addCollector(String annotation, Collection<Class<?>> collector) { 068 collectors.put(annotation, collector); 069 } 070 071 public Collection<Class<?>> getCollector(String annotation) { 072 return collectors.get(annotation); 073 } 074 075 public Map<String, Collection<Class<?>>> getCollectors() { 076 return collectors; 077 } 078 079 @SuppressWarnings("unchecked") 080 public void scan() throws ReflectiveOperationException, IOException { 081 Enumeration<URL> urls = bundle.findEntries(packageBase, "*.class", true); 082 if (urls == null) { 083 return; 084 } 085 Set<String> annotations = collectors.keySet(); 086 while (urls.hasMoreElements()) { 087 URL url = urls.nextElement(); 088 InputStream in = url.openStream(); 089 try { 090 ClassReader cr = new ClassReader(in); 091 AnnotationReader reader = new AnnotationReader(annotations); 092 cr.accept(reader, null, ClassReader.SKIP_DEBUG | ClassReader.SKIP_CODE | ClassReader.SKIP_FRAMES); 093 if (reader.hasResults()) { 094 String cname = reader.getClassName(); 095 for (String anno : reader.getResults()) { 096 collectors.get(anno).add(bundle.loadClass(cname)); 097 } 098 } 099 } finally { 100 in.close(); 101 } 102 } 103 } 104 105 public Set<Class<?>> getClasses() { 106 HashSet<Class<?>> result = new HashSet<Class<?>>(); 107 for (Collection<Class<?>> c : collectors.values()) { 108 result.addAll(c); 109 } 110 return result; 111 } 112 113 public Set<Class<?>> getClasses(String anno) { 114 return new HashSet<Class<?>>(collectors.get(anno)); 115 } 116}