Webarchive packageing prepared for including IoC metadata descriptors

- including configured IoC descriptors in war distribution
	- improved dependency fetching (on demand)
	- fixed some spelling errors

Hessian Webservice support
	- created hessian servlet as a generic http interface for provided services
	- Interface def., Impl. and Tests
	- services can be exposed via HessianSkeletonProvider by defining a mapping key, Interface and an implementation instance.

git-svn-id: https://svn.apache.org/repos/asf/lucene/java/trunk@474244 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Simon Willnauer 2006-11-13 10:51:04 +00:00
parent ebf6f78719
commit 5627c6201c
19 changed files with 853 additions and 45 deletions

View File

@ -12,4 +12,18 @@ Build management (Ant)
2. Changed build management to create core and IoC / DI container jars to enable replacement of the container impl.
- created default IoC container build in ./gdata-build/hivemind-build.xml
3. Webarchive packageing prepared for including IoC metadata descriptors
- including configured IoC descriptors in war distribution
- improved dependency fetching (on demand)
- fixed some spelling errors
New Features
1. Hessian Webservice support
- created hessian servlet as a generic http interface for provided services
- services can be exposed via HessianSkeletonProvider by defining a mapping key, Interface and an implementation instance.

View File

@ -52,9 +52,8 @@
<!-- redefine compile-core and compile-test to exclude 3rd party dependend sources -->
<target name="compile-core" depends="init">
<target name="compile-core" depends="init, build-dependencies">
<echo>Use gdata - compile-core task </echo>
<antcall target="build-dependencies" />
<compile srcdir="src/java" destdir="${build.dir}/classes/java">
<classpath>
<path refid="classpath"/>
@ -65,8 +64,7 @@
<antcall target="compile-IoC-container"/>
</target>
<target name="compile-test" depends="compile-core">
<antcall target="test-dependencies" />
<target name="compile-test" depends="compile-core, test-dependencies">
<echo>Use gdata - compile-test task </echo>
<compile srcdir="src/test" destdir="${build.dir}/classes/test">
<classpath>
@ -89,9 +87,8 @@
<mkdir dir="${dist.dir}" />
</target>
<target name="war-gdata" depends="prepare-dist">
<target name="war-gdata" depends="prepare-dist,run-dependencies">
<echo>Distributing GData War </echo>
<antcall target="run-dependencies" />
<war destfile="${dist.dir}/${gdata.war.name}.war" webxml="webroot/WEB-INF/web.xml">
<metainf dir="webroot/meta-inf" />
<fileset dir="webroot" defaultexcludes="true">
@ -99,6 +96,7 @@
<exclude name="meta-inf/" />
<exclude name="WEB-INF/web.xml" />
</fileset>
<fileset dir="${ioc.descriptors.dir}" excludes="${ioc.descriptors.excludes}" includes="${ioc.descriptors.includes}"/>
<lib dir="${gdata.lib.dir}">
<include name="commons-logging-1.1.jar" />
<include name="gdata-client-1.0.jar" />
@ -108,18 +106,10 @@
<include name="nekohtml.jar" />
<include name="xercesImpl.jar" />
<include name="${db4o.jar}" if="db4o.jar.present" />
</lib>
<lib dir="${gdata.external.lib.dir}">
<include name="hivemind-1.1.jar" />
<include name="hivemind-jmx-1.1.jar" />
<include name="hivemind-lib-1.1.jar" />
<include name="javassist-3.0.jar"/>
<include name="oro-2.0.6.jar"/>
</lib>
<lib refid="ioc-container-jars"/>
<lib dir="${build.dir}" includes="${final.name}.jar" />
<lib dir="${build.dir}" includes="${ioc.container.jar}" />
<lib dir="${build.dir}" includes="${final.name}${ioc.container.jar.prefix}" />
<lib file="${lucene.jar}" />
</war>
</target>

View File

