2011年5月26日 星期四

OSGI Tutorial (4) - Spring DM ,The Resource Abstraction

OSGi每個Bundle 都有各自的ClassLoader, SpringDM會在每一個Bundle啟動時創建ApplicationContext,如果對Spring 有點概念的應該都會知道在Spring裡面是如何獲取Resource, 而在Spring DM裡面的文件有提到:
Spring resource prefixes such as file: and http: are also supportedm , Resources loaded using 
such prefixes may come from any location, they are not restricted to being defined within the 
resource-loading bundle or its attached fragments. 

OSGi platforms may define their own unique prefixes for accessing bundle contents. 
For example, Equinox defines the bundleresource: and bundlentry: prefixes. These platform 
specific prefixes may also be used with Spring OSGi, at the cost, of course, of tying yourself 
to a particular OSGi implementation.
原本的file: , http: 也是可以使用的, 並不被限制於自身的bundle位置, osgi 的平台每個實作的不一樣,所以預設的prefix 也許會不一樣,Equinox 就是bundleresource: and bundlentry: ,如果你對Spring 的Resource 不太了解的話,建議可以先看這份官方的Doc Link-> Spring 3.x - 4. Resources

一樣先建立二個Bundle , 2個Bundle 的結構如下
OSGIApp.Sample.OSGiSample

OSGIApp.Sample.OSGiSample2

然後在OSGIApp.Sample.OSGiSample 裡面的Activator 裡面取Resource , code如下
package com.my;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;

import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.BundleException;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.core.io.Resource;
import org.springframework.osgi.context.BundleContextAware;

public class Activator implements ApplicationContextAware,BundleContextAware {
 
 ApplicationContext application;
 Bundle bundle;
 Bundle bundle2;
 BundleContext btx;
  
 public void start() throws BundleException, IOException{
  
  //default setting,If no prefix is specified, the bundle space (osgibundle:) will be used.
  Resource res = application.getResource("/TxtFile/ResoureText.txt");
  System.out.println("Resource(Default osgibundle) = "   res);
  System.out.println("Resource(Default osgibundle) = "   res.getURI());
  System.out.println("Resource(Default osgibundle) = "   res.getURL());
  File f = res.getFile();
  System.out.println("File(osgibundle) getAbsolutePath = "  f.getAbsolutePath() );
  System.out.println("File(osgibundle) getPath = "  f.getPath() );
  System.out.println();
  
  //osgibundlejar prefix , Searches only the bundle jar. Provides low-level access.
  //using the same semantics as the Bundle.getEntry method. Delegates internally to the Bundle.findEntries .
  Resource res2 = application.getResource("osgibundlejar:/TxtFile/ResoureText.txt");
  System.out.println("Resource2(osgibundlejar) = "   res2);
  System.out.println("Resource2(osgibundlejar) = "   res2.getURI());
  System.out.println("Resource2(osgibundlejar) = "   res2.getURL());
  try{ 
   File f2 = res2.getFile(); // can't use it.
//   File f2 = new File(res2.getURI().toString()); //it's work.
   System.out.println("File(osgibundlejar) getAbsolutePath = "  f2.getAbsolutePath() );
   System.out.println("File(osgibundlejar) getPath = "  f2.getPath() );

  }catch(FileNotFoundException ex){
   System.out.println(ex);
  }
  System.out.println();
  
  //classpath:(the same as classpath*:) prefix , Searches the bundle classloader (the bundle, all imported packages and required bundles). 
  Resource res3 = application.getResource("classpath:/TxtFile/ResoureText.txt");
  System.out.println("Resource3(classpath) = "   res3);
  System.out.println("Resource3(classpath) = "   res3.getURI());
  System.out.println("Resource3(classpath) = "   res3.getURL());
  File f3 = res3.getFile();
  System.out.println("File(classpath) getAbsolutePath = "  f3.getAbsolutePath() );
  System.out.println("File(classpath) getPath = "  f3.getPath() );
  System.out.println();
  
  //To use osgi framework that get resource from the osgi bundle. 
  bundle = btx.getBundle();  
  System.out.println("Bundle GetResoruce = "    bundle.getResource("/TxtFile/ResoureText.txt"));
  System.out.println("bundle getEntry  = "  bundle.getEntry("/TxtFile/ResoureText.txt"));
  File f4 = new File(bundle.getResource("/TxtFile/ResoureText.txt").toString());
  System.out.println("File(classpath) getAbsolutePath = "  f4.getAbsolutePath() );
  System.out.println("File(classpath) getPath = "  f4.getPath() );
  System.out.println();
  
  System.out.println("bundl2 = " bundle2);
  System.out.println("get uri = " bundle2.getResource("/XmlFolder/Test.xml"));
  System.out.println("Bundle2 GetResoruce = "    bundle2.getResource("/XmlFolder/Test.xml"));
  System.out.println("bundle2 getEntry  = "  bundle2.getEntry("/XmlFolder/Test.xml"));
  File f5 = new File(bundle2.getResource("/XmlFolder/Test.xml").toString());
  System.out.println("File(classpath) getAbsolutePath = "  f5.getAbsolutePath() );
  System.out.println("File(classpath) getPath = "  f5.getPath() );
  System.out.println();
  //  System.out.println("bundle  = " bundle);
  
  //update sampe2 bundle 
//  bundle.update();
 }
 
