2011年10月11日 星期二

OSGi : get all package list using BundleWiring on Virgo

這邊主要是利用BundleWiring 在OSGI 4.3新增的listResources()method 來取得package下的所有class , 原本可以透過Spring 的Resource 來取得File。
但是Resource.getFile()沒辦法直接list全部的檔案(傳folder 進去會出IOException : cannot be resolved as absolute), 要用其他的api,
不過後來發現沒有使用 BundleWiring.listResources() , 來的方便,最主要的目的是針對有設定某個MANIFEST header 指定的package 下的全部class, BundleWiring.listResources()的用法如下

BundleWiring wiring = bundle.adapt(BundleWiring.class);
Collection<String> allResourcePathClassName= wiring.listResources(resourceClassPath,"*.class", BundleWiring.LISTRESOURCES_LOCAL);

這邊有2個屬性能使用, 一個是
BundleWiring.LISTRESOURCES_RECURSE
The list resource names operation must limit the result to the names of matching resources contained in this bundle wiring's bundle revision and its attached fragment 
revisions.

BundleWiring.LISTRESOURCES_LOCAL
The list resource names operation must recurse into subdirectories.

這邊我只scan 指定的package下,所以使用LISTRESOURCES_LOCAL, listResources()還支持了pattern , 這邊使用的是"*.class" ,回傳的result 就會如下
resources = [com/gfactor/jpa/persistence/test/test.class, com/gfactor
/jpa/persistence/test/test1.class] 

Sapmle
package com.gfactor.jpa.internal.loader;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Dictionary;
import java.util.List;

import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.wiring.BundleWiring;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.osgi.context.BundleContextAware;
import org.springframework.util.ClassUtils;

public class OsgiPersistenceClassLoader implements BundleContextAware{
 public static final String JPA_MANIFEST_HEADER = "Meta-Persistence-ScanPackage";
 private final Logger logger = LoggerFactory.getLogger(this.getClass()); 
 
 private BundleContext bundleContext;
 
 
 /**
  * Get all Entity class from persistence units bundle , 
  * The persistence units bundle have Meta-Persistence-ScanPackage information on the MANIFEST.mf.
  * @return List<Class> 
  */
 public List<Class<?>> getPersistenceList(){
  List<Class<?>> clazzList = new ArrayList<Class<?>>();
  Bundle[] bundles = bundleContext.getBundles();
  
  clazzList = resolverAllPersistenceUnitsClass(bundles);
  
  return clazzList;
 }
 
 private List<Class<?>> resolverAllPersistenceUnitsClass(Bundle[] bundles){
  List<Class<?>> classList =  new ArrayList<Class<?>>();
  logger.info("resolverAllPersistenceUnitsClass ......");
  
  for (Bundle bundle : bundles) {      
   Dictionary<String, String> customJpaMetaInfoHeader =bundle.getHeaders(JPA_MANIFEST_HEADER);
   final String allScanPackageListString = customJpaMetaInfoHeader.get(JPA_MANIFEST_HEADER);
   
   if (allScanPackageListString == null)
    continue;
   
   
   logger.info("bundle name = "   bundle.getSymbolicName());   
   logger.info("get JPA_MANIFEST_HEADER String = "   allScanPackageListString);
   
   for (String scanClassPath : allScanPackageListString.split(",")) {    
    BundleWiring wiring = bundle.adapt(BundleWiring.class);
    String resourceClassPath = convertClassNameToResourcePath(scanClassPath);    
    Collection<String> allResourcePathClassName= wiring.listResources(resourceClassPath,"*.class", BundleWiring.LISTRESOURCES_LOCAL);
       
    for (String string : allResourcePathClassName) {         
     String loadClassName = convertResourcePathToClassName(string);     
     printDebugMessage(wiring, resourceClassPath, allResourcePathClassName,loadClassName);     
     
     try {
      Class<?> loadClazz = bundle.loadClass(loadClassName);
      classList.add(loadClazz);
     } catch (ClassNotFoundException e) {
      logger.error("can't load class..." , e);
     }
     
    }
    logger.info("");
   }
    
  }
  
  logger.info("all persistence class size = "   classList.size());
  return classList;
 }


 private void printDebugMessage(BundleWiring wiring,
   String resourceClassPath, Collection<String> resources,String loadClassName) {
  
//  if(!logger.isDebugEnabled()) return;
  
  logger.info("resolverAllPersistenceUnitsClass resolverAllPersistenceUnitsClass : Check BundleWiring = ["  wiring   "]"); 
  logger.info("resolverAllPersistenceUnitsClass resolverAllPersistenceUnitsClass : resourceClassPath = ["  resourceClassPath   "]");
  logger.info("resolverAllPersistenceUnitsClass resolverAllPersistenceUnitsClass : resources Class = ["  resources   "]");
  logger.info("resolverAllPersistenceUnitsClass resolverAllPersistenceUnitsClass : loadClassName = ["  loadClassName   "]");
 }
 
 /**
  * Convert a "."-based fully qualified class name to a "/"-based resource path. 
  * @param packageName
  * @return String(ResourcePathName)
  */
 private String convertClassNameToResourcePath(String packageName){
  return ClassUtils.convertClassNameToResourcePath(packageName);
 }
 
 /**
  * Convert a "/"-based resource path to a "."-based fully qualified class name.
  * The param className will replace all ".class" to "" , 
  * e.g: com/my/test.class to com.my.test  
  * @param className
  * @return String(className)
  */
 private String convertResourcePathToClassName(String className){
  String returnClassName = className.replaceAll(".class", "");
  returnClassName = ClassUtils.convertResourcePathToClassName(returnClassName);
  return returnClassName;
 }
 
 @Override
 public void setBundleContext(BundleContext bundleContext) {
  this.bundleContext = bundleContext;
 }

}


Reference :

Interface BundleWiring

沒有留言:

張貼留言