@ -17,13 +17,7 @@
<project name="dependency">
<target name="prepare">
<mkdir dir="${external.lib.dir}"/>
<ibiblio-dependency artifact="easymock" version="1.1" group="easymock" folder="easymock/1.1" use="run"/>
</target>
<target name="-display-download-warning" unless="download-warning-marker-displayed">
<target name="display-download-warning" unless="download-warning-marker-displayed">
<echo>
**************************************************************************************************
* *
@ -47,15 +41,15 @@
<attribute name="artifact" description="The name of the JAR artfiact to download." />
<attribute name="version" description="The version number of the artifact to download." />
<attribute name="group" description="The Maven group-id containing the JAR." />
<attribute name="use" default="compile" description="Useage of the dependency: compile, test or run. Subdirectory to place the artiface in." />
<attribute name="use" default="compile" description="Useage of the dependency: compile, test or run. Subdirectory to place the artifact in." />
<attribute name="folder" default="jars"/>
<attribute name="reposurl" default="http://www.ibiblio.org/maven2"/>
<sequential>
<mkdir dir="${gdata.external.lib.dir}" />
<antcall target="-display-download-warning" inheritAll="true"/>
<antcall target="display-download-warning" inheritAll="true"/>
<download-file dldest="${gdata.external.lib.dir}/@{artifact}-@{version}.jar" dlsrc="@{reposurl}/@{group}/@{folder}/@{artifact}-@{version}.jar" />
<property name="download-warning-marker-displayed" value="true"/>
</sequential>
</macrodef>

View File

@ -18,38 +18,45 @@
-->
<project name="get-dependencies">
<property name="repository.url.maven" value="http://www.ibiblio.org/maven"/>
<import file="dependency.xml"/>
<target name="run-dependencies">
<target name="run-dependencies" unless="run.dependencies.fetched" depends="common-dependencies">
<echo>Resolving dependencies for distribution / war build</echo>
<antcall target="common-dependencies"/>
<ibiblio-dependency artifact="oro" version="2.0.6" group="oro" reposurl="${repository.url.maven}"/>
<ibiblio-dependency artifact="javassist" version="3.0" group="javassist" reposurl="${repository.url.maven}"/>
<property name="run.dependencies.fetched" value="true"/>
</target>
<target name="common-dependencies">
<target name="common-dependencies" unless="common.dependencies.fetched">
<echo>Resolving common dependencies </echo>
<ibiblio-dependency artifact="hivemind" version="1.1" group="hivemind" reposurl="${repository.url.maven}"/>
<ibiblio-dependency artifact="hivemind-lib" version="1.1" group="hivemind" reposurl="${repository.url.maven}"/>
<ibiblio-dependency artifact="hivemind-jmx" version="1.1" group="hivemind" reposurl="${repository.url.maven}"/>
<ibiblio-dependency artifact="hessian" version="3.0.20" group="hessian" folder="download" reposurl="http://www.caucho.com"/>
<path id="common.build.path">
<fileset dir="${gdata.external.lib.dir}">
<include name="hivemind-1.1.jar"/>
<include name="hivemind-lib-1.1.jar"/>
<include name="hivemind-jmx-1.1.jar"/>
<include name="hessian-3.0.20.jar"/>
</fileset>
</path>
<property name="common.dependencies.fetched" value="true"/>
</target>
<target name="build-dependencies">
<antcall target="common-dependencies"/>
<target name="build-dependencies" unless="build.dependencies.fetched" depends="common-dependencies">
<echo>Resolving dependencies for build process</echo>
<path id="build.path">
<path refid="common.build.path"/>
</path>
<echo>Resolving dependencies for build process</echo>
<property name="build.dependencies.fetched" value="true"/>
</target>
<target name="test-dependencies">
<target name="test-dependencies" unless="test.dependencies.fetched">
<echo>Resolving dependencies for test cases</echo>
<ibiblio-dependency artifact="easymock" version="1.2_Java1.5" group="easymock" folder="easymock/1.2_Java1.5" />
<path id="test.build.path">
@ -57,6 +64,7 @@
<include name="easymock-1.2_Java1.5.jar"/>
</fileset>
</path>
<property name="test.dependencies.fetched" value="true"/>
</target>

View File