 public void stop() throws BundleException{
  //stop sample2 , 
//  bundle.stop();
 }
// 
// public void setBundle(Bundle bundle) {
//  System.out.println("bnudle set");
//  this.bundle = bundle;
// }
//
 
 
 public void setBundleContext(BundleContext bundleContext) {
  System.out.println("set bundle context ");
  this.btx= bundleContext;
  
 }

 public void setBundle2(Bundle bundle2) {
  this.bundle2 = bundle2;
 }

 public void setApplicationContext(ApplicationContext arg0)
   throws BeansException {  
  this.application = arg0;
  
 }

}


然後這邊是完整的Log清單
set bundle context  
Resource(Default osgibundle) = OSGi resource[/TxtFile/ResoureText.txt|bnd.id=60|bnd.sym=OSGIApp.Sample.OSGiSample] 
Resource(Default osgibundle) = bundleentry://60.fwk1834141/TxtFile/ResoureText.txt 
Resource(Default osgibundle) = bundleentry://60.fwk1834141/TxtFile/ResoureText.txt 
File(osgibundle) getAbsolutePath = C:\Eclipse-Virgo-WebServer\work\org.eclipse.virgo.kernel.deployer_2.1.0.RELEASE\staging\global\bundle\OSGIApp.Sample.OSGiSample\1.0.0\OSGiSample.jar\TxtFile\ResoureText.txt 
File(osgibundle) getPath = C:\Eclipse-Virgo-WebServer\work\org.eclipse.virgo.kernel.deployer_2.1.0.RELEASE\staging\global\bundle\OSGIApp.Sample.OSGiSample\1.0.0\OSGiSample.jar\TxtFile\ResoureText.txt 
 
Resource2(osgibundlejar) = OSGi resource[osgibundlejar:/TxtFile/ResoureText.txt|bnd.id=60|bnd.sym=OSGIApp.Sample.OSGiSample] 
Resource2(osgibundlejar) = bundleentry://60.fwk1834141/TxtFile/ResoureText.txt 
Resource2(osgibundlejar) = bundleentry://60.fwk1834141/TxtFile/ResoureText.txt 
java.io.FileNotFoundException: OSGi resource[osgibundlejar:/TxtFile/ResoureText.txt|bnd.id=60|bnd.sym=OSGIApp.Sample.OSGiSample] cannot be resolved to absolute file path 
 
Resource3(classpath) = OSGi resource[classpath:/TxtFile/ResoureText.txt|bnd.id=60|bnd.sym=OSGIApp.Sample.OSGiSample] 
Resource3(classpath) = file:/C:/Eclipse-Virgo-WebServer/work/osgi/configuration/org.eclipse.osgi/bundles/36/data/store/org.eclipse.osgi/bundles/60/1/bundlefile/TxtFile/ResoureText.txt 
Resource3(classpath) = file:/C:/Eclipse-Virgo-WebServer/work/osgi/configuration/org.eclipse.osgi/bundles/36/data/store/org.eclipse.osgi/bundles/60/1/bundlefile/TxtFile/ResoureText.txt 
File(classpath) getAbsolutePath = C:\Eclipse-Virgo-WebServer\work\osgi\configuration\org.eclipse.osgi\bundles\36\data\store\org.eclipse.osgi\bundles\60\1\bundlefile\TxtFile\ResoureText.txt 
File(classpath) getPath = C:\Eclipse-Virgo-WebServer\work\osgi\configuration\org.eclipse.osgi\bundles\36\data\store\org.eclipse.osgi\bundles\60\1\bundlefile\TxtFile\ResoureText.txt 
 
