Oct
源起
在 OSGi 原始的 R1 時代,Framework/Http/Log/Device Access 的部份就已經上場,這裡將試做 Http/Log 的部份,並使用 R4 的 Declarative Services 規格 org.osgi.service.component 來試驗。
規格書的 R4 Compendium V4.0.1 Specification 中 102 Http Service Specification 指的就是 org.osgi.service.http 這個部份,該部分實做可以參考 org.eclipse.equinox.http.HttpService。
如何用 Http Service
這裡建議使用 eclipse 來做,先建立一個空白標準 OSGi 專案,然後需要動到三個檔案,因為 eclipse PDE 尚未支援 Service-Component 的標籤,所以要自行到 MANIFEST 去填寫。
- META-INF/MANIFEST.MF (修改檔案 Service-Component point to component.xml)
- OSGI-INF/component.xml (新增檔案 implementation point to Component.java)
- Component.java (新增檔案 activate and deactivate methods)
META-INF/MANIFEST.MF
Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: HelloHttp Plug-in Bundle-SymbolicName: HelloHttp Bundle-Version: 1.0.0 Bundle-Localization: plugin Import-Package: javax.servlet;version="2.3.0", javax.servlet.http;version="2.3.0", org.osgi.framework;version="1.3.0", org.osgi.service.component;version="1.0.0", org.osgi.service.http;version="1.2.0", org.osgi.service.log;version="1.3.0" Service-Component: OSGI-INF/component.xml
OSGI-INF/component.xml
<?xml version="1.0" encoding="UTF-8"?>
<component name="hello.component">
<implementation class="hello.Component"/>
<reference name="LOG"
interface="org.osgi.service.log.LogService"
cardinality="1..1"
policy="static"/>
<reference name="HTTP"
interface="org.osgi.service.http.HttpService"
cardinality="0..1"
policy="dynamic"
bind="setHttp"
unbind="unsetHttp"/>
</component>
hello/Component.java
package hello;
import java.io.IOException;
import java.util.Date;
import java.util.Hashtable;
import javax.servlet.Servlet;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.osgi.service.component.ComponentContext;
import org.osgi.service.http.HttpService;
import org.osgi.service.http.NamespaceException;
import org.osgi.service.log.LogService;
public class Component {
LogService log;
HttpService http;
protected void activate(ComponentContext context) {
log = (LogService) context.locateService("LOG");
log.log(LogService.LOG_INFO, "#### Hello World");
}
protected void deactivate(ComponentContext context) {
log.log(LogService.LOG_INFO, "#### Goodbye World");
}
protected void setHttp(HttpService h) {
this.http = h;
this.registerServlet();
}
protected void unsetHttp(HttpService h) {
this.http.unregister("/haha");
this.http = null;
}
private void registerServlet() {
Hashtable initparams = new Hashtable();
initparams.put("name", "value");
Servlet myServlet = new HttpServlet() {
String name = "foo";
public void init(ServletConfig config) {
this.name = (String) config.getInitParameter("name");
}
public void doGet(HttpServletRequest req, HttpServletResponse rsp)
throws IOException {
String foo = req.getParameter("foo");
rsp.setContentType("text/html;charset=UTF-8");
StringBuilder sb = new StringBuilder();
sb.append("The init parameter : " + this.name);
sb.append("<BR/>");
sb.append("The foo parameter : " + foo);
sb.append("<BR/>");
sb.append("日期 : " + new Date());
sb.append("<BR/>");
// servlet 2.3 only
//Locale reqLocal = req.getLocale();
//sb.append("The country is :" + reqLocal.getCountry()).append("<BR/>");
//sb.append("The language is :" + reqLocal.getLanguage());
rsp.getWriter().println(sb.toString());
}
};
try {
http.registerServlet("/haha", myServlet, initparams,null);
} catch (ServletException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NamespaceException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
測試
先看看 bundle 以及 log 服務是否運作。 然後開 http://127.0.0.1/haha?foo=abc 看看,之後再關掉 http service。
osgi> ss
Framework is launched.
id State Bundle
0 ACTIVE system.bundle_3.3.0.v20060919
2 ACTIVE org.eclipse.equinox.ds_1.0.0.v20060828
4 ACTIVE org.eclipse.equinox.log_1.0.100.v20060717
6 ACTIVE org.eclipse.osgi.services_3.1.100.v20060918
12 ACTIVE HelloHttp_1.0.0
13 ACTIVE org.eclipse.equinox.http_1.0.100.v20060821
14 ACTIVE org.eclipse.equinox.servlet.api_1.0.0.v20060717
osgi> log
>Info [4] Log created; Log Size=100; Log Threshold=4 initial@reference:file:org.eclipse.equinox.log_1.0.100.v20060717.jar/
>Info [4] ServiceEvent REGISTERED {service.id=21}
>Info [4] ServiceEvent REGISTERED {service.id=22}
>Info [4] ServiceEvent REGISTERED {service.id=23}
>Info [4] BundleEvent STARTED initial@reference:file:org.eclipse.equinox.log_1.0.100.v20060717.jar/
>Info [6] BundleEvent STARTED initial@reference:file:org.eclipse.osgi.services_3.1.100.v20060918.jar/
>Info [12] #### Hello World initial@reference:file:../HelloLog/
>Info [12] BundleEvent STARTED initial@reference:file:../HelloLog/
>Info [13] ServiceEvent REGISTERED {service.id=24}
>Info [13] ServiceEvent REGISTERED {service.id=25}
>Info [13] ServiceEvent REGISTERED {service.id=26}
>Info [13] BundleEvent STARTED initial@reference:file:org.eclipse.equinox.http_1.0.100.v20060821.jar/
>Info [14] BundleEvent STARTED initial@reference:file:org.eclipse.equinox.servlet.api_1.0.0.v20060717.jar/
>Info [0] FrameworkEvent STARTLEVEL CHANGED System Bundle
osgi> stop 13
osgi> log
>Info [13] ServiceEvent UNREGISTERING {service.id=25}
>Info [13] ServiceEvent UNREGISTERING {service.id=26}
>Info [13] ServiceEvent UNREGISTERING {service.id=24}
>Info [13] BundleEvent STOPPED initial@reference:file:org.eclipse.equinox.http_1.0.100.v20060821.jar/
網路上找個新的 Http Service 來換。
osgi> install http://www.knopflerfish.org/repo/jars/http/http_all-2.0.0.jar
Bundle id is 15
osgi> ss
Framework is launched.
id State Bundle
0 ACTIVE system.bundle_3.3.0.v20060919
2 ACTIVE org.eclipse.equinox.ds_1.0.0.v20060828
4 ACTIVE org.eclipse.equinox.log_1.0.100.v20060717
6 ACTIVE org.eclipse.osgi.services_3.1.100.v20060918
12 ACTIVE HelloHttp_1.0.0
13 RESOLVED org.eclipse.equinox.http_1.0.100.v20060821
14 ACTIVE org.eclipse.equinox.servlet.api_1.0.0.v20060717
15 INSTALLED org.knopflerfish.bundle.http_2.0.0
osgi> start 15
osgi> ss
Framework is launched.
id State Bundle
0 ACTIVE system.bundle_3.3.0.v20060919
2 ACTIVE org.eclipse.equinox.ds_1.0.0.v20060828
4 ACTIVE org.eclipse.equinox.log_1.0.100.v20060717
6 ACTIVE org.eclipse.osgi.services_3.1.100.v20060918
12 ACTIVE HelloHttp_1.0.0
13 RESOLVED org.eclipse.equinox.http_1.0.100.v20060821
14 ACTIVE org.eclipse.equinox.servlet.api_1.0.0.v20060717
15 ACTIVE org.knopflerfish.bundle.http_2.0.0
osgi> log
>Info [15] BundleEvent INSTALLED http://www.knopflerfish.org/repo/jars/http/http_all-2.0.0.jar
>Info [15] BundleEvent RESOLVED http://www.knopflerfish.org/repo/jars/http/http_all-2.0.0.jar
>Info [15] ServiceEvent REGISTERED {service.id=27}
>Info [15] No CM present, using default configuration http://www.knopflerfish.org/repo/jars/http/http_all-2.0.0.jar
>Debug [15] Updated pid=org.knopflerfish.bundle.http.factory.HttpServer.default http://www.knopflerfish.org/repo/jars/http/http_all-2.0.0.jar
>Debug [15] create pid=org.knopflerfish.bundle.http.factory.HttpServer.default http://www.knopflerfish.org/repo/jars/http/http_all-2.0.0.jar
>Debug [15] Creating socket http://www.knopflerfish.org/repo/jars/http/http_all-2.0.0.jar
>Info [15] HTTP server started on port 8080 http://www.knopflerfish.org/repo/jars/http/http_all-2.0.0.jar
>Info [15] ServiceEvent REGISTERED {service.id=28}
>Info [15] BundleEvent STARTED http://www.knopflerfish.org/repo/jars/http/http_all-2.0.0.jar
>Debug [15] Alias "/haha" was registered by bundle 12 http://www.knopflerfish.org/repo/jars/http/http_all-2.0.0.jar
再測一次看看。