@ -16,21 +16,30 @@
limitations under the License.
-->
<project name="gdata-server-hivemind" >
<property name="ioc.container.jar" value="${final.name}-hivemind.jar"/>
<property name="ioc.container.jar.prefix" value="-hivemind.jar"/>
<property name="ioc.descriptors.dir" value="./src/hivemind/descriptor"/>
<property name="ioc.descriptors.excludes" value=""/>
<property name="ioc.descriptors.includes" value="**/*.xml"/>
<description>
Compiles and Jars the hivemind dependencies for gdata-server
</description>
<target name="prepare-IoC-container">
<available file="${build.dir}/${final.name}.jar" property="gdata.core.jar.present"/>
<fail unless="${gdata.core.jar.present}" message="Must gdata core jar first. run build.xml - 'jar-core' task"/>
<fail if="${gdata.core.jar.present}" message="Must gdata core jar first. run build.xml - 'jar-core' task"/>
<path id="IoC.container.build.path">
<fileset dir="${build.dir}">
<include name="${final.name}.jar"/>
</fileset>
</path>
<fileset id="ioc-container-jars" dir="${gdata.external.lib.dir}">
<include name="hivemind-1.1.jar" />
<include name="hivemind-jmx-1.1.jar" />
<include name="hivemind-lib-1.1.jar" />
<include name="javassist-3.0.jar"/>
<include name="oro-2.0.6.jar"/>
<include name="hessian-3.0.20.jar"/>
</fileset>
</target>
<!-- redefine compile-core and compile-test to exclude 3rd party dependend sources -->
<target name="compile-IoC-container" depends="prepare-IoC-container">
@ -47,12 +56,12 @@
<target name="jar-IoC-container" depends="compile-IoC-container">
<echo>Jar IoC Container classes and metadata</echo>
<jar
destfile="${build.dir}/${ioc.container.jar}"
destfile="${build.dir}/${final.name}${ioc.container.jar.prefix}"
basedir="${build.dir}/classes/hivemind">
<manifest>
<attribute name="Created-By" value="Apache Jakarta"/>
<section name="org/apache/lucene/">
<attribute name="Specifica tion-Title" value="Lucene Search Engine"/>
<attribute name="Specification-Title" value="Lucene Search Engine"/>
<attribute name="Specification-Version" value="${version}"/>
<attribute name="Specification-Vendor" value="Lucene"/>
<attribute name="Implementation-Title" value="org.apache.lucene"/>

View File

@ -17,7 +17,6 @@
-->
<project name="gdata-ioc-container">
<import file="hivemind-build.xml"/>
<target name="compile-IoC-container"/>
<target name="jar-IoC-container" depends="compile-IoC-container"/>
<!-- specify your IOC container build file here -->
<import file="hivemind-build.xml"/>
</project>

View File

@ -0,0 +1,55 @@
<?xml version="1.0"?>
<!--
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<module id="gdata.hivemind.webservice" version="1.0.0" package="org.apache.lucene.gdata.hivemind.webservice">
<configuration-point id="WebserviceMapping">
Schema used to expose internal services as a webservice via the Hessian protocol.
The webservices are available via the HessianServiceServlet according to its mapping in the web.xml file
<schema>
<element name="webservice" key-attribute="serviceId">
<attribute name="serviceId" required="true" />
<attribute name="serviceInterface" required="true" translator="class" />
<attribute name="serviceImpl" required="true" translator="object"/>
<rules>
<create-object class="org.apache.lucene.gdata.hivemind.webservice.WebserviceMappingBean"/>
<read-attribute attribute="serviceInterface" property="serviceInterface"/>
<read-attribute attribute="serviceImpl" property="serviceImpl"/>
<invoke-parent method="addElement" />
</rules>
</element>
</schema>
</configuration-point>
<contribution configuration-id="WebserviceMapping">
<webservice serviceId="test" serviceInterface="test.ITest" serviceImpl="instance:test.TestImpl"/>
</contribution>
<service-point id="HessianSkeletonProvider" interface="HessianSkeletonProvider">
<invoke-factory>
<construct class="HessianSkeletonProviderImpl">
<set-configuration configuration-id="WebserviceMapping"
property="mapping" />
</construct>
</invoke-factory>
</service-point>
</module>

