最近使用Openfire和Spark做一个即时通讯客户端,想着自己能够做一个群聊的插件,所以需要自己去搭建环境,下面记录一下步骤以及遇到错误的解决办法(官网有点坑)。
Sparkplug Kit文档:Development Guide
官方demo 插件Jar:examples.jar
这个jar解压后,配合docs看,有里面的demo的源码
还有就是之前搭建好的源码开发环境,编译成功的target文件夹(很重要...因为这个sparkplug_kit开发环境是很老的spark版本...)
百度文库里面一个doc中文版:http://wenku.baidu.com/view/7a8c04c9d5bbfd0a79567350.html
PS:实际用到的仅仅有sparkplug_kit_2_0_7.zip和Spark编译成功的target文件夹!
1)创建一个叫Sparkplug的JavaProject
File->New->Java Project->填写Project name->Finish
2)将 sparkplug_kit_2_0_7.zip 解压出来目录下的 builder、spark文件夹拷贝到这个项目的目录下
3)将之前spark源码开发环境编译成功后的 target/build 下的文件夹替换当前项目 Sparkplug/spark/(先将spark下的所有文件及文件夹删除) 目录下的所有文件, 然后删除Sparkplug/src
1)右键项目,设置Build Path-》Configure Build Path...
2)Source:选中Sparkplug/src-> remove->Link Source->Browse...->选择Sparkplug/builder/src->Finish
Libraries:Add JARs...->Sparkplug/spark/lib 下的所有jar(去除log4j.properties)
在Sparkplug/src下新建一个包目录,com.mypackage,然后创建一个MyPlugin.java,实现Plugin接口。
New->Class->填写Package: com.mypackage,Name: MyPlugin->Finish
public class MyPlugin implements Plugin { /** * Called after Spark is loaded to initialize the new plugin. * 初始化事件 */ @Override public void initialize() { System.out.println("——————————Welcome To Spark———————————"); addTabToSpark(); } /** * Called when Spark is shutting down to allow for persistence of information * or releasing of resources. * 关闭事件,以便对信息的持久化或释放资源 */ @Override public void shutdown() { System.out.println("——————————shutdown———————————"); } /** * Return true if the Spark can shutdown on users request. * @return true if Spark can shutdown on users request. * 是否允许用户直接关闭 * 返回 是否允许 */ @Override public boolean canShutDown() { return false; } /** * Is called when a user explicitly asked to uninstall this plugin. * The plugin owner is responsible to clean up any resources and * remove any components install in Spark. * 删除插件事件 * 清除资源文件、组件等等 */ @Override public void uninstall() { } /** * 将我自己的标签到Spark工作空间 */ private void addTabToSpark(){ System.out.println("——————————addTabToSpark———————————"); // 从 SparkManager(Spark管理器) 获取 Workspace UI(主界面) 对象 Workspace workspace = SparkManager.getWorkspace(); // 从 Workspace UI 对象获取 SparkTabbedPane(底部Tab栏) 对象 SparkTabbedPane sparkTabbedPane = workspace.getWorkspacePane(); // 添加自定义Tab sparkTabbedPane.addTab("我的标签", null, new JButton("哈哈")); } }
可以看到,我们需要实现initialize()、shutdown()、canShutDown()、uninstall() 四个方法
前2个很好理解,canShutDown()目前还没弄清楚是干嘛的...-_-#,uninstall()还没用到过。
总之先来个最简单的例子创建一个自己的标签。
打开Sparkplug/builder 目录下的 plugin.xml 文件
<!-- Define your plugin --> <plugin> <!-- 插件的名称 --> <name>My Plugin</name> <!-- 插件的版本 --> <version>1.0</version> <!-- 插件的作者 --> <author>Don Juan</author> <!-- 关于该插件更多信息的地址 --> <homePage>http://www.jivesoftware.org</homePage> <!-- 邮箱地址 --> <email>[email protected]</email> <!-- 插件的描述 --> <description>This is my first cool Spark Plugin.</description> <!-- 类路径 --> <class>com.mypackage.MyPlugin</class> <!-- 允许该插件最小的Spark版本号,如果Spark的版本号比需要的小,则插件不会被启动 --> <minSparkVersion>2.0.0</minSparkVersion> </plugin>如果你的包结构是这样的话,就不用改了,如果不一样请修改<class>标签下的路径
打开sparkplugs/builder/build 下的 build.xml
<project name="sparkplug" default="jar" basedir=".."> <property name="plug.dir" value="${basedir}/."/> <property name="plug.lib.dir" value="${plug.dir}/lib"/> <property name="classes.dir" value="${basedir}/build/classes"/> <property name="src.dir" value="${plug.dir}/src"/> <property name="target.dir" value="${plug.dir}/target"/> <property name="target.lib.dir" value="${plug.dir}/target/lib"/> <property name="jar.file" value="${target.dir}/lib/plugin-classes.jar"/> <property name="spark.home" value="${plug.dir}/../spark" /> <path id="lib.classpath"> <fileset dir="${plug.lib.dir}" includes="**/*.jar, **/*.zip"/> <fileset dir="${spark.home}/lib" includes="**/*.jar, **/*.zip"/> <fileset dir="${spark.home}/lib/windows" includes="**/*.jar" /> </path> <target name="clean" description="Cleans all build related output"> <delete file="${jar.file}"/> <delete dir="${classes.dir}"/> <delete dir="${target.dir}"/> </target> <target name="compile" description="Compiles plugin source"> <mkdir dir="${classes.dir}"/> <javac srcdir="${src.dir}" destdir="${classes.dir}" classpathref="lib.classpath" source="1.6" debug="true" target="1.6"/> <copy todir="${classes.dir}"> <fileset dir="${src.dir}" includes="**/*.png"/> <fileset dir="${src.dir}" includes="**/*.gif"/> <fileset dir="${src.dir}" includes="**/*.jpg"/> <fileset dir="${src.dir}" includes="**/*.jpeg"/> </copy> </target> <target name="jar" depends="clean,compile" description="Makes a plugin jar"> <mkdir dir="${target.dir}" /> <mkdir dir="${target.lib.dir}"/> <copy todir="${target.lib.dir}"> <fileset file="${plug.lib.dir}/lib" includes="**/*"/> </copy> <copy todir="${target.dir}"> <fileset file="${plug.dir}/plugin.xml"/> </copy> <jar basedir="${classes.dir}" file="${jar.file}" update="false"/> <zip zipfile="${plug.dir}/myplugin.jar" basedir="${target.dir}" /> </target> <target name="run" depends="jar" description="Makes a plugin jar and starts Spark with that plugin"> <copy todir="${basedir}/../spark/plugins" file="${plug.dir}/myplugin.jar" /> <property name="sparklib" value="${basedir}/../spark/lib" /> <java fork="true" classname="org.jivesoftware.Spark" dir="${basedir}/../spark/bin"> <classpath> <fileset dir="${sparklib}"> <include name="**/*.jar" /> <include name="**/*.exe" /> <include name="**/*.dll" /> </fileset> <pathelement location="${basedir}/../spark/resources" /> </classpath> <jvmarg value="-Dappdir=${basedir}/../spark" /> </java> </target> </project>
<target name="compile" description="Compiles plugin source"> <mkdir dir="${classes.dir}"/> <javac srcdir="${src.dir}" destdir="${classes.dir}" classpathref="lib.classpath" source="1.4" debug="true" target="1.4"/> <copy todir="${classes.dir}"> <fileset dir="${src.dir}" includes="**/*.png"/> <fileset dir="${src.dir}" includes="**/*.gif"/> <fileset dir="${src.dir}" includes="**/*.jpg"/> <fileset dir="${src.dir}" includes="**/*.jpeg"/> </copy> </target>
基本配置都不用改,只需将1.4改为1.7(根据自己安装的JDK版本)即可。
然后选择Window ——> Show View ——> Ant ——> Add Buildfiles
加入Sparkplug/builder/build/build.xml,双击sparkplugs
看到控制台BUILD SUCCESSFUL,就好了~
目录Sparkplug/builder下的myplugin.jar 就是打包成功后的插件了,如果要直接使用的话,只需将其拷贝进spark软件目录下plugins文件夹中就可以了。
不要直接运行!
右键项目 Run As ——> Run Configurations
创建一个Java Application
Main:
Project:选择当前项目Sparkplug
MainClass:org.jivesoftware.launcher.Startup
建议勾上Stop in Main
Arguments:
VM arguments:
-Dplugin="${workspace_loc:Sparkplug}\builder\target\plugin.xml"
-Djava.library.path=spark/lib/windows64(根据自己的系统选择)
ClassPath:
User Entries ——> Advanced Options ——> Add Foldes 选择 Sparkplug/spark/resources
Common:
勾选Debug、Run
点击Run。
可能会报如下错误:
Exception in thread "main" java.lang.SecurityException: no manifiest section for signature file entry org/bouncycastle/asn1/ocsp/ResponderID.class at sun.security.util.SignatureFileVerifier.verifySection(SignatureFileVerifier.java:377) at sun.security.util.SignatureFileVerifier.processImpl(SignatureFileVerifier.java:231) at sun.security.util.SignatureFileVerifier.process(SignatureFileVerifier.java:176) at java.util.jar.JarVerifier.processEntry(JarVerifier.java:234) at java.util.jar.JarVerifier.update(JarVerifier.java:188) at java.util.jar.JarFile.initializeVerifier(JarFile.java:321) at java.util.jar.JarFile.getInputStream(JarFile.java:386) at sun.misc.URLClassPath$JarLoader$2.getInputStream(URLClassPath.java:689) at sun.misc.Resource.cachedInputStream(Resource.java:59) at sun.misc.Resource.getByteBuffer(Resource.java:154) at java.net.URLClassLoader.defineClass(URLClassLoader.java:249) at java.net.URLClassLoader.access$000(URLClassLoader.java:56) at java.net.URLClassLoader$1.run(URLClassLoader.java:195) at java.security.AccessController.doPrivileged(Native Method) at java.net.URLClassLoader.findClass(URLClassLoader.java:188) at java.lang.ClassLoader.loadClass(ClassLoader.java:306) at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:276) at java.lang.ClassLoader.loadClass(ClassLoader.java:251) at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:319) at com.buybal.testmer.servlet.test.main(test.java:40)
第一种方法:
在本地找到spark/lib/base.jar,以winrar打开(注意不要解压缩),删除META_INF文件夹下除了MANIFEST.MF外的所有东西
然后关闭WINRAR!