001/* 002 * Copyright (c) 2006-2011 Nuxeo SA (http://nuxeo.com/) and others. 003 * 004 * All rights reserved. This program and the accompanying materials 005 * are made available under the terms of the Eclipse Public License v1.0 006 * which accompanies this distribution, and is available at 007 * http://www.eclipse.org/legal/epl-v10.html 008 * 009 * Contributors: 010 * bstefanescu 011 */ 012package org.nuxeo.ecm.webengine.jaxrs.scan; 013 014import java.io.IOException; 015import java.io.InputStream; 016import java.net.URL; 017import java.util.ArrayList; 018import java.util.Collection; 019import java.util.Enumeration; 020import java.util.HashMap; 021import java.util.HashSet; 022import java.util.Map; 023import java.util.Set; 024 025import org.objectweb.asm.ClassReader; 026import org.osgi.framework.Bundle; 027 028/** 029 * @author <a href="mailto:bs@nuxeo.com">Bogdan Stefanescu</a> 030 */ 031public class Scanner { 032 033 public final static String PATH_ANNO = "Ljavax/ws/rs/Path;"; 034 035 public final static String PROVIDER_ANNO = "Ljavax/ws/rs/ext/Provider;"; 036 037 protected Bundle bundle; 038 039 protected String packageBase; 040 041 protected Map<String, Collection<Class<?>>> collectors; 042 043 public Scanner(Bundle bundle, String packageBase) { 044 this(bundle, packageBase, PATH_ANNO, PROVIDER_ANNO); 045 } 046 047 public Scanner(Bundle bundle, String packageBase, String... annotations) { 048 this.bundle = bundle; 049 this.packageBase = packageBase == null ? "/" : packageBase; 050 this.collectors = new HashMap<String, Collection<Class<?>>>(); 051 for (String annotation : annotations) { 052 addCollector(annotation); 053 } 054 } 055 056 public void addCollector(String annotation) { 057 collectors.put(annotation, new ArrayList<Class<?>>()); 058 } 059 060 public void addCollector(String annotation, Collection<Class<?>> collector) { 061 collectors.put(annotation, collector); 062 } 063 064 public Collection<Class<?>> getCollector(String annotation) { 065 return collectors.get(annotation); 066 } 067 068 public Map<String, Collection<Class<?>>> getCollectors() { 069 return collectors; 070 } 071 072 @SuppressWarnings("unchecked") 073 public void scan() throws ReflectiveOperationException, IOException { 074 Enumeration<URL> urls = bundle.findEntries(packageBase, "*.class", true); 075 if (urls == null) { 076 return; 077 } 078 Set<String> annotations = collectors.keySet(); 079 while (urls.hasMoreElements()) { 080 URL url = urls.nextElement(); 081 InputStream in = url.openStream(); 082 try { 083 ClassReader cr = new ClassReader(in); 084 AnnotationReader reader = new AnnotationReader(annotations); 085 cr.accept(reader, null, ClassReader.SKIP_DEBUG | ClassReader.SKIP_CODE | ClassReader.SKIP_FRAMES); 086 if (reader.hasResults()) { 087 String cname = reader.getClassName(); 088 for (String anno : reader.getResults()) { 089 collectors.get(anno).add(bundle.loadClass(cname)); 090 } 091 } 092 } finally { 093 in.close(); 094 } 095 } 096 } 097 098 public Set<Class<?>> getClasses() { 099 HashSet<Class<?>> result = new HashSet<Class<?>>(); 100 for (Collection<Class<?>> c : collectors.values()) { 101 result.addAll(c); 102 } 103 return result; 104 } 105 106 public Set<Class<?>> getClasses(String anno) { 107 return new HashSet<Class<?>>(collectors.get(anno)); 108 } 109}