View File

@ -0,0 +1,78 @@
<?xml version="1.0"?>
<!--
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<module id="gdata.request" version="1.0.0" package="org.apache.lucene.gdata.servlet.handler">
<service-point id="FeedQueryHandler" interface="GDataRequestHandler">
<invoke-factory model="threaded">
<construct class="DefaultGetHandler">
</construct>
</invoke-factory>
</service-point>
<service-point id="FeedUpdateHandler" interface="GDataRequestHandler">
<invoke-factory model="threaded">
<construct class="DefaultUpdateHandler">
</construct>
</invoke-factory>
</service-point>
<service-point id="FeedDeleteHandler" interface="GDataRequestHandler">
<invoke-factory model="threaded">
<construct class="DefaultDeleteHandler">
</construct>
</invoke-factory>
</service-point>
<service-point id="FeedInsertHandler" interface="GDataRequestHandler">
<invoke-factory model="threaded">
<construct class="DefaultInsertHandler">
</construct>
</invoke-factory>
</service-point>
<configuration-point id="RequestHandlers">
<schema>
<element name="handler" key-attribute="name">
<attribute name="name" required="true" />
<attribute name="object" required="true"
translator="object" />
<rules>
<push-attribute attribute="object" />
<invoke-parent method="addElement" />
</rules>
</element>
</schema>
</configuration-point>
<contribution configuration-id="RequestHandlers">
<handler name="QueryHandler" object="service:FeedQueryHandler" />
<handler name="UpdateHandler" object="service:FeedUpdateHandler" />
<handler name="DeleteHandler" object="service:FeedDeleteHandler" />
<handler name="InsertHandler" object="service:FeedInsertHandler" />
</contribution>
<service-point id="RequestHandlerFactory" interface="RequestHandlerFactory">
<invoke-factory>
<construct class="org.apache.lucene.gdata.hivemind.servlet.HivemindRequestHandlerFactory">
<set-configuration configuration-id="RequestHandlers"
property="handlerMap" />
</construct>
</invoke-factory>
</service-point>
</module>

View File

@ -0,0 +1,30 @@
<?xml version="1.0"?>
<!--
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<module id="gdata" version="1.0.0"
package="org.apache.lucene.gdata">
The master module for the Apache Lucene GData-Server.
<dependency module-id="hivemind" version="1.1.0" />
<dependency module-id="hivemind.lib" version="1.1.0" />
<sub-module descriptor="hivemind-descriptors/gdata.hivemind.webservice.xml" />
<sub-module descriptor="hivemind-descriptors/gdata.request.xml" />
</module>

View File

@ -0,0 +1,71 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.lucene.gdata.hivemind.servlet;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.hivemind.Registry;
import org.apache.hivemind.servlet.HiveMindFilter;
import org.apache.lucene.gdata.hivemind.webservice.HessianServiceSkeletonInvoker;
import org.apache.lucene.gdata.hivemind.webservice.HessianSkeletonProvider;
/**
* Central Hessian servlet which provides access to all hessian exposed services
* via a single servlet.
*
* @author Simon Willnauer
*
*/
public class HessianServiceServlet extends HttpServlet {
/**
*
*/
private static final long serialVersionUID = 5519783120466089391L;
/**
* @see javax.servlet.http.HttpServlet#doPost(javax.servlet.http.HttpServletRequest,
* javax.servlet.http.HttpServletResponse)
*/
@Override
protected void doPost(HttpServletRequest arg0, HttpServletResponse arg1)
throws ServletException, IOException {
try {
HessianSkeletonProvider provider = getSkeletonProvider(arg0);
HessianServiceSkeletonInvoker invoker = provider
.getServiceSkeletonInvoker(arg0);
invoker.invoke(arg0, arg1);
} catch (Throwable e) {
throw new ServletException("Nested Exception occured -- Message: "
+ e.getMessage(), e);
}
}
private HessianSkeletonProvider getSkeletonProvider(
HttpServletRequest request) {
Registry reg = HiveMindFilter.getRegistry(request);
return (HessianSkeletonProvider) reg
.getService(HessianSkeletonProvider.class);
}
}