Bundle GetResoruce = file:/C:/Eclipse-Virgo-WebServer/work/osgi/configuration/org.eclipse.osgi/bundles/36/data/store/org.eclipse.osgi/bundles/60/1/bundlefile/TxtFile/ResoureText.txt 
bundle getEntry  = bundleentry://60.fwk1834141/TxtFile/ResoureText.txt 
File(classpath) getAbsolutePath = C:\Eclipse-Virgo-WebServer\file:\C:\Eclipse-Virgo-WebServer\work\osgi\configuration\org.eclipse.osgi\bundles\36\data\store\org.eclipse.osgi\bundles\60\1\bundlefile\TxtFile\ResoureText.txt 
File(classpath) getPath = file:\C:\Eclipse-Virgo-WebServer\work\osgi\configuration\org.eclipse.osgi\bundles\36\data\store\org.eclipse.osgi\bundles\60\1\bundlefile\TxtFile\ResoureText.txt 
 
bundl2 = OSGIApp.Sample.OSGiSample2_1.0.0 [57] 
get uri = file:/C:/Eclipse-Virgo-WebServer/work/osgi/configuration/org.eclipse.osgi/bundles/36/data/store/org.eclipse.osgi/bundles/57/2/bundlefile/XmlFolder/Test.xml 
Bundle2 GetResoruce = file:/C:/Eclipse-Virgo-WebServer/work/osgi/configuration/org.eclipse.osgi/bundles/36/data/store/org.eclipse.osgi/bundles/57/2/bundlefile/XmlFolder/Test.xml 
bundle2 getEntry  = bundleentry://57.fwk1834141/XmlFolder/Test.xml 
File(classpath) getAbsolutePath = C:\Eclipse-Virgo-WebServer\file:\C:\Eclipse-Virgo-WebServer\work\osgi\configuration\org.eclipse.osgi\bundles\36\data\store\org.eclipse.osgi\bundles\57\2\bundlefile\XmlFolder\Test.xml 
File(classpath) getPath = file:\C:\Eclipse-Virgo-WebServer\work\osgi\configuration\org.eclipse.osgi\bundles\36\data\store\org.eclipse.osgi\bundles\57\2\bundlefile\XmlFolder\Test.xml                                                  

這邊要注意一下預設的prefix 是osgibundle: , 須要注意的是osgibundlejar: 這邊只提供low-lever access, 如果直接Resource.getFile() 會出現FileNotFoundException, 需使用getURI() 來取得檔案, 可以注意到預設的osgibundle 取出的檔案PATH跟其他的有不一樣,在Eclipse Virgo裡面是去jar檔的位置尋找, osgibundlejar則是跟osgi預設的行為很象, Equinox 裡面是設定bundleresource: and bundlentry: prefixes。

Reference:
Spring dm文件裡面有介紹, 相關的prefix

Table 6.1. OSGi resource search strategies

OSGi Search StrategyPrefixExplanation
Class Spaceclasspath:Searches the bundle classloader (the bundle, all imported packages and required bundles). Forces the bundle to be resolved.
This method has similar semantics to
Bundle#getResource(String)
Class Spaceclasspath*:Searches the bundle classloader (the bundle and all imported packages and required bundles). Forces the bundle to be resolved.
This method has similar semantics to
Bundle#getResources(String)
JAR File (or JarSpace)osgibundlejar:Searches only the bundle jar. Provides low-level access without requiring the bundle to be resolved.
Bundle Spaceosgibundle:Searches the bundle jar and its attached fragments (if there are any). Does not create a class loader or force the bundle to be resolved.


Chapter 6. Bundles and Application Contexts : 6.4. The Resource Abstraction
阅读 springdm in action 笔记--Spring DM extenders Link

沒有留言:

張貼留言