`
德安德鲁
  • 浏览: 45013 次
  • 性别: Icon_minigender_1
  • 来自: 西安
社区版块
存档分类
最新评论

OSGI-自动发现,加载Bundle(jar包)

    博客分类:
  • OSGI
阅读更多

 

一、 创建Plug-in Project工程,名为“PluginMgrCenter”,主要实现定时监控给定文件夹下jar包,对未加载的jar包进行加载

1、创建工程

 

2、工程结构如下图示意:    


 3、实现Activator类的方法,Activator类的作用,说白了就是该Bundle启动,停止会调用该类覆写的start(),stop()方法。

 

 

 

Activator类的start()方法中,保存osgi框架传进来的BundleContext对象,并启动一个定时任务。

 

代码如下:

 

package pluginmgrcenter;

import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;

import directwatcher.DirectWatcherTask;
import directwatcher.ScheduleTimerPool;

public class Activator implements BundleActivator
{
	
	private static BundleContext bundleContext;
	
	public static BundleContext getBundleContext()
	{
		return bundleContext;
	}
	
	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.osgi.framework.BundleActivator#start(org.osgi.framework.BundleContext
	 * )
	 */
	public void start(BundleContext context) throws Exception
	{
		bundleContext = context;
		try
		{
			DirectWatcherTask directWatcherTask = new DirectWatcherTask(
					bundleContext, "d:\\plugin\\");
			ScheduleTimerPool.getInstance().schedule(directWatcherTask, 10000,
					10000);
		}
		catch (Exception e)
		{
			e.printStackTrace();
		}
		
	}
	
	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.osgi.framework.BundleActivator#stop(org.osgi.framework.BundleContext)
	 */
	public void stop(BundleContext context) throws Exception
	{
		System.out.println("Bye World!");
	}
	
}
 4、ScheduleTimerPool.java类定义了一个简单的定时器。用于定时执行DirectWatcherTask.java中的jar包扫描任务。
package directwatcher;

import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;

public class ScheduleTimerPool
{
	
	private static ScheduleTimerPool scheduleTimerPool;
	
	static BlockingQueue<Runnable> queue = new LinkedBlockingQueue<Runnable>();
	
	public static final ScheduleTimerPool getInstance()
	{
		if (null == scheduleTimerPool)
		{
			scheduleTimerPool = new ScheduleTimerPool();
		}
		return scheduleTimerPool;
	}
	
	private static Timer timer;
	
	public void schedule(TimerTask task, long deplay, long interval)
	{
		if (null == timer)
		{
			timer = new Timer();
		}
		timer.schedule(task, deplay, interval);
	}
}

 5、DirectWatcherTask.java中run()方法实现了对指定路径的jar包进行扫描

      a、如果发现该jar未被加载,则安装启动该jar包

      b、如果该jar包版本有更新,则更新该jar包

    代码如下:

 * 
 */
package directwatcher;

import java.io.File;
import java.io.FileFilter;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import java.util.TimerTask;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;

import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.BundleException;
import org.osgi.framework.Version;

/**
 * @author Administrator
 * 
 */
public class DirectWatcherTask extends TimerTask
{
	
	private BundleContext bundleContext;
	public String bundleFolderPath;
	
	public DirectWatcherTask(BundleContext bundleContext,
			String bundleFolderPath)
	{
		super();
		this.bundleContext = bundleContext;
		this.bundleFolderPath = bundleFolderPath;
		System.out.println("插件目录:" + bundleFolderPath);
	}
	
	@Override
	public void run()
	{
		try
		{
			if (bundleContext == null)
			{
				System.out.println("bundleContext is null");
				return;
			}
			
			File folderInfo = new File(bundleFolderPath);
			// 如果目录不存在
			if (!folderInfo.exists() || !folderInfo.isDirectory())
			{
				System.out.println("bundleFloderPath is error!");
				return;
			}
			
			File[] files = folderInfo.listFiles(new FileFilter()
			{
				
				@Override
				public boolean accept(File pathname)
				{
					if (!pathname.isFile())
						return false;
					return pathname.getName().toLowerCase().endsWith(".jar");
				}
			});
			
			List<Bundle> newBundleList = new ArrayList<Bundle>();
			for (File file : files)
			{
				ZipFile zipFile = null;
				try
				{
					zipFile = new ZipFile(file);
					ZipEntry zipEntry = zipFile
							.getEntry("META-INF/MANIFEST.MF");
					if (zipEntry == null || zipEntry.isDirectory())
						continue;
					InputStream inputStream = zipFile.getInputStream(zipEntry);
					Properties prop = new Properties();
					prop.load(inputStream);
					
					// 得到插件的名称和版本
					String bundleName = prop.getProperty("Bundle-SymbolicName");
					Version bundleVersion = Version.parseVersion(prop
							.getProperty("Bundle-Version"));
					
					Bundle preBundle = null;
					Bundle[] bundles = bundleContext.getBundles();
					for (Bundle bundle : bundles)
					{
						if (bundle.getSymbolicName().equals(bundleName))
						{
							preBundle = bundle;
							break;
						}
					}
					
					Bundle newBundle = null;
					// 如果之前没有此插件,则安装
					if (preBundle == null)
					{
						System.out.println("自动安装新插件:" + bundleName + "  "
								+ bundleVersion);
						FileInputStream fileInputStream = new FileInputStream(
								file);
						newBundle = bundleContext.installBundle(file.getName(),
								fileInputStream);
						fileInputStream.close();
					}// 否则更新
					else
					{
						if (bundleVersion.compareTo(preBundle.getVersion()) > 0)
						{
							System.out.println("自动将插件:" + bundleName + " 由 "
									+ preBundle.getVersion() + "更新到"
									+ bundleVersion);
							FileInputStream fileInputStream = new FileInputStream(
									file);
							preBundle.update(fileInputStream);
							newBundle = preBundle;
							fileInputStream.close();
						}
					}
					// 尝试启动插件
					if (newBundle != null)
					{
						newBundleList.add(newBundle);
					}
				}
				catch (IllegalStateException ex)
				{
					continue;
				}
				catch (Exception ex)
				{
					ex.printStackTrace();
				}
				finally
				{
					if (zipFile != null)
					{
						try
						{
							zipFile.close();
						}
						catch (Exception ex)
						{
							ex.printStackTrace();
						}
					}
				}
			}
			
			// 尝试启动所有的插件
			boolean isAllBundleStartSuccess;
			for (int i = 0; i < newBundleList.size(); i++)
			{
				isAllBundleStartSuccess = true;
				for (Bundle newBundle : newBundleList)
				{
					if (newBundle.getState() != Bundle.ACTIVE
							&& newBundle.getState() != Bundle.STARTING)
					{
						try
						{
							newBundle.start();
						}
						catch (BundleException e)
						{
							isAllBundleStartSuccess = false;
						}
					}
				}
				if (isAllBundleStartSuccess)
				{
					break;
				}
			}
			
			// 启动尝试启动失败的插件以打印异常信息
			for (Bundle newBundle : newBundleList)
			{
				if (newBundle.getState() != Bundle.ACTIVE
						&& newBundle.getState() != Bundle.STARTING)
				{
					try
					{
						newBundle.start();
					}
					catch (BundleException e)
					{
						e.printStackTrace();
					}
				}
			}
		}
		catch (Exception e)
		{
			System.out.println("quickwebframework_web:插件自动管理线程接到线程中止命令,线程已终止!");
		}
	}
	
}

 这样bundle管理Bundle已经成型了。

 二:配置Myeclipse的“Run Configurations”

进入“Run Configurations”页面-->单击 OSGI Framework后点击“新建”图标-->选中新建的默认名称为“New_configuration”的Launch。

在“New_configuration”的Launch右侧的“Bundles”标签页,右方选择“Deselect ALL”后,在 Bundles选择框中选择“PluginMgrCenter” bundle,如下图示意:

 
 然后在搜索栏中搜索“*osgi”进行搜索,搜索结果中选择“org.eclipse.osgi(3.5.1.R35x_v20090827)”如下:


 3、创建Plug-In测试工程

1、创建工程名为“PluginAgent”的Plug-in工程,用于被Bundle管理Bundle管理,呵呵,是不是很拗口?本文的实验就是安装,启动,更新。

工程目录结构如下:

 2、其中Activator.java如下,start()方法在控制台打印“hello pluginAgent!”  stop()方法打印“bye pluginAgent!”

代码如下

package pluginagent;

import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;

public class Activator implements BundleActivator
{
	
	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.osgi.framework.BundleActivator#start(org.osgi.framework.BundleContext
	 * )
	 */
	public void start(BundleContext context) throws Exception
	{
		System.out.println("hello pluginAgent!");
	}
	
	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.osgi.framework.BundleActivator#stop(org.osgi.framework.BundleContext)
	 */
	public void stop(BundleContext context) throws Exception
	{
		System.out.println("bye pluginAgent!");
	}
	
}

 3、导出“PluginAgent”工程为“PluginAgent.jar”的jar包,路径为D:\plugin


 

 四、测试

1、以第二步骤配置的 “New_configuration” Launch 运行。

2、执行“ss”命令,查询当前只有两个Bundle运行

3、等待控制台打印出“自动安装新插件:PluginAgent  1.0.0.qualifier”,则表示系统已经检测到“D:\plugin”目录下的jar包,并识别后开始加载。

4、“Hello pluginAgent”则表示PluginAgent.jar已经加载成功。

5、再次执行“ss”命令,观察到已经有“PluginAgent_1.0.0.qualifier”Bundle安装并且启动成功,状态为ACTIVE。

 

测试结果图示:



 

 

 

    

 

  • 大小: 24.4 KB
  • 大小: 6.6 KB
  • 大小: 5 KB
  • 大小: 54.5 KB
  • 大小: 28.6 KB
  • 大小: 37 KB
  • 大小: 20.6 KB
分享到:
评论
4 楼 德安德鲁 2013-06-27  
牛人云小白 写道
TM的,过了两天一看,还是这一篇旧作,啥时候出新么。大神。
爷今天去面试,祝爷好运。

新作正在酝酿,周五必发
3 楼 牛人云小白 2013-06-27  
TM的,过了两天一看,还是这一篇旧作,啥时候出新么。大神。
爷今天去面试,祝爷好运。
2 楼 德安德鲁 2013-06-20  
牛人云小白 写道
这位大神,请问尊姓大名?
我只能说,我仰慕你。

=============
牛人旱地小牛牛
1 楼 牛人云小白 2013-06-20  
这位大神,请问尊姓大名?
我只能说,我仰慕你。

相关推荐

    spring-osgi-1.2.0-rc1-with-dependencies.zip

    开发者在使用Spring OSGi时,需要了解如何编写OSGi兼容的jar包,以及如何在Spring配置文件中声明和管理OSGi服务。此外,调试和测试OSGi环境下的应用程序也是一项挑战,因为它们涉及到复杂的生命周期管理和依赖关系...

    spring-osgi-1.2.0.zip

    7. **Bundles**:Spring应用被打包成OSGi兼容的bundle(JAR文件),它们可以被OSGi容器加载并执行。 在实际开发中,Spring OSGi使得开发者能够利用OSGi的动态性,例如,可以在运行时安装、卸载、更新和启动Spring...

    osgi解决不同版本jar包冲突的demo

    然而,在OSGi环境中,我们可以为每个版本的“myself”jar包创建一个独立的bundle,每个bundle都有自己的类加载器,它们可以并存且互不影响。 为了设置OSGi环境并进行测试,你需要以下步骤: 1. **配置OSGi框架**:...

    osgi-webservice教程

    - 确保所有依赖库都已适配OSGi环境,避免使用非OSGi友好的jar包。 - 在处理动态性时,考虑服务的生命周期管理,特别是当服务更新或移除时,确保客户端能够优雅地处理。 - 注意线程安全问题,因为多个服务消费者可能...

    org.eclipse.osgi-3.7.2

    在Eclipse OSGi框架下,每个bundle都有自己的类加载器,这使得bundle可以有自己的类空间,避免了类加载冲突。同时,OSGi的动态性体现在bundle可以在运行时被安装、启动、停止或卸载,这极大地提高了软件的可维护性和...

    org.eclipse.osgi-3.7.0

    5. **动态依赖解析**:OSGi框架会自动处理bundle之间的依赖关系,确保在需要时加载依赖,而在不再需要时释放。这种机制使得应用能够快速适应环境变化,如添加新的bundle或更新现有bundle。 6. **版本管理**:每个...

    ant-1.6.5-osgi.jar.zip

    标题中的"ant-1.6.5-osgi.jar.zip"是一个压缩文件,它包含了两个主要元素:ant-1.6.5-osgi.jar和ant.license.txt。这个压缩包是针对Apache Ant的一个版本,具体是1.6.5版本,并且与OSGi(Open Service Gateway ...

    org.eclipse.osgi-3.8.0

    4. **版本管理**:OSGi 对包版本进行了严格管理,确保不同 bundle 中的相同包版本不会冲突,有助于避免类加载问题。 5. **生命周期管理**:OSGi 定义了 bundle 的生命周期,包括未安装、安装、解析、启动、停止、...

    org.osgi.core-4.2.0

    描述 "osgi最新jar包org.osgi.core-4.2.0" 告诉我们这是一个最新的 OSGi jar 包,其中包含了 OSGi 的核心功能。jar(Java Archive)是 Java 平台中用于打包类文件和其他资源的标准格式。因此,`org.osgi.core-4.2.0....

    Jar转换为Bundle工具

    标题中的“Jar转换为Bundle工具”指的是将传统的Java Archive (JAR) 文件转换为OSGI Bundle的过程。OSGI(Open Service Gateway Initiative)是一种模块化系统和Java服务框架,它允许在单个Java虚拟机(JVM)上运行...

    org.eclipse.osgi-3.8.1

    6. **依赖管理**: Bundle的元数据(MANIFEST.MF文件)中声明了其依赖关系,OSGi框架会自动解决这些依赖。 7. **安全机制**: OSGi提供了细粒度的安全模型,可以控制Bundle对资源的访问权限。 Eclipse OSGi在Eclipse...

    blueprint-osgi-bundle:OSGi 示例

    5. **生命周期管理**:OSGi捆绑包有启动、活动、停止和未安装等状态,框架会根据需要自动管理这些状态,确保组件的正确加载和卸载。 6. **版本管理**:OSGi支持版本化的捆绑包,允许同时存在不同版本的服务,避免...

    OSGI bundle

    OSGI bundle提供了一种模块化的软件开发方式,使得Java应用程序可以按需加载和卸载组件。`online-1.0.0.jar`和`jxemail-1.0.0.jar`是两个示例bundle,分别实现了在线用户管理和邮件发送的功能。通过Apache Felix这样...

    osgi开发jar包

    这些工具能够自动生成满足OSGi规范的MANIFEST.MF,并将依赖关系正确地打包进bundle。 6. **服务注册与查找**:在OSGi环境中,服务是一种共享的资源,可以通过Service Registry进行注册和查找。一个bundle可以提供...

    Felix_OSGi实作

    OSGi规范使得Java程序可以被设计成一套小型的、独立的模块(称为Bundle),这些模块可以在运行时动态地加载、卸载、启动或停止。 Felix是一个遵循OSGi规范的轻量级、模块化的Service Oriented Runtime,由Apache...

    spring-osgi.jar及其依赖包

    4. **自动依赖管理**:Spring OSGi可以自动管理bundle之间的依赖关系,通过声明式服务(Declarative Services, DS)来声明服务和依赖,降低配置复杂性。 5. **集成其他Spring特性**:Spring OSGi支持Spring的AOP、...

    felix学习二-发布classpath为bundle

    OSGi的核心概念是“bundle”,即模块化的JAR文件,它们可以有自己的类路径,并能动态地安装、启动、更新和卸载。本篇文章将深入探讨如何将classpath作为bundle发布在Felix框架中。 首先,我们需要了解OSGi的bundle...

    tiger-types-osgi-2.1.44.zip

    1. **OSGi**:OSGi提供了一种模块化系统,使得Java应用程序可以被划分为称为“bundle”的组件,每个组件都有自己的类加载器,这有助于减少类冲突和管理依赖关系。它还支持动态部署和更新,使得系统能够在线升级而...

    osgi-bundle-hello-world:使用Maven的演示OSGI捆绑包

    5. `target`: Maven构建后生成的输出目录,包括编译后的class文件和最终的OSGi捆绑包(可能以.jar或.bundle为扩展名)。 总结一下,这个项目旨在教授如何使用Maven创建一个基本的OSGi捆绑包,以及如何在OSGi容器中...

    osgi-core技术文档与说明

    OSGi模块实际上是一个Java存档文件(JAR),但具有特定的OSGi清单文件(Manifest)格式。清单文件包含了模块的元数据和它的依赖关系。模块层的主要职责是定义模块的生命周期,包括模块的加载、解析、启动、停止、...

Global site tag (gtag.js) - Google Analytics