View File

@ -0,0 +1,41 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.lucene.gdata.hivemind.webservice;
import java.io.IOException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Internal invoker interface to support more than one version of the protocol. <b>Currently only Version 3.0.20 is supported.<b>
*
* @author Simon Willnauer
*
*/
public interface HessianServiceSkeletonInvoker {
/**
* @param arg0 - httpServletRequest to access the input stream for processing
* @param arg1 - httpServletResponse to access the output stream for processing
* @throws IOException - if reading or writeing causes an IOException
* @throws Throwable - if the Hessian Impl. causes an error
*/
public abstract void invoke(HttpServletRequest arg0, HttpServletResponse arg1)
throws IOException, Throwable;
}

View File

@ -0,0 +1,116 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.lucene.gdata.hivemind.webservice;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.caucho.hessian.io.AbstractHessianOutput;
import com.caucho.hessian.io.Hessian2Input;
import com.caucho.hessian.io.Hessian2Output;
import com.caucho.hessian.io.HessianOutput;
import com.caucho.hessian.io.SerializerFactory;
import com.caucho.hessian.server.HessianSkeleton;
/**
* Wrapps the hessian skeleton invokation logic.
* This is based on the protocol description of the hessian protocol
* @author Simon Willnauer
*
*/
class HessianServiceSkeletonInvokerImpl implements
HessianServiceSkeletonInvoker {
private static final Log LOG = LogFactory.getLog(HessianServiceSkeletonInvokerImpl.class);
private SerializerFactory serializerFactory;
private final HessianSkeleton skeleton;
/**
* Creates a new HessianServiceSkeletonInvoker
* @param skeleton - The skeleton instance to invoke to process the request
*
*/
HessianServiceSkeletonInvokerImpl(final HessianSkeleton skeleton) {
this.skeleton = skeleton;
}
/**
* @throws Throwable
* @see org.apache.lucene.gdata.hivemind.webservice.HessianServiceSkeletonInvoker#invoke(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
*/
public void invoke(HttpServletRequest arg0, HttpServletResponse arg1) throws Throwable {
InputStream inputStream = arg0.getInputStream();
OutputStream outputStream = arg1.getOutputStream();
/*
*This works only with hessian >= hessian-3.0.20!!
*but remember this is not a framework
*/
Hessian2Input hessianInput = new Hessian2Input(inputStream);
if (this.serializerFactory != null) {
hessianInput.setSerializerFactory(this.serializerFactory);
}
int code = hessianInput.read();
if (code != 'c') {
throw new IOException("expected 'c' in hessian input at " + code);
}
AbstractHessianOutput hessianOutput = null;
int major = hessianInput.read();
// useless read just get the stream in the right position.
int minor = hessianInput.read();
if (major >= 2) {
hessianOutput = new Hessian2Output(outputStream);
}
else {
hessianOutput = new HessianOutput(outputStream);
}
if (this.serializerFactory != null) {
hessianOutput.setSerializerFactory(this.serializerFactory);
}
try {
this.skeleton.invoke(hessianInput, hessianOutput);
} catch (Throwable e) {
LOG.error("Unexpected Exception thrown -- "+e.getMessage(),e);
throw e;
}
}
/**
* @return Returns the serializerFactory.
*/
public SerializerFactory getSerializerFactory() {
return this.serializerFactory;
}
/**
* @param serializerFactory The serializerFactory to set.
*/
public void setSerializerFactory(SerializerFactory serializerFactory) {
this.serializerFactory = serializerFactory;
}
}

View File

