Package br.com.caelum.vraptor.scan

Source Code of br.com.caelum.vraptor.scan.ScannotationComponentScanner

/***
* Copyright (c) 2009 Caelum - www.caelum.com.br/opensource All rights reserved.
*
* 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 br.com.caelum.vraptor.scan;

import java.io.IOException;
import java.lang.annotation.Annotation;
import java.net.URL;
import java.util.Collection;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.scannotation.AnnotationDB;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import br.com.caelum.vraptor.core.BaseComponents;
import br.com.caelum.vraptor.ioc.Stereotype;

/**
* A Scannotation based Component Scanner
*
* @author Sérgio Lopes
* @since 3.2
*/
public class ScannotationComponentScanner implements ComponentScanner {

  private static final Logger logger = LoggerFactory.getLogger(ScannotationComponentScanner.class);

  public Collection<String> scan(ClasspathResolver resolver) {
    final URL webInfClasses = resolver.findWebInfClassesLocation();
    final List<String> basePackages = resolver.findBasePackages();

    HashSet<String> results = new HashSet<String>();

    Map<String, Set<String>> webInfClassesAnnotationMap = scanWebInfClasses(webInfClasses);
    Map<String, Set<String>> basePackagesAnnotationMap = scanBasePackages(basePackages);

    Set<String> stereotypeNames = findStereotypes(webInfClassesAnnotationMap, basePackagesAnnotationMap, basePackages);

    findComponentsFromWebInfClasses(webInfClassesAnnotationMap, stereotypeNames, results);
    findComponentsFromBasePackages(basePackagesAnnotationMap, basePackages, results);

    return results;
  }

  private Map<String, Set<String>> scanWebInfClasses(URL webInfClasses) {
    try {
      AnnotationDB db = createAnnotationDB();
      db.scanArchives(webInfClasses);
      return db.getAnnotationIndex();
    } catch (IOException e) {
      throw new ScannerException("Could not scan WEB-INF/classes", e);
    }
  }

  private Map<String, Set<String>> scanBasePackages(List<String> basePackages) {
    try {
      AnnotationDB db = createAnnotationDB();

      for (String basePackage : basePackages) {
        String resource = basePackage.replace('.', '/');
        Enumeration<URL> urls = Thread.currentThread().getContextClassLoader().getResources(resource);
        if (!urls.hasMoreElements()) {
          logger.error("There's no occurence of package {} in classpath", basePackage);
          continue;
        }
        do {
          URL url = urls.nextElement();

          String file = url.getFile();
          file = file.substring(0, file.length() - resource.length() - 1);
          if (file.charAt(file.length() - 1) == '!') {
            file = file.substring(0, file.length() - 1);
          }
          if (!file.startsWith("file:")) {
            file = "file:" + file;
          }

          db.scanArchives(new URL(file));
        } while (urls.hasMoreElements());
      }

      return db.getAnnotationIndex();
    } catch (IOException e) {
      throw new ScannerException("Could not scan base packages", e);
    }
  }

  private Set<String> findStereotypes(Map<String, Set<String>> webInfClassesAnnotationMap, Map<String, Set<String>> basePackagesAnnotationMap, List<String> basePackages) {
    HashSet<String> results = new HashSet<String>();

    // add VRaptor's default
    for (Class<? extends Annotation> stereotype : BaseComponents.getStereotypes()) {
      results.add(stereotype.getName());
    }

    // check WEB-INF/classes first
    Set<String> myStereotypes = webInfClassesAnnotationMap.get(Stereotype.class.getName());
    if (myStereotypes != null) {
      results.addAll(myStereotypes);
    }

    // check basePackages
    Set<String> libStereotypes = basePackagesAnnotationMap.get(Stereotype.class.getName());
    if (libStereotypes != null) {
      for (String stereotype : libStereotypes) {
        for (String basePackage : basePackages) {
          if (stereotype.startsWith(basePackage)) {
            results.add(stereotype);
            break;
          }
        }
      }
    }

    return results;
  }

  private void findComponentsFromWebInfClasses(Map<String, Set<String>> index, Set<String> stereotypeNames, Set<String> results) {
    for (String stereotype : stereotypeNames) {
      Set<String> classes = index.get(stereotype);
      if (classes != null)
        results.addAll(classes);
    }
  }

  private void findComponentsFromBasePackages(Map<String, Set<String>> index, List<String> basePackages, Set<String> results) {
    for (Class<? extends Annotation> stereotype : BaseComponents.getStereotypes()) {
      Set<String> classes = index.get(stereotype.getName());

      if (classes != null) {
        for (String clazz : classes) {
          for (String basePackage : basePackages) {
            if (clazz.startsWith(basePackage)) {
              results.add(clazz);
              break;
            }
          }
        }
      }
    }
  }

  private AnnotationDB createAnnotationDB() {
    AnnotationDB db = new AnnotationDB();
    db.setScanClassAnnotations(true);
    db.setScanFieldAnnotations(false);
    db.setScanMethodAnnotations(false);
    db.setScanParameterAnnotations(false);
    return db;
  }
}
TOP

Related Classes of br.com.caelum.vraptor.scan.ScannotationComponentScanner

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.