@ -0,0 +1,50 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.lucene.gdata.hivemind.webservice;
import javax.servlet.http.HttpServletRequest;
/**
* Serviceprovider for within hivemind configured services to expose as
* webservices. This SkeletonProvider will return the corresponding service to
* the given <code>HttpServletRequest</code>.
* <p>
* Services exported via this provider will be available via a Hessian service
* endpoint, accessible via a Hessian proxy
* </p>
* <p>
* Fo information on Hessian see: <a
* href="http://www.caucho.com/hessian">Hessian protocol</a>
* </p>
*
* @author Simon Willnauer
*
*/
public interface HessianSkeletonProvider {
/**
* Selects the configured Service according to the given request.
*
* @param arg0 -
* the current HttpServletRequest
* @return - a corresponding HessianServiceSkeletonInvoker
*/
HessianServiceSkeletonInvoker getServiceSkeletonInvoker(
HttpServletRequest arg0);
}

View File

@ -0,0 +1,109 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.lucene.gdata.hivemind.webservice;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import javax.servlet.http.HttpServletRequest;
import com.caucho.hessian.server.HessianSkeleton;
/**
* Simple provider implementation.
* @author Simon Willnauer
*
*/
public class HessianSkeletonProviderImpl implements HessianSkeletonProvider {
private Map<String, WebserviceMappingBean> mapping;
private ConcurrentHashMap<String, HessianSkeleton> skeletonCache = new ConcurrentHashMap<String, HessianSkeleton>();
/**
* Creates a new HessianSkeletonProviderImpl instance
*/
public HessianSkeletonProviderImpl() {
super();
}
/**
* The last part of the request URL is used to identify a configured service
* mapping.
*
* @param path -
* the servletrequest path info
* @return - the corresponding HessianSkeleton
*/
protected HessianSkeleton getMappingFromPath(String path) {
if (path.endsWith("/"))
path = path.substring(0, path.length() - 1);
String requestedService = path.substring(path.lastIndexOf("/") + 1);
HessianSkeleton retVal = this.skeletonCache.get(requestedService);
if (retVal == null) {
WebserviceMappingBean wsBean = this.mapping.get(requestedService);
if (wsBean == null)
throw new NoSuchServiceException();
if (!checkInterface(wsBean))
throw new RuntimeException(
"The configured webservice interface is not assignable from the corresponding service");
retVal = new HessianSkeleton(wsBean.getServiceImpl(), wsBean
.getServiceInterface());
/*
* rather create this service twice as synchronize the whole block
*/
this.skeletonCache.putIfAbsent(requestedService, retVal);
}
return retVal;
}
@SuppressWarnings("unchecked")
private boolean checkInterface(WebserviceMappingBean bean) {
return bean.getServiceInterface().isAssignableFrom(
bean.getServiceImpl().getClass());
}
/**
* @see org.apache.lucene.gdata.hivemind.webservice.HessianSkeletonProvider#getServiceSkeletonInvoker(javax.servlet.http.HttpServletRequest)
*/
public HessianServiceSkeletonInvoker getServiceSkeletonInvoker(
HttpServletRequest arg0) {
if (arg0 == null)
throw new IllegalArgumentException(
"HttpServletRequest must not be null");
HessianSkeleton mappingFromRequest = getMappingFromPath(arg0
.getPathInfo());
return new HessianServiceSkeletonInvokerImpl(mappingFromRequest);
}
/**
* @return Returns the mapping.
*/
public Map<String, WebserviceMappingBean> getMapping() {
return this.mapping;
}
/**
* @param mapping
* The mapping to set.
*/
public void setMapping(Map<String, WebserviceMappingBean> mapping) {
this.mapping = mapping;
}
}

View File

@ -0,0 +1,33 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.lucene.gdata.hivemind.webservice;
/**
* Service Exception thrown if the requested service is not registered or not available.
* @author Simon Willnauer
*
*/
public class NoSuchServiceException extends RuntimeException {
/**
*
*/
private static final long serialVersionUID = -3485216993407631494L;
}

View File

@ -0,0 +1,77 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.lucene.gdata.hivemind.webservice;
/**
* This class is a simple configuration bean to expose a certain service via a
* hessian webservice. The configuration requieres the classtype of the
* interface and an instance of a subclass to invoke the interface methodes.
* <p>
* This bean will be created by Hivemind for each configured service and will be
* passed to the
* {@link org.apache.lucene.gdata.hivemind.webservice.HessianSkeletonProvider}
* as a Map.
* </p>
*
* @author Simon Willnauer
*
*/
public class WebserviceMappingBean {
private Class serviceInterface;
private Object serviceImpl;
/**
* Bean constructor
*/
public WebserviceMappingBean() {
super();
}
/**
* @return Returns the serviceImpl.
*/
public Object getServiceImpl() {
return this.serviceImpl;
}
/**
* @param serviceImpl
* The serviceImpl to set.
*/
public void setServiceImpl(Object serviceImpl) {
this.serviceImpl = serviceImpl;
}
/**
* @return Returns the serviceInterface.
*/
public Class getServiceInterface() {
return this.serviceInterface;
}
/**
* @param serviceInterface
* The serviceInterface to set.
*/
public void setServiceInterface(Class serviceInterface) {
this.serviceInterface = serviceInterface;
}
}

View File

@ -0,0 +1,134 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.lucene.gdata.hivemind.webservice;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import junit.framework.TestCase;
import org.easymock.MockControl;
import com.caucho.hessian.server.HessianSkeleton;
/**
* @author Simon Willnauer
*
*/
public class HessianSkeletonProviderImplTest extends TestCase {
HessianSkeletonProviderImpl provider;
MockControl<HttpServletRequest> mockControl;
HttpServletRequest mockedRequest;
static String mapKey = "test";
static String testPathSuccess = "/endpoint/" + mapKey;
static String testPathFail = "/endpoint/fail";
private Map<String, WebserviceMappingBean> mapping;
protected void setUp() throws Exception {
this.mockControl = MockControl.createControl(HttpServletRequest.class);
this.mockedRequest = this.mockControl.getMock();
this.provider = new HessianSkeletonProviderImpl();
this.mapping = new HashMap<String, WebserviceMappingBean>();
WebserviceMappingBean bean = new WebserviceMappingBean();
bean.setServiceImpl(new TestService());
bean.setServiceInterface(Serializable.class);
this.mapping.put(mapKey, bean);
this.provider.setMapping(this.mapping);
}
protected void tearDown() throws Exception {
super.tearDown();
}
/*
* Test method for
* 'org.apache.lucene.gdata.hivemind.webservice.HessianSkeletonProviderImpl.getServiceSkeletonInvoker(HttpServletRequest)'
*/
public void testGetServiceSkeletonInvoker() {
this.mockControl.expectAndDefaultReturn(this.mockedRequest
.getPathInfo(), testPathSuccess);
this.mockControl.replay();
assertNotNull(this.provider
.getServiceSkeletonInvoker(this.mockedRequest));
this.mockControl.verify();
this.mockControl.reset();
this.mockControl.expectAndDefaultReturn(this.mockedRequest
.getPathInfo(), testPathFail);
this.mockControl.replay();
try {
assertNotNull(this.provider
.getServiceSkeletonInvoker(this.mockedRequest));
fail("Service should not be found");
} catch (NoSuchServiceException e) {
//
}
this.mockControl.verify();
this.mockControl.reset();
}
/**
*
*/
public void testGetMappingFromPath() {
try {
this.provider.getMappingFromPath(testPathFail);
fail("Service should not be found");
} catch (NoSuchServiceException e) {
//
}
HessianSkeleton retVal = this.provider
.getMappingFromPath(testPathSuccess);
assertNotNull(retVal);
HessianSkeleton retVal1 = this.provider
.getMappingFromPath(testPathSuccess + "/");
assertEquals(retVal, retVal1);
assertNotNull(retVal);
assertEquals(Serializable.class.getName(), retVal.getAPIClassName());
}
/**
*
*/
public void testVerifyInterfaceImpl() {
this.mapping.get(mapKey).setServiceImpl(new WebserviceMappingBean());
try {
this.provider.getMappingFromPath(testPathSuccess);
fail("Impl is not assignable to Interface");
} catch (RuntimeException e) {
//
}
}
private static class TestService implements Serializable {
// just for test case
}
}