mirror of https://github.com/apache/lucene.git
LUCENE-1055: Remove gdata from trunk.
git-svn-id: https://svn.apache.org/repos/asf/lucene/java/trunk@596501 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
e395be3faf
commit
b04703fe8f
|
@ -1,4 +1,4 @@
|
|||
Lucene Change Log
|
||||
Lucene Change Log
|
||||
$Id$
|
||||
|
||||
======================= Trunk (not yet released) =======================
|
||||
|
@ -283,6 +283,9 @@ Build
|
|||
|
||||
5. LUCENE-1051: Include javadocs in the maven artifacts. (Michael Busch)
|
||||
|
||||
6. LUCENE-1055: Remove gdata-server from build files and its sources
|
||||
from trunk. (Michael Busch)
|
||||
|
||||
Test Cases
|
||||
|
||||
======================= Release 2.2.0 2007-06-19 =======================
|
||||
|
|
17
build.xml
17
build.xml
|
@ -217,16 +217,6 @@
|
|||
|
||||
<target name="javadocs-all" description="Generate javadoc for core, demo and contrib classes" depends="build-contrib">
|
||||
<sequential>
|
||||
<dirset dir="contrib/gdata-server/src/core/src/java" id="gdata-server-core">
|
||||
<include name="**" if="build-1-5-contrib" />
|
||||
</dirset>
|
||||
<dirset dir="contrib/gdata-server/src/gom/src/java" id="gdata-server-gom">
|
||||
<include name="**" if="build-1-5-contrib" />
|
||||
</dirset>
|
||||
<dirset dir="contrib/gdata-server/src/hivemind/src/java" id="gdata-server-hivemind">
|
||||
<include name="**" if="build-1-5-contrib" />
|
||||
</dirset>
|
||||
|
||||
<mkdir dir="${javadoc.dir}"/>
|
||||
<invoke-javadoc
|
||||
destdir="${javadoc.dir}">
|
||||
|
@ -237,9 +227,8 @@
|
|||
<packageset dir="src/demo"/>
|
||||
|
||||
<!-- please keep this list up to date, and in alpha order... -->
|
||||
<!-- with the minor exception of gdata which is managed by ref -->
|
||||
|
||||
<!-- ie: `find contrib/* -path \*src/java | grep -v gdata | sort` -->
|
||||
<!-- ie: `find contrib/* -path \*src/java | sort` -->
|
||||
|
||||
<!-- if you make changes to the list of package sets, also -->
|
||||
<!-- make sure the group list below is updated. -->
|
||||
|
@ -264,9 +253,6 @@
|
|||
<packageset dir="contrib/wordnet/src/java"/>
|
||||
<packageset dir="contrib/xml-query-parser/src/java"/>
|
||||
<!-- end alpha sort -->
|
||||
<packageset refid="gdata-server-core" />
|
||||
<packageset refid="gdata-server-gom" />
|
||||
<packageset refid="gdata-server-hivemind" />
|
||||
|
||||
<!-- If the main javadoc Group listing includes an "Other -->
|
||||
<!-- Packages" group after the ones listed here, then those -->
|
||||
|
@ -281,7 +267,6 @@
|
|||
<group title="contrib: Benchmark" packages="org.apache.lucene.benchmark*"/>
|
||||
<group title="contrib: DB" packages="org.apache.lucene.store.db*:org.apache.lucene.store.je*:com.sleepycat*"/>
|
||||
<group title="contrib: Highlighter" packages="org.apache.lucene.search.highlight*"/>
|
||||
<group title="contrib: GData Server (Java1.5)" packages="org.apache.lucene.gdata.*"/>
|
||||
<group title="contrib: Lucli" packages="lucli*"/>
|
||||
<group title="contrib: Memory" packages="org.apache.lucene.index.memory*"/>
|
||||
<group title="contrib: Miscellaneous " packages="org.apache.lucene.misc*:org.apache.lucene.queryParser.analyzing*:org.apache.lucene.queryParser.precedence*"/>
|
||||
|
|
|
@ -56,11 +56,6 @@
|
|||
<path id="javadoc.classpath">
|
||||
<path refid="classpath"/>
|
||||
<pathelement location="${ant.home}/lib/ant.jar"/>
|
||||
|
||||
<!-- NOTE: gdata jars only used with jdk 5 but include them even for lower jdk -->
|
||||
<fileset dir="${common.dir}/contrib">
|
||||
<include name="**/*.jar"/>
|
||||
</fileset>
|
||||
</path>
|
||||
|
||||
<property name="project.name" value="site"/> <!-- todo: is this used by anakia or something else? -->
|
||||
|
@ -537,3 +532,4 @@
|
|||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -1,41 +0,0 @@
|
|||
Lucene GData-Server change log
|
||||
|
||||
$Id:$
|
||||
|
||||
trunk (not yet release)
|
||||
|
||||
Build management (Ant)
|
||||
1. Changes to fetch third-party libs via maven repository
|
||||
- Added build file folder ./gdata-build
|
||||
- created macroes to fetch jar files in ./gdata-build/dependencies.xml
|
||||
- created tasks to fetch runtime, build and test relevant jar files in ./gdata-build/get-dependencies.xml
|
||||
|
||||
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
|
||||
|
||||
4. Changed project structure
|
||||
- Applied new structure of the gdata-server project.
|
||||
- All source and test-sources are located under the ./src/ folder.
|
||||
- Created GData Object Model (GOM) folder ./src/gom, Core-Folder ./src/core and ./src/hivemind
|
||||
- Sources and Tests now splitted into their "sub" projects.
|
||||
|
||||
|
||||
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.
|
||||
|
||||
2. GData Object Model
|
||||
- The GOM will replace the Google Client API as a internal and extensible object representation.
|
||||
- GOM provides a easier extension mechanimn for creating custom GData feeds and entries
|
||||
|
||||
Bug Fixes
|
||||
|
||||
1. LUCENE-1005: DateFormater (sic) was not properly formatting dates on certain machines (lucene.zones.a.o). Added a
|
||||
setTimeZone() call after the instantiation of the DateFormat to set the TimeZone to GMT. (Chris Hostetter, Mike McCandless, Grant Ingersoll)
|
|
@ -1,134 +0,0 @@
|
|||
<?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.
|
||||
|
||||
-->
|
||||
|
||||
<project name="gdata-server" default="default">
|
||||
<description>
|
||||
Serverside Google Data API implementation
|
||||
</description>
|
||||
<!-- NOTE: attempting to import ../contrib-build.xml or
|
||||
../../common-build.xml breaks everything
|
||||
whole build file should be cleaned up later if possible
|
||||
-->
|
||||
<condition property="build-1-5-contrib">
|
||||
<equals arg1="1.5" arg2="${ant.java.version}" />
|
||||
</condition>
|
||||
|
||||
<import file="gdata-build/get-dependencies.xml" />
|
||||
<property name="javac.source" value="1.5" />
|
||||
<property name="javac.target" value="1.5" />
|
||||
|
||||
<property name="gdata.lib.dir" value="lib" />
|
||||
<property name="gdata.external.lib.dir" value="./ext-libs" />
|
||||
<property name="db4o.jar" value="db4o-5.5-java5.jar" />
|
||||
<!-- properties for war task -->
|
||||
<property name="ioc.descriptors.dir" value="./src/hivemind/descriptor" />
|
||||
<property name="ioc.descriptors.excludes" value="" />
|
||||
<property name="ioc.descriptors.includes" value="**/*.xml" />
|
||||
|
||||
<property name="gdata.war.name" value="gdata-server" />
|
||||
|
||||
<property name="jar.name.core" value="lucene-core-${version}" />
|
||||
<property name="jar.name.gom" value="lucene-gom-${version}" />
|
||||
<property name="jar.name.hivemind" value="lucene-hivemind-${version}" />
|
||||
|
||||
<fileset id="hivemind.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>
|
||||
|
||||
<fileset id="gom.jars" dir="${gdata.external.lib.dir}">
|
||||
<include name="stax-1.1.2-dev.jar" />
|
||||
<include name="stax-api-1.0.1.jar" />
|
||||
</fileset>
|
||||
|
||||
|
||||
<!-- set property for third party jars -->
|
||||
<available property="db4o.jar.present" type="file" file="${gdata.external.lib.dir}/${db4o.jar}" value="test" />
|
||||
<condition property="junit.excludes" value="**/db4o/**/*.java">
|
||||
<not>
|
||||
<isset property="db4o.jar.present" />
|
||||
</not>
|
||||
</condition>
|
||||
|
||||
<condition property="do.download">
|
||||
<not>
|
||||
<and>
|
||||
<available file="${gdata.external.lib.dir}/stax-api-1.0.1.jar" />
|
||||
<available file="${gdata.external.lib.dir}/stax-1.1.2-dev.jar" />
|
||||
<available file="${gdata.external.lib.dir}/hivemind-1.1.jar" />
|
||||
<available file="${gdata.external.lib.dir}/hivemind-lib-1.1.jar" />
|
||||
<available file="${gdata.external.lib.dir}/hivemind-jmx-1.1.jar" />
|
||||
<available file="${gdata.external.lib.dir}/hessian-3.0.20.jar" />
|
||||
<available file="${gdata.external.lib.dir}/easymock-1.2_Java1.5.jar" />
|
||||
<available file="${gdata.external.lib.dir}/oro-2.0.6.jar" />
|
||||
</and>
|
||||
</not>
|
||||
</condition>
|
||||
<target name="jar-core" description="Packages the JAR file" depends="init" if="build-1-5-contrib">
|
||||
<ant dir="src/core" target="jar-core" inheritRefs="true" />
|
||||
<ant dir="src/hivemind" target="jar-core" inheritRefs="true" />
|
||||
<ant dir="src/gom" target="jar-core" inheritRefs="true" />
|
||||
</target>
|
||||
|
||||
<target name="test" depends="compile-test" if="build-1-5-contrib">
|
||||
<ant dir="src/core" target="test" inheritRefs="true" />
|
||||
<ant dir="src/gom" target="test" inheritRefs="true" />
|
||||
<ant dir="src/hivemind" target="test" inheritRefs="true" />
|
||||
</target>
|
||||
|
||||
<target name="compile-core" depends="init,download" if="build-1-5-contrib">
|
||||
<ant dir="src/core" target="compile-core" inheritRefs="true" />
|
||||
<ant dir="src/hivemind" target="compile-core" inheritRefs="true" />
|
||||
<ant dir="src/gom" target="compile-core" inheritRefs="true" />
|
||||
</target>
|
||||
|
||||
<target name="compile-test" depends="init,compile-core,download" if="build-1-5-contrib">
|
||||
<ant dir="src/core" target="compile-test" inheritRefs="true" />
|
||||
<ant dir="src/hivemind" target="compile-test" inheritRefs="true" />
|
||||
<ant dir="src/gom" target="compile-test" inheritRefs="true" />
|
||||
</target>
|
||||
|
||||
<target name="clean" depends="init" if="build-1-5-contrib">
|
||||
<ant dir="src/core" target="clean" inheritRefs="true" />
|
||||
<ant dir="src/hivemind" target="clean" inheritRefs="true" />
|
||||
<ant dir="src/gom" target="clean" inheritRefs="true" />
|
||||
</target>
|
||||
|
||||
<target name="war-gdata" depends="init,clean,jar-core" if="build-1-5-contrib">
|
||||
<ant dir="src/core" target="war-gdata" inheritRefs="true" />
|
||||
</target>
|
||||
|
||||
<target name="default" description="default" depends="init,download" if="build-1-5-contrib">
|
||||
<ant dir="src/core" target="default" inheritRefs="true" />
|
||||
<ant dir="src/hivemind" target="default" inheritRefs="true" />
|
||||
<ant dir="src/gom" target="default" inheritRefs="true" />
|
||||
</target>
|
||||
|
||||
<target name="init" depends="check-1-5" />
|
||||
<target name="check-1-5" unless="build-1-5-contrib" >
|
||||
<echo>Java 1.5 support not availabble (or prohibited by explicitly set property) ... skipping task</echo>
|
||||
</target>
|
||||
|
||||
<target name="build-artifacts-and-tests" depends="default,compile-test" />
|
||||
<target name="dist-maven"/>
|
||||
</project>
|
|
@ -1,64 +0,0 @@
|
|||
<?xml version="1.0"?>
|
||||
<!--
|
||||
Copyright 2004, 2005 The Apache Software Foundation
|
||||
|
||||
Licensed 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.
|
||||
-->
|
||||
|
||||
<project name="dependency">
|
||||
|
||||
<target name="display-download-warning" unless="download-warning-marker-displayed">
|
||||
<echo>
|
||||
**************************************************************************************************
|
||||
* *
|
||||
* D O W N L O A D W A R N I N G *
|
||||
* *
|
||||
* Dependent libraries will be downloaded. These are NOT necessarily downloaded from apache.org, *
|
||||
* and may use other licences besides the Apache Software License. Dependencies will use an *
|
||||
* open-source license compatible with the ASL, such as Berkeley Software Distribution (BSD) or *
|
||||
* Mozilla Public License (MPL). *
|
||||
* *
|
||||
**************************************************************************************************
|
||||
</echo>
|
||||
<!-- <input
|
||||
validargs="continue"
|
||||
message="Enter 'continue' to continue with the build:"/>
|
||||
|
||||
<mkdir dir="${external.package.dir}"/>
|
||||
<echo file="${download-warning-marker.file}">Download warning accepted.</echo>-->
|
||||
</target>
|
||||
<macrodef name="ibiblio-dependency">
|
||||
<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 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"/>
|
||||
<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>
|
||||
|
||||
<macrodef name="download-file">
|
||||
<attribute name="dlsrc" description="The URL of the file to download." />
|
||||
<attribute name="dldest" description="The directory and file to copy to." />
|
||||
<sequential>
|
||||
<get src="@{dlsrc}" dest="@{dldest}" verbose="true" usetimestamp="true" ignoreerrors="true" />
|
||||
</sequential>
|
||||
</macrodef>
|
||||
</project>
|
|
@ -1,58 +0,0 @@
|
|||
<?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.
|
||||
|
||||
-->
|
||||
|
||||
<project name="get-dependencies">
|
||||
<property name="repository.url.maven" value="http://www.ibiblio.org/maven" />
|
||||
<import file="dependency.xml" />
|
||||
<target name="extBuildPath">
|
||||
<echo>Preparing build path for external dependencies</echo>
|
||||
|
||||
<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>
|
||||
<path id="build.path">
|
||||
<path refid="common.build.path" />
|
||||
</path>
|
||||
|
||||
<path id="test.build.path">
|
||||
<fileset dir="${gdata.external.lib.dir}">
|
||||
<include name="easymock-1.2_Java1.5.jar" />
|
||||
</fileset>
|
||||
<path refid="common.build.path" />
|
||||
</path>
|
||||
</target>
|
||||
|
||||
<target name="download" if="do.download" depends="extBuildPath">
|
||||
<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" />
|
||||
<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}" />
|
||||
<ibiblio-dependency artifact="easymock" version="1.2_Java1.5" group="easymock" folder="easymock/1.2_Java1.5" />
|
||||
<ibiblio-dependency artifact="stax" version="1.1.2-dev" group="stax" folder="jars" reposurl="http://dist.codehaus.org" />
|
||||
<ibiblio-dependency artifact="stax-api" version="1.0.1" group="stax" folder="jars" reposurl="http://dist.codehaus.org" />
|
||||
</target>
|
||||
|
||||
</project>
|
|
@ -1,2 +0,0 @@
|
|||
AnyObjectId[b1b89c9c921f16af22a88db3ff28975a8e40d886] was removed in git history.
|
||||
Apache SVN contains full history.
|
|
@ -1,2 +0,0 @@
|
|||
AnyObjectId[75580be255065727b20b41c2d338b14792bb35cd] was removed in git history.
|
||||
Apache SVN contains full history.
|
|
@ -1,2 +0,0 @@
|
|||
AnyObjectId[1783dbea232ced6db122268f8faa5ce773c7ea42] was removed in git history.
|
||||
Apache SVN contains full history.
|
|
@ -1,2 +0,0 @@
|
|||
AnyObjectId[2ff9bbd90d63f92cdffea944869ed9bea7ead49c] was removed in git history.
|
||||
Apache SVN contains full history.
|
|
@ -1,2 +0,0 @@
|
|||
AnyObjectId[311a546765c97a9bc9e60f4c56da07f1246ab3da] was removed in git history.
|
||||
Apache SVN contains full history.
|
|
@ -1,2 +0,0 @@
|
|||
AnyObjectId[dde9972109dd25f14f732052984b0d3719b17795] was removed in git history.
|
||||
Apache SVN contains full history.
|
|
@ -1,2 +0,0 @@
|
|||
AnyObjectId[ebd5b4b2a7a1d8b67c1717b364fb9affb35dca1e] was removed in git history.
|
||||
Apache SVN contains full history.
|
|
@ -1,2 +0,0 @@
|
|||
AnyObjectId[018d6effad3823d0ea59f1b58ab154fc2652f418] was removed in git history.
|
||||
Apache SVN contains full history.
|
|
@ -1,2 +0,0 @@
|
|||
AnyObjectId[33990e8a1fdf24e15701e4cf8d9f091038394ecd] was removed in git history.
|
||||
Apache SVN contains full history.
|
|
@ -1,110 +0,0 @@
|
|||
<?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.
|
||||
|
||||
-->
|
||||
<project name="gdata-core" default="default">
|
||||
|
||||
<description>
|
||||
Lucene gdata server core build file
|
||||
</description>
|
||||
|
||||
<path id="additional.dependencies">
|
||||
<fileset dir="../../${gdata.lib.dir}">
|
||||
<include name="servlet-api.jar" />
|
||||
<include name="commons-logging-1.1.jar" />
|
||||
<include name="gdata-client-1.0.jar" />
|
||||
<include name="commons-digester-1.7.jar" />
|
||||
<include name="commons-beanutils.jar" />
|
||||
<include name="commons-collections-3.2.jar" />
|
||||
<include name="nekohtml.jar" />
|
||||
<include name="xercesImpl.jar" />
|
||||
</fileset>
|
||||
<fileset dir="../../${gdata.external.lib.dir}">
|
||||
<include name="easymock-1.2_Java1.5.jar" />
|
||||
<include name="${db4o.jar}" if="db4o.jar.present" />
|
||||
</fileset>
|
||||
</path>
|
||||
<property name="build.dir" location="../../../../build/contrib/gdata-server/core" />
|
||||
<property name="dist.dir" location="../../../../dist/contrib/gdata-server/core" />
|
||||
|
||||
|
||||
|
||||
<!-- redefine compile-core and compile-test to exclude 3rd party dependend sources -->
|
||||
<target name="compile-core" depends="init">
|
||||
<echo>Use gdata - compile-core task </echo>
|
||||
<compile srcdir="src/java" destdir="${build.dir}/classes/java">
|
||||
<classpath>
|
||||
<path refid="classpath"/>
|
||||
<path refid="build.path"/>
|
||||
</classpath>
|
||||
<exclude name="org/apache/lucene/gdata/storage/db4o/**" unless="db4o.jar.present" />
|
||||
</compile>
|
||||
</target>
|
||||
|
||||
<target name="compile-test" depends="compile-core">
|
||||
<echo>Use gdata - compile-test task </echo>
|
||||
<compile srcdir="src/test" destdir="${build.dir}/classes/test">
|
||||
<classpath>
|
||||
<path refid="test.build.path"/>
|
||||
<path refid="test.classpath"/>
|
||||
</classpath>
|
||||
<exclude name="org/apache/lucene/gdata/storage/db4o/**" unless="db4o.jar.present" />
|
||||
</compile>
|
||||
<copy todir="${build.dir}/classes/test">
|
||||
<fileset dir="src/test" excludes="**/*.java" />
|
||||
</copy>
|
||||
</target>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<pathconvert property="project.classpath" targetos="unix" refid="additional.dependencies" />
|
||||
<import file="../../../contrib-build.xml" />
|
||||
|
||||
|
||||
|
||||
<target name="war-gdata" depends="jar-core">
|
||||
<echo>Distributing GData War </echo>
|
||||
<war destfile="${build.dir}/${gdata.war.name}.war" webxml="../../webroot/WEB-INF/web.xml">
|
||||
<metainf dir="../../webroot/meta-inf" />
|
||||
<fileset dir="../../webroot" defaultexcludes="true">
|
||||
<exclude name="meta-inf/context.xml" />
|
||||
<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" />
|
||||
<include name="commons-digester-1.7.jar" />
|
||||
<include name="commons-beanutils.jar" />
|
||||
<include name="commons-collections-3.2.jar" />
|
||||
<include name="nekohtml.jar" />
|
||||
<include name="xercesImpl.jar" />
|
||||
<include name="${db4o.jar}" if="db4o.jar.present" />
|
||||
</lib>
|
||||
<lib refid="hivemind.jars" />
|
||||
<lib refid="gom.jars" />
|
||||
<lib dir="${build.dir}" includes="${jar.name.core}.jar" />
|
||||
<lib dir="${build.dir}/../gom" includes="${jar.name.gom}.jar" />
|
||||
<lib dir="${build.dir}/../hivemind" includes="${jar.name.hivemind}.jar" />
|
||||
<lib file="${lucene.jar}" />
|
||||
</war>
|
||||
</target>
|
||||
|
||||
</project>
|
|
@ -1,340 +0,0 @@
|
|||
/**
|
||||
* Copyright 2004 The Apache Software Foundation
|
||||
*
|
||||
* Licensed 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.data;
|
||||
|
||||
import java.net.URL;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import com.google.gdata.data.Person;
|
||||
|
||||
/**
|
||||
* The GData-Server system provides acccount to be associated with registered
|
||||
* feed. Every feed has an owner account. The account holder is automaticaly in
|
||||
* role to modify his feeds. One account can own <i>n</i> feeds having <i>m</i>
|
||||
* entries.
|
||||
* <p>
|
||||
* Additionally an account can be in role to modify other feeds, create accounts
|
||||
* or feeds. See {@link AccountRole} for detailed infomation about roles. One
|
||||
* account can also have more than one role. All roles in {@link AccountRole}
|
||||
* can be combined
|
||||
* </p>
|
||||
* <p>
|
||||
* For each account values for author name, author email and author link can be
|
||||
* set at creation time or during an update. These values will be used as the
|
||||
* corresponding values for the feed
|
||||
* {@link org.apache.lucene.gdata.data.ServerBaseFeed#addAuthor(Person)} if no
|
||||
* value for the feed has be specified.
|
||||
* </p>
|
||||
*
|
||||
* @author Simon Willnauer
|
||||
*
|
||||
*/
|
||||
public class GDataAccount {
|
||||
private String name;
|
||||
|
||||
private String authorname;
|
||||
|
||||
private String authorMail;
|
||||
|
||||
private URL authorLink;
|
||||
|
||||
private String password;
|
||||
|
||||
private Set<AccountRole> roles = new HashSet<AccountRole>(4);
|
||||
|
||||
/**
|
||||
* Creates a new GDataAccount. The default role {@link AccountRole#USER}
|
||||
* will be set.
|
||||
*
|
||||
*/
|
||||
public GDataAccount() {
|
||||
this.roles.add(AccountRole.USER);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @return - the password
|
||||
*/
|
||||
public String getPassword() {
|
||||
return this.password;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param password -
|
||||
* the account Password
|
||||
*/
|
||||
public void setPassword(String password) {
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return - the account name
|
||||
*/
|
||||
public String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param name
|
||||
* The name to set.
|
||||
*/
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return - the http link specified for the author
|
||||
*/
|
||||
public URL getAuthorLink() {
|
||||
return this.authorLink;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param authorLink -
|
||||
* the http link specified for the author
|
||||
*/
|
||||
public void setAuthorLink(URL authorLink) {
|
||||
this.authorLink = authorLink;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return - the authors mail address
|
||||
*/
|
||||
public String getAuthorMail() {
|
||||
return this.authorMail;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param authorMail -
|
||||
* the authors mail address
|
||||
*/
|
||||
public void setAuthorMail(String authorMail) {
|
||||
this.authorMail = authorMail;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return - the name specified as being the author name
|
||||
*/
|
||||
public String getAuthorname() {
|
||||
return this.authorname;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param authorname -
|
||||
* the name specified as being the author name
|
||||
*/
|
||||
public void setAuthorname(String authorname) {
|
||||
this.authorname = authorname;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the given role to the role list
|
||||
*
|
||||
* @param role -
|
||||
* the role to add to the role list
|
||||
*/
|
||||
public void setRole(AccountRole role) {
|
||||
if (role == null)
|
||||
return;
|
||||
this.roles.add(role);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return - the set containing all roles
|
||||
*/
|
||||
public Set<AccountRole> getRoles() {
|
||||
return this.roles;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param role -
|
||||
* the role to check
|
||||
* @return <code>true</code> if the role list contains the given role
|
||||
*/
|
||||
public boolean isUserInRole(AccountRole role) {
|
||||
if (role == null)
|
||||
return false;
|
||||
return this.roles.contains(role);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see GDataAccount#setRolesAsInt(int)
|
||||
* @return - the integer representation for the user roles
|
||||
*/
|
||||
public int getRolesAsInt() {
|
||||
// 1 as the Userrole is always set
|
||||
int bits = 1;
|
||||
for (AccountRole role : this.roles) {
|
||||
if (role == AccountRole.ENTRYAMINISTRATOR)
|
||||
bits ^= 2;
|
||||
else if (role == AccountRole.FEEDAMINISTRATOR)
|
||||
bits ^= 4;
|
||||
else if (role == AccountRole.USERADMINISTRATOR)
|
||||
bits ^= 8;
|
||||
|
||||
}
|
||||
return bits;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the roles from a int representation.
|
||||
* <ol>
|
||||
* <li>The fist bit set indicates a {@link AccountRole#USER} - int value 1</li>
|
||||
* <li>The second bit set indicates a {@link AccountRole#ENTRYAMINISTRATOR} -
|
||||
* int value 2</li>
|
||||
* <li>The third bit set indicates a {@link AccountRole#FEEDAMINISTRATOR} -
|
||||
* int value 4</li>
|
||||
* <li>The forth bit set indicates a {@link AccountRole#USERADMINISTRATOR} -
|
||||
* int value 8</li>
|
||||
* <ol>
|
||||
* This method will only set roles, will not remove roles! A combination of
|
||||
* roles is also possible e.g. the int value 6 combines
|
||||
* {@link AccountRole#ENTRYAMINISTRATOR} and
|
||||
* {@link AccountRole#FEEDAMINISTRATOR}.
|
||||
*
|
||||
* @param i -
|
||||
* the integer used to set the roles
|
||||
*/
|
||||
public void setRolesAsInt(int i) {
|
||||
|
||||
if ((i & 2) > 0)
|
||||
this.roles.add(AccountRole.ENTRYAMINISTRATOR);
|
||||
if ((i & 4) > 0)
|
||||
this.roles.add(AccountRole.FEEDAMINISTRATOR);
|
||||
if ((i & 8) > 0)
|
||||
this.roles.add(AccountRole.USERADMINISTRATOR);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.lang.Object#equals(java.lang.Object)
|
||||
*/
|
||||
public boolean equals(Object o) {
|
||||
if(this.name == null)
|
||||
return super.equals(o);
|
||||
if(o == null)
|
||||
return false;
|
||||
if (this == o)
|
||||
return true;
|
||||
if (!(o instanceof GDataAccount))
|
||||
return false;
|
||||
GDataAccount toCompare = (GDataAccount) o;
|
||||
if (this.name.equals(toCompare.name))
|
||||
return true;
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.lang.Object#hashCode()
|
||||
*/
|
||||
public int hashCode() {
|
||||
if(this.name == null)
|
||||
return super.hashCode();
|
||||
int ret = 37;
|
||||
ret = 9 * ret + this.name.hashCode();
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks the requiered values for creating an account are set. Required
|
||||
* values are <tt>name</tt> and <tt>password</tt> the minimum length of
|
||||
* these values is 6.
|
||||
*
|
||||
* @return <code>true</code> if an only if password and name are not <code>null</code> and the length is <tt>> 5</tt>
|
||||
*/
|
||||
public boolean requiredValuesSet() {
|
||||
return (this.name != null && this.password != null
|
||||
&& this.name.length() > 5 && this.password.length() > 5);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.lang.Object#toString()
|
||||
*/
|
||||
public String toString(){
|
||||
StringBuilder builder = new StringBuilder("GdataAccount: ");
|
||||
builder.append("name: ").append(this.name);
|
||||
builder.append(" password: ").append((this.password!= null?" length: "+this.password.length():null));
|
||||
builder.append(" author: ").append(this.authorname);
|
||||
builder.append(" author email: ").append(this.authorMail);
|
||||
builder.append(" author link: ").append(this.authorLink!=null?"":this.authorLink);
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* checks whether the given integer matches the account role.
|
||||
* @param intRole - integer representation of a role
|
||||
* @param role - the account role to match
|
||||
* @return <code>true</code> if and only if the given roles match, otherwise <code>false</code>
|
||||
*/
|
||||
public static boolean isInRole(int intRole, AccountRole role){
|
||||
if(role == AccountRole.USER)
|
||||
return (intRole&1)>0;
|
||||
if (role == AccountRole.ENTRYAMINISTRATOR)
|
||||
return (intRole&2) >0 ;
|
||||
else if (role == AccountRole.FEEDAMINISTRATOR)
|
||||
return (intRole&4) >0 ;
|
||||
else if (role == AccountRole.USERADMINISTRATOR)
|
||||
return (intRole&8) >0 ;
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return - a new Administrator account
|
||||
*/
|
||||
public static final GDataAccount createAdminAccount(){
|
||||
GDataAccount retVal = new GDataAccount();
|
||||
retVal.setName("administrator");
|
||||
retVal.setPassword("password");
|
||||
retVal.setRole(AccountRole.USERADMINISTRATOR);
|
||||
retVal.setRole(AccountRole.FEEDAMINISTRATOR);
|
||||
retVal.setRole(AccountRole.ENTRYAMINISTRATOR);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* This enum respesents all account roles an account can have.
|
||||
*
|
||||
* @author Simon Willnauer
|
||||
*
|
||||
*/
|
||||
public enum AccountRole {
|
||||
|
||||
/**
|
||||
* Can create / alter user
|
||||
*/
|
||||
USERADMINISTRATOR,
|
||||
|
||||
/**
|
||||
* Can create / alter feeds
|
||||
*/
|
||||
FEEDAMINISTRATOR,
|
||||
/**
|
||||
* Can create / alter entries
|
||||
*/
|
||||
ENTRYAMINISTRATOR,
|
||||
/**
|
||||
* can create / alter his own feed entries
|
||||
*/
|
||||
USER
|
||||
}
|
||||
|
||||
}
|
|
@ -1,642 +0,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.
|
||||
*/
|
||||
|
||||
package org.apache.lucene.gdata.data;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.Reader;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.lucene.gdata.server.registry.ProvidedService;
|
||||
|
||||
import com.google.gdata.client.Service;
|
||||
import com.google.gdata.data.BaseEntry;
|
||||
import com.google.gdata.data.Content;
|
||||
import com.google.gdata.data.DateTime;
|
||||
import com.google.gdata.data.Entry;
|
||||
import com.google.gdata.data.Extension;
|
||||
import com.google.gdata.data.ExtensionProfile;
|
||||
import com.google.gdata.data.Link;
|
||||
import com.google.gdata.data.Source;
|
||||
import com.google.gdata.data.TextConstruct;
|
||||
import com.google.gdata.util.ParseException;
|
||||
import com.google.gdata.util.ServiceException;
|
||||
import com.google.gdata.util.XmlBlob;
|
||||
import com.google.gdata.util.common.xml.XmlWriter;
|
||||
|
||||
/**
|
||||
* The GData-Server uses the GDATA-Client API for an interal representation of
|
||||
* entries. These entities have dynamic elements like Links being generated
|
||||
* using the requested URL.<br/> Some components of the server also need
|
||||
* additional infomation like the service type
|
||||
* {@link org.apache.lucene.gdata.server.registry.ProvidedService} of the entry
|
||||
* and the feedid a entry belongs to. All these information are
|
||||
* encapsulated in the ServerBaseEntry decorating a concrete sub class of <tt>BaseEntry</tt>. The actual
|
||||
* {@link com.google.gdata.data.BaseEntry} will be passed to the ServerBaseEntry
|
||||
* at creation time via the constructor. To use the ServerBaseFeed for generation a provided format like
|
||||
* RSS/ATOM the corresponding {@link com.google.gdata.data.ExtensionProfile} has
|
||||
* to be provided to the generation method.
|
||||
* <p> For a general overview of the generic BaseFeed class see the gdata-client API documentation</p>
|
||||
*
|
||||
* @see com.google.gdata.data.ExtensionProfile
|
||||
* @see com.google.gdata.data.BaseFeed
|
||||
*
|
||||
* @author Simon Willnauer
|
||||
*
|
||||
*/
|
||||
public class ServerBaseEntry {
|
||||
private String feedId;
|
||||
|
||||
private String serviceType;
|
||||
|
||||
private ProvidedService serviceConfig;
|
||||
private BaseEntry entry;
|
||||
private static final int DEFAULTVERSION = 1;
|
||||
private int version;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @return - the provided service for the source entry
|
||||
*/
|
||||
public ProvidedService getServiceConfig() {
|
||||
return this.serviceConfig;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param serviceConfig - the provided service for the source entry
|
||||
*/
|
||||
public void setServiceConfig(ProvidedService serviceConfig) {
|
||||
this.serviceConfig = serviceConfig;
|
||||
if (serviceConfig != null)
|
||||
this.serviceType = serviceConfig.getName();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return - the name of the service related of the feed containing this entry
|
||||
*/
|
||||
public String getServiceType() {
|
||||
return this.serviceType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new ServerBaseEntry.
|
||||
* To provide a concrete entry to decorate after object creation use {@link ServerBaseEntry#setEntry(BaseEntry)}
|
||||
*
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public ServerBaseEntry() {
|
||||
this(new Entry());
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param arg0 - the source entry
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public ServerBaseEntry(BaseEntry arg0) {
|
||||
this.entry = arg0;
|
||||
this.setVersion(DEFAULTVERSION);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param link - a link added to this entry
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public void addLink(final Link link) {
|
||||
this.entry.getLinks().add(link);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return - the id of the owning feed
|
||||
*/
|
||||
public String getFeedId() {
|
||||
return this.feedId;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param feedId - the id of the owning feed
|
||||
*/
|
||||
public void setFeedId(String feedId) {
|
||||
this.feedId = feedId;
|
||||
}
|
||||
/**
|
||||
* @return - the decorated entry
|
||||
*/
|
||||
public BaseEntry getEntry(){
|
||||
return this.entry;
|
||||
}
|
||||
/**
|
||||
* @param entry - the entry to decorate
|
||||
*/
|
||||
public void setEntry(BaseEntry entry){
|
||||
this.entry = entry;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see com.google.gdata.data.BaseEntry#addHtmlLink(java.lang.String, java.lang.String, java.lang.String)
|
||||
*/
|
||||
public void addHtmlLink(String arg0, String arg1, String arg2) {
|
||||
|
||||
this.entry.addHtmlLink(arg0, arg1, arg2);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @see com.google.gdata.data.BaseEntry#generateAtom(com.google.gdata.util.common.xml.XmlWriter, com.google.gdata.data.ExtensionProfile)
|
||||
*/
|
||||
|
||||
public void generateAtom(XmlWriter arg0, ExtensionProfile arg1) throws IOException {
|
||||
|
||||
this.entry.generateAtom(arg0, arg1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see com.google.gdata.data.BaseEntry#generateRss(com.google.gdata.util.common.xml.XmlWriter, com.google.gdata.data.ExtensionProfile)
|
||||
*/
|
||||
|
||||
public void generateRss(XmlWriter arg0, ExtensionProfile arg1) throws IOException {
|
||||
|
||||
this.entry.generateRss(arg0, arg1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see com.google.gdata.data.BaseEntry#getAuthors()
|
||||
*/
|
||||
|
||||
public List getAuthors() {
|
||||
|
||||
return this.entry.getAuthors();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see com.google.gdata.data.BaseEntry#getCanEdit()
|
||||
*/
|
||||
|
||||
public boolean getCanEdit() {
|
||||
|
||||
return this.entry.getCanEdit();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see com.google.gdata.data.BaseEntry#getCategories()
|
||||
*/
|
||||
|
||||
public Set getCategories() {
|
||||
|
||||
return this.entry.getCategories();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see com.google.gdata.data.BaseEntry#getContent()
|
||||
*/
|
||||
|
||||
public Content getContent() {
|
||||
|
||||
return this.entry.getContent();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see com.google.gdata.data.BaseEntry#getContributors()
|
||||
*/
|
||||
|
||||
public List getContributors() {
|
||||
|
||||
return this.entry.getContributors();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see com.google.gdata.data.BaseEntry#getEditLink()
|
||||
*/
|
||||
|
||||
public Link getEditLink() {
|
||||
|
||||
return this.entry.getEditLink();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see com.google.gdata.data.BaseEntry#getHtmlLink()
|
||||
*/
|
||||
|
||||
public Link getHtmlLink() {
|
||||
|
||||
return this.entry.getHtmlLink();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see com.google.gdata.data.BaseEntry#getId()
|
||||
*/
|
||||
|
||||
public String getId() {
|
||||
|
||||
return this.entry.getId();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see com.google.gdata.data.BaseEntry#getLink(java.lang.String, java.lang.String)
|
||||
*/
|
||||
|
||||
public Link getLink(String arg0, String arg1) {
|
||||
|
||||
return this.entry.getLink(arg0, arg1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see com.google.gdata.data.BaseEntry#getLinks()
|
||||
*/
|
||||
|
||||
public List getLinks() {
|
||||
|
||||
return this.entry.getLinks();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see com.google.gdata.data.BaseEntry#getPublished()
|
||||
*/
|
||||
|
||||
public DateTime getPublished() {
|
||||
|
||||
return this.entry.getPublished();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see com.google.gdata.data.BaseEntry#getRights()
|
||||
*/
|
||||
|
||||
public TextConstruct getRights() {
|
||||
|
||||
return this.entry.getRights();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see com.google.gdata.data.BaseEntry#getSelf()
|
||||
*/
|
||||
|
||||
public BaseEntry getSelf() throws IOException, ServiceException {
|
||||
|
||||
return this.entry.getSelf();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see com.google.gdata.data.BaseEntry#getSelfLink()
|
||||
*/
|
||||
|
||||
public Link getSelfLink() {
|
||||
|
||||
return this.entry.getSelfLink();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see com.google.gdata.data.BaseEntry#getService()
|
||||
*/
|
||||
|
||||
public Service getService() {
|
||||
|
||||
return this.entry.getService();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see com.google.gdata.data.BaseEntry#getSource()
|
||||
*/
|
||||
|
||||
public Source getSource() {
|
||||
|
||||
return this.entry.getSource();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see com.google.gdata.data.BaseEntry#getSummary()
|
||||
*/
|
||||
|
||||
public TextConstruct getSummary() {
|
||||
|
||||
return this.entry.getSummary();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see com.google.gdata.data.BaseEntry#getTitle()
|
||||
*/
|
||||
|
||||
public TextConstruct getTitle() {
|
||||
|
||||
return this.entry.getTitle();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see com.google.gdata.data.BaseEntry#getUpdated()
|
||||
*/
|
||||
|
||||
public DateTime getUpdated() {
|
||||
|
||||
return this.entry.getUpdated();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see com.google.gdata.data.BaseEntry#getVersionId()
|
||||
*/
|
||||
|
||||
public String getVersionId() {
|
||||
|
||||
return this.entry.getVersionId();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see com.google.gdata.data.BaseEntry#isDraft()
|
||||
*/
|
||||
|
||||
public boolean isDraft() {
|
||||
|
||||
return this.entry.isDraft();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see com.google.gdata.data.BaseEntry#parseAtom(com.google.gdata.data.ExtensionProfile, java.io.InputStream)
|
||||
*/
|
||||
|
||||
public void parseAtom(ExtensionProfile arg0, InputStream arg1) throws IOException, ParseException {
|
||||
|
||||
this.entry.parseAtom(arg0, arg1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see com.google.gdata.data.BaseEntry#parseAtom(com.google.gdata.data.ExtensionProfile, java.io.Reader)
|
||||
*/
|
||||
|
||||
public void parseAtom(ExtensionProfile arg0, Reader arg1) throws IOException, ParseException {
|
||||
|
||||
this.entry.parseAtom(arg0, arg1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see com.google.gdata.data.BaseEntry#setCanEdit(boolean)
|
||||
*/
|
||||
|
||||
public void setCanEdit(boolean arg0) {
|
||||
|
||||
this.entry.setCanEdit(arg0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see com.google.gdata.data.BaseEntry#setContent(com.google.gdata.data.Content)
|
||||
*/
|
||||
|
||||
public void setContent(Content arg0) {
|
||||
|
||||
this.entry.setContent(arg0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see com.google.gdata.data.BaseEntry#setContent(com.google.gdata.data.TextConstruct)
|
||||
*/
|
||||
|
||||
public void setContent(TextConstruct arg0) {
|
||||
|
||||
this.entry.setContent(arg0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see com.google.gdata.data.BaseEntry#setDraft(boolean)
|
||||
*/
|
||||
|
||||
public void setDraft(boolean arg0) {
|
||||
|
||||
this.entry.setDraft(arg0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see com.google.gdata.data.BaseEntry#setId(java.lang.String)
|
||||
*/
|
||||
|
||||
public void setId(String arg0) {
|
||||
|
||||
this.entry.setId(arg0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see com.google.gdata.data.BaseEntry#setPublished(com.google.gdata.data.DateTime)
|
||||
*/
|
||||
|
||||
public void setPublished(DateTime arg0) {
|
||||
|
||||
this.entry.setPublished(arg0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see com.google.gdata.data.BaseEntry#setRights(com.google.gdata.data.TextConstruct)
|
||||
*/
|
||||
|
||||
public void setRights(TextConstruct arg0) {
|
||||
|
||||
this.entry.setRights(arg0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see com.google.gdata.data.BaseEntry#setService(com.google.gdata.client.Service)
|
||||
*/
|
||||
|
||||
public void setService(Service arg0) {
|
||||
|
||||
this.entry.setService(arg0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see com.google.gdata.data.BaseEntry#setSource(com.google.gdata.data.Source)
|
||||
*/
|
||||
|
||||
public void setSource(Source arg0) {
|
||||
|
||||
this.entry.setSource(arg0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see com.google.gdata.data.BaseEntry#setSummary(com.google.gdata.data.TextConstruct)
|
||||
*/
|
||||
|
||||
public void setSummary(TextConstruct arg0) {
|
||||
|
||||
this.entry.setSummary(arg0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see com.google.gdata.data.BaseEntry#setTitle(com.google.gdata.data.TextConstruct)
|
||||
*/
|
||||
|
||||
public void setTitle(TextConstruct arg0) {
|
||||
|
||||
this.entry.setTitle(arg0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see com.google.gdata.data.BaseEntry#setUpdated(com.google.gdata.data.DateTime)
|
||||
*/
|
||||
|
||||
public void setUpdated(DateTime arg0) {
|
||||
|
||||
this.entry.setUpdated(arg0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see com.google.gdata.data.BaseEntry#setVersionId(java.lang.String)
|
||||
*/
|
||||
|
||||
public void setVersionId(String arg0) {
|
||||
|
||||
this.entry.setVersionId(arg0);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @see com.google.gdata.data.ExtensionPoint#addExtension(com.google.gdata.data.Extension)
|
||||
*/
|
||||
|
||||
public void addExtension(Extension arg0) {
|
||||
|
||||
this.entry.addExtension(arg0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see com.google.gdata.data.ExtensionPoint#addRepeatingExtension(com.google.gdata.data.Extension)
|
||||
*/
|
||||
|
||||
public void addRepeatingExtension(Extension arg0) {
|
||||
|
||||
this.entry.addRepeatingExtension(arg0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @see com.google.gdata.data.ExtensionPoint#generateCumulativeXmlBlob(com.google.gdata.data.ExtensionProfile)
|
||||
*/
|
||||
|
||||
public XmlBlob generateCumulativeXmlBlob(ExtensionProfile arg0) throws IOException {
|
||||
|
||||
return this.entry.generateCumulativeXmlBlob(arg0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @see com.google.gdata.data.ExtensionPoint#getRepeatingExtension(java.lang.Class)
|
||||
*/
|
||||
|
||||
public <T extends Extension> List<T> getRepeatingExtension(Class<T> arg0) {
|
||||
|
||||
return this.entry.getRepeatingExtension(arg0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see com.google.gdata.data.ExtensionPoint#getXmlBlob()
|
||||
*/
|
||||
|
||||
public XmlBlob getXmlBlob() {
|
||||
|
||||
return this.entry.getXmlBlob();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @see com.google.gdata.data.ExtensionPoint#parseCumulativeXmlBlob(com.google.gdata.util.XmlBlob, com.google.gdata.data.ExtensionProfile, java.lang.Class)
|
||||
*/
|
||||
|
||||
public void parseCumulativeXmlBlob(XmlBlob arg0, ExtensionProfile arg1, Class arg2) throws IOException, ParseException {
|
||||
|
||||
this.entry.parseCumulativeXmlBlob(arg0, arg1, arg2);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see com.google.gdata.data.ExtensionPoint#removeExtension(java.lang.Class)
|
||||
*/
|
||||
|
||||
public void removeExtension(Class arg0) {
|
||||
|
||||
this.entry.removeExtension(arg0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see com.google.gdata.data.ExtensionPoint#removeExtension(com.google.gdata.data.Extension)
|
||||
*/
|
||||
|
||||
public void removeExtension(Extension arg0) {
|
||||
|
||||
this.entry.removeExtension(arg0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see com.google.gdata.data.ExtensionPoint#removeRepeatingExtension(com.google.gdata.data.Extension)
|
||||
*/
|
||||
|
||||
public void removeRepeatingExtension(Extension arg0) {
|
||||
|
||||
this.entry.removeRepeatingExtension(arg0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see com.google.gdata.data.ExtensionPoint#setExtension(com.google.gdata.data.Extension)
|
||||
*/
|
||||
|
||||
public void setExtension(Extension arg0) {
|
||||
|
||||
this.entry.setExtension(arg0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see com.google.gdata.data.ExtensionPoint#setXmlBlob(com.google.gdata.util.XmlBlob)
|
||||
*/
|
||||
|
||||
public void setXmlBlob(XmlBlob arg0) {
|
||||
|
||||
this.entry.setXmlBlob(arg0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see com.google.gdata.data.BaseEntry#declareExtensions(com.google.gdata.data.ExtensionProfile)
|
||||
*/
|
||||
|
||||
public void declareExtensions(ExtensionProfile arg0) {
|
||||
this.entry.declareExtensions(arg0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the version.
|
||||
*/
|
||||
public int getVersion() {
|
||||
return this.version;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param version The version to set.
|
||||
*/
|
||||
public void setVersion(int version) {
|
||||
if(version < this.version)
|
||||
throw new IllegalArgumentException("Version must be greater than the current version -- current version: "+this.version);
|
||||
this.version = version;
|
||||
setVersionId(""+this.version);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
|
@ -1,684 +0,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.
|
||||
*/
|
||||
|
||||
package org.apache.lucene.gdata.data;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.Reader;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.lucene.gdata.server.registry.ProvidedService;
|
||||
|
||||
import com.google.gdata.client.Service;
|
||||
import com.google.gdata.data.BaseEntry;
|
||||
import com.google.gdata.data.BaseFeed;
|
||||
import com.google.gdata.data.Category;
|
||||
import com.google.gdata.data.DateTime;
|
||||
import com.google.gdata.data.Extension;
|
||||
import com.google.gdata.data.ExtensionProfile;
|
||||
import com.google.gdata.data.Feed;
|
||||
import com.google.gdata.data.Generator;
|
||||
import com.google.gdata.data.Link;
|
||||
import com.google.gdata.data.Person;
|
||||
import com.google.gdata.data.TextConstruct;
|
||||
import com.google.gdata.util.ParseException;
|
||||
import com.google.gdata.util.ServiceException;
|
||||
import com.google.gdata.util.XmlBlob;
|
||||
import com.google.gdata.util.common.xml.XmlWriter;
|
||||
|
||||
/**
|
||||
* The GData-Server uses the GDATA-Client API for an interal representation of
|
||||
* entries. These entities have dynamic elements like Links being generated
|
||||
* using the requested URL.<br/> Some components of the server also need
|
||||
* additional infomation like the service type
|
||||
* {@link org.apache.lucene.gdata.server.registry.ProvidedService} of the feed.
|
||||
* All these information are
|
||||
* encapsulated in the ServerBaseFeed decoration a concrete subl class of <tt>BaseFeed</tt>. The type of the
|
||||
* {@link com.google.gdata.data.BaseEntry} contained it this feed will be passed to the ServerBaseFeed
|
||||
* at creation time via the constructor. To retrieve the original entry call
|
||||
* {@link ServerBaseFeed#getFeed()} returns a
|
||||
* {@link com.google.gdata.data.BaseFeed} instance which can be casted into the
|
||||
* actual type. To use the ServerBaseEntry for generation a provided format like
|
||||
* RSS/ATOM the corresponding {@link com.google.gdata.data.ExtensionProfile} has
|
||||
* to be provided to the generation method.
|
||||
*
|
||||
* @author Simon Willnauer
|
||||
*
|
||||
*/
|
||||
public class ServerBaseFeed {
|
||||
|
||||
private String serviceType;
|
||||
|
||||
private ProvidedService serviceConfig;
|
||||
|
||||
private GDataAccount account;
|
||||
|
||||
private BaseFeed feed;
|
||||
/**
|
||||
* @return Returns the account.
|
||||
*/
|
||||
public GDataAccount getAccount() {
|
||||
return this.account;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param account The account to set.
|
||||
*/
|
||||
public void setAccount(GDataAccount account) {
|
||||
this.account = account;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new ServerBaseFeed and decorates a basic instance of {@link Feed}
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public ServerBaseFeed() {
|
||||
this.feed = new Feed();
|
||||
|
||||
}
|
||||
/**
|
||||
* @param feed - the feed to decorate
|
||||
*
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public ServerBaseFeed(BaseFeed feed) {
|
||||
this.feed = feed;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the feed.
|
||||
*/
|
||||
public BaseFeed getFeed() {
|
||||
return this.feed;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param feed The feed to set.
|
||||
*/
|
||||
public void setFeed(BaseFeed feed) {
|
||||
this.feed = feed;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see com.google.gdata.data.BaseFeed#declareExtensions(com.google.gdata.data.ExtensionProfile)
|
||||
*/
|
||||
public void declareExtensions(ExtensionProfile extProfile) {
|
||||
|
||||
this.feed.declareExtensions(extProfile);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param link -
|
||||
* a link added to the link list of the feed
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public void addLink(final Link link) {
|
||||
this.feed.getLinks().add(link);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param collection -
|
||||
* a collection of <code>Link</code> instance to be added to
|
||||
* the feeds link list
|
||||
*/
|
||||
public void addLinks(final Collection<Link> collection) {
|
||||
this.feed.getLinks().addAll(collection);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return - the name of the service related of the feed represented by this
|
||||
* ServerBaseFeed
|
||||
*/
|
||||
public String getServiceType() {
|
||||
return this.serviceType;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param serviceType -
|
||||
* the name of the service related of the feed represented by
|
||||
* this ServerBaseFeed
|
||||
*/
|
||||
public void setServiceType(String serviceType) {
|
||||
this.serviceType = serviceType;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return - the provided service
|
||||
*/
|
||||
public ProvidedService getServiceConfig() {
|
||||
return this.serviceConfig;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param serviceConfig - -
|
||||
* the provided service
|
||||
*/
|
||||
public void setServiceConfig(ProvidedService serviceConfig) {
|
||||
this.serviceConfig = serviceConfig;
|
||||
if (serviceConfig != null)
|
||||
this.serviceType = this.serviceConfig.getName();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param person -
|
||||
* adds an author to the feed
|
||||
*/
|
||||
public void addAuthor(final Person person) {
|
||||
this.feed.getAuthors().add(person);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see com.google.gdata.data.BaseFeed#createEntry()
|
||||
*/
|
||||
|
||||
public BaseEntry createEntry() {
|
||||
|
||||
return this.feed.createEntry();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see com.google.gdata.data.BaseFeed#generateAtom(com.google.gdata.util.common.xml.XmlWriter, com.google.gdata.data.ExtensionProfile)
|
||||
*/
|
||||
|
||||
public void generateAtom(XmlWriter arg0, ExtensionProfile arg1) throws IOException {
|
||||
|
||||
this.feed.generateAtom(arg0, arg1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see com.google.gdata.data.BaseFeed#generateAtomColl(com.google.gdata.util.common.xml.XmlWriter)
|
||||
*/
|
||||
|
||||
public void generateAtomColl(XmlWriter arg0) throws IOException {
|
||||
|
||||
this.feed.generateAtomColl(arg0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see com.google.gdata.data.BaseFeed#generateRss(com.google.gdata.util.common.xml.XmlWriter, com.google.gdata.data.ExtensionProfile)
|
||||
*/
|
||||
|
||||
public void generateRss(XmlWriter arg0, ExtensionProfile arg1) throws IOException {
|
||||
|
||||
this.feed.generateRss(arg0, arg1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see com.google.gdata.data.BaseFeed#getCanPost()
|
||||
*/
|
||||
|
||||
public boolean getCanPost() {
|
||||
|
||||
return this.feed.getCanPost();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see com.google.gdata.data.BaseFeed#getEntries()
|
||||
*/
|
||||
|
||||
public List getEntries() {
|
||||
|
||||
return this.feed.getEntries();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see com.google.gdata.data.BaseFeed#getEntryPostLink()
|
||||
*/
|
||||
|
||||
public Link getEntryPostLink() {
|
||||
|
||||
return this.feed.getEntryPostLink();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see com.google.gdata.data.BaseFeed#getItemsPerPage()
|
||||
*/
|
||||
|
||||
public int getItemsPerPage() {
|
||||
|
||||
return this.feed.getItemsPerPage();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see com.google.gdata.data.BaseFeed#getSelf()
|
||||
*/
|
||||
|
||||
public BaseFeed getSelf() throws IOException, ServiceException {
|
||||
|
||||
return this.feed.getSelf();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see com.google.gdata.data.BaseFeed#getSelfLink()
|
||||
*/
|
||||
|
||||
public Link getSelfLink() {
|
||||
|
||||
return this.feed.getSelfLink();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see com.google.gdata.data.BaseFeed#getService()
|
||||
*/
|
||||
|
||||
public Service getService() {
|
||||
|
||||
return this.feed.getService();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see com.google.gdata.data.BaseFeed#getStartIndex()
|
||||
*/
|
||||
|
||||
public int getStartIndex() {
|
||||
|
||||
return this.feed.getStartIndex();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see com.google.gdata.data.BaseFeed#getTotalResults()
|
||||
*/
|
||||
|
||||
public int getTotalResults() {
|
||||
|
||||
return this.feed.getTotalResults();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see com.google.gdata.data.BaseFeed#insert(E)
|
||||
*/
|
||||
|
||||
public BaseEntry insert(BaseEntry arg0) throws ServiceException, IOException {
|
||||
|
||||
return this.feed.insert(arg0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see com.google.gdata.data.BaseFeed#parseAtom(com.google.gdata.data.ExtensionProfile, java.io.InputStream)
|
||||
*/
|
||||
|
||||
public void parseAtom(ExtensionProfile arg0, InputStream arg1) throws IOException, ParseException {
|
||||
|
||||
this.feed.parseAtom(arg0, arg1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see com.google.gdata.data.BaseFeed#parseAtom(com.google.gdata.data.ExtensionProfile, java.io.Reader)
|
||||
*/
|
||||
|
||||
public void parseAtom(ExtensionProfile arg0, Reader arg1) throws IOException, ParseException {
|
||||
|
||||
this.feed.parseAtom(arg0, arg1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see com.google.gdata.data.BaseFeed#setCanPost(boolean)
|
||||
*/
|
||||
|
||||
public void setCanPost(boolean arg0) {
|
||||
|
||||
this.feed.setCanPost(arg0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see com.google.gdata.data.BaseFeed#setItemsPerPage(int)
|
||||
*/
|
||||
|
||||
public void setItemsPerPage(int arg0) {
|
||||
|
||||
this.feed.setItemsPerPage(arg0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see com.google.gdata.data.BaseFeed#setService(com.google.gdata.client.Service)
|
||||
*/
|
||||
|
||||
public void setService(Service arg0) {
|
||||
|
||||
this.feed.setService(arg0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see com.google.gdata.data.BaseFeed#setStartIndex(int)
|
||||
*/
|
||||
|
||||
public void setStartIndex(int arg0) {
|
||||
|
||||
this.feed.setStartIndex(arg0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see com.google.gdata.data.BaseFeed#setTotalResults(int)
|
||||
*/
|
||||
|
||||
public void setTotalResults(int arg0) {
|
||||
|
||||
this.feed.setTotalResults(arg0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see com.google.gdata.data.Source#addHtmlLink(java.lang.String, java.lang.String, java.lang.String)
|
||||
*/
|
||||
|
||||
public void addHtmlLink(String arg0, String arg1, String arg2) {
|
||||
|
||||
this.feed.addHtmlLink(arg0, arg1, arg2);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see com.google.gdata.data.Source#getAuthors()
|
||||
*/
|
||||
|
||||
public List<Person> getAuthors() {
|
||||
|
||||
return this.feed.getAuthors();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see com.google.gdata.data.Source#getCategories()
|
||||
*/
|
||||
|
||||
public Set<Category> getCategories() {
|
||||
|
||||
return this.feed.getCategories();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see com.google.gdata.data.Source#getContributors()
|
||||
*/
|
||||
|
||||
public List<Person> getContributors() {
|
||||
|
||||
return this.feed.getContributors();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see com.google.gdata.data.Source#getGenerator()
|
||||
*/
|
||||
|
||||
public Generator getGenerator() {
|
||||
|
||||
return this.feed.getGenerator();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see com.google.gdata.data.Source#getHtmlLink()
|
||||
*/
|
||||
|
||||
public Link getHtmlLink() {
|
||||
|
||||
return this.feed.getHtmlLink();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see com.google.gdata.data.Source#getIcon()
|
||||
*/
|
||||
|
||||
public String getIcon() {
|
||||
|
||||
return this.feed.getIcon();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see com.google.gdata.data.Source#getId()
|
||||
*/
|
||||
|
||||
public String getId() {
|
||||
|
||||
return this.feed.getId();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see com.google.gdata.data.Source#getLink(java.lang.String, java.lang.String)
|
||||
*/
|
||||
|
||||
public Link getLink(String arg0, String arg1) {
|
||||
|
||||
return this.feed.getLink(arg0, arg1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see com.google.gdata.data.Source#getLinks()
|
||||
*/
|
||||
|
||||
public List<Link> getLinks() {
|
||||
|
||||
return this.feed.getLinks();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see com.google.gdata.data.Source#getLogo()
|
||||
*/
|
||||
|
||||
public String getLogo() {
|
||||
|
||||
return this.feed.getLogo();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see com.google.gdata.data.Source#getRights()
|
||||
*/
|
||||
|
||||
public TextConstruct getRights() {
|
||||
|
||||
return this.feed.getRights();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see com.google.gdata.data.Source#getSubtitle()
|
||||
*/
|
||||
|
||||
public TextConstruct getSubtitle() {
|
||||
|
||||
return this.feed.getSubtitle();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see com.google.gdata.data.Source#getTitle()
|
||||
*/
|
||||
|
||||
public TextConstruct getTitle() {
|
||||
|
||||
return this.feed.getTitle();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see com.google.gdata.data.Source#getUpdated()
|
||||
*/
|
||||
|
||||
public DateTime getUpdated() {
|
||||
|
||||
return this.feed.getUpdated();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see com.google.gdata.data.Source#setGenerator(com.google.gdata.data.Generator)
|
||||
*/
|
||||
|
||||
public void setGenerator(Generator arg0) {
|
||||
|
||||
this.feed.setGenerator(arg0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see com.google.gdata.data.Source#setIcon(java.lang.String)
|
||||
*/
|
||||
|
||||
public void setIcon(String arg0) {
|
||||
|
||||
this.feed.setIcon(arg0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see com.google.gdata.data.Source#setId(java.lang.String)
|
||||
*/
|
||||
|
||||
public void setId(String arg0) {
|
||||
|
||||
this.feed.setId(arg0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see com.google.gdata.data.Source#setLogo(java.lang.String)
|
||||
*/
|
||||
|
||||
public void setLogo(String arg0) {
|
||||
|
||||
this.feed.setLogo(arg0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see com.google.gdata.data.Source#setRights(com.google.gdata.data.TextConstruct)
|
||||
*/
|
||||
|
||||
public void setRights(TextConstruct arg0) {
|
||||
|
||||
this.feed.setRights(arg0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see com.google.gdata.data.Source#setSubtitle(com.google.gdata.data.TextConstruct)
|
||||
*/
|
||||
|
||||
public void setSubtitle(TextConstruct arg0) {
|
||||
|
||||
this.feed.setSubtitle(arg0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see com.google.gdata.data.Source#setTitle(com.google.gdata.data.TextConstruct)
|
||||
*/
|
||||
|
||||
public void setTitle(TextConstruct arg0) {
|
||||
|
||||
this.feed.setTitle(arg0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see com.google.gdata.data.Source#setUpdated(com.google.gdata.data.DateTime)
|
||||
*/
|
||||
|
||||
public void setUpdated(DateTime arg0) {
|
||||
|
||||
this.feed.setUpdated(arg0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see com.google.gdata.data.ExtensionPoint#addExtension(com.google.gdata.data.Extension)
|
||||
*/
|
||||
|
||||
public void addExtension(Extension arg0) {
|
||||
|
||||
this.feed.addExtension(arg0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see com.google.gdata.data.ExtensionPoint#addRepeatingExtension(com.google.gdata.data.Extension)
|
||||
*/
|
||||
|
||||
public void addRepeatingExtension(Extension arg0) {
|
||||
|
||||
this.feed.addRepeatingExtension(arg0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see com.google.gdata.data.ExtensionPoint#getExtension(java.lang.Class)
|
||||
*/
|
||||
|
||||
public <T extends Extension> T getExtension(Class<T> arg0) {
|
||||
|
||||
return this.feed.getExtension(arg0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see com.google.gdata.data.ExtensionPoint#getRepeatingExtension(java.lang.Class)
|
||||
*/
|
||||
|
||||
public <T extends Extension> List<T> getRepeatingExtension(Class<T> arg0) {
|
||||
|
||||
return this.feed.getRepeatingExtension(arg0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see com.google.gdata.data.ExtensionPoint#getXmlBlob()
|
||||
*/
|
||||
|
||||
public XmlBlob getXmlBlob() {
|
||||
|
||||
return this.feed.getXmlBlob();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see com.google.gdata.data.ExtensionPoint#parseCumulativeXmlBlob(com.google.gdata.util.XmlBlob, com.google.gdata.data.ExtensionProfile, java.lang.Class)
|
||||
*/
|
||||
|
||||
public void parseCumulativeXmlBlob(XmlBlob arg0, ExtensionProfile arg1, Class arg2) throws IOException, ParseException {
|
||||
|
||||
this.feed.parseCumulativeXmlBlob(arg0, arg1, arg2);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see com.google.gdata.data.ExtensionPoint#removeExtension(java.lang.Class)
|
||||
*/
|
||||
|
||||
public void removeExtension(Class arg0) {
|
||||
|
||||
this.feed.removeExtension(arg0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see com.google.gdata.data.ExtensionPoint#removeExtension(com.google.gdata.data.Extension)
|
||||
*/
|
||||
|
||||
public void removeExtension(Extension arg0) {
|
||||
|
||||
this.feed.removeExtension(arg0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see com.google.gdata.data.ExtensionPoint#removeRepeatingExtension(com.google.gdata.data.Extension)
|
||||
*/
|
||||
|
||||
public void removeRepeatingExtension(Extension arg0) {
|
||||
|
||||
this.feed.removeRepeatingExtension(arg0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see com.google.gdata.data.ExtensionPoint#setExtension(com.google.gdata.data.Extension)
|
||||
*/
|
||||
|
||||
public void setExtension(Extension arg0) {
|
||||
|
||||
this.feed.setExtension(arg0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see com.google.gdata.data.ExtensionPoint#setXmlBlob(com.google.gdata.util.XmlBlob)
|
||||
*/
|
||||
|
||||
public void setXmlBlob(XmlBlob arg0) {
|
||||
|
||||
this.feed.setXmlBlob(arg0);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,10 +0,0 @@
|
|||
<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<meta name="Author" content="Simon Willnauer">
|
||||
</head>
|
||||
<body>
|
||||
Contains classes for the internal representation of GData feeds and entries.
|
||||
</body>
|
||||
</html>
|
|
@ -1 +0,0 @@
|
|||
<html><body>Top-level package.</body></html>
|
|
@ -1,45 +0,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.
|
||||
*/
|
||||
package org.apache.lucene.gdata.search;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.lucene.search.Query;
|
||||
|
||||
/**
|
||||
*
|
||||
* @param <T>
|
||||
*
|
||||
*/
|
||||
public interface GDataSearcher <T>{
|
||||
|
||||
/**
|
||||
* executes an Query and returns a list of defined return values of type T
|
||||
* @param query - the query to apply to the searcher
|
||||
* @param hitcount - the amount of hits returned by this search
|
||||
* @param offset - the hit count offset
|
||||
* @param feedId
|
||||
* @return List of T
|
||||
* @throws IOException - if the underlying lucene searcher throws an IO Exception
|
||||
*/
|
||||
public List<T> search(Query query,int hitcount, int offset, String feedId)throws IOException;
|
||||
/**
|
||||
* Destroys this Searcher
|
||||
*/
|
||||
public abstract void close();
|
||||
}
|
|
@ -1,39 +0,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.
|
||||
*/
|
||||
|
||||
package org.apache.lucene.gdata.search;
|
||||
|
||||
import org.apache.lucene.gdata.server.registry.ProvidedService;
|
||||
import org.apache.lucene.gdata.server.registry.ServerComponent;
|
||||
|
||||
/**
|
||||
* TODO document this when Search comes into play
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
public interface SearchComponent extends ServerComponent {
|
||||
/**
|
||||
* TODO document this when Search comes into play
|
||||
*
|
||||
* @param service
|
||||
*
|
||||
* @return a GDataSearcher
|
||||
*/
|
||||
public abstract GDataSearcher<String> getServiceSearcher(ProvidedService service);
|
||||
|
||||
}
|
|
@ -1,136 +0,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.
|
||||
*/
|
||||
|
||||
package org.apache.lucene.gdata.search;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import org.apache.lucene.document.Document;
|
||||
import org.apache.lucene.document.Field;
|
||||
import org.apache.lucene.gdata.search.index.IndexDocument;
|
||||
import org.apache.lucene.gdata.utils.ReferenceCounter;
|
||||
import org.apache.lucene.index.Term;
|
||||
import org.apache.lucene.search.Hits;
|
||||
import org.apache.lucene.search.IndexSearcher;
|
||||
import org.apache.lucene.search.Query;
|
||||
import org.apache.lucene.search.QueryFilter;
|
||||
import org.apache.lucene.search.TermQuery;
|
||||
|
||||
/**
|
||||
* Standard implementation of
|
||||
* {@link org.apache.lucene.gdata.search.GDataSearcher}
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class StandardGdataSearcher implements GDataSearcher<String> {
|
||||
private final AtomicBoolean isClosed = new AtomicBoolean(false);
|
||||
|
||||
private final ReferenceCounter<IndexSearcher> searcher;
|
||||
|
||||
private static final Map<String, QueryFilter> queryFilterCache = new HashMap<String, QueryFilter>();
|
||||
|
||||
/** constructs a new GdataSearcher
|
||||
* @param searcher - the current lucene searcher instance
|
||||
*/
|
||||
public StandardGdataSearcher(ReferenceCounter<IndexSearcher> searcher) {
|
||||
if (searcher == null)
|
||||
throw new IllegalArgumentException("searcher must not be null");
|
||||
|
||||
this.searcher = searcher;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.lucene.gdata.search.GDataSearcher#search(org.apache.lucene.search.Query,
|
||||
* int, int, java.lang.String)
|
||||
*/
|
||||
public List<String> search(Query query, int hitcount, int offset,
|
||||
String feedId) throws IOException {
|
||||
if (hitcount < 0 || offset < 0)
|
||||
throw new IllegalArgumentException(
|
||||
"hit count and offset must not be less than 0");
|
||||
if (this.isClosed.get())
|
||||
throw new IllegalStateException("Searcher is closed");
|
||||
if (query == null)
|
||||
throw new RuntimeException("query is null can not apply search");
|
||||
if (feedId == null)
|
||||
throw new IllegalArgumentException("feed id must not be null");
|
||||
QueryFilter filter = null;
|
||||
synchronized (queryFilterCache) {
|
||||
filter = queryFilterCache.get(feedId);
|
||||
|
||||
if (filter == null)
|
||||
filter = new QueryFilter(new TermQuery(new Term(
|
||||
IndexDocument.FIELD_FEED_ID, feedId)));
|
||||
queryFilterCache.put(feedId, filter);
|
||||
}
|
||||
IndexSearcher indexSearcher = this.searcher.get();
|
||||
Hits hits = indexSearcher.search(query, filter);
|
||||
|
||||
return collectHits(hits, hitcount, offset);
|
||||
|
||||
}
|
||||
|
||||
protected List<String> collectHits(Hits hits, int hitcount, int offset)
|
||||
throws IOException {
|
||||
int hitLength = hits.length();
|
||||
if (hitLength < offset || hitLength == 0)
|
||||
return new ArrayList<String>(0);
|
||||
if (offset > 0)
|
||||
--offset;
|
||||
/*
|
||||
* include the offset
|
||||
*/
|
||||
int remainingHits = hitLength - offset;
|
||||
int returnSize = remainingHits > hitcount ? hitcount : remainingHits;
|
||||
List<String> retVal = new ArrayList<String>(returnSize);
|
||||
for (int i = 0; i < returnSize; i++) {
|
||||
Document doc = hits.doc(offset++);
|
||||
/*
|
||||
* the entry id is sufficient to retrieve the entry from the
|
||||
* storage. the result will be ordered by score (default)
|
||||
*/
|
||||
Field field = doc.getField(IndexDocument.FIELD_ENTRY_ID);
|
||||
retVal.add(i, field.stringValue());
|
||||
}
|
||||
return retVal;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.lucene.gdata.search.GDataSearcher#close()
|
||||
*/
|
||||
public void close() {
|
||||
this.isClosed.set(true);
|
||||
this.searcher.decrementRef();
|
||||
|
||||
}
|
||||
|
||||
static void flushFilterCache() {
|
||||
synchronized (queryFilterCache) {
|
||||
queryFilterCache.clear();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -1,179 +0,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.
|
||||
*/
|
||||
package org.apache.lucene.gdata.search.analysis;
|
||||
|
||||
import org.apache.lucene.document.Field;
|
||||
import org.apache.lucene.document.Field.Index;
|
||||
import org.apache.lucene.document.Field.Store;
|
||||
import org.apache.lucene.gdata.data.ServerBaseEntry;
|
||||
import org.apache.lucene.gdata.search.config.IndexSchemaField;
|
||||
import org.apache.lucene.gdata.search.config.IndexSchemaField.ContentType;
|
||||
import org.apache.lucene.gdata.search.index.GdataIndexerException;
|
||||
import org.apache.lucene.gdata.utils.ReflectionUtils;
|
||||
import org.w3c.dom.Node;
|
||||
|
||||
/**
|
||||
* Creating Indexable document requires processing of incoming entities as
|
||||
* GData Entries. Entries in the GData protocol might have very different
|
||||
* structures and content. They all have on thing in common as they are atom xml
|
||||
* format. To retrieve the configured elements of the atom format and process the
|
||||
* actual content might differ from element to element.
|
||||
* <p>
|
||||
* Each predefined ContentStrategy can be used to retrieve certain content from
|
||||
* the defined element. Which element to process is defined using a XPath
|
||||
* expression in the gdata-config.xml file.
|
||||
* </p>
|
||||
* <p>
|
||||
* <tt>ContentStrategy</tt> implementation should not be accessed directly. To
|
||||
* get a <tt>ContentStrategy</tt> for a specific
|
||||
* {@link org.apache.lucene.gdata.search.config.IndexSchemaField.ContentType}
|
||||
* use the {@link ContentStrategy#getFieldStrategy} factory method. This method
|
||||
* expects a IndexSchemaField instance with a set <tt>ContentType</tt>. The
|
||||
* return value is a new <tt>ContentStrategy</tt> instance for the defined
|
||||
* <tt>ContentType</tt>.
|
||||
* </p>
|
||||
*
|
||||
* @see org.apache.lucene.gdata.search.config.IndexSchemaField.ContentType
|
||||
* @see org.apache.lucene.gdata.search.index.IndexDocumentBuilder
|
||||
*
|
||||
*
|
||||
*/
|
||||
public abstract class ContentStrategy {
|
||||
protected final Store store;
|
||||
|
||||
protected final Index index;
|
||||
|
||||
protected final IndexSchemaField config;
|
||||
|
||||
protected String content;
|
||||
|
||||
protected String fieldName;
|
||||
|
||||
protected ContentStrategy(IndexSchemaField fieldConfiguration) {
|
||||
this(null, null, fieldConfiguration);
|
||||
}
|
||||
|
||||
protected ContentStrategy(Index index, Store store,
|
||||
IndexSchemaField fieldConfig) {
|
||||
if(fieldConfig == null)
|
||||
throw new IllegalArgumentException("IndexSchemaField must not be null");
|
||||
this.config = fieldConfig;
|
||||
this.fieldName = fieldConfig.getName();
|
||||
if (index != null) {
|
||||
this.index = index;
|
||||
} else {
|
||||
this.index = fieldConfig.getIndex() == null ? IndexSchemaField.DEFAULT_INDEX_STRATEGY
|
||||
: fieldConfig.getIndex();
|
||||
}
|
||||
if (store != null) {
|
||||
this.store = store;
|
||||
} else {
|
||||
this.store = fieldConfig.getStore() == null ? IndexSchemaField.DEFAULT_STORE_STRATEGY
|
||||
: fieldConfig.getStore();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param indexable
|
||||
* @throws NotIndexableException
|
||||
*/
|
||||
public abstract void processIndexable(
|
||||
Indexable<? extends Node, ? extends ServerBaseEntry> indexable)
|
||||
throws NotIndexableException;
|
||||
|
||||
/**
|
||||
* This method creates a lucene field from the retrieved content of the
|
||||
* entity. Values for Field.Index, Field.Store, the field name and the boost
|
||||
* factor are configured in the <tt>IndexSchemaField</tt> passed by the
|
||||
* constructor e.g the factory method. This method might be overwritten by
|
||||
* subclasses.
|
||||
*
|
||||
* @return the Lucene {@link Field}
|
||||
*/
|
||||
public Field[] createLuceneField() {
|
||||
/*
|
||||
* should I test the content for being empty?!
|
||||
* does that make any difference if empty fields are indexed?!
|
||||
*/
|
||||
if(this.fieldName==null|| this.content == null)
|
||||
throw new GdataIndexerException("Required field not set fieldName: "+this.fieldName+" content: "+this.content);
|
||||
if(this.content.length()==0){
|
||||
return new Field[0];
|
||||
}
|
||||
Field retValue = new Field(this.fieldName, this.content, this.store,
|
||||
this.index);
|
||||
float boost = this.config.getBoost();
|
||||
if (boost != 1.0f)
|
||||
retValue.setBoost(boost);
|
||||
return new Field[]{retValue};
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* This factory method creates the <tt>ContentStrategy</tt> corresponding
|
||||
* to the set <tt>ContentType</tt> value in the <tt>IndexSchemaField</tt>
|
||||
* passed to the method as the single parameter.
|
||||
* <p>
|
||||
* The ContentType must not be null
|
||||
* </p>
|
||||
*
|
||||
* @param fieldConfig -
|
||||
* the field config to use to identify the corresponding
|
||||
* <tt>ContentStrategy</tt>
|
||||
* @return - a new <tt>ContentStrategy</tt> instance
|
||||
*/
|
||||
public static ContentStrategy getFieldStrategy(IndexSchemaField fieldConfig) {
|
||||
if (fieldConfig == null)
|
||||
throw new IllegalArgumentException(
|
||||
"field configuration must not be null");
|
||||
ContentType type = fieldConfig.getContentType();
|
||||
if (type == null)
|
||||
throw new IllegalArgumentException(
|
||||
"ContentType in IndexSchemaField must not be null");
|
||||
fieldConfig.getAnalyzerClass();
|
||||
|
||||
switch (type) {
|
||||
case CATEGORY:
|
||||
return new GdataCategoryStrategy(fieldConfig);
|
||||
case HTML:
|
||||
return new HTMLStrategy(fieldConfig);
|
||||
case XHTML:
|
||||
return new XHtmlStrategy(fieldConfig);
|
||||
case GDATADATE:
|
||||
return new GdataDateStrategy(fieldConfig);
|
||||
case TEXT:
|
||||
return new PlainTextStrategy(fieldConfig);
|
||||
case KEYWORD:
|
||||
return new KeywordStrategy(fieldConfig);
|
||||
case CUSTOM:
|
||||
/*
|
||||
* check if this class can be created with default constructor is checked
|
||||
* in IndexSchemaField#setFieldClass and throws RuntimeEx if not. So
|
||||
* server can not start up.
|
||||
*/
|
||||
return ReflectionUtils.getDefaultInstance(fieldConfig
|
||||
.getFieldClass());
|
||||
case MIXED:
|
||||
return new MixedContentStrategy(fieldConfig);
|
||||
default:
|
||||
throw new RuntimeException("No content strategy found for " + type);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -1,110 +0,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.
|
||||
*/
|
||||
package org.apache.lucene.gdata.search.analysis;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.StringReader;
|
||||
import java.io.StringWriter;
|
||||
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
import javax.xml.xpath.XPath;
|
||||
import javax.xml.xpath.XPathConstants;
|
||||
import javax.xml.xpath.XPathExpressionException;
|
||||
import javax.xml.xpath.XPathFactory;
|
||||
|
||||
import org.apache.lucene.gdata.data.ServerBaseEntry;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Node;
|
||||
import org.xml.sax.InputSource;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
import com.google.gdata.data.ExtensionProfile;
|
||||
import com.google.gdata.util.common.xml.XmlWriter;
|
||||
|
||||
/**
|
||||
* <tt>Indexable</tt> implementation using the W3C Dom API and JAXP XPath
|
||||
* engine
|
||||
*
|
||||
*
|
||||
* @param <R> -
|
||||
* a subtype of {@link org.w3c.dom.Node} returned by the applyPath
|
||||
* method
|
||||
* @param <I> -
|
||||
* a subtype of {@link org.apache.lucene.gdata.data.ServerBaseEntry}
|
||||
*/
|
||||
public class DomIndexable<R extends Node, I extends ServerBaseEntry> extends
|
||||
Indexable<R, I> {
|
||||
private final Document document;
|
||||
|
||||
private final XPath xPath;
|
||||
|
||||
/**
|
||||
* @param applyAble
|
||||
* @throws NotIndexableException
|
||||
*/
|
||||
public DomIndexable(I applyAble) throws NotIndexableException {
|
||||
super(applyAble);
|
||||
if (this.applyAble.getServiceConfig() == null)
|
||||
throw new NotIndexableException("ServiceConfig is not set");
|
||||
try {
|
||||
this.document = buildDomDocument();
|
||||
} catch (ParserConfigurationException e) {
|
||||
throw new NotIndexableException("Can not create document builder",
|
||||
e);
|
||||
|
||||
} catch (IOException e) {
|
||||
throw new NotIndexableException(
|
||||
"IO Exception occurred while building indexable", e);
|
||||
|
||||
} catch (SAXException e) {
|
||||
throw new NotIndexableException("Can not parse entry", e);
|
||||
|
||||
}
|
||||
this.xPath = XPathFactory.newInstance().newXPath();
|
||||
|
||||
}
|
||||
|
||||
private Document buildDomDocument() throws ParserConfigurationException,
|
||||
IOException, SAXException {
|
||||
StringWriter stringWriter = new StringWriter();
|
||||
ExtensionProfile profile = this.applyAble.getServiceConfig()
|
||||
.getExtensionProfile();
|
||||
if (profile == null)
|
||||
throw new IllegalStateException("ExtensionProfile is not set");
|
||||
XmlWriter writer = new XmlWriter(stringWriter);
|
||||
this.applyAble.generateAtom(writer, profile);
|
||||
DocumentBuilder builder = DocumentBuilderFactory.newInstance()
|
||||
.newDocumentBuilder();
|
||||
return builder.parse(new InputSource(new StringReader(stringWriter
|
||||
.toString())));
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.lucene.gdata.search.analysis.Indexable#applyPath(java.lang.String)
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public R applyPath(String expression) throws XPathExpressionException {
|
||||
|
||||
return (R) this.xPath.evaluate(expression, this.document,
|
||||
XPathConstants.NODE);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,167 +0,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.
|
||||
*/
|
||||
package org.apache.lucene.gdata.search.analysis;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.xml.xpath.XPathExpressionException;
|
||||
|
||||
import org.apache.lucene.document.Field;
|
||||
import org.apache.lucene.gdata.data.ServerBaseEntry;
|
||||
import org.apache.lucene.gdata.search.config.IndexSchemaField;
|
||||
import org.apache.lucene.gdata.search.index.GdataIndexerException;
|
||||
import org.w3c.dom.NamedNodeMap;
|
||||
import org.w3c.dom.Node;
|
||||
|
||||
/**
|
||||
* This strategy retrieves the category term and and the scheme from a category
|
||||
* element. The content is represented by the term which can be configured via
|
||||
* the configuration file.
|
||||
* <p>
|
||||
* The category element has at least one attribute with the name "scheme" which
|
||||
* is not mandatory. The term can be the default attribute "term" or the text
|
||||
* content of the element, this is configured via the path of the field.
|
||||
* </p>
|
||||
* <p>
|
||||
* <tt><category scheme="http://www.example.com/type" term="blog.post"/><tt>
|
||||
* </p>
|
||||
* TODO extend javadoc for search info
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class GdataCategoryStrategy extends ContentStrategy {
|
||||
protected String categoryScheme;
|
||||
|
||||
protected String categorySchemeField;
|
||||
|
||||
private static final String LABEL = "label";
|
||||
|
||||
private static final String SCHEME = "scheme";
|
||||
|
||||
private static final String TERM = "term";
|
||||
|
||||
/**
|
||||
* the string to search a schema if no schema is specified
|
||||
*/
|
||||
public static final String CATEGORY_SCHEMA_NULL_VALUE = "LUCISCHEMANULL";
|
||||
|
||||
/**
|
||||
* Schema field suffix
|
||||
*/
|
||||
public static final String CATEGORY_SCHEMA_FIELD_SUFFIX = "-schema";
|
||||
|
||||
protected GdataCategoryStrategy(IndexSchemaField fieldConfiguration) {
|
||||
super(fieldConfiguration);
|
||||
this.categorySchemeField = new StringBuilder(this.fieldName).append(
|
||||
CATEGORY_SCHEMA_FIELD_SUFFIX).toString();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws NotIndexableException
|
||||
* @see org.apache.lucene.gdata.search.analysis.ContentStrategy#processIndexable(org.apache.lucene.gdata.search.analysis.Indexable)
|
||||
*/
|
||||
@Override
|
||||
public void processIndexable(
|
||||
Indexable<? extends Node, ? extends ServerBaseEntry> indexable)
|
||||
throws NotIndexableException {
|
||||
String contentPath = this.config.getPath();
|
||||
Node node = null;
|
||||
try {
|
||||
node = indexable.applyPath(contentPath);
|
||||
} catch (XPathExpressionException e) {
|
||||
|
||||
throw new NotIndexableException("Can not apply path");
|
||||
}
|
||||
if (node == null)
|
||||
throw new NotIndexableException(
|
||||
"Could not retrieve content for schema field: "
|
||||
+ this.config);
|
||||
|
||||
StringBuilder contentBuilder = new StringBuilder();
|
||||
StringBuilder schemeBuilder = new StringBuilder();
|
||||
String nodeName = node.getNodeName();
|
||||
/*
|
||||
* enable more than one category element -- check the node name if
|
||||
* category strategy is used with an element not named "category"
|
||||
*/
|
||||
while (node != null && nodeName != null
|
||||
&& nodeName.equals(node.getNodeName())) {
|
||||
NamedNodeMap attributeMap = node.getAttributes();
|
||||
if (attributeMap == null)
|
||||
throw new NotIndexableException(
|
||||
"category term attribute not present");
|
||||
/*
|
||||
* the "term" is the internal string used by the software to
|
||||
* identify the category, while the "label" is the human-readable
|
||||
* string presented to a user in a user interface.
|
||||
*/
|
||||
Node termNode = attributeMap.getNamedItem(TERM);
|
||||
if (termNode == null)
|
||||
throw new NotIndexableException(
|
||||
"category term attribute not present");
|
||||
contentBuilder.append(termNode.getTextContent()).append(" ");
|
||||
|
||||
Node labelNode = attributeMap.getNamedItem(LABEL);
|
||||
if (labelNode != null)
|
||||
contentBuilder.append(labelNode.getTextContent()).append(" ");
|
||||
|
||||
Node schemeNode = attributeMap.getNamedItem(SCHEME);
|
||||
if (schemeNode != null)
|
||||
schemeBuilder.append(schemeNode.getTextContent());
|
||||
node = node.getNextSibling();
|
||||
}
|
||||
|
||||
this.content = contentBuilder.toString();
|
||||
this.categoryScheme = schemeBuilder.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.lucene.gdata.search.analysis.ContentStrategy#createLuceneField()
|
||||
*/
|
||||
@Override
|
||||
public Field[] createLuceneField() {
|
||||
List<Field> retValue = new ArrayList<Field>(2);
|
||||
if (this.fieldName == null)
|
||||
throw new GdataIndexerException("Required field 'name' is null -- "
|
||||
+ this.config);
|
||||
if (this.content == null)
|
||||
throw new GdataIndexerException(
|
||||
"Required field 'content' is null -- " + this.config);
|
||||
|
||||
Field categoryTerm = new Field(this.fieldName, this.content,
|
||||
this.store, this.index);
|
||||
float boost = this.config.getBoost();
|
||||
if (boost != 1.0f)
|
||||
categoryTerm.setBoost(boost);
|
||||
retValue.add(categoryTerm);
|
||||
/*
|
||||
* if schema is not set index null value to enable search for categories
|
||||
* without a schema
|
||||
*/
|
||||
if (this.categoryScheme == null || this.categoryScheme.length() == 0) {
|
||||
this.categoryScheme = CATEGORY_SCHEMA_NULL_VALUE;
|
||||
}
|
||||
Field categoryURN = new Field(this.categorySchemeField,
|
||||
this.categoryScheme, Field.Store.YES, Field.Index.UN_TOKENIZED);
|
||||
retValue.add(categoryURN);
|
||||
return retValue.toArray(new Field[0]);
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -1,99 +0,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.
|
||||
*/
|
||||
package org.apache.lucene.gdata.search.analysis;
|
||||
|
||||
import javax.xml.xpath.XPathExpressionException;
|
||||
|
||||
import org.apache.lucene.document.Field;
|
||||
import org.apache.lucene.gdata.data.ServerBaseEntry;
|
||||
import org.apache.lucene.gdata.search.config.IndexSchemaField;
|
||||
import org.apache.lucene.gdata.search.index.GdataIndexerException;
|
||||
import org.w3c.dom.Node;
|
||||
|
||||
import com.google.gdata.data.DateTime;
|
||||
|
||||
/**
|
||||
* This content strategy retrieves a so called GData Date from a RFC 3339
|
||||
* timestamp format. The format will be parsed and indexed as a timestamp value.
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class GdataDateStrategy extends ContentStrategy {
|
||||
|
||||
protected GdataDateStrategy(IndexSchemaField fieldConfiguration) {
|
||||
super(fieldConfiguration);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws NotIndexableException
|
||||
* @see org.apache.lucene.gdata.search.analysis.ContentStrategy#processIndexable(org.apache.lucene.gdata.search.analysis.Indexable)
|
||||
*/
|
||||
@Override
|
||||
public void processIndexable(
|
||||
Indexable<? extends Node, ? extends ServerBaseEntry> indexable)
|
||||
throws NotIndexableException {
|
||||
String path = this.config.getPath();
|
||||
Node node;
|
||||
try {
|
||||
node = indexable.applyPath(path);
|
||||
} catch (XPathExpressionException e1) {
|
||||
throw new NotIndexableException("Can not apply path -- " + path
|
||||
+ " FieldConfig: " + this.config);
|
||||
}
|
||||
if (node == null)
|
||||
throw new NotIndexableException(
|
||||
"Could not retrieve content for schema field: "
|
||||
+ this.config);
|
||||
String textContent = node.getTextContent();
|
||||
try {
|
||||
this.content = getTimeStamp(textContent);
|
||||
} catch (NumberFormatException e) {
|
||||
throw new NotIndexableException("Can not parse GData date -- "
|
||||
+ textContent);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.lucene.gdata.search.analysis.ContentStrategy#createLuceneField()
|
||||
*/
|
||||
@Override
|
||||
public Field[] createLuceneField() {
|
||||
if(this.fieldName == null)
|
||||
throw new GdataIndexerException(
|
||||
"Required field 'name' is null -- " +this.config);
|
||||
if(this.content == null)
|
||||
throw new GdataIndexerException(
|
||||
"Required field 'content' is null -- " +this.config);
|
||||
if(this.content.length()==0)
|
||||
return new Field[0];
|
||||
Field retValue = new Field(this.fieldName, this.content,
|
||||
Field.Store.YES, Field.Index.UN_TOKENIZED);
|
||||
float boost = this.config.getBoost();
|
||||
if (boost != 1.0f)
|
||||
retValue.setBoost(boost);
|
||||
return new Field[] { retValue };
|
||||
|
||||
}
|
||||
|
||||
private static String getTimeStamp(String dateString) {
|
||||
return Long.toString(DateTime.parseDateTimeChoice(dateString).getValue());
|
||||
}
|
||||
|
||||
}
|
|
@ -1,99 +0,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.
|
||||
*/
|
||||
package org.apache.lucene.gdata.search.analysis;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.StringReader;
|
||||
import java.io.StringWriter;
|
||||
|
||||
import javax.xml.xpath.XPathExpressionException;
|
||||
|
||||
import org.apache.lucene.gdata.data.ServerBaseEntry;
|
||||
import org.apache.lucene.gdata.search.config.IndexSchemaField;
|
||||
import org.apache.xerces.xni.XNIException;
|
||||
import org.apache.xerces.xni.parser.XMLDocumentFilter;
|
||||
import org.apache.xerces.xni.parser.XMLInputSource;
|
||||
import org.apache.xerces.xni.parser.XMLParserConfiguration;
|
||||
import org.cyberneko.html.HTMLConfiguration;
|
||||
import org.cyberneko.html.filters.ElementRemover;
|
||||
import org.cyberneko.html.filters.Writer;
|
||||
import org.w3c.dom.Node;
|
||||
|
||||
/**
|
||||
* This ContentStrategy applies the path to the Indexable and retrieves the
|
||||
* plain string content from the returning node. All of the nodes text content
|
||||
* will cleaned from any html tags.
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class HTMLStrategy extends
|
||||
org.apache.lucene.gdata.search.analysis.ContentStrategy {
|
||||
private static final String REMOVE_SCRIPT = "script";
|
||||
|
||||
private static final String CHAR_ENCODING = "UTF-8";
|
||||
|
||||
protected HTMLStrategy(IndexSchemaField fieldConfiguration) {
|
||||
super(fieldConfiguration);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.lucene.gdata.search.analysis.ContentStrategy#processIndexable(org.apache.lucene.gdata.search.analysis.Indexable)
|
||||
*/
|
||||
@Override
|
||||
public void processIndexable(Indexable<? extends Node, ? extends ServerBaseEntry> indexable)
|
||||
throws NotIndexableException {
|
||||
String path = this.config.getPath();
|
||||
Node node = null;
|
||||
try {
|
||||
node = indexable.applyPath(path);
|
||||
} catch (XPathExpressionException e1) {
|
||||
throw new NotIndexableException("Can not apply path -- " + path);
|
||||
|
||||
}
|
||||
if(node == null)
|
||||
throw new NotIndexableException("Could not retrieve content for schema field: "+this.config);
|
||||
StringReader contentReader = new StringReader(node.getTextContent());
|
||||
/*
|
||||
* remove all elements and script parts
|
||||
*/
|
||||
ElementRemover remover = new ElementRemover();
|
||||
remover.removeElement(REMOVE_SCRIPT);
|
||||
StringWriter contentWriter = new StringWriter();
|
||||
Writer writer = new Writer(contentWriter, CHAR_ENCODING);
|
||||
XMLDocumentFilter[] filters = { remover, writer, };
|
||||
XMLParserConfiguration parser = new HTMLConfiguration();
|
||||
parser.setProperty("http://cyberneko.org/html/properties/filters",
|
||||
filters);
|
||||
XMLInputSource source = new XMLInputSource(null, null, null,
|
||||
contentReader, CHAR_ENCODING);
|
||||
try {
|
||||
parser.parse(source);
|
||||
} catch (XNIException e) {
|
||||
throw new NotIndexableException("Can not parse html -- ", e);
|
||||
|
||||
} catch (IOException e) {
|
||||
throw new NotIndexableException("Can not parse html -- ", e);
|
||||
|
||||
}
|
||||
this.content = contentWriter.toString();
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
|
@ -1,75 +0,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.
|
||||
*/
|
||||
package org.apache.lucene.gdata.search.analysis;
|
||||
|
||||
import javax.xml.xpath.XPathExpressionException;
|
||||
|
||||
import org.apache.lucene.gdata.data.ServerBaseEntry;
|
||||
import org.w3c.dom.Node;
|
||||
|
||||
/**
|
||||
* This class wraps the access to the GData entities to access them via xpath
|
||||
* expressions. An arbitrary valid Xpath expression can be passed to the
|
||||
* <tt>applyPath</tt> method to access an element, attribute etc. in the gdata
|
||||
* entity.
|
||||
*
|
||||
*
|
||||
* @param <R> -
|
||||
* a subtype of {@link org.w3c.dom.Node} returned by the applyPath
|
||||
* method
|
||||
* @param <I> -
|
||||
* a subtype of {@link org.apache.lucene.gdata.data.ServerBaseEntry}
|
||||
*/
|
||||
public abstract class Indexable<R extends Node, I extends ServerBaseEntry> {
|
||||
protected ServerBaseEntry applyAble;
|
||||
|
||||
/**
|
||||
* @param applyAble
|
||||
*/
|
||||
Indexable(I applyAble) {
|
||||
this.applyAble = applyAble;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param xPath -
|
||||
* a valid xpath expression
|
||||
* @return - the requested element <b>R</b>
|
||||
* @throws XPathExpressionException
|
||||
*/
|
||||
public abstract R applyPath(String xPath) throws XPathExpressionException;
|
||||
|
||||
/**
|
||||
* Factory method to create new <tt>Indexable</tt> instances.
|
||||
*
|
||||
* @param <R> -
|
||||
* a subtype of {@link org.w3c.dom.Node} returned by the
|
||||
* applyPath method
|
||||
* @param <I> -
|
||||
* a subtype of
|
||||
* {@link org.apache.lucene.gdata.data.ServerBaseEntry}
|
||||
* @param entry -
|
||||
* the entry to wrap in a <tt>Indexable</tt>
|
||||
* @return - a new instance of <tt>Indexable</tt> to access the entry via
|
||||
* Xpath
|
||||
* @throws NotIndexableException - if <b>I<b> can not be parsed.
|
||||
*/
|
||||
public static <R extends Node, I extends ServerBaseEntry> Indexable<R, I> getIndexable(
|
||||
I entry) throws NotIndexableException {
|
||||
return new DomIndexable<R, I>(entry);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,58 +0,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.
|
||||
*/
|
||||
package org.apache.lucene.gdata.search.analysis;
|
||||
|
||||
import javax.xml.xpath.XPathExpressionException;
|
||||
|
||||
import org.apache.lucene.document.Field;
|
||||
import org.apache.lucene.gdata.data.ServerBaseEntry;
|
||||
import org.apache.lucene.gdata.search.config.IndexSchemaField;
|
||||
import org.w3c.dom.Node;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class KeywordStrategy extends ContentStrategy {
|
||||
|
||||
/**
|
||||
* @param fieldConfig
|
||||
*/
|
||||
public KeywordStrategy(IndexSchemaField fieldConfig) {
|
||||
super(Field.Index.UN_TOKENIZED,Field.Store.YES,fieldConfig);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.lucene.gdata.search.analysis.ContentStrategy#processIndexable(org.apache.lucene.gdata.search.analysis.Indexable)
|
||||
*/
|
||||
@Override
|
||||
public void processIndexable(Indexable<? extends Node, ? extends ServerBaseEntry> indexable) throws NotIndexableException {
|
||||
String path = this.config.getPath();
|
||||
try {
|
||||
Node node = indexable.applyPath(path);
|
||||
if(node == null)
|
||||
throw new NotIndexableException("Could not retrieve content for schema field: "+this.config);
|
||||
this.content = node.getTextContent();
|
||||
} catch (XPathExpressionException e) {
|
||||
throw new NotIndexableException("Can not apply Path", e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
|
@ -1,97 +0,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.
|
||||
*/
|
||||
|
||||
package org.apache.lucene.gdata.search.analysis;
|
||||
|
||||
import javax.xml.xpath.XPathExpressionException;
|
||||
|
||||
import org.apache.lucene.document.Field;
|
||||
import org.apache.lucene.gdata.data.ServerBaseEntry;
|
||||
import org.apache.lucene.gdata.search.config.IndexSchemaField;
|
||||
import org.apache.lucene.gdata.search.config.IndexSchemaField.ContentType;
|
||||
import org.w3c.dom.Node;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class MixedContentStrategy extends ContentStrategy {
|
||||
protected ContentStrategy strategy;
|
||||
|
||||
protected MixedContentStrategy(IndexSchemaField fieldConfiguration) {
|
||||
super(fieldConfiguration);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws NotIndexableException
|
||||
* @see org.apache.lucene.gdata.search.analysis.ContentStrategy#processIndexable(org.apache.lucene.gdata.search.analysis.Indexable)
|
||||
*/
|
||||
@Override
|
||||
public void processIndexable(
|
||||
Indexable<? extends Node, ? extends ServerBaseEntry> indexable)
|
||||
throws NotIndexableException {
|
||||
String path = this.config.getTypePath();
|
||||
|
||||
try {
|
||||
Node node = indexable.applyPath(path);
|
||||
if (node == null)
|
||||
this.strategy = new PlainTextStrategy(this.config);
|
||||
else {
|
||||
String contentType = node.getTextContent();
|
||||
|
||||
this.strategy = chooseStrategy(contentType, this.config);
|
||||
}
|
||||
this.strategy.processIndexable(indexable);
|
||||
} catch (XPathExpressionException e) {
|
||||
throw new NotIndexableException("Can not apply path -- " + path);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.lucene.gdata.search.analysis.ContentStrategy#createLuceneField()
|
||||
*/
|
||||
@Override
|
||||
public Field[] createLuceneField() {
|
||||
|
||||
return this.strategy.createLuceneField();
|
||||
}
|
||||
|
||||
private static ContentStrategy chooseStrategy(final String contentType,
|
||||
final IndexSchemaField config) {
|
||||
ContentType type = null;
|
||||
try {
|
||||
type = ContentType.valueOf(contentType==null?"TEXT":contentType.toUpperCase());
|
||||
} catch (Throwable e) {
|
||||
type = ContentType.TEXT;
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case HTML:
|
||||
return new HTMLStrategy(config);
|
||||
|
||||
case XHTML:
|
||||
return new XHtmlStrategy(config);
|
||||
|
||||
default:
|
||||
return new PlainTextStrategy(config);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,79 +0,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.
|
||||
*/
|
||||
|
||||
package org.apache.lucene.gdata.search.analysis;
|
||||
|
||||
/**
|
||||
* This exception will be thrown by ContentStrategy instances if an exception
|
||||
* occurs while retrieving content from entries
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class NotIndexableException extends Exception {
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = 1538388864181786380L;
|
||||
|
||||
/**
|
||||
* Constructs a new NotIndexableException
|
||||
*/
|
||||
public NotIndexableException() {
|
||||
super();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new NotIndexableException with the specified detail message.
|
||||
*
|
||||
* @param arg0 -
|
||||
* detail message
|
||||
*/
|
||||
public NotIndexableException(String arg0) {
|
||||
super(arg0);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new NotIndexableException with the specified detail message
|
||||
* and nested exception.
|
||||
*
|
||||
* @param arg0 -
|
||||
* detail message
|
||||
* @param arg1 -
|
||||
* nested exception
|
||||
*/
|
||||
public NotIndexableException(String arg0, Throwable arg1) {
|
||||
super(arg0, arg1);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new NotIndexableException with a nested exception caused
|
||||
* this exception.
|
||||
*
|
||||
* @param arg0 -
|
||||
* nested exception
|
||||
*/
|
||||
public NotIndexableException(Throwable arg0) {
|
||||
super(arg0);
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -1,55 +0,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.
|
||||
*/
|
||||
|
||||
package org.apache.lucene.gdata.search.analysis;
|
||||
|
||||
import javax.xml.xpath.XPathExpressionException;
|
||||
|
||||
import org.apache.lucene.gdata.data.ServerBaseEntry;
|
||||
import org.apache.lucene.gdata.search.config.IndexSchemaField;
|
||||
import org.w3c.dom.Node;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class PlainTextStrategy extends ContentStrategy {
|
||||
|
||||
protected PlainTextStrategy(IndexSchemaField fieldConfiguration) {
|
||||
super(fieldConfiguration);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.lucene.gdata.search.analysis.ContentStrategy#processIndexable(org.apache.lucene.gdata.search.analysis.Indexable)
|
||||
*/
|
||||
@Override
|
||||
public void processIndexable(Indexable<? extends Node, ? extends ServerBaseEntry> indexable)
|
||||
throws NotIndexableException {
|
||||
String path = this.config.getPath();
|
||||
try {
|
||||
Node node = indexable.applyPath(path);
|
||||
if(node == null)
|
||||
throw new NotIndexableException("Could not retrieve content for schema field: "+this.config);
|
||||
this.content = node.getTextContent();
|
||||
|
||||
} catch (XPathExpressionException e) {
|
||||
throw new NotIndexableException("Can not apply Path", e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,30 +0,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.
|
||||
*/
|
||||
package org.apache.lucene.gdata.search.analysis;
|
||||
|
||||
import org.apache.lucene.gdata.search.config.IndexSchemaField;
|
||||
|
||||
public class XHtmlStrategy extends HTMLStrategy {
|
||||
|
||||
/**
|
||||
* @param fieldConfig
|
||||
*/
|
||||
public XHtmlStrategy(IndexSchemaField fieldConfig) {
|
||||
super(fieldConfig);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,10 +0,0 @@
|
|||
<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<meta name="Author" content="Simon Willnauer">
|
||||
</head>
|
||||
<body>
|
||||
Classes used for extracting content from entries and building lucene documents.
|
||||
</body>
|
||||
</html>
|
|
@ -1,525 +0,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.
|
||||
*/
|
||||
package org.apache.lucene.gdata.search.config;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.apache.lucene.analysis.Analyzer;
|
||||
import org.apache.lucene.analysis.PerFieldAnalyzerWrapper;
|
||||
import org.apache.lucene.analysis.standard.StandardAnalyzer;
|
||||
import org.apache.lucene.gdata.search.index.IndexDocument;
|
||||
import org.apache.lucene.gdata.utils.ReflectionUtils;
|
||||
|
||||
/**
|
||||
* This class is used to configure the indexing and search component. Each
|
||||
* service on the GData server will have an own search index. For this purpose
|
||||
* one single index schema will be configured in the gdata-config.xml file. This
|
||||
* file will be mapped on this class on startup.
|
||||
* <p>
|
||||
* This class breaks some encapsulation of general java classes to be
|
||||
* configurable via the xml configuration file. The will be very less type and
|
||||
* value checking of the properties inside this file. Mandatory values must be
|
||||
* set in the configuration file. The server won't start up if these values are
|
||||
* missing. See definition in the xml schema file. If this class is instantiated
|
||||
* manually the value for the name of the schema should be set before this is
|
||||
* passed to the IndexController.
|
||||
* </p>
|
||||
* <p>
|
||||
* One IndexSchema consists of multiple instances of
|
||||
* {@link org.apache.lucene.gdata.search.config.IndexSchemaField} each of this
|
||||
* instances describes a single field in the index and all schema informations
|
||||
* about the field.
|
||||
* <p>
|
||||
*
|
||||
*
|
||||
* @see org.apache.lucene.gdata.search.config.IndexSchemaField
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class IndexSchema {
|
||||
private final Set<String> searchableFieldNames = new HashSet<String>();
|
||||
|
||||
private static final Log LOG = LogFactory.getLog(IndexSchema.class);
|
||||
|
||||
/**
|
||||
* a static final value for properties are not set by the configuration file
|
||||
* this value will be set to all long and int properties by default
|
||||
*/
|
||||
public static final int NOT_SET_VALUE = -1;
|
||||
private static final int DEFAULT_OPTIMIZE_COUNT = 1;
|
||||
private static final int DEFAULT_COMMIT_COUNT = 1;
|
||||
|
||||
private String indexLocation;
|
||||
|
||||
/*
|
||||
* this should be final change it if possible --> see commons digester /
|
||||
* RegistryBuilder
|
||||
*/
|
||||
private String name;
|
||||
|
||||
private boolean useTimedIndexer;
|
||||
|
||||
private long indexerIdleTime = NOT_SET_VALUE;
|
||||
|
||||
private Analyzer serviceAnalyzer;
|
||||
|
||||
private String defaultSearchField;
|
||||
|
||||
private PerFieldAnalyzerWrapper perFieldAnalyzer;
|
||||
|
||||
private Collection<IndexSchemaField> schemaFields;
|
||||
|
||||
private int maxBufferedDocs = NOT_SET_VALUE;
|
||||
|
||||
private int maxMergeDocs = NOT_SET_VALUE;
|
||||
|
||||
private int mergeFactor = NOT_SET_VALUE;
|
||||
|
||||
private int maxFieldLength = NOT_SET_VALUE;
|
||||
|
||||
private long writeLockTimeout = NOT_SET_VALUE;
|
||||
|
||||
private long commitLockTimeout = NOT_SET_VALUE;
|
||||
|
||||
private int commitAfterDocuments = DEFAULT_COMMIT_COUNT;
|
||||
|
||||
private int optimizeAfterCommit = DEFAULT_OPTIMIZE_COUNT;
|
||||
|
||||
private boolean useCompoundFile = false;
|
||||
|
||||
/**
|
||||
* Creates a new IndexSchema and initialize the standard service analyzer to
|
||||
* {@link StandardAnalyzer}
|
||||
*
|
||||
*/
|
||||
public IndexSchema() {
|
||||
this.schemaFields = new ArrayList<IndexSchemaField>();
|
||||
/*
|
||||
* keep as standard if omitted in the configuration
|
||||
*/
|
||||
this.serviceAnalyzer = new StandardAnalyzer();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the schema and checks all required values
|
||||
*/
|
||||
public void initialize() {
|
||||
for (IndexSchemaField field : this.schemaFields) {
|
||||
if (!field.checkRequieredValues())
|
||||
throw new RuntimeException("Required Value for field: "
|
||||
+ field.getName() + " is missing");
|
||||
}
|
||||
if (this.defaultSearchField == null)
|
||||
throw new RuntimeException("DefaulSearchField must not be null");
|
||||
if (this.name == null)
|
||||
throw new RuntimeException(
|
||||
"Schema field is not set -- must not be null");
|
||||
if (this.indexLocation == null)
|
||||
throw new RuntimeException("IndexLocation must not be null");
|
||||
if(!this.searchableFieldNames.contains(this.defaultSearchField)){
|
||||
throw new RuntimeException("the default search field: "+this.defaultSearchField+" is registered as a field");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the useCompoundFile.
|
||||
*/
|
||||
public boolean isUseCompoundFile() {
|
||||
return this.useCompoundFile;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param useCompoundFile
|
||||
* The useCompoundFile to set.
|
||||
*/
|
||||
public void setUseCompoundFile(boolean useCompoundFile) {
|
||||
this.useCompoundFile = useCompoundFile;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a new {@link IndexSchemaField} to the schema. if the fields name
|
||||
* equals {@link IndexDocument#FIELD_ENTRY_ID} or the field is
|
||||
* <code>null</code> it will simply ignored
|
||||
*
|
||||
* @param field -
|
||||
* the index schema field to add as a field of this schema.
|
||||
*/
|
||||
public void addSchemaField(final IndexSchemaField field) {
|
||||
if (field == null)
|
||||
return;
|
||||
/*
|
||||
* skip fields configured in the gdata-config.xml file if their names
|
||||
* match a primary key field id of the IndexDocument
|
||||
*/
|
||||
if (field.getName().equals(IndexDocument.FIELD_ENTRY_ID)
|
||||
|| field.getName().equals(IndexDocument.FIELD_FEED_ID))
|
||||
return;
|
||||
if (field.getAnalyzerClass() != null) {
|
||||
/*
|
||||
* enable per field analyzer if one is set.
|
||||
*/
|
||||
Analyzer analyzer = getAnalyzerInstance(field.getAnalyzerClass());
|
||||
/*
|
||||
* null values will be omitted here
|
||||
*/
|
||||
buildPerFieldAnalyzerWrapper(analyzer, field.getName());
|
||||
}
|
||||
this.schemaFields.add(field);
|
||||
this.searchableFieldNames.add(field.getName());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return Returns the fieldConfiguration.
|
||||
*/
|
||||
public Collection<IndexSchemaField> getFields() {
|
||||
return this.schemaFields;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return - the analyzer instance to be used for this schema
|
||||
*/
|
||||
public Analyzer getSchemaAnalyzer() {
|
||||
if (this.perFieldAnalyzer == null)
|
||||
return this.serviceAnalyzer;
|
||||
return this.perFieldAnalyzer;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the serviceAnalyzer.
|
||||
*/
|
||||
public Analyzer getServiceAnalyzer() {
|
||||
return this.serviceAnalyzer;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param serviceAnalyzer
|
||||
* The serviceAnalyzer to set.
|
||||
*/
|
||||
public void setServiceAnalyzer(Analyzer serviceAnalyzer) {
|
||||
if (serviceAnalyzer == null)
|
||||
return;
|
||||
this.serviceAnalyzer = serviceAnalyzer;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the commitLockTimout.
|
||||
*/
|
||||
public long getCommitLockTimeout() {
|
||||
return this.commitLockTimeout;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param commitLockTimeout
|
||||
* The commitLockTimeout to set.
|
||||
*/
|
||||
public void setCommitLockTimeout(long commitLockTimeout) {
|
||||
// TODO enable this in config
|
||||
this.commitLockTimeout = commitLockTimeout;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the maxBufferedDocs.
|
||||
*/
|
||||
public int getMaxBufferedDocs() {
|
||||
|
||||
return this.maxBufferedDocs;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param maxBufferedDocs
|
||||
* The maxBufferedDocs to set.
|
||||
*/
|
||||
public void setMaxBufferedDocs(int maxBufferedDocs) {
|
||||
this.maxBufferedDocs = maxBufferedDocs;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the maxFieldLength.
|
||||
*/
|
||||
public int getMaxFieldLength() {
|
||||
return this.maxFieldLength;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param maxFieldLength
|
||||
* The maxFieldLength to set.
|
||||
*/
|
||||
public void setMaxFieldLength(int maxFieldLength) {
|
||||
this.maxFieldLength = maxFieldLength;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the maxMergeDocs.
|
||||
*/
|
||||
public int getMaxMergeDocs() {
|
||||
return this.maxMergeDocs;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param maxMergeDocs
|
||||
* The maxMergeDocs to set.
|
||||
*/
|
||||
public void setMaxMergeDocs(int maxMergeDocs) {
|
||||
this.maxMergeDocs = maxMergeDocs;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the mergeFactor.
|
||||
*/
|
||||
public int getMergeFactor() {
|
||||
return this.mergeFactor;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mergeFactor
|
||||
* The mergeFactor to set.
|
||||
*/
|
||||
public void setMergeFactor(int mergeFactor) {
|
||||
this.mergeFactor = mergeFactor;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the writeLockTimeout.
|
||||
*/
|
||||
public long getWriteLockTimeout() {
|
||||
return this.writeLockTimeout;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param writeLockTimeout
|
||||
* The writeLockTimeout to set.
|
||||
*/
|
||||
public void setWriteLockTimeout(long writeLockTimeout) {
|
||||
this.writeLockTimeout = writeLockTimeout;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param fields
|
||||
* The fieldConfiguration to set.
|
||||
*/
|
||||
public void setSchemaFields(Collection<IndexSchemaField> fields) {
|
||||
this.schemaFields = fields;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the name.
|
||||
*/
|
||||
public String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.lang.Object#equals(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object object) {
|
||||
if (this == object)
|
||||
return true;
|
||||
if (object == null)
|
||||
return false;
|
||||
if (object instanceof IndexSchema) {
|
||||
if(this.name ==null)
|
||||
return super.equals(object);
|
||||
return this.name.equals(((IndexSchema) object).getName());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.lang.Object#hashCode()
|
||||
*/
|
||||
@Override
|
||||
public int hashCode() {
|
||||
if (this.name == null)
|
||||
return super.hashCode();
|
||||
return this.name.hashCode();
|
||||
}
|
||||
|
||||
private void buildPerFieldAnalyzerWrapper(Analyzer anazlyer, String field) {
|
||||
if (anazlyer == null || field == null || field.length() == 0)
|
||||
return;
|
||||
if (this.perFieldAnalyzer == null)
|
||||
this.perFieldAnalyzer = new PerFieldAnalyzerWrapper(
|
||||
this.serviceAnalyzer);
|
||||
this.perFieldAnalyzer.addAnalyzer(field, anazlyer);
|
||||
}
|
||||
|
||||
private static Analyzer getAnalyzerInstance(Class<? extends Analyzer> clazz) {
|
||||
if (!ReflectionUtils.extendsType(clazz, Analyzer.class)) {
|
||||
LOG.warn("Can not create analyzer for class " + clazz.getName());
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
return clazz.newInstance();
|
||||
} catch (Exception e) {
|
||||
LOG.warn("Can not create analyzer for class " + clazz.getName());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param name
|
||||
* The name to set.
|
||||
*/
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the indexLocation.
|
||||
*/
|
||||
public String getIndexLocation() {
|
||||
return this.indexLocation;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param indexLocation
|
||||
* The indexLocation to set.
|
||||
*/
|
||||
public void setIndexLocation(String indexLocation) {
|
||||
this.indexLocation = indexLocation;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the defaultField.
|
||||
*/
|
||||
public String getDefaultSearchField() {
|
||||
return this.defaultSearchField;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param defaultField
|
||||
* The defaultField to set.
|
||||
*/
|
||||
public void setDefaultSearchField(String defaultField) {
|
||||
this.defaultSearchField = defaultField;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the indexerIdleTime.
|
||||
*/
|
||||
public long getIndexerIdleTime() {
|
||||
return this.indexerIdleTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param indexerIdleTime
|
||||
* The indexerIdleTime to set.
|
||||
*/
|
||||
public void setIndexerIdleTime(long indexerIdleTime) {
|
||||
this.indexerIdleTime = indexerIdleTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the useTimedIndexer.
|
||||
*/
|
||||
public boolean isUseTimedIndexer() {
|
||||
return this.useTimedIndexer;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param useTimedIndexer
|
||||
* The useTimedIndexer to set.
|
||||
*/
|
||||
public void setUseTimedIndexer(boolean useTimedIndexer) {
|
||||
this.useTimedIndexer = useTimedIndexer;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.lang.Object#toString()
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder builder = new StringBuilder(this.getClass().getName())
|
||||
.append(" ");
|
||||
builder.append("Name: ").append(this.name).append(" ");
|
||||
builder.append("MaxBufferedDocs: ").append(this.maxBufferedDocs)
|
||||
.append(" ");
|
||||
builder.append("MaxFieldLength: ").append(this.maxFieldLength).append(
|
||||
" ");
|
||||
builder.append("MaxMergeDocs: ").append(this.maxMergeDocs).append(" ");
|
||||
builder.append("MergeFactor: ").append(this.mergeFactor).append(" ");
|
||||
builder.append("CommitLockTimeout: ").append(this.commitLockTimeout)
|
||||
.append(" ");
|
||||
builder.append("WriteLockTimeout: ").append(this.writeLockTimeout)
|
||||
.append(" ");
|
||||
builder.append("indexerIdleTime: ").append(this.indexerIdleTime)
|
||||
.append(" ");
|
||||
builder.append("useCompoundFile: ").append(this.useCompoundFile)
|
||||
.append(" ");
|
||||
builder.append("Added SchemaField instances: ").append(
|
||||
this.schemaFields.size()).append(" ");
|
||||
|
||||
builder.append("IndexLocation: ").append(this.indexLocation)
|
||||
.append(" ");
|
||||
return builder.toString();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the searchableFieldNames.
|
||||
*/
|
||||
public Set<String> getSearchableFieldNames() {
|
||||
return this.searchableFieldNames;
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines after how many added,removed or updated document the indexer should commit.
|
||||
* @return Returns the commitAfterDocuments.
|
||||
*/
|
||||
public int getCommitAfterDocuments() {
|
||||
return this.commitAfterDocuments;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param commitAfterDocuments The commitAfterDocuments to set.
|
||||
*/
|
||||
public void setCommitAfterDocuments(int commitAfterDocuments) {
|
||||
if(commitAfterDocuments < DEFAULT_COMMIT_COUNT)
|
||||
return;
|
||||
this.commitAfterDocuments = commitAfterDocuments;
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines after how many commits the indexer should optimize the index
|
||||
* @return Returns the optimizeAfterCommit.
|
||||
*/
|
||||
public int getOptimizeAfterCommit() {
|
||||
|
||||
return this.optimizeAfterCommit;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param optimizeAfterCommit The optimizeAfterCommit to set.
|
||||
*/
|
||||
public void setOptimizeAfterCommit(int optimizeAfterCommit) {
|
||||
if(optimizeAfterCommit < DEFAULT_OPTIMIZE_COUNT )
|
||||
return;
|
||||
this.optimizeAfterCommit = optimizeAfterCommit;
|
||||
}
|
||||
}
|
|
@ -1,380 +0,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.
|
||||
*/
|
||||
|
||||
package org.apache.lucene.gdata.search.config;
|
||||
|
||||
import org.apache.lucene.analysis.Analyzer;
|
||||
import org.apache.lucene.document.Field;
|
||||
import org.apache.lucene.document.Field.Index;
|
||||
import org.apache.lucene.document.Field.Store;
|
||||
import org.apache.lucene.gdata.search.analysis.ContentStrategy;
|
||||
import org.apache.lucene.gdata.search.analysis.GdataCategoryStrategy;
|
||||
import org.apache.lucene.gdata.search.analysis.GdataDateStrategy;
|
||||
import org.apache.lucene.gdata.search.analysis.HTMLStrategy;
|
||||
import org.apache.lucene.gdata.search.analysis.KeywordStrategy;
|
||||
import org.apache.lucene.gdata.search.analysis.MixedContentStrategy;
|
||||
import org.apache.lucene.gdata.search.analysis.PlainTextStrategy;
|
||||
import org.apache.lucene.gdata.search.analysis.XHtmlStrategy;
|
||||
import org.apache.lucene.gdata.utils.ReflectionUtils;
|
||||
|
||||
/**
|
||||
* Each field in the search index is defined by a instance of
|
||||
* {@link IndexSchemaField}. The schema definition will be loaded at startup
|
||||
* and the defined values will be set to instances of this class. Each
|
||||
* constructed field will be passed to an instance of
|
||||
* {@link org.apache.lucene.gdata.search.config.IndexSchema}.
|
||||
* <p>
|
||||
* IndexSchemaField contains all informations about how the content from
|
||||
* incoming entries has to be extracted and how the actual content has to be
|
||||
* index into the lucene index.
|
||||
* </p>
|
||||
* <p>
|
||||
* Each field will have a defined
|
||||
* {@link org.apache.lucene.gdata.search.analysis.ContentStrategy} which does
|
||||
* process the extraction of the field content from an incoming entry.
|
||||
* </p>
|
||||
* @see org.apache.lucene.gdata.search.analysis.ContentStrategy
|
||||
* @see org.apache.lucene.gdata.search.config.IndexSchema
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class IndexSchemaField {
|
||||
/**
|
||||
* Default value for Field.Store
|
||||
* @see org.apache.lucene.document.Field
|
||||
*/
|
||||
public static final Store DEFAULT_STORE_STRATEGY = Field.Store.NO;
|
||||
/**
|
||||
* Default value for Field.Index
|
||||
* @see org.apache.lucene.document.Field
|
||||
*/
|
||||
public static final Index DEFAULT_INDEX_STRATEGY = Field.Index.TOKENIZED;
|
||||
private static final float DEFAULT_BOOST = 1.0f;
|
||||
private static final float MINIMAL_BOOST = 0.1f;
|
||||
private float boost = DEFAULT_BOOST;
|
||||
|
||||
private String name;
|
||||
|
||||
private ContentType contentType;
|
||||
|
||||
private Index index = DEFAULT_INDEX_STRATEGY;
|
||||
|
||||
private Store store = DEFAULT_STORE_STRATEGY;
|
||||
|
||||
private String path;
|
||||
|
||||
private String typePath;
|
||||
|
||||
private Class<? extends Analyzer> analyzerClass;
|
||||
|
||||
private Class<? extends ContentStrategy> fieldClass;
|
||||
|
||||
/**
|
||||
* Constructs a new SchemaField <br>
|
||||
* Default values:
|
||||
* <ol>
|
||||
* <li>boost: <i>1.0</i></li>
|
||||
* <li>index: <i>TOKENIZED</i></li>
|
||||
* <li>store: <i>NO</i></li>
|
||||
* </ol>
|
||||
*/
|
||||
public IndexSchemaField() {
|
||||
super();
|
||||
}
|
||||
boolean checkRequieredValues(){
|
||||
/*
|
||||
* This class will be inst. by the reg builder.
|
||||
* Check all values to be set. otherwise return false.
|
||||
* false will cause a runtime exception in IndexSchema
|
||||
*/
|
||||
boolean returnValue = (this.name != null&&this.path!=null&&this.contentType!=null&&this.index!=null&&this.store!=null&&this.boost>=MINIMAL_BOOST);
|
||||
if(this.contentType == ContentType.CUSTOM)
|
||||
returnValue &=this.fieldClass!=null;
|
||||
else if(this.contentType == ContentType.MIXED)
|
||||
returnValue &=this.typePath!=null;
|
||||
|
||||
return returnValue;
|
||||
}
|
||||
/**
|
||||
* @return Returns the alanyzerClass.
|
||||
*/
|
||||
public Class<? extends Analyzer> getAnalyzerClass() {
|
||||
return this.analyzerClass;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param alanyzerClass
|
||||
* The alanyzerClass to set.
|
||||
*/
|
||||
public void setAnalyzerClass(Class<? extends Analyzer> alanyzerClass) {
|
||||
this.analyzerClass = alanyzerClass;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the fieldClass.
|
||||
*/
|
||||
public Class<? extends ContentStrategy> getFieldClass() {
|
||||
return this.fieldClass;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the class or strategy is used to extract this field Attention: this
|
||||
* method set the contentTyp to {@link ContentType#CUSTOM}
|
||||
*
|
||||
* @param fieldClass
|
||||
* The fieldClass to set.
|
||||
*/
|
||||
public void setFieldClass(Class<? extends ContentStrategy> fieldClass) {
|
||||
if(fieldClass == null)
|
||||
throw new IllegalArgumentException("ContentStrategy must not be null");
|
||||
if(!ReflectionUtils.extendsType(fieldClass,ContentStrategy.class))
|
||||
throw new RuntimeException("The configured ContentStrategy does not extend ContentStrategy, can not use as a custom strategy -- "+fieldClass.getName());
|
||||
if(!ReflectionUtils.hasDesiredConstructor(fieldClass,new Class[]{IndexSchemaField.class}))
|
||||
throw new RuntimeException("Can not create instance of "+fieldClass.getName());
|
||||
this.fieldClass = fieldClass;
|
||||
/*
|
||||
* set custom - field class is only needed by custom
|
||||
*/
|
||||
this.contentType = ContentType.CUSTOM;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the index.
|
||||
*/
|
||||
public Index getIndex() {
|
||||
return this.index;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param index
|
||||
* The index to set.
|
||||
*/
|
||||
public void setIndex(Index index) {
|
||||
this.index = index;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the name.
|
||||
*/
|
||||
public String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param name
|
||||
* The name to set.
|
||||
*/
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the path.
|
||||
*/
|
||||
public String getPath() {
|
||||
return this.path;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param path
|
||||
* The path to set.
|
||||
*/
|
||||
public void setPath(String path) {
|
||||
this.path = path;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the store.
|
||||
*/
|
||||
public Store getStore() {
|
||||
return this.store;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param store
|
||||
* The store to set.
|
||||
*/
|
||||
public void setStore(Store store) {
|
||||
this.store = store;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the type.
|
||||
*/
|
||||
public ContentType getContentType() {
|
||||
return this.contentType;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param type
|
||||
* The type to set.
|
||||
*/
|
||||
public void setContentType(ContentType type) {
|
||||
this.contentType = type;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the content type of this field by the name of the enum type. This
|
||||
* method is not case sensitive.
|
||||
*
|
||||
* @param type -
|
||||
* type name as string
|
||||
*/
|
||||
public void setType(String type) {
|
||||
ContentType[] types = ContentType.class.getEnumConstants();
|
||||
for (int i = 0; i < types.length; i++) {
|
||||
if (types[i].name().toLowerCase().equals(type)) {
|
||||
this.contentType = types[i];
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines the {@link ContentStrategy} to use for a
|
||||
* <tt>IndexSchemaField</tt> to extract the content from the entry
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
public enum ContentType {
|
||||
|
||||
/**
|
||||
* HTML content strategy {@link HTMLStrategy }
|
||||
*/
|
||||
HTML,
|
||||
/**
|
||||
* XHTML content strategy {@link XHtmlStrategy }
|
||||
*/
|
||||
XHTML,
|
||||
/**
|
||||
* Text content strategy {@link PlainTextStrategy }
|
||||
*/
|
||||
TEXT,
|
||||
/**
|
||||
* GDataDate content strategy {@link GdataDateStrategy }
|
||||
*/
|
||||
GDATADATE,
|
||||
/**
|
||||
* KEYWORD content strategy {@link KeywordStrategy }
|
||||
*/
|
||||
KEYWORD,
|
||||
/**
|
||||
* Category content strategy {@link GdataCategoryStrategy }
|
||||
*/
|
||||
CATEGORY,
|
||||
/**
|
||||
* Custom content strategy (user defined)
|
||||
*/
|
||||
CUSTOM,
|
||||
/**
|
||||
* Mixed content strategy {@link MixedContentStrategy }
|
||||
*/
|
||||
MIXED
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the boost.
|
||||
*/
|
||||
public float getBoost() {
|
||||
return this.boost;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param boost
|
||||
* The boost to set.
|
||||
*/
|
||||
public void setBoost(float boost) {
|
||||
if (boost <= 0)
|
||||
return;
|
||||
this.boost = boost;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.lang.Object#toString()
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder builder = new StringBuilder(this.getClass()
|
||||
.getSimpleName()).append(" ");
|
||||
builder.append("field name: ").append(this.name).append(" ");
|
||||
builder.append("path: ").append(this.path).append(" ");
|
||||
builder.append("content type ").append(this.contentType).append(" ");
|
||||
builder.append("field class: ").append(this.fieldClass).append(" ");
|
||||
builder.append("analyzer: ").append(this.analyzerClass).append(" ");
|
||||
builder.append("boost: ").append(this.boost).append(" ");
|
||||
builder.append("INDEX: ").append(this.index).append(" ");
|
||||
builder.append("STORE: ").append(this.store);
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the Store class by simple name
|
||||
*
|
||||
* @param name -
|
||||
* one of yes, no, compress
|
||||
*/
|
||||
public void setStoreByName(String name) {
|
||||
if (name.toLowerCase().equals("yes"))
|
||||
this.store = Field.Store.YES;
|
||||
else if (name.toLowerCase().equals("no"))
|
||||
this.store = Field.Store.NO;
|
||||
else if (name.toLowerCase().equals("compress"))
|
||||
this.store = Field.Store.COMPRESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the Index class by simple name
|
||||
*
|
||||
* @param name -
|
||||
* un_tokenized, tokenized, no, no_norms
|
||||
*/
|
||||
public void setIndexByName(String name) {
|
||||
if (name.toLowerCase().equals("un_tokenized"))
|
||||
this.index = Field.Index.UN_TOKENIZED;
|
||||
else if (name.toLowerCase().equals("tokenized"))
|
||||
this.index = Field.Index.TOKENIZED;
|
||||
else if (name.toLowerCase().equals("no_norms"))
|
||||
this.index = Field.Index.NO_NORMS;
|
||||
else if (name.toLowerCase().equals("no"))
|
||||
this.index = Field.Index.NO;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the typePath.
|
||||
*/
|
||||
public String getTypePath() {
|
||||
return this.typePath;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param typePath
|
||||
* The typePath to set.
|
||||
*/
|
||||
public void setTypePath(String typePath) {
|
||||
this.typePath = typePath;
|
||||
/*
|
||||
* set Mixed - this property is only needed by mixed type
|
||||
*/
|
||||
setContentType(ContentType.MIXED);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,10 +0,0 @@
|
|||
<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<meta name="Author" content="Simon Willnauer">
|
||||
</head>
|
||||
<body>
|
||||
All classes used for index and search configuration
|
||||
</body>
|
||||
</html>
|
|
@ -1,167 +0,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.
|
||||
*/
|
||||
package org.apache.lucene.gdata.search.index;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import org.apache.lucene.document.Document;
|
||||
import org.apache.lucene.document.Field;
|
||||
import org.apache.lucene.gdata.search.analysis.ContentStrategy;
|
||||
import org.apache.lucene.index.Term;
|
||||
|
||||
/**
|
||||
* Simple implementation
|
||||
*
|
||||
*
|
||||
* @see org.apache.lucene.gdata.search.index.IndexDocument
|
||||
*/
|
||||
class GDataIndexDocument implements IndexDocument {
|
||||
private final IndexAction action;
|
||||
|
||||
private final boolean commitAfter;
|
||||
|
||||
private final boolean optimizeAfter;
|
||||
|
||||
private String id;
|
||||
|
||||
protected Collection<ContentStrategy> fields;
|
||||
|
||||
private final String feedId;
|
||||
|
||||
GDataIndexDocument(final IndexAction action, final String entryId,final String feedId,final boolean commitAfter,final boolean optimizeAfter) {
|
||||
this.action = action;
|
||||
this.id = entryId;
|
||||
this.feedId = feedId;
|
||||
this.fields = new ArrayList<ContentStrategy>(10);
|
||||
this.commitAfter = commitAfter;
|
||||
this.optimizeAfter = optimizeAfter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a new field e.g. <tt>ContentStrategy</tt> to the IndexDocument
|
||||
*
|
||||
* @param field -
|
||||
* the strategy to add
|
||||
*/
|
||||
public void addField(ContentStrategy field) {
|
||||
if (field == null)
|
||||
return;
|
||||
this.fields.add(field);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.lucene.gdata.search.index.IndexDocument#getWriteable()
|
||||
*/
|
||||
public Document getWriteable() {
|
||||
Document retVal = new Document();
|
||||
retVal.add(new Field(FIELD_ENTRY_ID, this.id, Field.Store.YES,
|
||||
Field.Index.UN_TOKENIZED));
|
||||
retVal.add(new Field(FIELD_FEED_ID, this.feedId, Field.Store.YES,
|
||||
Field.Index.UN_TOKENIZED));
|
||||
for (ContentStrategy strategy : this.fields) {
|
||||
Field[] fieldArray = strategy.createLuceneField();
|
||||
for (int i = 0; i < fieldArray.length; i++) {
|
||||
retVal.add(fieldArray[i]);
|
||||
}
|
||||
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.lucene.gdata.search.index.IndexDocument#getDeletealbe()
|
||||
*/
|
||||
public Term getDeletealbe() {
|
||||
|
||||
return new Term(IndexDocument.FIELD_ENTRY_ID, this.id);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.lucene.gdata.search.index.IndexDocument#isUpdate()
|
||||
*/
|
||||
public boolean isUpdate() {
|
||||
|
||||
return isAction(IndexAction.UPDATE);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.lucene.gdata.search.index.IndexDocument#isDelete()
|
||||
*/
|
||||
public boolean isDelete() {
|
||||
|
||||
return isAction(IndexAction.DELETE);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.lucene.gdata.search.index.IndexDocument#isInsert()
|
||||
*/
|
||||
public boolean isInsert() {
|
||||
|
||||
return isAction(IndexAction.INSERT);
|
||||
}
|
||||
|
||||
private boolean isAction(IndexAction indexAction) {
|
||||
return this.action == indexAction;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.lucene.gdata.search.index.IndexDocument#commitAfter()
|
||||
*/
|
||||
public boolean commitAfter() {
|
||||
|
||||
return this.commitAfter;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.lucene.gdata.search.index.IndexDocument#optimizeAfter()
|
||||
*/
|
||||
public boolean optimizeAfter() {
|
||||
|
||||
return this.optimizeAfter;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.lang.Object#equals(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public final boolean equals(Object obj) {
|
||||
if(obj == null)
|
||||
return false;
|
||||
if(this == obj)
|
||||
return true;
|
||||
if(obj instanceof GDataIndexDocument){
|
||||
GDataIndexDocument other = (GDataIndexDocument)obj;
|
||||
if(this.id == null)
|
||||
return false;
|
||||
return this.id.equals(other.id);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.lang.Object#hashCode()
|
||||
*/
|
||||
@Override
|
||||
public final int hashCode() {
|
||||
if(this.id == null)
|
||||
return super.hashCode();
|
||||
return this.id.hashCode();
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
|
@ -1,105 +0,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.
|
||||
*/
|
||||
|
||||
package org.apache.lucene.gdata.search.index;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.apache.lucene.analysis.standard.StandardAnalyzer;
|
||||
import org.apache.lucene.gdata.search.config.IndexSchema;
|
||||
import org.apache.lucene.index.IndexWriter;
|
||||
import org.apache.lucene.index.LogDocMergePolicy;
|
||||
import org.apache.lucene.store.Directory;
|
||||
|
||||
/**
|
||||
* Configurable decorator for a lucene {@link IndexWriter}
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class GDataIndexWriter extends IndexWriter {
|
||||
private static final Log LOG = LogFactory.getLog(GDataIndexWriter.class);
|
||||
|
||||
private String serviceName;
|
||||
|
||||
private void initialize(IndexSchema config) {
|
||||
this.serviceName = config.getName();
|
||||
setUseCompoundFile(config.isUseCompoundFile());
|
||||
if (config.getMaxBufferedDocs() != IndexSchema.NOT_SET_VALUE)
|
||||
setMaxBufferedDocs(config.getMaxBufferedDocs());
|
||||
if (config.getMaxMergeDocs() != IndexSchema.NOT_SET_VALUE && getMergePolicy() instanceof LogDocMergePolicy)
|
||||
setMaxMergeDocs(config.getMaxMergeDocs());
|
||||
if (config.getMergeFactor() != IndexSchema.NOT_SET_VALUE)
|
||||
setMergeFactor(config.getMergeFactor());
|
||||
if (config.getMaxFieldLength() != IndexSchema.NOT_SET_VALUE)
|
||||
setMaxFieldLength(config.getMaxFieldLength());
|
||||
if (config.getWriteLockTimeout() != IndexSchema.NOT_SET_VALUE)
|
||||
setWriteLockTimeout(config.getWriteLockTimeout());
|
||||
//no commit lock anymore
|
||||
//TODO fix this
|
||||
// if (config.getCommitLockTimeout() != IndexSchema.NOT_SET_VALUE)
|
||||
// setCommitLockTimeout(config.getCommitLockTimeout());
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates and configures a new GdataIndexWriter
|
||||
*
|
||||
* @param arg0 -
|
||||
* the index directory
|
||||
* @param arg1 -
|
||||
* create index
|
||||
* @param arg2 -
|
||||
* the index schema configuration including all parameter to set
|
||||
* up the index writer
|
||||
* @throws IOException
|
||||
* -if the directory cannot be read/written to, or if it does
|
||||
* not exist, and <code>create</code> is <code>false</code>
|
||||
*/
|
||||
protected GDataIndexWriter(Directory arg0, boolean arg1, IndexSchema arg2)
|
||||
throws IOException {
|
||||
/*
|
||||
* Use Schema Analyzer rather than service analyzer.
|
||||
* Schema analyzer returns either the service analyzer or a per field analyzer if configured.
|
||||
*/
|
||||
super(arg0, (arg2 == null ? new StandardAnalyzer() : arg2.getSchemaAnalyzer()), arg1);
|
||||
if (arg2 == null) {
|
||||
/*
|
||||
* if no schema throw exception - schema is mandatory for the index writer.
|
||||
*/
|
||||
try {
|
||||
this.close();
|
||||
} catch (IOException e) {
|
||||
//
|
||||
}
|
||||
throw new IllegalArgumentException("configuration must not be null");
|
||||
|
||||
}
|
||||
this.initialize(arg2);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.lucene.index.IndexWriter#close()
|
||||
*/
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
super.close();
|
||||
LOG.info("Closing GdataIndexWriter for service " + this.serviceName);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,517 +0,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.
|
||||
*/
|
||||
package org.apache.lucene.gdata.search.index;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.apache.lucene.gdata.search.config.IndexSchema;
|
||||
import org.apache.lucene.index.IndexReader;
|
||||
import org.apache.lucene.index.IndexWriter;
|
||||
import org.apache.lucene.index.TermDocs;
|
||||
import org.apache.lucene.search.IndexSearcher;
|
||||
import org.apache.lucene.store.Directory;
|
||||
|
||||
/**
|
||||
* A GDataIndexer encapsulates every writing access to the search index.
|
||||
* <p>
|
||||
* Insert, updates and deletes to the index happens inside this class. All
|
||||
* modification will be base on an instance of
|
||||
* {@link org.apache.lucene.gdata.search.index.IndexDocument} which contains all
|
||||
* informations and command for the indexer.<br>
|
||||
* Although this class provides methods to add, remove and update document in
|
||||
* the index all <tt>IndexDocument</tt> instances should be added to the task
|
||||
* queue via the {@link GDataIndexer#addIndexableDocumentTask(Future)} method.
|
||||
* Inside this class runs an instance of
|
||||
* {@link org.apache.lucene.gdata.search.index.IndexTask} listening on this
|
||||
* queue. The analysis of the actual documents happens inside the
|
||||
* {@link java.util.concurrent.Future} object added to the
|
||||
* queue. This enables the indexer to do his actual work. Documents will be
|
||||
* build / analyzed concurrently while already finished tasks can be added to
|
||||
* the index.
|
||||
* </p>
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class GDataIndexer {
|
||||
private static final Log LOG = LogFactory.getLog(GDataIndexer.class);
|
||||
|
||||
protected IndexWriter writer;
|
||||
|
||||
protected IndexSearcher searcher;
|
||||
|
||||
protected AtomicInteger committed = new AtomicInteger(0);
|
||||
|
||||
protected AtomicInteger optimized = new AtomicInteger(0);
|
||||
|
||||
private AtomicBoolean isDestroyed = new AtomicBoolean(false);
|
||||
|
||||
protected AtomicInteger docsAdded = new AtomicInteger();
|
||||
|
||||
protected AtomicInteger docsUpdated = new AtomicInteger();
|
||||
|
||||
protected AtomicInteger docsDeleted = new AtomicInteger();
|
||||
|
||||
private final Directory dir;
|
||||
|
||||
private final List<IndexEventListener> listeners = new ArrayList<IndexEventListener>();
|
||||
|
||||
protected final BlockingQueue<Future<IndexDocument>> futurQueue = new LinkedBlockingQueue<Future<IndexDocument>>(
|
||||
100);
|
||||
|
||||
private final IndexSchema serviceConfiguration;
|
||||
|
||||
private final ExecutorService indexTaskExecutor;
|
||||
|
||||
protected IndexTask indexTask;
|
||||
|
||||
private static final Integer ZERO = new Integer(0);
|
||||
|
||||
private static final Integer ONE = new Integer(1);
|
||||
|
||||
private final Map<IndexDocument, Integer> action;
|
||||
|
||||
protected GDataIndexer(final IndexSchema schema, Directory dir,
|
||||
boolean create) throws IOException {
|
||||
if (schema == null)
|
||||
throw new IllegalArgumentException(
|
||||
"IndexServiceConfiguration must not be null");
|
||||
if (dir == null)
|
||||
throw new IllegalArgumentException(
|
||||
"IndexDirectory must not be null");
|
||||
|
||||
this.serviceConfiguration = schema;
|
||||
this.dir = dir;
|
||||
openWriter(create);
|
||||
this.indexTaskExecutor = Executors.newSingleThreadExecutor();
|
||||
this.action = new HashMap<IndexDocument, Integer>(128);
|
||||
|
||||
}
|
||||
|
||||
protected void setIndexTask(final IndexTask task) {
|
||||
if (task != null && this.indexTask == null)
|
||||
this.indexTask = task;
|
||||
}
|
||||
|
||||
protected void init() {
|
||||
if (this.indexTask == null)
|
||||
this.indexTask = new IndexTask(this, this.futurQueue);
|
||||
this.indexTaskExecutor.execute(this.indexTask);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the given future task to the queue, and waits if the queue is full.
|
||||
* The queue size is set to 100 by default.
|
||||
*
|
||||
* @param task -
|
||||
* the task to be scheduled
|
||||
* @throws InterruptedException -
|
||||
* if the queue is interrupted
|
||||
*/
|
||||
public void addIndexableDocumentTask(final Future<IndexDocument> task)
|
||||
throws InterruptedException {
|
||||
if (this.isDestroyed.get())
|
||||
throw new IllegalStateException(
|
||||
"Indexer has already been destroyed");
|
||||
this.futurQueue.put(task);
|
||||
}
|
||||
|
||||
/*
|
||||
* a added doc should not be in the index, be sure and delete possible
|
||||
* duplicates
|
||||
*/
|
||||
protected synchronized void addDocument(IndexDocument indexable)
|
||||
throws IOException {
|
||||
if (!indexable.isInsert())
|
||||
throw new GdataIndexerException(
|
||||
"Index action must be set to insert");
|
||||
setAction(indexable);
|
||||
doWrite(indexable);
|
||||
this.docsAdded.incrementAndGet();
|
||||
|
||||
}
|
||||
|
||||
private void setAction(IndexDocument doc) {
|
||||
Integer docCountToKeep = this.action.get(doc);
|
||||
if (!doc.isDelete() && (docCountToKeep == null || docCountToKeep == 0)) {
|
||||
/*
|
||||
* add a ONE for ONE documents to keep for this IndexDocument when
|
||||
* doDelete. doDelete will keep the latest added document and
|
||||
* deletes all other documents for this IndexDocument e.g. all
|
||||
* duplicates
|
||||
*/
|
||||
this.action.put(doc, ONE);
|
||||
} else if (doc.isDelete()
|
||||
&& (docCountToKeep == null || docCountToKeep > 0)) {
|
||||
/*
|
||||
* add a zero for zero documents to keep for this IndexDocument when
|
||||
* doDelete
|
||||
*/
|
||||
this.action.put(doc, ZERO);
|
||||
}
|
||||
}
|
||||
|
||||
protected synchronized void updateDocument(IndexDocument indexable)
|
||||
throws IOException {
|
||||
if (!indexable.isUpdate())
|
||||
throw new GdataIndexerException(
|
||||
"Index action must be set to update");
|
||||
setAction(indexable);
|
||||
doWrite(indexable);
|
||||
this.docsUpdated.incrementAndGet();
|
||||
}
|
||||
|
||||
protected synchronized void deleteDocument(IndexDocument indexable) {
|
||||
if (!indexable.isDelete())
|
||||
throw new GdataIndexerException(
|
||||
"Index action must be set to delete");
|
||||
|
||||
setAction(indexable);
|
||||
this.docsDeleted.incrementAndGet();
|
||||
}
|
||||
|
||||
/**
|
||||
* This method commits all changes to the index and closes all open
|
||||
* resources (e.g. IndexWriter and IndexReader). This method notifies all
|
||||
* registered Commit listeners if invoked.
|
||||
*
|
||||
* @param optimize -
|
||||
* <code>true</code> if the index should be optimized on this
|
||||
* commit
|
||||
* @throws IOException -
|
||||
* if an IOException occurs
|
||||
*/
|
||||
protected synchronized void commit(boolean optimize) throws IOException {
|
||||
if (LOG.isInfoEnabled())
|
||||
LOG.info("Commit called with optimize = " + optimize);
|
||||
|
||||
int changes = this.docsAdded.intValue() + this.docsDeleted.intValue()
|
||||
+ this.docsUpdated.intValue();
|
||||
/*
|
||||
* don't call listeners to prevent unnecessary close / open of searchers
|
||||
*/
|
||||
if (changes == 0)
|
||||
return;
|
||||
this.committed.incrementAndGet();
|
||||
if(optimize)
|
||||
this.optimized.incrementAndGet();
|
||||
doDeltete();
|
||||
if (optimize) {
|
||||
closeSearcher();
|
||||
openWriter();
|
||||
this.writer.optimize();
|
||||
}
|
||||
closeSearcher();
|
||||
closeWriter();
|
||||
this.docsAdded.set(0);
|
||||
this.docsDeleted.set(0);
|
||||
this.docsUpdated.set(0);
|
||||
notifyCommitListeners(this.serviceConfiguration.getName());
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a new IndexEventListener. All registered listeners will be
|
||||
* notified if the index has been committed.
|
||||
*
|
||||
* @param listener -
|
||||
* the listener to register
|
||||
*
|
||||
*/
|
||||
public void registerIndexEventListener(IndexEventListener listener) {
|
||||
if (listener == null || this.listeners.contains(listener))
|
||||
return;
|
||||
this.listeners.add(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a registered IndexEventListener
|
||||
*
|
||||
* @param listener -
|
||||
* the listener to remove
|
||||
*/
|
||||
public void removeIndexEventListener(IndexEventListener listener) {
|
||||
|
||||
if (listener == null || !this.listeners.contains(listener))
|
||||
return;
|
||||
this.listeners.remove(listener);
|
||||
}
|
||||
|
||||
protected void notifyCommitListeners(String serviceId) {
|
||||
if (LOG.isInfoEnabled())
|
||||
LOG.info("notify commit event listeners for service id: "
|
||||
+ serviceId + " -- current size of registered listeners: "
|
||||
+ this.listeners.size());
|
||||
for (IndexEventListener listener : this.listeners) {
|
||||
listener.commitCallBack(serviceId);
|
||||
}
|
||||
}
|
||||
|
||||
protected void closeWriter() throws IOException {
|
||||
try {
|
||||
if (this.writer != null)
|
||||
this.writer.close();
|
||||
} finally {
|
||||
this.writer = null;
|
||||
}
|
||||
}
|
||||
|
||||
protected void closeSearcher() throws IOException {
|
||||
try {
|
||||
if (this.searcher != null)
|
||||
this.searcher.close();
|
||||
} finally {
|
||||
this.searcher = null;
|
||||
}
|
||||
}
|
||||
|
||||
protected void openSearcher() throws IOException {
|
||||
if (this.searcher == null)
|
||||
this.searcher = new IndexSearcher(this.dir);
|
||||
}
|
||||
|
||||
protected void openWriter() throws IOException {
|
||||
openWriter(false);
|
||||
}
|
||||
|
||||
private void openWriter(boolean create) throws IOException {
|
||||
if (this.writer == null)
|
||||
this.writer = new GDataIndexWriter(this.dir, create,
|
||||
this.serviceConfiguration);
|
||||
}
|
||||
|
||||
/*
|
||||
* This should only be called in a synchronized block
|
||||
*/
|
||||
protected void doWrite(IndexDocument document) throws IOException {
|
||||
closeSearcher();
|
||||
openWriter();
|
||||
this.writer.addDocument(document.getWriteable());
|
||||
|
||||
}
|
||||
|
||||
// only access synchronized
|
||||
int[] documentNumber;
|
||||
|
||||
/*
|
||||
* This should only be called in a synchronized block
|
||||
*/
|
||||
protected void doDeltete() throws IOException {
|
||||
if (this.action.size() == 0)
|
||||
return;
|
||||
if (LOG.isInfoEnabled())
|
||||
LOG
|
||||
.info("Deleting documents and duplicates from index, size of IndexDocuments "
|
||||
+ this.action.size());
|
||||
closeWriter();
|
||||
openSearcher();
|
||||
|
||||
IndexReader reader = this.searcher.getIndexReader();
|
||||
TermDocs termDocs = reader.termDocs();
|
||||
for (Map.Entry<IndexDocument, Integer> entry : this.action.entrySet()) {
|
||||
IndexDocument indexDocument = entry.getKey();
|
||||
Integer docToKeep = entry.getValue();
|
||||
// extend the array if needed
|
||||
if (this.documentNumber == null
|
||||
|| docToKeep > this.documentNumber.length)
|
||||
this.documentNumber = new int[docToKeep];
|
||||
|
||||
for (int i = 0; i < this.documentNumber.length; i++) {
|
||||
|
||||
this.documentNumber[i] = -1;
|
||||
}
|
||||
/*
|
||||
* get the term to find the document from the document itself
|
||||
*/
|
||||
termDocs.seek(indexDocument.getDeletealbe());
|
||||
|
||||
int pos = 0;
|
||||
|
||||
while (termDocs.next()) {
|
||||
/*
|
||||
* if this is a pure delete just delete it an continue
|
||||
*/
|
||||
if (docToKeep == 0) {
|
||||
reader.deleteDocument(termDocs.doc());
|
||||
continue;
|
||||
}
|
||||
|
||||
int prev = this.documentNumber[pos];
|
||||
this.documentNumber[pos] = termDocs.doc();
|
||||
if (prev != -1) {
|
||||
reader.deleteDocument(prev);
|
||||
}
|
||||
|
||||
if (++pos >= docToKeep)
|
||||
pos = 0;
|
||||
|
||||
}
|
||||
}
|
||||
/*
|
||||
* clear the map after all documents are processed
|
||||
*/
|
||||
this.action.clear();
|
||||
closeSearcher();
|
||||
}
|
||||
|
||||
protected synchronized void destroy() throws IOException {
|
||||
this.isDestroyed.set(true);
|
||||
if (!this.indexTask.isStopped())
|
||||
this.indexTask.stop();
|
||||
this.futurQueue.add(new FinishingFuture());
|
||||
this.indexTaskExecutor.shutdown();
|
||||
closeWriter();
|
||||
closeSearcher();
|
||||
if (LOG.isInfoEnabled())
|
||||
LOG.info("Destroying GdataIndexer for service -- "
|
||||
+ this.serviceConfiguration.getName());
|
||||
|
||||
}
|
||||
|
||||
// Used only for testing
|
||||
protected synchronized IndexWriter getWriter() {
|
||||
return this.writer;
|
||||
}
|
||||
|
||||
/**
|
||||
* This factory method creates a new GDataIndexer using a instance of
|
||||
* {@link org.apache.lucene.gdata.search.index.IndexTask}
|
||||
*
|
||||
* @param config -
|
||||
* the config to be used to configure the indexer
|
||||
* @param dir -
|
||||
* the directory to index to
|
||||
* @param create -
|
||||
* <code>true</code> to create a new index, <code>false</code>
|
||||
* to use the existing one.
|
||||
* @return - a new GDataIndexer instance
|
||||
* @throws IOException -
|
||||
* if an IOException occurs while initializing the indexer
|
||||
*/
|
||||
public static synchronized GDataIndexer createGdataIndexer(
|
||||
final IndexSchema config, Directory dir, boolean create)
|
||||
throws IOException {
|
||||
GDataIndexer retVal = new GDataIndexer(config, dir, create);
|
||||
retVal.setIndexTask(new IndexTask(retVal, retVal.futurQueue));
|
||||
retVal.init();
|
||||
return retVal;
|
||||
}
|
||||
|
||||
/**
|
||||
* This factory method creates a new GDataIndexer using a instance of
|
||||
* {@link org.apache.lucene.gdata.search.index.TimedIndexTask}.
|
||||
* This indexer will automatically commit the index
|
||||
* if no modification to the index occur for the given time. The used time
|
||||
* unit is {@link TimeUnit#SECONDS}. Values less than the default value
|
||||
* will be ignored. For the default value see
|
||||
* {@link org.apache.lucene.gdata.search.index.TimedIndexTask}.
|
||||
*
|
||||
* @param config -
|
||||
* the config to be used to configure the indexer
|
||||
* @param dir -
|
||||
* the directory to index to
|
||||
* @param create -
|
||||
* <code>true</code> to create a new index, <code>false</code>
|
||||
* to use the existing one.
|
||||
* @param commitTimeout -
|
||||
* the amount of seconds to wait until a commit should be
|
||||
* scheduled
|
||||
* @return - a new GDataIndexer instance
|
||||
* @throws IOException -
|
||||
* if an IOException occurs while initializing the indexer
|
||||
*/
|
||||
public static synchronized GDataIndexer createTimedGdataIndexer(
|
||||
final IndexSchema config, Directory dir, boolean create,
|
||||
long commitTimeout) throws IOException {
|
||||
|
||||
GDataIndexer retVal = new GDataIndexer(config, dir, create);
|
||||
retVal.setIndexTask(new TimedIndexTask(retVal, retVal.futurQueue,
|
||||
commitTimeout));
|
||||
retVal.init();
|
||||
return retVal;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
static final class FinishingFuture implements Future<IndexDocument> {
|
||||
|
||||
/**
|
||||
* @see java.util.concurrent.Future#cancel(boolean)
|
||||
*/
|
||||
public boolean cancel(boolean arg0) {
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.util.concurrent.Future#isCancelled()
|
||||
*/
|
||||
public boolean isCancelled() {
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.util.concurrent.Future#isDone()
|
||||
*/
|
||||
public boolean isDone() {
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.util.concurrent.Future#get()
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public IndexDocument get() throws InterruptedException,
|
||||
ExecutionException {
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.util.concurrent.Future#get(long,
|
||||
* java.util.concurrent.TimeUnit)
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public IndexDocument get(long arg0, TimeUnit arg1)
|
||||
throws InterruptedException, ExecutionException,
|
||||
TimeoutException {
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -1,75 +0,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.
|
||||
*/
|
||||
|
||||
package org.apache.lucene.gdata.search.index;
|
||||
|
||||
/**
|
||||
* This exception will be thrown if an exception in the indexing component
|
||||
* occurs
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class GdataIndexerException extends RuntimeException {
|
||||
|
||||
private static final long serialVersionUID = -8245420079471690182L;
|
||||
|
||||
/**
|
||||
* Creates a new GdataIndexerException
|
||||
*/
|
||||
public GdataIndexerException() {
|
||||
super();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new GdataIndexerException with a new exception message
|
||||
*
|
||||
* @param arg0 -
|
||||
* exception message
|
||||
*/
|
||||
public GdataIndexerException(String arg0) {
|
||||
super(arg0);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new GdataIndexerException with a new exception message and a
|
||||
* root cause
|
||||
*
|
||||
* @param arg0 -
|
||||
* exception message
|
||||
* @param arg1 -
|
||||
* the root cause
|
||||
*/
|
||||
public GdataIndexerException(String arg0, Throwable arg1) {
|
||||
super(arg0, arg1);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new GdataIndexerException with a root cause
|
||||
*
|
||||
* @param arg0 -
|
||||
* the root cause
|
||||
*/
|
||||
public GdataIndexerException(Throwable arg0) {
|
||||
super(arg0);
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -1,38 +0,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.
|
||||
*/
|
||||
package org.apache.lucene.gdata.search.index;
|
||||
|
||||
/**
|
||||
* This enum defines all possible actions on a GData index.
|
||||
*
|
||||
* @see org.apache.lucene.gdata.search.index.IndexDocument
|
||||
* @see org.apache.lucene.gdata.search.index.IndexDocumentBuilderTask
|
||||
*
|
||||
*
|
||||
*/
|
||||
public enum IndexAction {
|
||||
/**
|
||||
* update action
|
||||
*/
|
||||
UPDATE, /**
|
||||
* delete action
|
||||
*/
|
||||
DELETE, /**
|
||||
* insert / add action
|
||||
*/
|
||||
INSERT
|
||||
}
|
|
@ -1,547 +0,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.
|
||||
*/
|
||||
package org.apache.lucene.gdata.search.index;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.apache.lucene.gdata.data.ServerBaseEntry;
|
||||
import org.apache.lucene.gdata.data.ServerBaseFeed;
|
||||
import org.apache.lucene.gdata.search.GDataSearcher;
|
||||
import org.apache.lucene.gdata.search.SearchComponent;
|
||||
import org.apache.lucene.gdata.search.StandardGdataSearcher;
|
||||
import org.apache.lucene.gdata.search.config.IndexSchema;
|
||||
import org.apache.lucene.gdata.server.registry.Component;
|
||||
import org.apache.lucene.gdata.server.registry.ComponentType;
|
||||
import org.apache.lucene.gdata.server.registry.EntryEventListener;
|
||||
import org.apache.lucene.gdata.server.registry.GDataServerRegistry;
|
||||
import org.apache.lucene.gdata.server.registry.ProvidedService;
|
||||
import org.apache.lucene.gdata.utils.ReferenceCounter;
|
||||
import org.apache.lucene.index.IndexFileNameFilter;
|
||||
import org.apache.lucene.search.Filter;
|
||||
import org.apache.lucene.search.IndexSearcher;
|
||||
import org.apache.lucene.store.Directory;
|
||||
import org.apache.lucene.store.FSDirectory;
|
||||
|
||||
/**
|
||||
* Default implementation of the {@link SearchComponent} interface. All actions
|
||||
* on the index will be controlled from this class. Only this class grants read
|
||||
* or write actions access to the index.
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
@Component(componentType = ComponentType.SEARCHCONTROLLER)
|
||||
public class IndexController implements SearchComponent, IndexEventListener,
|
||||
EntryEventListener {
|
||||
static final Log LOG = LogFactory.getLog(IndexController.class);
|
||||
|
||||
private final AtomicBoolean isInitialized = new AtomicBoolean(false);
|
||||
|
||||
private final AtomicBoolean destroyed = new AtomicBoolean(false);
|
||||
|
||||
protected Map<String, ServiceIndex> indexerMap;
|
||||
|
||||
private final ExecutorService taskExecutor;
|
||||
|
||||
/**
|
||||
* Creates a new IndexController -- call
|
||||
* {@link IndexController#initialize()} to set up the controller.
|
||||
*/
|
||||
public IndexController() {
|
||||
this.taskExecutor = Executors.newCachedThreadPool();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.lucene.gdata.search.SearchComponent#initialize()
|
||||
*/
|
||||
public synchronized void initialize() {
|
||||
if (this.isInitialized.get())
|
||||
throw new IllegalStateException(
|
||||
"IndexController is already initialized");
|
||||
this.destroyed.set(false);
|
||||
/*
|
||||
* if this fails the server must not startup --> throw runtime exception
|
||||
*/
|
||||
GDataServerRegistry.getRegistry().registerEntryEventListener(this);
|
||||
|
||||
GDataServerRegistry.getRegistry().registerEntryEventListener(this);
|
||||
Collection<ProvidedService> services = GDataServerRegistry
|
||||
.getRegistry().getServices();
|
||||
this.indexerMap = new ConcurrentHashMap<String, ServiceIndex>(services
|
||||
.size());
|
||||
|
||||
for (ProvidedService service : services) {
|
||||
IndexSchema schema = service.getIndexSchema();
|
||||
/*
|
||||
* initialize will fail if mandatory values are not set. This is
|
||||
* just a
|
||||
*/
|
||||
schema.initialize();
|
||||
addIndexSchema(schema);
|
||||
}
|
||||
this.isInitialized.set(true);
|
||||
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* add a schema to the index controller and create the indexer. create
|
||||
* directories and check out existing indexes
|
||||
*/
|
||||
protected void addIndexSchema(final IndexSchema schema) {
|
||||
checkDestroyed();
|
||||
if (schema.getName() == null)
|
||||
throw new IllegalStateException(
|
||||
"schema has no name -- is not associated with any service");
|
||||
if (this.indexerMap.containsKey(schema.getName()))
|
||||
throw new IllegalStateException("schema for service "
|
||||
+ schema.getName() + " is already registered");
|
||||
if (LOG.isInfoEnabled())
|
||||
LOG.info("add new IndexSchema for service " + schema.getName()
|
||||
+ " -- " + schema);
|
||||
try {
|
||||
ServiceIndex bean = createIndexer(schema);
|
||||
ReferenceCounter<IndexSearcher> searcher = getNewServiceSearcher(bean.getDirectory());
|
||||
bean.setSearcher(searcher);
|
||||
this.indexerMap.put(schema.getName(), bean);
|
||||
} catch (IOException e) {
|
||||
LOG.error("Can not create indexer for service " + schema.getName(),
|
||||
e);
|
||||
throw new GdataIndexerException(
|
||||
"Can not create indexer for service " + schema.getName(), e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
protected ServiceIndex createIndexer(final IndexSchema schema) throws IOException {
|
||||
GDataIndexer indexer;
|
||||
File indexLocation = createIndexLocation(schema.getIndexLocation(),
|
||||
schema.getName());
|
||||
boolean create = createIndexDirectory(indexLocation);
|
||||
Directory dir = FSDirectory.getDirectory(indexLocation, create);
|
||||
if (LOG.isInfoEnabled())
|
||||
LOG.info("Create new Indexer for IndexSchema: " + schema);
|
||||
/*
|
||||
* timed or committed indexer?! keep the possibility to let users decide
|
||||
* to use scheduled commits
|
||||
*/
|
||||
if (schema.isUseTimedIndexer())
|
||||
indexer = GDataIndexer.createTimedGdataIndexer(schema, dir, create,
|
||||
schema.getIndexerIdleTime());
|
||||
else
|
||||
indexer = GDataIndexer.createGdataIndexer(schema, dir, create);
|
||||
indexer.registerIndexEventListener(this);
|
||||
return new ServiceIndex(schema, indexer, dir);
|
||||
}
|
||||
|
||||
/*
|
||||
* if this fails the server must not startup!!
|
||||
*/
|
||||
protected File createIndexLocation(final String path,final String name) {
|
||||
if (path == null || name == null)
|
||||
throw new GdataIndexerException(
|
||||
"Path or Name of the index location is not set Path: "
|
||||
+ path + " name: " + name);
|
||||
/*
|
||||
* check if parent e.g. the configured path is a directory
|
||||
*/
|
||||
File parent = new File(path);
|
||||
if (!parent.isDirectory())
|
||||
throw new IllegalArgumentException(
|
||||
"the given path is not a directory -- " + path);
|
||||
/*
|
||||
* try to create and throw ex if fail
|
||||
*/
|
||||
if (!parent.exists())
|
||||
if (!parent.mkdir())
|
||||
throw new RuntimeException("Can not create directory -- "
|
||||
+ path);
|
||||
/*
|
||||
* try to create and throw ex if fail
|
||||
*/
|
||||
File file = new File(parent, name);
|
||||
if (file.isFile())
|
||||
throw new IllegalArgumentException(
|
||||
"A file with the name"
|
||||
+ name
|
||||
+ " already exists in "
|
||||
+ path
|
||||
+ " -- a file of the name of the service must not exist in the index location");
|
||||
|
||||
if (!file.exists()) {
|
||||
if (!file.mkdir())
|
||||
throw new RuntimeException("Can not create directory -- "
|
||||
+ file.getAbsolutePath());
|
||||
}
|
||||
return file;
|
||||
}
|
||||
|
||||
protected boolean createIndexDirectory(final File file) {
|
||||
/*
|
||||
* use a lucene filename filter to figure out if there is an existing
|
||||
* index in the defined directory
|
||||
*/
|
||||
String[] luceneFiles = file.list(new IndexFileNameFilter());
|
||||
return !(luceneFiles.length > 0);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.lucene.gdata.search.index.IndexEventListener#commitCallBack(java.lang.String)
|
||||
*/
|
||||
public synchronized void commitCallBack(final String service) {
|
||||
checkDestroyed();
|
||||
if(LOG.isInfoEnabled())
|
||||
LOG.info("CommitCallback triggered - register new searcher for service: "+service);
|
||||
/*
|
||||
* get the old searcher and replace it if possible.
|
||||
*/
|
||||
ServiceIndex index = this.indexerMap.get(service);
|
||||
ReferenceCounter<IndexSearcher> searcher = index.getSearcher();
|
||||
|
||||
try {
|
||||
index.setSearcher(getNewServiceSearcher(index.getDirectory()));
|
||||
} catch (IOException e) {
|
||||
LOG.fatal("Can not create new Searcher -- keep the old one ", e);
|
||||
return;
|
||||
}
|
||||
/*
|
||||
* if new searcher if registered decrement old one to get it destroyed if unused
|
||||
*/
|
||||
searcher.decrementRef();
|
||||
}
|
||||
/*
|
||||
* create a new ReferenceCounter for the indexSearcher.
|
||||
* The reference is already incremented before returned
|
||||
*/
|
||||
private ReferenceCounter<IndexSearcher> getNewServiceSearcher(final Directory dir)
|
||||
throws IOException {
|
||||
if(LOG.isInfoEnabled())
|
||||
LOG.info("Create new ServiceSearcher");
|
||||
IndexSearcher searcher = new IndexSearcher(dir);
|
||||
ReferenceCounter<IndexSearcher> holder = new ReferenceCounter<IndexSearcher>(
|
||||
searcher) {
|
||||
|
||||
@Override
|
||||
protected void close() {
|
||||
try {
|
||||
LOG
|
||||
.info("Close IndexSearcher -- Zero references remaining");
|
||||
this.resource.close();
|
||||
} catch (IOException e) {
|
||||
LOG.warn("Can not close IndexSearcher -- ", e);
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
holder.increamentReference();
|
||||
return holder;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.lucene.gdata.server.registry.EntryEventListener#fireUpdateEvent(org.apache.lucene.gdata.data.ServerBaseEntry)
|
||||
*/
|
||||
public void fireUpdateEvent(final ServerBaseEntry entry) {
|
||||
createNewIndexerTask(entry, IndexAction.UPDATE);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.lucene.gdata.server.registry.EntryEventListener#fireInsertEvent(org.apache.lucene.gdata.data.ServerBaseEntry)
|
||||
*/
|
||||
public void fireInsertEvent(final ServerBaseEntry entry) {
|
||||
createNewIndexerTask(entry, IndexAction.INSERT);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.lucene.gdata.server.registry.EntryEventListener#fireDeleteEvent(org.apache.lucene.gdata.data.ServerBaseEntry)
|
||||
*/
|
||||
public void fireDeleteEvent(final ServerBaseEntry entry) {
|
||||
createNewIndexerTask(entry, IndexAction.DELETE);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.lucene.gdata.server.registry.EntryEventListener#fireDeleteAllEntries(org.apache.lucene.gdata.data.ServerBaseFeed)
|
||||
*/
|
||||
public void fireDeleteAllEntries(final ServerBaseFeed feed) {
|
||||
createNewDeleteAllEntriesTask(feed);
|
||||
}
|
||||
|
||||
private void createNewDeleteAllEntriesTask(final ServerBaseFeed feed){
|
||||
checkDestroyed();
|
||||
checkInitialized();
|
||||
if(LOG.isInfoEnabled())
|
||||
LOG.info("Deleting all entries for feed dispatch new IndexDocumentBuilder -- "+feed.getId());
|
||||
String serviceName = feed.getServiceConfig().getName();
|
||||
ServiceIndex bean = this.indexerMap.get(serviceName);
|
||||
if (bean == null)
|
||||
throw new RuntimeException("no indexer for service " + serviceName
|
||||
+ " registered");
|
||||
Lock lock = bean.getLock();
|
||||
lock.lock();
|
||||
try{
|
||||
IndexDocumentBuilder<IndexDocument> callable = new IndexFeedDeleteTask(feed.getId());
|
||||
sumbitTask(callable,bean.getIndexer());
|
||||
}finally{
|
||||
lock.unlock();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
// TODO add test for this method!!
|
||||
private void createNewIndexerTask(final ServerBaseEntry entry, final IndexAction action) {
|
||||
checkDestroyed();
|
||||
checkInitialized();
|
||||
String serviceName = entry.getServiceConfig().getName();
|
||||
if (LOG.isInfoEnabled())
|
||||
LOG.info("New Indexer Task submitted - Action: " + action
|
||||
+ " for service: " + serviceName);
|
||||
ServiceIndex bean = this.indexerMap.get(serviceName);
|
||||
if (bean == null)
|
||||
throw new RuntimeException("no indexer for service " + serviceName
|
||||
+ " registered");
|
||||
/*
|
||||
* lock on service to synchronize the event order. This lock has
|
||||
* fairness parameter set to true. Grant access to the longest waiting
|
||||
* thread. Using fairness is slower but is acceptable in this context
|
||||
*/
|
||||
Lock lock = bean.getLock();
|
||||
lock.lock();
|
||||
try {
|
||||
IndexSchema schema = bean.getSchema();
|
||||
boolean commitAfter = bean.incrementActionAndReset(schema.getCommitAfterDocuments());
|
||||
IndexDocumentBuilder<IndexDocument> callable = new IndexDocumentBuilderTask<IndexDocument>(
|
||||
entry, bean.getSchema(), action, commitAfter,bean.getOptimize(schema.getOptimizeAfterCommit()));
|
||||
sumbitTask(callable,bean.getIndexer());
|
||||
} finally {
|
||||
/*
|
||||
* make sure to unlock
|
||||
*/
|
||||
lock.unlock();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void sumbitTask(final Callable<IndexDocument> callable, final GDataIndexer indexer){
|
||||
Future<IndexDocument> task = this.taskExecutor.submit(callable);
|
||||
try {
|
||||
indexer.addIndexableDocumentTask(task);
|
||||
} catch (InterruptedException e) {
|
||||
throw new GdataIndexerException(
|
||||
"Can not accept any index tasks -- interrupted. ", e);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.lucene.gdata.search.SearchComponent#getServiceSearcher(org.apache.lucene.gdata.server.registry.ProvidedService)
|
||||
*/
|
||||
public GDataSearcher<String> getServiceSearcher(final ProvidedService service) {
|
||||
checkDestroyed();
|
||||
checkInitialized();
|
||||
|
||||
/*
|
||||
* get and increment. searcher will be decremented if GdataSearcher is
|
||||
* closed
|
||||
*/
|
||||
ReferenceCounter<IndexSearcher> searcher;
|
||||
synchronized (this) {
|
||||
ServiceIndex serviceIndex = this.indexerMap.get(service.getName());
|
||||
if(serviceIndex == null)
|
||||
throw new RuntimeException("no index for service "+service.getName());
|
||||
searcher = serviceIndex.getSearcher();
|
||||
searcher.increamentReference();
|
||||
}
|
||||
|
||||
return new StandardGdataSearcher(searcher);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.lucene.gdata.search.SearchComponent#destroy()
|
||||
*/
|
||||
public synchronized void destroy() {
|
||||
checkDestroyed();
|
||||
if(!this.isInitialized.get())
|
||||
return;
|
||||
this.destroyed.set(true);
|
||||
this.isInitialized.set(false);
|
||||
LOG.info("Shutting down IndexController -- destroy has been called");
|
||||
Set<Entry<String, ServiceIndex>> entrySet = this.indexerMap.entrySet();
|
||||
for (Entry<String, ServiceIndex> entry : entrySet) {
|
||||
ServiceIndex bean = entry.getValue();
|
||||
bean.getSearcher().decrementRef();
|
||||
GDataIndexer indexer = bean.getIndexer();
|
||||
try {
|
||||
indexer.destroy();
|
||||
} catch (IOException e) {
|
||||
LOG.warn("Can not destroy indexer for service: "
|
||||
+ bean.getSchema().getName(), e);
|
||||
}
|
||||
}
|
||||
this.taskExecutor.shutdown();
|
||||
this.indexerMap.clear();
|
||||
}
|
||||
|
||||
private void checkDestroyed(){
|
||||
if (this.destroyed.get())
|
||||
throw new IllegalStateException(
|
||||
"IndexController has been destroyed");
|
||||
}
|
||||
private void checkInitialized(){
|
||||
if(!this.isInitialized.get())
|
||||
throw new IllegalStateException(
|
||||
"IndexController has not been initialized");
|
||||
}
|
||||
|
||||
|
||||
final static class ServiceIndex {
|
||||
private AtomicInteger actionCount = new AtomicInteger(0);
|
||||
|
||||
private AtomicInteger commitCount = new AtomicInteger(0);
|
||||
|
||||
private final Lock lock;
|
||||
|
||||
private final IndexSchema schema;
|
||||
|
||||
private final GDataIndexer indexer;
|
||||
|
||||
private final Directory directory;
|
||||
|
||||
private Filter addedDocumentFilter;
|
||||
|
||||
private ReferenceCounter<IndexSearcher> searcher;
|
||||
|
||||
// private final Map<String,IndexAction> actionMap;
|
||||
|
||||
|
||||
|
||||
ServiceIndex(final IndexSchema schema, GDataIndexer indexer,
|
||||
Directory directory) {
|
||||
this.schema = schema;
|
||||
this.indexer = indexer;
|
||||
this.lock = new ReentrantLock(true);
|
||||
this.directory = directory;
|
||||
// this.actionMap = new HashMap<String,IndexAction>(128);
|
||||
}
|
||||
|
||||
Lock getLock() {
|
||||
return this.lock;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the indexer.
|
||||
*/
|
||||
GDataIndexer getIndexer() {
|
||||
return this.indexer;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the schema.
|
||||
*/
|
||||
IndexSchema getSchema() {
|
||||
return this.schema;
|
||||
}
|
||||
|
||||
// public void addAction(IndexAction action,ServerBaseEntry entry){
|
||||
//
|
||||
// }
|
||||
/**
|
||||
* Counts how many actions have been executed on this index
|
||||
*
|
||||
* @param reset - count mod reset value equals 0 causes a commit
|
||||
*
|
||||
* @return <code>true</code> if the count mod reset value equals 0, otherwise
|
||||
* false;
|
||||
*/
|
||||
boolean incrementActionAndReset(int reset) {
|
||||
if (this.actionCount.incrementAndGet()%reset == 0) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the directory.
|
||||
*/
|
||||
public Directory getDirectory() {
|
||||
return this.directory;
|
||||
}
|
||||
/**
|
||||
* @return Returns the addedDocumentFilter.
|
||||
*/
|
||||
public Filter getAddedDocumentFilter() {
|
||||
return this.addedDocumentFilter;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param addedDocumentFilter The addedDocumentFilter to set.
|
||||
*/
|
||||
public void setAddedDocumentFilter(Filter addedDocumentFilter) {
|
||||
this.addedDocumentFilter = addedDocumentFilter;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the searcher.
|
||||
*/
|
||||
public ReferenceCounter<IndexSearcher> getSearcher() {
|
||||
return this.searcher;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param searcher The searcher to set.
|
||||
*/
|
||||
public void setSearcher(ReferenceCounter<IndexSearcher> searcher) {
|
||||
this.searcher = searcher;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the commitCount.
|
||||
*/
|
||||
public int commitCountIncrement() {
|
||||
return this.commitCount.incrementAndGet();
|
||||
}
|
||||
/**
|
||||
* @param reset - the number after how many commits the index should be optimized
|
||||
* @return <code>true</code> if and only if the commit count mod reset equals 0, otherwise <code>false</code>.
|
||||
*/
|
||||
public boolean getOptimize(int reset){
|
||||
if(this.commitCount.get()%reset == 0){
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -1,100 +0,0 @@
|
|||
/**
|
||||
* Copyright 2004 The Apache Software Foundation
|
||||
*
|
||||
* Licensed 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.search.index;
|
||||
|
||||
import org.apache.lucene.document.Document;
|
||||
import org.apache.lucene.index.Term;
|
||||
|
||||
/**
|
||||
* IndexDocument encapsulates the acual entity to store, update or delete. All
|
||||
* infomation to process the action on this document are provided via this
|
||||
* interface.
|
||||
* <p>
|
||||
* This enables the GDataIndexer to index every kind of document. All the
|
||||
* processing of the original document happens somewhere behind this facade.
|
||||
* {@link org.apache.lucene.gdata.search.index.IndexDocumentBuilderTask} passed
|
||||
* to the {@link org.apache.lucene.gdata.search.index.GDataIndexer} task queue
|
||||
* produce instances of this interface concurrently.
|
||||
* </p>
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
public interface IndexDocument {
|
||||
/**
|
||||
* the index field to identify a document in the index. This acts as a
|
||||
* primary key to fetch the entire entry from the storage
|
||||
*/
|
||||
public static final String FIELD_ENTRY_ID = "enryId";
|
||||
/**
|
||||
* the index field to associate a document with a specific feed
|
||||
*/
|
||||
public static final String FIELD_FEED_ID = "feedId";
|
||||
public static final String GDATA_MANDATORY_FIELD_UPDATED = "updated";
|
||||
public static final String GDATA_MANDATORY_FIELD_CATEGORY = "category";
|
||||
|
||||
/**
|
||||
* @return <code>true</code> if and only if this document is an update,
|
||||
* otherwise <code>false</code>
|
||||
*/
|
||||
public abstract boolean isUpdate();
|
||||
|
||||
/**
|
||||
* @return <code>true</code> if and only if this document is a delete,
|
||||
* otherwise <code>false</code>
|
||||
*/
|
||||
public abstract boolean isDelete();
|
||||
|
||||
/**
|
||||
* @return <code>true</code> if and only if this document is an insert,
|
||||
* otherwise <code>false</code>
|
||||
*/
|
||||
public abstract boolean isInsert();
|
||||
|
||||
/**
|
||||
*
|
||||
* @return - the lucene document to write to the index if the action is
|
||||
* insert or updated, otherwise it will return <code>null</code>;
|
||||
*/
|
||||
public abstract Document getWriteable();
|
||||
|
||||
/**
|
||||
* @return - a term that identifies this document in the index to delete
|
||||
* this document on a update or delete
|
||||
*/
|
||||
public abstract Term getDeletealbe();
|
||||
|
||||
/**
|
||||
* Indicates that the index should be commited after this document has been
|
||||
* processed
|
||||
*
|
||||
* @return <code>true</code> if the index should be commited after this
|
||||
* document, otherwise <code>false</code>
|
||||
*/
|
||||
public abstract boolean commitAfter();
|
||||
|
||||
/**
|
||||
* Indicates that the index should be optimized after this document has been
|
||||
* processed
|
||||
*
|
||||
*
|
||||
* @return <code>true</code> if the index should be optimized after this
|
||||
* document, otherwise <code>false</code>
|
||||
*/
|
||||
public abstract boolean optimizeAfter();
|
||||
|
||||
}
|
|
@ -1,33 +0,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.
|
||||
*/
|
||||
package org.apache.lucene.gdata.search.index;
|
||||
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
/**
|
||||
* Interface for DocumentBuilders
|
||||
*
|
||||
* @param <T> IndexDocument implementation
|
||||
*
|
||||
*/
|
||||
public interface IndexDocumentBuilder<T extends IndexDocument> extends Callable<T>{
|
||||
/**
|
||||
* @see java.util.concurrent.Callable#call()
|
||||
*/
|
||||
public T call() throws GdataIndexerException;
|
||||
|
||||
}
|
|
@ -1,105 +0,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.
|
||||
*/
|
||||
|
||||
package org.apache.lucene.gdata.search.index;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.apache.lucene.gdata.data.ServerBaseEntry;
|
||||
import org.apache.lucene.gdata.search.analysis.ContentStrategy;
|
||||
import org.apache.lucene.gdata.search.analysis.Indexable;
|
||||
import org.apache.lucene.gdata.search.analysis.NotIndexableException;
|
||||
import org.apache.lucene.gdata.search.config.IndexSchema;
|
||||
import org.apache.lucene.gdata.search.config.IndexSchemaField;
|
||||
|
||||
/**
|
||||
* This callable does all of the entiti processing concurrently while added to
|
||||
* the {@link org.apache.lucene.gdata.search.index.GDataIndexer} task queue;
|
||||
*
|
||||
* @see org.apache.lucene.gdata.search.analysis.Indexable
|
||||
* @see org.apache.lucene.gdata.search.analysis.ContentStrategy
|
||||
*
|
||||
*
|
||||
*/
|
||||
class IndexDocumentBuilderTask<T extends IndexDocument> implements IndexDocumentBuilder<T> {
|
||||
private static final Log LOG = LogFactory
|
||||
.getLog(IndexDocumentBuilderTask.class);
|
||||
|
||||
private final ServerBaseEntry entry;
|
||||
|
||||
private final IndexSchema schema;
|
||||
|
||||
private final IndexAction action;
|
||||
|
||||
private final boolean commitAfter;
|
||||
private final boolean optimizeAfter;
|
||||
protected IndexDocumentBuilderTask(final ServerBaseEntry entry,
|
||||
final IndexSchema schema, IndexAction action, boolean commitAfter, boolean optimizeAfter) {
|
||||
/*
|
||||
* omit check for null parameter this happens in the controller.
|
||||
*/
|
||||
this.schema = schema;
|
||||
this.entry = entry;
|
||||
this.action = action;
|
||||
this.commitAfter = commitAfter;
|
||||
this.optimizeAfter = optimizeAfter;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.util.concurrent.Callable#call()
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public T call() throws GdataIndexerException {
|
||||
|
||||
Collection<IndexSchemaField> fields = this.schema.getFields();
|
||||
GDataIndexDocument document = new GDataIndexDocument(this.action,
|
||||
this.entry.getId(),this.entry.getFeedId(), this.commitAfter,this.optimizeAfter);
|
||||
if(this.action != IndexAction.DELETE){
|
||||
int addedFields = 0;
|
||||
for (IndexSchemaField field : fields) {
|
||||
/*
|
||||
* get the strategy to process the field
|
||||
*/
|
||||
ContentStrategy strategy = ContentStrategy.getFieldStrategy(field);
|
||||
if (LOG.isInfoEnabled())
|
||||
LOG.info("Process indexable for " + field);
|
||||
try {
|
||||
/*
|
||||
* get the indexable via the factory method to enable new /
|
||||
* different implementation of the interface (this could be a
|
||||
* faster dom impl e.g. dom4j)
|
||||
*/
|
||||
strategy.processIndexable(Indexable.getIndexable(this.entry));
|
||||
addedFields++;
|
||||
} catch (NotIndexableException e) {
|
||||
LOG.warn("Can not create field for " + field+" field will be skipped -- reason: ", e);
|
||||
continue;
|
||||
}
|
||||
|
||||
document.addField(strategy);
|
||||
|
||||
}
|
||||
if(addedFields == 0)
|
||||
throw new GdataIndexerException("No field added to document for Schema: "+this.schema);
|
||||
}
|
||||
return (T)document;
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -1,36 +0,0 @@
|
|||
/**
|
||||
* Copyright 2004 The Apache Software Foundation
|
||||
*
|
||||
* Licensed 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.search.index;
|
||||
|
||||
/**
|
||||
* This interface should be implemented by classes need to be notified when an
|
||||
* index is commited
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
public interface IndexEventListener {
|
||||
|
||||
/**
|
||||
* This method will be invoked by an instance of {@link GDataIndexer} if the
|
||||
* index is commited
|
||||
*
|
||||
* @param service -
|
||||
* the name of the service the invoking indexer runs for
|
||||
*/
|
||||
public abstract void commitCallBack(String service);
|
||||
|
||||
}
|
|
@ -1,140 +0,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.
|
||||
*/
|
||||
|
||||
package org.apache.lucene.gdata.search.index;
|
||||
|
||||
import org.apache.lucene.document.Document;
|
||||
import org.apache.lucene.index.Term;
|
||||
|
||||
/**
|
||||
* This IndexDocumentBuilder deletes a entire feed form the index the builder is
|
||||
* passed to if the feed has any entries in the search index. Each created and
|
||||
* passed IndexFeedDeleteTask forces a commit.
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class IndexFeedDeleteTask implements IndexDocumentBuilder<IndexDocument> {
|
||||
private final String feedId;
|
||||
|
||||
IndexFeedDeleteTask(String feedId) {
|
||||
if (feedId == null)
|
||||
throw new IllegalArgumentException("feedId must not be null");
|
||||
this.feedId = feedId;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.lucene.gdata.search.index.IndexDocumentBuilder#call()
|
||||
*/
|
||||
public IndexDocument call() throws GdataIndexerException {
|
||||
return new FeedDeleteDocument(this.feedId);
|
||||
|
||||
}
|
||||
|
||||
private static class FeedDeleteDocument implements IndexDocument {
|
||||
private final Term deleteTerm;
|
||||
|
||||
FeedDeleteDocument(String feedId) {
|
||||
this.deleteTerm = new Term(FIELD_FEED_ID, feedId);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.lucene.gdata.search.index.IndexDocument#isUpdate()
|
||||
*/
|
||||
public boolean isUpdate() {
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.lucene.gdata.search.index.IndexDocument#isDelete()
|
||||
*/
|
||||
public boolean isDelete() {
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.lucene.gdata.search.index.IndexDocument#isInsert()
|
||||
*/
|
||||
public boolean isInsert() {
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.lucene.gdata.search.index.IndexDocument#getWriteable()
|
||||
*/
|
||||
public Document getWriteable() {
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.lucene.gdata.search.index.IndexDocument#getDeletealbe()
|
||||
*/
|
||||
public Term getDeletealbe() {
|
||||
|
||||
return this.deleteTerm;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.lucene.gdata.search.index.IndexDocument#commitAfter()
|
||||
*/
|
||||
public boolean commitAfter() {
|
||||
/*
|
||||
* force commit after delete a entire feed and its entries
|
||||
*/
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.lucene.gdata.search.index.IndexDocument#optimizeAfter()
|
||||
*/
|
||||
public boolean optimizeAfter() {
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.lang.Object#equals(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if(obj == null)
|
||||
return false;
|
||||
if (obj instanceof IndexFeedDeleteTask) {
|
||||
IndexFeedDeleteTask other = (IndexFeedDeleteTask) obj;
|
||||
return this.feedId.equals(other.feedId);
|
||||
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.lang.Object#hashCode()
|
||||
*/
|
||||
@Override
|
||||
public int hashCode() {
|
||||
|
||||
return this.feedId.hashCode();
|
||||
}
|
||||
|
||||
}
|
|
@ -1,169 +0,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.
|
||||
*/
|
||||
|
||||
package org.apache.lucene.gdata.search.index;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.xml.sax.Attributes;
|
||||
import org.xml.sax.ContentHandler;
|
||||
import org.xml.sax.InputSource;
|
||||
import org.xml.sax.Locator;
|
||||
import org.xml.sax.SAXException;
|
||||
import org.xml.sax.XMLReader;
|
||||
import org.xml.sax.helpers.XMLReaderFactory;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
*/
|
||||
class IndexLogReader {
|
||||
|
||||
static Map<String,IndexAction> readIndexLog(File indexLogFile, Map<String,IndexAction> contentMap) throws SAXException,IOException{
|
||||
XMLReader reader = XMLReaderFactory.createXMLReader();
|
||||
|
||||
Map<String, IndexAction> logContent = contentMap;
|
||||
if(logContent == null)
|
||||
logContent = new HashMap<String,IndexAction>(64);
|
||||
|
||||
reader.setContentHandler(new IndexLogContentHandler(logContent));
|
||||
InputSource source = new InputSource(new FileInputStream(indexLogFile));
|
||||
try{
|
||||
reader.parse(source);
|
||||
}catch (SAXException e) {
|
||||
/*
|
||||
* try to append the Root element end
|
||||
* this happens if the server crashes.
|
||||
* If it dies while writing an entry the log file has to be fixed manually
|
||||
*/
|
||||
IndexLogWriter.tryCloseRoot(indexLogFile);
|
||||
source = new InputSource(new FileInputStream(indexLogFile));
|
||||
reader.parse(source);
|
||||
}
|
||||
return logContent;
|
||||
}
|
||||
|
||||
|
||||
private static class IndexLogContentHandler implements ContentHandler {
|
||||
private final Map<String, IndexAction> logContent;
|
||||
private String currentID;
|
||||
private String currentAction;
|
||||
private boolean isId;
|
||||
private boolean isAction;
|
||||
IndexLogContentHandler(final Map<String, IndexAction> content) {
|
||||
this.logContent = content;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.xml.sax.ContentHandler#setDocumentLocator(org.xml.sax.Locator)
|
||||
*/
|
||||
public void setDocumentLocator(Locator locator) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.xml.sax.ContentHandler#startDocument()
|
||||
*/
|
||||
public void startDocument() throws SAXException {
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.xml.sax.ContentHandler#endDocument()
|
||||
*/
|
||||
public void endDocument() throws SAXException {
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.xml.sax.ContentHandler#startPrefixMapping(java.lang.String, java.lang.String)
|
||||
*/
|
||||
public void startPrefixMapping(String prefix, String uri)
|
||||
throws SAXException {
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.xml.sax.ContentHandler#endPrefixMapping(java.lang.String)
|
||||
*/
|
||||
public void endPrefixMapping(String prefix) throws SAXException {
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.xml.sax.ContentHandler#startElement(java.lang.String, java.lang.String, java.lang.String, org.xml.sax.Attributes)
|
||||
*/
|
||||
public void startElement(String uri, String localName, String qName,
|
||||
Attributes atts) throws SAXException {
|
||||
if(localName.equals("entryid")){
|
||||
this.isId = true;
|
||||
}else if(localName.equals("action")){
|
||||
this.isAction = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.xml.sax.ContentHandler#endElement(java.lang.String, java.lang.String, java.lang.String)
|
||||
*/
|
||||
public void endElement(String uri, String localName, String qName)
|
||||
throws SAXException {
|
||||
if(localName.equals("entryid")){
|
||||
this.isId = false;
|
||||
}else if(localName.equals("action")){
|
||||
this.isAction = false;
|
||||
}else if(localName.equals("indexentry")){
|
||||
this.logContent.put(this.currentID,IndexAction.valueOf(this.currentAction));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.xml.sax.ContentHandler#characters(char[], int, int)
|
||||
*/
|
||||
public void characters(char[] ch, int start, int length)
|
||||
throws SAXException {
|
||||
if(this.isId)
|
||||
this.currentID = new String(ch,start,length);
|
||||
if(this.isAction)
|
||||
this.currentAction = new String(ch,start,length);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.xml.sax.ContentHandler#ignorableWhitespace(char[], int, int)
|
||||
*/
|
||||
public void ignorableWhitespace(char[] ch, int start, int length)
|
||||
throws SAXException {
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.xml.sax.ContentHandler#processingInstruction(java.lang.String, java.lang.String)
|
||||
*/
|
||||
public void processingInstruction(String target, String data)
|
||||
throws SAXException {
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.xml.sax.ContentHandler#skippedEntity(java.lang.String)
|
||||
*/
|
||||
public void skippedEntity(String name) throws SAXException {
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -1,113 +0,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.
|
||||
*/
|
||||
|
||||
package org.apache.lucene.gdata.search.index;
|
||||
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.io.RandomAccessFile;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
*/
|
||||
class IndexLogWriter {
|
||||
private static final String LINE_BREAK = System
|
||||
.getProperty("line.separator");
|
||||
|
||||
private static final String XMLHEADER = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
|
||||
+ LINE_BREAK;
|
||||
private static final String CHARSET = "UTF-8";
|
||||
private static final String ROOT_BEGIN = "<indexlog>" + LINE_BREAK;
|
||||
|
||||
private static final String ROOT_END = "</indexlog>";
|
||||
|
||||
|
||||
|
||||
private final BufferedWriter writer;
|
||||
|
||||
private final AtomicBoolean isClosed;
|
||||
|
||||
/**
|
||||
* @param file
|
||||
* @throws IOException
|
||||
*
|
||||
*/
|
||||
public IndexLogWriter(File file) throws IOException {
|
||||
|
||||
this.writer = new BufferedWriter(new OutputStreamWriter(
|
||||
new FileOutputStream(file), CHARSET));
|
||||
this.writer.write(XMLHEADER);
|
||||
this.writer.write(ROOT_BEGIN);
|
||||
this.writer.flush();
|
||||
this.isClosed = new AtomicBoolean(false);
|
||||
|
||||
}
|
||||
|
||||
synchronized void writeAction(String id, IndexAction action)
|
||||
throws IOException {
|
||||
if (this.isClosed.get())
|
||||
throw new IllegalStateException("Writer is already closed");
|
||||
this.writer.write(buildElement(id, action.name()));
|
||||
this.writer.flush();
|
||||
}
|
||||
|
||||
static synchronized void tryCloseRoot(File file) throws IOException {
|
||||
/*
|
||||
* try to append the Root element end
|
||||
* this happens if the server crashes.
|
||||
* If it dies while writing an entry the log file has to be fixed manually
|
||||
*/
|
||||
RandomAccessFile raFile = new RandomAccessFile(file, "rw");
|
||||
raFile.seek(raFile.length());
|
||||
raFile.write(IndexLogWriter.ROOT_END.getBytes(CHARSET));
|
||||
raFile.close();
|
||||
|
||||
|
||||
}
|
||||
|
||||
private static String buildElement(String id, String action) {
|
||||
StringBuilder builder = new StringBuilder("\t<indexentry>")
|
||||
.append(LINE_BREAK);
|
||||
builder.append("\t\t<entryid>");
|
||||
builder.append(id);
|
||||
builder.append("</entryid>").append(LINE_BREAK);
|
||||
builder.append("\t\t<action>");
|
||||
builder.append(action);
|
||||
builder.append("</action>").append(LINE_BREAK);
|
||||
builder.append("\t</indexentry>").append(LINE_BREAK);
|
||||
return builder.toString();
|
||||
|
||||
}
|
||||
|
||||
synchronized void close() throws IOException {
|
||||
if (!this.isClosed.compareAndSet(false,true))
|
||||
throw new IllegalStateException("Writer is already closed");
|
||||
try {
|
||||
this.writer.write(ROOT_END);
|
||||
this.writer.flush();
|
||||
} finally {
|
||||
this.writer.close();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -1,175 +0,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.
|
||||
*/
|
||||
|
||||
package org.apache.lucene.gdata.search.index;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
/**
|
||||
*
|
||||
* Class to be used inside a
|
||||
* {@link org.apache.lucene.gdata.search.index.GDataIndexer} to process the task
|
||||
* queue. This class calls the commit method of the indexer if commit is
|
||||
* scheduled.
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
class IndexTask implements Runnable {
|
||||
private static final Log INNERLOG = LogFactory.getLog(IndexTask.class);
|
||||
|
||||
private AtomicBoolean stopped = new AtomicBoolean(false);
|
||||
|
||||
private final GDataIndexer indexer;
|
||||
|
||||
protected AtomicBoolean commit = new AtomicBoolean(false);
|
||||
|
||||
protected AtomicBoolean optimize = new AtomicBoolean(false);
|
||||
|
||||
/*
|
||||
* keep protected for subclassing
|
||||
*/
|
||||
protected final BlockingQueue<Future<IndexDocument>> taskQueue;
|
||||
|
||||
IndexTask(final GDataIndexer indexer,
|
||||
final BlockingQueue<Future<IndexDocument>> taskQueue) {
|
||||
this.indexer = indexer;
|
||||
this.taskQueue = taskQueue;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.lang.Runnable#run()
|
||||
*/
|
||||
public void run() {
|
||||
|
||||
while (!this.stopped.get() || this.taskQueue.size() != 0) {
|
||||
|
||||
try {
|
||||
/*
|
||||
* get the future from the queue and wait until processing has
|
||||
* been done
|
||||
*/
|
||||
Future<IndexDocument> future = getTask();
|
||||
if (future != null) {
|
||||
IndexDocument document = future.get();
|
||||
setOptimize(document);
|
||||
processDocument(document);
|
||||
/*
|
||||
* the document contains the info for commit or optimize -->
|
||||
* this comes from the controller
|
||||
*/
|
||||
if (document == null || document.commitAfter())
|
||||
this.indexer.commit(document == null ? false : this.optimize.getAndSet(false));
|
||||
}
|
||||
if (this.commit.getAndSet(false))
|
||||
this.indexer.commit(this.optimize.getAndSet(false));
|
||||
|
||||
} catch (InterruptedException e) {
|
||||
INNERLOG.warn("Queue is interrupted exiting IndexTask -- ", e);
|
||||
|
||||
} catch (GdataIndexerException e) {
|
||||
/*
|
||||
*
|
||||
* TODO fire callback here as well
|
||||
*/
|
||||
INNERLOG.error("can not retrieve Field from IndexDocument ", e);
|
||||
} catch (ExecutionException e) {
|
||||
/*
|
||||
* TODO callback for fail this exception is caused by an
|
||||
* exception while processing the document. call back for failed
|
||||
* docs should be placed here
|
||||
*/
|
||||
INNERLOG.error("Future throws execution exception ", e);
|
||||
|
||||
} catch (IOException e) {
|
||||
INNERLOG.error("IOException thrown while processing document ",
|
||||
e);
|
||||
|
||||
} catch (Throwable e) {
|
||||
/*
|
||||
* catch all to prevent the thread from dieing
|
||||
*/
|
||||
INNERLOG.error(
|
||||
"Unexpected exception while processing document -- "
|
||||
+ e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
try {
|
||||
this.indexer.commit(this.optimize.getAndSet(false));
|
||||
} catch (IOException e) {
|
||||
INNERLOG.warn("commit on going down failed - "+e.getMessage(),e);
|
||||
|
||||
}
|
||||
this.stop();
|
||||
}
|
||||
protected void setOptimize(IndexDocument document){
|
||||
if(document == null)
|
||||
return;
|
||||
this.optimize.set(document.optimizeAfter());
|
||||
}
|
||||
|
||||
/*
|
||||
* keep this protected for subclassing see TimedIndexTask!
|
||||
*/
|
||||
protected Future<IndexDocument> getTask() throws InterruptedException {
|
||||
return this.taskQueue.take();
|
||||
}
|
||||
|
||||
private void processDocument(IndexDocument document) throws IOException {
|
||||
/*
|
||||
* a null document is used for waking up the task if the indexer has
|
||||
* been destroyed to finish up and commit. should I change this?! -->
|
||||
* see TimedIndexTask#getTask() also!!
|
||||
*/
|
||||
if (document == null) {
|
||||
INNERLOG.warn("Can not process document -- is null -- run commit");
|
||||
return;
|
||||
}
|
||||
if (document.isDelete()) {
|
||||
this.indexer.deleteDocument(document);
|
||||
return;
|
||||
} else if (document.isInsert()) {
|
||||
this.indexer.addDocument(document);
|
||||
return;
|
||||
} else if (document.isUpdate()) {
|
||||
this.indexer.updateDocument(document);
|
||||
return;
|
||||
}
|
||||
/*
|
||||
* that should not happen -- anyway skip the document and write it to
|
||||
* the log
|
||||
*/
|
||||
INNERLOG.warn("IndexDocument has no Action " + document);
|
||||
|
||||
}
|
||||
|
||||
protected boolean isStopped() {
|
||||
return this.stopped.get();
|
||||
}
|
||||
|
||||
protected void stop() {
|
||||
this.stopped.set(true);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,68 +0,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.
|
||||
*/
|
||||
|
||||
package org.apache.lucene.gdata.search.index;
|
||||
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* This {@link IndexTask} will idle the given time if no task is on the queue.
|
||||
* If the idle time exceeds the task will force a commit on the index. The timer
|
||||
* will be reset if a task is on the queue.
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
class TimedIndexTask extends IndexTask {
|
||||
protected final static TimeUnit TIME_UNIT = TimeUnit.SECONDS;
|
||||
|
||||
protected final static long DEFAULT_IDLE_TIME = 30;
|
||||
|
||||
private final long idleTime;
|
||||
|
||||
TimedIndexTask(final GDataIndexer indexer,
|
||||
final BlockingQueue<Future<IndexDocument>> taskQueue,
|
||||
final long idleTime) {
|
||||
super(indexer, taskQueue);
|
||||
this.idleTime = idleTime < DEFAULT_IDLE_TIME ? DEFAULT_IDLE_TIME
|
||||
: idleTime;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.lucene.gdata.search.index.IndexTask#getTask()
|
||||
*/
|
||||
@Override
|
||||
protected Future<IndexDocument> getTask() throws InterruptedException {
|
||||
/*
|
||||
* wait for a certain time and return null if no task is on the queue.
|
||||
* If return null --> commit will be called
|
||||
*/
|
||||
Future<IndexDocument> retVal = this.taskQueue.poll(this.idleTime, TIME_UNIT);
|
||||
if(retVal== null)
|
||||
this.commit.set(true);
|
||||
return retVal;
|
||||
|
||||
}
|
||||
|
||||
protected long getIdleTime(){
|
||||
return this.idleTime;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,10 +0,0 @@
|
|||
<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<meta name="Author" content="Simon Willnauer">
|
||||
</head>
|
||||
<body>
|
||||
Contains classes processing of documents and accessing the search index of the server
|
||||
</body>
|
||||
</html>
|
|
@ -1,10 +0,0 @@
|
|||
<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<meta name="Author" content="Simon Willnauer">
|
||||
</head>
|
||||
<body>
|
||||
Classes used for query the lucene index for a specific feed instance
|
||||
</body>
|
||||
</html>
|
|
@ -1,59 +0,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.
|
||||
*/
|
||||
|
||||
package org.apache.lucene.gdata.search.query;
|
||||
|
||||
import org.apache.lucene.analysis.Analyzer;
|
||||
import org.apache.lucene.gdata.search.config.IndexSchema;
|
||||
import org.apache.lucene.queryParser.QueryParser;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class GDataQueryParser extends QueryParser {
|
||||
|
||||
/**
|
||||
* Creates a new QueryParser instance and sets the default operator to
|
||||
* {@link org.apache.lucene.queryParser.QueryParser.Operator#AND}
|
||||
*
|
||||
* @param field -
|
||||
* the parser field
|
||||
* @param analyzer -
|
||||
* the parser analyzer
|
||||
*/
|
||||
public GDataQueryParser(String field, Analyzer analyzer) {
|
||||
super(field, analyzer);
|
||||
this.setDefaultOperator(Operator.AND);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new QueryParser instance and sets the default operator to
|
||||
* {@link org.apache.lucene.queryParser.QueryParser.Operator#AND}.
|
||||
* The parser will use
|
||||
* {@link IndexSchema#getDefaultSearchField} as the field and
|
||||
* {@link IndexSchema#getSchemaAnalyzer()} as the analyzer.
|
||||
*
|
||||
* @param schema -
|
||||
* the schema to set the default fields
|
||||
*/
|
||||
public GDataQueryParser(IndexSchema schema) {
|
||||
this(schema.getDefaultSearchField(), schema.getSchemaAnalyzer());
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -1,135 +0,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.
|
||||
*/
|
||||
|
||||
package org.apache.lucene.gdata.search.query;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.lucene.gdata.search.config.IndexSchema;
|
||||
|
||||
import com.google.gdata.data.DateTime;
|
||||
|
||||
/**
|
||||
* Simple static methods to translate the http query to a lucene query string.
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class QueryTranslator {
|
||||
private static final Set<String> STANDARD_REQUEST_PARAMETER = new HashSet<String>(3);
|
||||
private static final String GDATA_DEFAULT_SEARCH_PARAMETER = "q";
|
||||
private static final String UPDATED_MIN = Long.toString(0);
|
||||
private static final String UPDATED_MAX = Long.toString(Long.MAX_VALUE);
|
||||
// private static final String GDATA_CATEGORY_FIEL =
|
||||
|
||||
|
||||
|
||||
static{
|
||||
STANDARD_REQUEST_PARAMETER.add("max-results");
|
||||
STANDARD_REQUEST_PARAMETER.add("start-index");
|
||||
STANDARD_REQUEST_PARAMETER.add("alt");
|
||||
}
|
||||
/**
|
||||
* This method does a little preprocessing of the query. Basically it will map the given request parameters to a lucene syntax. Each
|
||||
* parameter matching a index field in the given schema will be translated into a grouped query string according to the lucene query syntax.
|
||||
* <p>
|
||||
* <ol>
|
||||
* <li>title=foo bar AND "FooBar" will be title:(foo bar AND "FooBar)</i>
|
||||
* <li>updated-min=2005-08-09T10:57:00-08:00 will be translated to updated:[1123613820000 TO 9223372036854775807] according to the gdata protocol</i>
|
||||
* </ol>
|
||||
* </p>
|
||||
* @param schema the index schema for the queried service
|
||||
* @param parameterMap - the http parameter map returning String[] instances as values
|
||||
* @param categoryQuery - the parsed category query from the request
|
||||
* @return - a lucene syntax query string
|
||||
*/
|
||||
public static String translateHttpSearchRequest(IndexSchema schema,
|
||||
Map<String, String[]> parameterMap, String categoryQuery) {
|
||||
Set<String> searchableFieldNames = schema.getSearchableFieldNames();
|
||||
Set<String> parameterSet = parameterMap.keySet();
|
||||
StringBuilder translatedQuery = new StringBuilder();
|
||||
if(categoryQuery != null){
|
||||
translatedQuery.append(translateCategory(translatedQuery,categoryQuery));
|
||||
}
|
||||
String updateMin = null;
|
||||
String updateMax = null;
|
||||
for (String parameterName : parameterSet) {
|
||||
if (STANDARD_REQUEST_PARAMETER.contains(parameterName))
|
||||
continue;
|
||||
if (searchableFieldNames.contains(parameterName)) {
|
||||
translatedQuery.append(parameterName).append(":(");
|
||||
translatedQuery.append(parameterMap.get(parameterName)[0]);
|
||||
translatedQuery.append(") ");
|
||||
continue;
|
||||
}
|
||||
if(parameterName.equals(GDATA_DEFAULT_SEARCH_PARAMETER)){
|
||||
translatedQuery.append(schema.getDefaultSearchField());
|
||||
translatedQuery.append(":(");
|
||||
translatedQuery.append(parameterMap.get(parameterName)[0]);
|
||||
translatedQuery.append(") ");
|
||||
continue;
|
||||
|
||||
}
|
||||
if(parameterName.endsWith("updated-min")){
|
||||
updateMin = parameterMap.get(parameterName)[0];
|
||||
continue;
|
||||
}
|
||||
if(parameterName.endsWith("updated-max")){
|
||||
updateMax = parameterMap.get(parameterName)[0];
|
||||
continue;
|
||||
}
|
||||
throw new RuntimeException("Can not apply parameter -- invalid -- "
|
||||
+ parameterName);
|
||||
}
|
||||
if(updateMax!=null || updateMin!= null)
|
||||
translatedQuery.append(translateUpdate(updateMin,updateMax));
|
||||
|
||||
return translatedQuery.length() == 0?null:translatedQuery.toString();
|
||||
}
|
||||
|
||||
|
||||
static String translateUpdate(String updateMin, String updateMax){
|
||||
StringBuilder builder = new StringBuilder("updated:[");
|
||||
if(updateMin != null)
|
||||
builder.append(Long.toString(DateTime.parseDateTime(updateMin).getValue()));
|
||||
else
|
||||
builder.append(UPDATED_MIN);
|
||||
builder.append(" TO ");
|
||||
if(updateMax != null)
|
||||
builder.append(Long.toString(DateTime.parseDateTime(updateMax).getValue()-1));
|
||||
else
|
||||
builder.append(UPDATED_MAX);
|
||||
builder.append("]");
|
||||
return builder.toString();
|
||||
|
||||
|
||||
}
|
||||
|
||||
static String translateCategory(StringBuilder builder, String categoryQuery){
|
||||
return categoryQuery;
|
||||
//TODO Implement this
|
||||
// GDataCategoryQueryParser parser = new GDataCategoryQueryParser()
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
|
@ -1,74 +0,0 @@
|
|||
package org.apache.lucene.gdata.server;
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* Will be thrown if a requested feed could not be found or is not
|
||||
* registerd.
|
||||
*
|
||||
* @author Simon Willnauer
|
||||
*
|
||||
*/
|
||||
public class FeedNotFoundException extends ServiceException {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* Constructs a new FeedNotFoundException
|
||||
* @param errorCode - gdata request errorcode
|
||||
*/
|
||||
public FeedNotFoundException(int errorCode) {
|
||||
super(errorCode);
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new FeedNotFoundException
|
||||
* @param arg0 - the exception message
|
||||
* @param errorCode - gdata request errorcode
|
||||
*/
|
||||
public FeedNotFoundException(String arg0,int errorCode) {
|
||||
super(arg0, errorCode);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new FeedNotFoundException
|
||||
* @param arg0 - the exceptin message
|
||||
* @param arg1 - the exception cause
|
||||
* @param errorCode - gdata request errorcode
|
||||
*/
|
||||
public FeedNotFoundException(String arg0, Throwable arg1,int errorCode) {
|
||||
super(arg0, arg1, errorCode);
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new FeedNotFoundException
|
||||
* @param arg0 - the exception cause
|
||||
* @param errorCode - gdata request errorcode
|
||||
*/
|
||||
public FeedNotFoundException(Throwable arg0,int errorCode) {
|
||||
super(arg0, errorCode);
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -1,171 +0,0 @@
|
|||
/**
|
||||
* Copyright 2004 The Apache Software Foundation
|
||||
*
|
||||
* Licensed 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.server;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Reader;
|
||||
|
||||
import org.apache.lucene.gdata.server.registry.ProvidedService;
|
||||
|
||||
import com.google.gdata.data.BaseEntry;
|
||||
import com.google.gdata.data.BaseFeed;
|
||||
import com.google.gdata.util.ParseException;
|
||||
|
||||
/**
|
||||
* {@link com.google.gdata.data.BaseFeed},
|
||||
* {@link com.google.gdata.data.BaseEntry} instances have to be build from a
|
||||
* {@link java.io.Reader} instance as they come in from a client request or out
|
||||
* of a storage.
|
||||
* <p>
|
||||
* To provide a generic builder class the {@link GDataEntityBuilder} requests
|
||||
* the type of the feed / entry and the corresponding
|
||||
* {@link com.google.gdata.data.ExtensionProfile} form the global
|
||||
* {@link org.apache.lucene.gdata.server.registry.GDataServerRegistry} and
|
||||
* builds the instances from the provided reader.
|
||||
* </p>
|
||||
* <p>
|
||||
* This build will not returne the abstract base classes.
|
||||
* </p>
|
||||
*
|
||||
* @author Simon Willnauer
|
||||
*
|
||||
*/
|
||||
public class GDataEntityBuilder {
|
||||
|
||||
/**
|
||||
* Builds a {@link BaseFeed} instance from the {@link Reader} provided by
|
||||
* the {@link GDataRequest}
|
||||
*
|
||||
* @param request -
|
||||
* the request to build the instance from
|
||||
* @return - a BaseFeed instance
|
||||
*
|
||||
* @throws IOException -
|
||||
* if an I/O Exception occures on the provided reader
|
||||
* @throws ParseException -
|
||||
* if the feed could not be parsed
|
||||
*/
|
||||
public static BaseFeed buildFeed(final GDataRequest request)
|
||||
throws IOException, ParseException {
|
||||
if (request == null)
|
||||
throw new IllegalArgumentException("request must not be null");
|
||||
ProvidedService config = request.getConfigurator();
|
||||
return buildFeed(request.getReader(), config);
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a {@link BaseFeed} from the provided {@link Reader}
|
||||
*
|
||||
*
|
||||
* @param reader -
|
||||
* the reader to build the feed from
|
||||
* @param config -
|
||||
* the feed instance config containing the extension profile to
|
||||
* parse the resource
|
||||
* @return - a BaseFeed instance
|
||||
*
|
||||
* @throws IOException -
|
||||
* if an I/O Exception occures on the provided reader
|
||||
* @throws ParseException -
|
||||
* if the feed could not be parsed
|
||||
*/
|
||||
public static BaseFeed buildFeed(final Reader reader,
|
||||
final ProvidedService config) throws ParseException, IOException {
|
||||
|
||||
BaseFeed retVal = null;
|
||||
retVal = createEntityInstance(config);
|
||||
retVal.parseAtom(config.getExtensionProfile(), reader);
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a {@link BaseEntry} instance from the {@link Reader} provided by
|
||||
* the {@link GDataRequest}
|
||||
*
|
||||
* @param request -
|
||||
* the request to build the instance from
|
||||
* @return - a BaseEntry instance
|
||||
*
|
||||
* @throws IOException -
|
||||
* if an I/O Exception occures on the provided reader
|
||||
* @throws ParseException -
|
||||
* if the entry could not be parsed
|
||||
*/
|
||||
public static BaseEntry buildEntry(final GDataRequest request)
|
||||
throws IOException, ParseException {
|
||||
if (request == null)
|
||||
throw new IllegalArgumentException("request must not be null");
|
||||
ProvidedService config = request.getConfigurator();
|
||||
return buildEntry(request.getReader(), config);
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a {@link BaseFeed} instance from the {@link Reader} provided by
|
||||
* the {@link GDataRequest}
|
||||
*
|
||||
* @param reader -
|
||||
* the reader to build the feed from
|
||||
* @param config -
|
||||
* the instance config containing the extension profile to parse
|
||||
* the resource
|
||||
* @return - a BaseFeed instance
|
||||
*
|
||||
* @throws IOException -
|
||||
* if an I/O Exception occures on the provided reader
|
||||
* @throws ParseException -
|
||||
* if the entry could not be parsed
|
||||
*/
|
||||
public static BaseEntry buildEntry(final Reader reader,
|
||||
final ProvidedService config) throws ParseException, IOException {
|
||||
|
||||
BaseEntry e = createEntityInstance(config).createEntry();
|
||||
e.parseAtom(config.getExtensionProfile(), reader);
|
||||
return e;
|
||||
}
|
||||
|
||||
private static BaseFeed createEntityInstance(
|
||||
final ProvidedService config) {
|
||||
if(config.getFeedType() == null)
|
||||
throw new IllegalArgumentException("feedtype is null in ProvidedService");
|
||||
|
||||
BaseFeed retVal = null;
|
||||
try {
|
||||
retVal = (BaseFeed) config.getFeedType().newInstance();
|
||||
} catch (Exception e) {
|
||||
throw new EntityBuilderException("Can't instanciate Feed for feedType "+config.getFeedType().getName(),e);
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
static class EntityBuilderException extends RuntimeException{
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = 7224011324202237951L;
|
||||
|
||||
EntityBuilderException(String arg0) {
|
||||
super(arg0);
|
||||
|
||||
}
|
||||
|
||||
EntityBuilderException(String arg0, Throwable arg1) {
|
||||
super(arg0, arg1);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -1,598 +0,0 @@
|
|||
/**
|
||||
* Copyright 2004 The Apache Software Foundation
|
||||
*
|
||||
* Licensed 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.server;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Reader;
|
||||
import java.util.Enumeration;
|
||||
import java.util.Map;
|
||||
import java.util.StringTokenizer;
|
||||
|
||||
import javax.servlet.http.Cookie;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.apache.lucene.gdata.search.config.IndexSchema;
|
||||
import org.apache.lucene.gdata.search.query.QueryTranslator;
|
||||
import org.apache.lucene.gdata.server.authentication.AuthenticationController;
|
||||
import org.apache.lucene.gdata.server.registry.GDataServerRegistry;
|
||||
import org.apache.lucene.gdata.server.registry.ProvidedService;
|
||||
|
||||
/**
|
||||
* The GDataRequest Class wraps the incoming HttpServletRequest. Needed
|
||||
* information coming with the HttpServletRequest can be accessed directly. It
|
||||
* represents an abstraction on the plain HttpServletRequest. Every GData
|
||||
* specific data coming from the client will be available and can be accessed
|
||||
* via the GDataRequest.
|
||||
* <p>
|
||||
* GDataRequest instances will be passed to any action requested by the client.
|
||||
* This class also holds the logic to retrieve important information like
|
||||
* response format, the requested feed instance and query parameters.
|
||||
*
|
||||
* </p>
|
||||
*
|
||||
* @author Simon Willnauer
|
||||
*
|
||||
*/
|
||||
/* this class might be extracted as an interface in later development */
|
||||
public class GDataRequest {
|
||||
|
||||
|
||||
private static final Log LOG = LogFactory.getLog(GDataRequest.class);
|
||||
|
||||
private static final String RESPONSE_FORMAT_PARAMETER = "alt";
|
||||
|
||||
private static final String RESPONSE_FORMAT_PARAMETER_RSS = "rss";
|
||||
private static final String RESPONSE_FORMAT_PARAMETER_HTML = "html";
|
||||
|
||||
private static final int DEFAULT_ITEMS_PER_PAGE = 25;
|
||||
|
||||
private static final int DEFAULT_START_INDEX = 1;
|
||||
|
||||
private static final String START_INDEX_NEXT_PAGE_PARAMETER = "start-index";
|
||||
|
||||
private static final String ITEMS_PER_PAGE_PARAMETER = "max-results";
|
||||
|
||||
private String contextPath;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private static final String RESPONSE_FORMAT_PARAMETER_ATOM = "atom";
|
||||
|
||||
private static final String HTTP_HEADER_IF_MODIFIED_SINCE = "If-Modified-Since";
|
||||
|
||||
private static final String HTTP_HEADER_AUTH = "Authorization";
|
||||
|
||||
private static final Object CATEGORY_QUERY_INDICATOR = "-";
|
||||
|
||||
// Atom is the default response format
|
||||
private OutputFormat responseFormat = OutputFormat.ATOM;
|
||||
|
||||
private final HttpServletRequest request;
|
||||
|
||||
private String feedId = null;
|
||||
|
||||
private String entryId = null;
|
||||
|
||||
private String service = null;
|
||||
|
||||
private ProvidedService configurator = null;
|
||||
|
||||
private boolean isSearchRequest = false;
|
||||
|
||||
private String entryVersion = null;
|
||||
|
||||
private GDataRequestType type;
|
||||
|
||||
private String categoryQuery;
|
||||
|
||||
private String translatedSearchQuery;
|
||||
|
||||
private boolean isFeedRequest = false;
|
||||
|
||||
/**
|
||||
* Creates a new FeedRequest
|
||||
*
|
||||
* @param requst -
|
||||
* the incoming HttpServletReqeust
|
||||
* @param type -
|
||||
* the request type
|
||||
*
|
||||
*/
|
||||
public GDataRequest(final HttpServletRequest requst,
|
||||
final GDataRequestType type) {
|
||||
if (requst == null)
|
||||
throw new IllegalArgumentException("request must not be null ");
|
||||
if (type == null)
|
||||
throw new IllegalArgumentException("request type must not be null ");
|
||||
this.request = requst;
|
||||
this.type = type;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the GDataRequest. This will initialize all needed values /
|
||||
* attributes in this request.
|
||||
*
|
||||
* @throws GDataRequestException
|
||||
*/
|
||||
public void initializeRequest() throws GDataRequestException {
|
||||
generateIdentificationProperties();
|
||||
setOutputFormat();
|
||||
|
||||
try {
|
||||
/*
|
||||
* ExtensionProfile and the type is used for building the Entry /
|
||||
* Feed Instances from an input stream or reader
|
||||
*
|
||||
*/
|
||||
this.configurator = GDataServerRegistry.getRegistry()
|
||||
.getProvidedService(this.service);
|
||||
|
||||
if (this.configurator == null)
|
||||
throw new GDataRequestException(
|
||||
"no Provided Service found for service id: "+this.service,GDataResponse.NOT_FOUND);
|
||||
applyRequestParameter();
|
||||
if(this.translatedSearchQuery != null)
|
||||
this.isSearchRequest = true;
|
||||
} catch(GDataRequestException ex){
|
||||
throw ex;
|
||||
} catch (Exception e) {
|
||||
throw new GDataRequestException(
|
||||
"failed to initialize GDataRequest -- "
|
||||
+ e.getMessage(), e,GDataResponse.SERVER_ERROR);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private void applyRequestParameter() throws GDataRequestException{
|
||||
IndexSchema schema = this.configurator.getIndexSchema();
|
||||
try{
|
||||
this.translatedSearchQuery = QueryTranslator.translateHttpSearchRequest(schema,this.request.getParameterMap(),this.categoryQuery);
|
||||
}catch (Exception e) {
|
||||
throw new GDataRequestException("Can not translate user query to search query",e,GDataResponse.BAD_REQUEST);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return - the id of the requested feed
|
||||
*/
|
||||
public String getFeedId() {
|
||||
|
||||
return this.feedId;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return - the entry id of the requested Entry if specified, otherwise
|
||||
* <code>null</code>
|
||||
*/
|
||||
public String getEntryId() {
|
||||
|
||||
return this.entryId;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the version Id of the requested Entry if specified, otherwise
|
||||
* <code>null</code>
|
||||
*/
|
||||
public String getEntryVersion() {
|
||||
return this.entryVersion;
|
||||
}
|
||||
|
||||
/**
|
||||
* A Reader instance to read form the client input stream
|
||||
*
|
||||
* @return - the HttpServletRequest {@link Reader}
|
||||
* @throws IOException -
|
||||
* if an I/O Exception occurs
|
||||
*/
|
||||
public Reader getReader() throws IOException {
|
||||
return this.request.getReader();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link HttpServletRequest} parameter map containing all
|
||||
* <i>GET</i> request parameters.
|
||||
*
|
||||
* @return the parameter map
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public Map<String, String[]> getQueryParameter() {
|
||||
return this.request.getParameterMap();
|
||||
}
|
||||
|
||||
/**
|
||||
* The {@link HttpServletRequest} request parameter names
|
||||
*
|
||||
* @return parameter names enumeration
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public Enumeration<String> getQueryParameterNames() {
|
||||
return this.request.getParameterNames();
|
||||
}
|
||||
|
||||
/**
|
||||
* Either <i>Atom</i> or <i>RSS</i>
|
||||
*
|
||||
* @return - The output format requested by the client
|
||||
*/
|
||||
public OutputFormat getRequestedResponseFormat() {
|
||||
|
||||
return this.responseFormat;
|
||||
}
|
||||
|
||||
private void generateIdentificationProperties()
|
||||
throws GDataRequestException {
|
||||
/* generate all needed data to identify the requested feed/entry */
|
||||
String pathInfo = this.request.getPathInfo();
|
||||
if (pathInfo.length() <= 1)
|
||||
throw new GDataRequestException(
|
||||
"No feed or entry specified for this request",GDataResponse.BAD_REQUEST);
|
||||
StringTokenizer tokenizer = new StringTokenizer(pathInfo, "/");
|
||||
this.service = tokenizer.nextToken();
|
||||
if (!tokenizer.hasMoreTokens())
|
||||
throw new GDataRequestException(
|
||||
"Can not find feed id in requested path " + pathInfo,GDataResponse.BAD_REQUEST);
|
||||
this.feedId = tokenizer.nextToken();
|
||||
|
||||
String appendix = tokenizer.hasMoreTokens() ? tokenizer.nextToken()
|
||||
: null;
|
||||
if (appendix == null){
|
||||
this.isFeedRequest = true;
|
||||
return;
|
||||
}
|
||||
if (appendix.equals(CATEGORY_QUERY_INDICATOR)) {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
while (tokenizer.hasMoreTokens())
|
||||
builder.append("/").append(tokenizer.nextToken());
|
||||
this.categoryQuery = builder.toString();
|
||||
} else {
|
||||
this.entryId = appendix;
|
||||
this.entryVersion = tokenizer.hasMoreTokens() ? tokenizer
|
||||
.nextToken() : "";
|
||||
}
|
||||
this.isFeedRequest = (this.type == GDataRequestType.GET && (this.entryId == null
|
||||
|| this.entryId.length() == 0 || (this.entryId.equals('/'))));
|
||||
}
|
||||
|
||||
private void setOutputFormat() {
|
||||
String formatParameter = this.request
|
||||
.getParameter(RESPONSE_FORMAT_PARAMETER);
|
||||
if (formatParameter == null)
|
||||
return;
|
||||
if (formatParameter.equalsIgnoreCase(RESPONSE_FORMAT_PARAMETER_RSS))
|
||||
this.responseFormat = OutputFormat.RSS;
|
||||
if (formatParameter.equalsIgnoreCase(RESPONSE_FORMAT_PARAMETER_HTML))
|
||||
this.responseFormat = OutputFormat.HTML;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @return - the number of returned items per page
|
||||
*/
|
||||
public int getItemsPerPage() {
|
||||
|
||||
if (this.request.getParameter(ITEMS_PER_PAGE_PARAMETER) == null)
|
||||
return DEFAULT_ITEMS_PER_PAGE;
|
||||
int retval = -1;
|
||||
try {
|
||||
retval = new Integer(this.request
|
||||
.getParameter(ITEMS_PER_PAGE_PARAMETER)).intValue();
|
||||
} catch (Exception e) {
|
||||
LOG.warn("Items per page could not be parsed - " + e.getMessage(),
|
||||
e);
|
||||
}
|
||||
|
||||
return retval < 0 ? DEFAULT_ITEMS_PER_PAGE : retval;
|
||||
}
|
||||
|
||||
/**
|
||||
* Start index represents the number of the first entry of the query -
|
||||
* result. The order depends on the query. Is the query a search query the
|
||||
* this value will be assigned to the score in a common feed query the value
|
||||
* will be assigned to the update time of the entries.
|
||||
*
|
||||
* @return - the requested start index
|
||||
*/
|
||||
public int getStartIndex() {
|
||||
String startIndex = this.request.getParameter(START_INDEX_NEXT_PAGE_PARAMETER);
|
||||
if (startIndex == null)
|
||||
return DEFAULT_START_INDEX;
|
||||
int retval = -1;
|
||||
try {
|
||||
retval = new Integer(startIndex).intValue();
|
||||
} catch (Exception e) {
|
||||
LOG.warn("Start-index could not be parsed - not an integer - " + e.getMessage());
|
||||
}
|
||||
return retval < 0 ? DEFAULT_START_INDEX : retval;
|
||||
}
|
||||
|
||||
/**
|
||||
* The self id is the feeds <i>href</i> pointing to the requested resource
|
||||
*
|
||||
* @return - the self id
|
||||
*/
|
||||
public String getSelfId() {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append(buildRequestIDString(false));
|
||||
builder.append("?");
|
||||
builder.append(getQueryString());
|
||||
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* The previous id is the feeds <i>href</i> pointing to the previous result of the requested resource
|
||||
*
|
||||
* @return - the self id
|
||||
*/
|
||||
public String getPreviousId(){
|
||||
|
||||
int startIndex = getStartIndex();
|
||||
if(startIndex == DEFAULT_START_INDEX )
|
||||
return null;
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append(buildRequestIDString(false));
|
||||
startIndex = startIndex-getItemsPerPage();
|
||||
builder.append(getPreparedQueryString(startIndex<1?DEFAULT_START_INDEX:startIndex));
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
|
||||
|
||||
private String getPreparedQueryString(int startIndex){
|
||||
String queryString = this.request.getQueryString();
|
||||
String startIndexValue = this.request.getParameter(START_INDEX_NEXT_PAGE_PARAMETER);
|
||||
String maxResultsValue = this.request.getParameter(ITEMS_PER_PAGE_PARAMETER);
|
||||
|
||||
StringBuilder builder = new StringBuilder("?");
|
||||
if(maxResultsValue == null){
|
||||
builder.append(ITEMS_PER_PAGE_PARAMETER).append("=").append(DEFAULT_ITEMS_PER_PAGE);
|
||||
builder.append("&");
|
||||
}
|
||||
if(startIndexValue== null){
|
||||
builder.append(START_INDEX_NEXT_PAGE_PARAMETER).append("=");
|
||||
builder.append(Integer.toString(startIndex));
|
||||
if(queryString!=null){
|
||||
builder.append("&");
|
||||
builder.append(queryString);
|
||||
}
|
||||
}else{
|
||||
builder.append(queryString.replaceAll("start-index=[\\d]*",START_INDEX_NEXT_PAGE_PARAMETER+"="+Integer.toString(startIndex)));
|
||||
}
|
||||
return builder.toString();
|
||||
}
|
||||
/**
|
||||
* The <i>href</i> id of the next page of the requested resource.
|
||||
*
|
||||
* @return the id of the next page
|
||||
*/
|
||||
public String getNextId() {
|
||||
int startIndex = getStartIndex();
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append(buildRequestIDString(false));
|
||||
startIndex = startIndex+getItemsPerPage();
|
||||
builder.append(getPreparedQueryString(startIndex));
|
||||
return builder.toString();
|
||||
|
||||
}
|
||||
|
||||
private String buildRequestIDString(boolean endingSlash) {
|
||||
StringBuilder builder = new StringBuilder("http://");
|
||||
builder.append(this.request.getHeader("Host"));
|
||||
builder.append(this.request.getRequestURI());
|
||||
if (!endingSlash && builder.charAt(builder.length() - 1) == '/')
|
||||
builder.setLength(builder.length() - 1);
|
||||
if (endingSlash && builder.charAt(builder.length() - 1) != '/')
|
||||
builder.append("/");
|
||||
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* This will return the current query string including all parameters.
|
||||
* Additionally the <code>max-resul</code> parameter will be added if not
|
||||
* specified.
|
||||
* <p>
|
||||
* <code>max-resul</code> indicates the number of results returned to the
|
||||
* client. The default value is 25.
|
||||
* </p>
|
||||
*
|
||||
* @return - the query string including all parameters
|
||||
*/
|
||||
public String getQueryString() {
|
||||
String retVal = this.request.getQueryString();
|
||||
|
||||
if (this.request.getParameter(ITEMS_PER_PAGE_PARAMETER) != null)
|
||||
return retVal;
|
||||
String tempString = (retVal == null ? ITEMS_PER_PAGE_PARAMETER + "="
|
||||
+ DEFAULT_ITEMS_PER_PAGE : "&" + ITEMS_PER_PAGE_PARAMETER + "="
|
||||
+ DEFAULT_ITEMS_PER_PAGE);
|
||||
|
||||
return retVal == null ? tempString : retVal + tempString;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* This enum represents the OutputFormat of the GDATA Server
|
||||
*
|
||||
* @author Simon Willnauer
|
||||
*
|
||||
*/
|
||||
public static enum OutputFormat {
|
||||
/**
|
||||
* Output format ATOM. ATOM is the default response format.
|
||||
*/
|
||||
ATOM,
|
||||
/**
|
||||
* Output format RSS
|
||||
*/
|
||||
RSS,
|
||||
/**
|
||||
* Output format html if user defined xsl style sheet is present
|
||||
*/
|
||||
HTML
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the requested path including the domain name and the requested
|
||||
* resource <i>http://www.apache.org/path/resource/</i>
|
||||
*
|
||||
* @return the context path
|
||||
*/
|
||||
public String getContextPath() {
|
||||
if (this.contextPath == null)
|
||||
this.contextPath = buildRequestIDString(true);
|
||||
return this.contextPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates the request type
|
||||
*
|
||||
* @author Simon Willnauer
|
||||
*
|
||||
*/
|
||||
public enum GDataRequestType {
|
||||
/**
|
||||
* Type FeedRequest
|
||||
*/
|
||||
GET,
|
||||
/**
|
||||
* Type UpdateRequest
|
||||
*/
|
||||
UPDATE,
|
||||
/**
|
||||
* Type DeleteRequest
|
||||
*/
|
||||
DELETE,
|
||||
/**
|
||||
* Type InsertRequest
|
||||
*/
|
||||
INSERT
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link GDataRequestType}
|
||||
*
|
||||
* @return the current request type
|
||||
*/
|
||||
public GDataRequestType getType() {
|
||||
return this.type;
|
||||
}
|
||||
|
||||
/**
|
||||
* If the request is a {@link GDataRequestType#GET} request and there is no
|
||||
* entry id specified, the requested resource is a feed.
|
||||
*
|
||||
* @return - <code>true</code> if an only if the requested resource is a
|
||||
* feed
|
||||
*/
|
||||
public boolean isFeedRequested() {
|
||||
|
||||
return this.isFeedRequest ;
|
||||
}
|
||||
|
||||
/**
|
||||
* * If the request is a {@link GDataRequestType#GET} request and there is
|
||||
* an entry id specified, the requested resource is an entry.
|
||||
*
|
||||
* @return - <code>true</code> if an only if the requested resource is an
|
||||
* entry
|
||||
*/
|
||||
public boolean isEntryRequested() {
|
||||
return !this.isFeedRequested();
|
||||
}
|
||||
/**
|
||||
* @return - <code>true</code> if an only if the user request is a search request, otherwise <code>false</code>
|
||||
*/
|
||||
public boolean isSearchRequested(){
|
||||
return this.isSearchRequest;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the configuration for this request
|
||||
*/
|
||||
public ProvidedService getConfigurator() {
|
||||
return this.configurator;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return - Returns the Internet Protocol (IP) address of the client or
|
||||
* last proxy that sent the request.
|
||||
*/
|
||||
public String getRemoteAddress() {
|
||||
return this.request.getRemoteAddr();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return - the value for the send auth token. The auth token will be send
|
||||
* as a request <tt>Authentication</tt> header.
|
||||
*/
|
||||
public String getAuthToken() {
|
||||
String token = this.request.getHeader(HTTP_HEADER_AUTH);
|
||||
if (token == null)
|
||||
return null;
|
||||
token = token.substring(token.indexOf("=") + 1);
|
||||
return token;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return - Returns an array containing all of the Cookie objects the
|
||||
* client sent with underlying HttpServletRequest.
|
||||
*/
|
||||
public Cookie[] getCookies() {
|
||||
return this.request.getCookies();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return - the cookie set instead of the authentication token or
|
||||
* <code>null</code> if no auth cookie is set
|
||||
*/
|
||||
public Cookie getAuthCookie() {
|
||||
Cookie[] cookies = this.request.getCookies();
|
||||
if (cookies == null)
|
||||
return null;
|
||||
for (int i = 0; i < cookies.length; i++) {
|
||||
if (cookies[i].getName().equals(AuthenticationController.TOKEN_KEY))
|
||||
return cookies[i];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return - the date string of the <tt>If-Modified-Since</tt> HTTP
|
||||
* request header, or null if header is not set
|
||||
*/
|
||||
public String getModifiedSince() {
|
||||
return this.request.getHeader(HTTP_HEADER_IF_MODIFIED_SINCE);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return - the underlying HttpServletRequest
|
||||
*/
|
||||
public HttpServletRequest getHttpServletRequest() {
|
||||
|
||||
return this.request;
|
||||
}
|
||||
|
||||
protected String getTranslatedQuery(){
|
||||
return this.translatedSearchQuery;
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -1,80 +0,0 @@
|
|||
/**
|
||||
* Copyright 2004 The Apache Software Foundation
|
||||
*
|
||||
* Licensed 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.server;
|
||||
|
||||
/**
|
||||
* This exception wraps all exceptions occur inside the {@link org.apache.lucene.gdata.server.GDataRequest}
|
||||
* @author Simon Willnauer
|
||||
*
|
||||
*/
|
||||
public class GDataRequestException extends Exception {
|
||||
private final int errorCode;
|
||||
/**
|
||||
* Serial version ID. -> Implements Serializable
|
||||
*/
|
||||
private static final long serialVersionUID = -4440777051466950723L;
|
||||
|
||||
/**
|
||||
/**
|
||||
* Constructs a new GDataRequestException
|
||||
* @param errorCode - gdata request error code
|
||||
*/
|
||||
public GDataRequestException(int errorCode) {
|
||||
super();
|
||||
this.errorCode = errorCode;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new GDataRequestException
|
||||
* @param arg0 - the exception message
|
||||
* @param errorCode - gdata request error code
|
||||
*/
|
||||
public GDataRequestException(String arg0,int errorCode) {
|
||||
super(arg0);
|
||||
this.errorCode = errorCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new GDataRequestException
|
||||
* @param arg0 - the exception message
|
||||
* @param arg1 - the exception cause
|
||||
* @param errorCode - gdata request error code
|
||||
*/
|
||||
public GDataRequestException(String arg0, Throwable arg1,int errorCode) {
|
||||
super(arg0, arg1);
|
||||
this.errorCode = errorCode;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new GDataRequestException
|
||||
* @param arg0 - the exception cause
|
||||
* @param errorCode - gdata request error code
|
||||
*/
|
||||
public GDataRequestException(Throwable arg0,int errorCode) {
|
||||
super(arg0);
|
||||
this.errorCode = errorCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the errorCode.
|
||||
*/
|
||||
public int getErrorCode() {
|
||||
return this.errorCode;
|
||||
}
|
||||
}
|
|
@ -1,449 +0,0 @@
|
|||
/**
|
||||
* Copyright 2004 The Apache Software Foundation
|
||||
*
|
||||
* Licensed 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.server;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.StringReader;
|
||||
import java.io.StringWriter;
|
||||
import java.io.Writer;
|
||||
import java.util.Date;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.xml.transform.Source;
|
||||
import javax.xml.transform.Templates;
|
||||
import javax.xml.transform.Transformer;
|
||||
import javax.xml.transform.TransformerException;
|
||||
import javax.xml.transform.stream.StreamResult;
|
||||
import javax.xml.transform.stream.StreamSource;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.apache.lucene.gdata.server.GDataRequest.OutputFormat;
|
||||
import org.apache.lucene.gdata.server.registry.ProvidedService;
|
||||
import org.apache.lucene.gdata.utils.DateFormater;
|
||||
|
||||
import com.google.gdata.data.BaseEntry;
|
||||
import com.google.gdata.data.BaseFeed;
|
||||
import com.google.gdata.data.DateTime;
|
||||
import com.google.gdata.data.ExtensionProfile;
|
||||
import com.google.gdata.util.common.xml.XmlWriter;
|
||||
import com.google.gdata.util.common.xml.XmlWriter.Namespace;
|
||||
|
||||
/**
|
||||
* The FeedRequest Class wraps the current HttpServletResponse. Any action on the
|
||||
* HttpServletRequest will be executed via this class. This represents an
|
||||
* abstraction on the plain {@link HttpServletResponse}. Any action which has
|
||||
* to be performed on the underlying {@link HttpServletResponse} will be
|
||||
* executed within this class.
|
||||
* <p>
|
||||
* The GData basically writes two different kinds of response to the output
|
||||
* stream.
|
||||
* <ol>
|
||||
* <li>update, delete or insert requests will respond with a status code and if
|
||||
* successful the feed entry modified or created</li>
|
||||
* <li>get requests will respond with a status code and if successful the
|
||||
* requested feed</li>
|
||||
* </ol>
|
||||
*
|
||||
* For this purpose the {@link GDataResponse} class provides the overloaded
|
||||
* method
|
||||
* {@link org.apache.lucene.gdata.server.GDataResponse#sendResponse}
|
||||
* which sends the entry e.g feed to the output stream.
|
||||
* </p>
|
||||
* <p>
|
||||
* This class will set the HTTP <tt>Last-Modified</tt> Header to enable
|
||||
* clients to send <tt>If-Modified-Since</tt> request header to avoid
|
||||
* retrieving the content again if it hasn't changed. If the content hasn't
|
||||
* changed since the If-Modified-Since time, then the GData service returns a
|
||||
* 304 (Not Modified) HTTP response.
|
||||
* </p>
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
* @author Simon Willnauer
|
||||
*
|
||||
*/
|
||||
public class GDataResponse {
|
||||
/**
|
||||
* Response code bad request
|
||||
*/
|
||||
public static final int BAD_REQUEST = HttpServletResponse.SC_BAD_REQUEST;
|
||||
/**
|
||||
* Response code version conflict
|
||||
*/
|
||||
public static final int CONFLICT = HttpServletResponse.SC_CONFLICT;
|
||||
/**
|
||||
* Response code forbidden access
|
||||
*/
|
||||
public static final int FORBIDDEN = HttpServletResponse.SC_FORBIDDEN;
|
||||
/**
|
||||
* Response code internal server error
|
||||
*/
|
||||
public static final int SERVER_ERROR = HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
|
||||
/**
|
||||
* Response code not found
|
||||
*/
|
||||
public static final int NOT_FOUND = HttpServletResponse.SC_NOT_FOUND;
|
||||
/**
|
||||
* Response code not modified since
|
||||
*/
|
||||
public static final int NOT_MODIFIED = HttpServletResponse.SC_NOT_MODIFIED;
|
||||
/**
|
||||
* Response code created
|
||||
*/
|
||||
public static final int CREATED = HttpServletResponse.SC_CREATED;
|
||||
/**
|
||||
* Response code unauthorized access
|
||||
*/
|
||||
public static final int UNAUTHORIZED = HttpServletResponse.SC_UNAUTHORIZED;
|
||||
|
||||
|
||||
static final Log LOG = LogFactory.getLog(GDataResponse.class);
|
||||
private int error;
|
||||
|
||||
private boolean isError = false;
|
||||
|
||||
private String encoding;
|
||||
|
||||
private OutputFormat outputFormat;
|
||||
|
||||
private final HttpServletResponse response;
|
||||
|
||||
protected static final String XMLMIME_ATOM = "text/xml";
|
||||
|
||||
protected static final String XMLMIME_RSS = "text/xml";
|
||||
|
||||
private static final String HEADER_LASTMODIFIED = "Last-Modified";
|
||||
|
||||
/**
|
||||
* Creates a new GDataResponse
|
||||
*
|
||||
* @param response -
|
||||
* The underlying {@link HttpServletResponse}
|
||||
*/
|
||||
public GDataResponse(HttpServletResponse response) {
|
||||
if (response == null)
|
||||
throw new IllegalArgumentException("response must not be null");
|
||||
this.response = response;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets an error code to this FeedResponse.
|
||||
*
|
||||
* @param errorCode -
|
||||
* {@link HttpServletResponse} error code
|
||||
*/
|
||||
public void setError(int errorCode) {
|
||||
this.isError = true;
|
||||
this.error = errorCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the status of the underlying response
|
||||
*
|
||||
* @see HttpServletResponse
|
||||
* @param responseCode -
|
||||
* the status of the response
|
||||
*/
|
||||
public void setResponseCode(int responseCode) {
|
||||
this.response.setStatus(responseCode);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method sends the specified error to the user if set
|
||||
*
|
||||
* @throws IOException -
|
||||
* if an I/O Exception occurs
|
||||
*/
|
||||
public void sendError() throws IOException {
|
||||
if (this.isError)
|
||||
this.response.sendError(this.error);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @return - the {@link HttpServletResponse} writer
|
||||
* @throws IOException -
|
||||
* If an I/O exception occurs
|
||||
*/
|
||||
public Writer getWriter() throws IOException {
|
||||
return this.response.getWriter();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a response for a get e.g. query request. This method must not
|
||||
* invoked in a case of an error performing the requested action.
|
||||
*
|
||||
* @param feed -
|
||||
* the feed to respond to the client
|
||||
* @param service - the service to render the feed
|
||||
*
|
||||
* @throws IOException -
|
||||
* if an I/O exception occurs, often caused by an already
|
||||
* closed Writer or OutputStream
|
||||
*
|
||||
*/
|
||||
public void sendResponse(final BaseFeed feed, final ProvidedService service)
|
||||
throws IOException {
|
||||
if (feed == null)
|
||||
throw new IllegalArgumentException("feed must not be null");
|
||||
if (service == null)
|
||||
throw new IllegalArgumentException(
|
||||
"provided service must not be null");
|
||||
DateTime time = feed.getUpdated();
|
||||
if (time != null)
|
||||
setLastModifiedHeader(time.getValue());
|
||||
FormatWriter writer = FormatWriter.getFormatWriter(this,service);
|
||||
writer.generateOutputFormat(feed,this.response);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Sends a response for an update, insert or delete request. This method
|
||||
* must not invoked in a case of an error performing the requested action. If
|
||||
* the specified response format is ATOM the default namespace will be set
|
||||
* to ATOM.
|
||||
*
|
||||
* @param entry -
|
||||
* the modified / created entry to send
|
||||
* @param service - the service to render the feed
|
||||
* @throws IOException -
|
||||
* if an I/O exception occurs, often caused by an already
|
||||
* closed Writer or OutputStream
|
||||
*/
|
||||
public void sendResponse(BaseEntry entry, ProvidedService service)
|
||||
throws IOException {
|
||||
if (entry == null)
|
||||
throw new IllegalArgumentException("entry must not be null");
|
||||
if (service == null)
|
||||
throw new IllegalArgumentException(
|
||||
"service must not be null");
|
||||
DateTime time = entry.getUpdated();
|
||||
if (time != null)
|
||||
setLastModifiedHeader(time.getValue());
|
||||
FormatWriter writer = FormatWriter.getFormatWriter(this,service);
|
||||
writer.generateOutputFormat(entry,this.response);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This encoding will be used to encode the xml representation of feed or
|
||||
* entry written to the {@link HttpServletResponse} output stream.
|
||||
*
|
||||
* @return - the entry / feed encoding
|
||||
*/
|
||||
public String getEncoding() {
|
||||
return this.encoding;
|
||||
}
|
||||
|
||||
/**
|
||||
* This encoding will be used to encode the xml representation of feed or
|
||||
* entry written to the {@link HttpServletResponse} output stream. <i>UTF-8</i>
|
||||
* <i>ISO-8859-1</i>
|
||||
*
|
||||
* @param encoding -
|
||||
* string represents the encoding
|
||||
*/
|
||||
public void setEncoding(String encoding) {
|
||||
this.encoding = encoding;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return - the response
|
||||
* {@link org.apache.lucene.gdata.server.GDataRequest.OutputFormat}
|
||||
*/
|
||||
public OutputFormat getOutputFormat() {
|
||||
return this.outputFormat;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param outputFormat -
|
||||
* the response
|
||||
* {@link org.apache.lucene.gdata.server.GDataRequest.OutputFormat}
|
||||
*/
|
||||
public void setOutputFormat(OutputFormat outputFormat) {
|
||||
this.outputFormat = outputFormat;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see Object#toString()
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder builder = new StringBuilder(" GDataResponse: ");
|
||||
builder.append("Error: ").append(this.error);
|
||||
builder.append(" outputFormat: ").append(getOutputFormat());
|
||||
builder.append(" encoding: ").append(this.encoding);
|
||||
|
||||
return builder.toString();
|
||||
|
||||
}
|
||||
|
||||
protected void setLastModifiedHeader(long lastModified) {
|
||||
String lastMod = DateFormater.formatDate(new Date(lastModified),
|
||||
DateFormater.HTTP_HEADER_DATE_FORMAT);
|
||||
this.response.setHeader(HEADER_LASTMODIFIED, lastMod);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see HttpServletResponse#setStatus(int)
|
||||
* @param status - the request status code
|
||||
*/
|
||||
public void setStatus(int status){
|
||||
this.response.setStatus(status);
|
||||
}
|
||||
|
||||
private static abstract class FormatWriter{
|
||||
|
||||
static FormatWriter getFormatWriter(final GDataResponse response, final ProvidedService service ){
|
||||
OutputFormat format = response.getOutputFormat();
|
||||
if(format == OutputFormat.HTML){
|
||||
return new HTMLFormatWriter(service);
|
||||
}
|
||||
return new SyndicateFormatWriter(service,format,response.getEncoding());
|
||||
}
|
||||
|
||||
abstract void generateOutputFormat(final BaseFeed feed, final HttpServletResponse response) throws IOException;
|
||||
abstract void generateOutputFormat(final BaseEntry entry, final HttpServletResponse response) throws IOException;
|
||||
|
||||
private static class HTMLFormatWriter extends FormatWriter{
|
||||
private static final String CONTENT_TYPE = "text/html";
|
||||
private final ProvidedService service;
|
||||
|
||||
HTMLFormatWriter(final ProvidedService service){
|
||||
this.service = service;
|
||||
}
|
||||
@Override
|
||||
void generateOutputFormat(BaseFeed feed, final HttpServletResponse response) throws IOException {
|
||||
Templates template = this.service.getTransformTemplate();
|
||||
response.setContentType(CONTENT_TYPE);
|
||||
if(template == null){
|
||||
sendNotAvailable(response);
|
||||
return;
|
||||
}
|
||||
StringWriter writer = new StringWriter();
|
||||
XmlWriter xmlWriter = new XmlWriter(writer);
|
||||
feed.generateAtom(xmlWriter,this.service.getExtensionProfile());
|
||||
try {
|
||||
writeHtml(template,response.getWriter(),writer);
|
||||
} catch (TransformerException e) {
|
||||
LOG.error("Can not transform feed for service "+this.service.getName(),e);
|
||||
sendNotAvailable(response);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
void generateOutputFormat(BaseEntry entry, final HttpServletResponse response) throws IOException{
|
||||
Templates template = this.service.getTransformTemplate();
|
||||
response.setContentType(CONTENT_TYPE);
|
||||
if(template == null){
|
||||
sendNotAvailable(response);
|
||||
return;
|
||||
}
|
||||
StringWriter writer = new StringWriter();
|
||||
XmlWriter xmlWriter = new XmlWriter(writer);
|
||||
entry.generateAtom(xmlWriter,this.service.getExtensionProfile());
|
||||
try {
|
||||
writeHtml(template,response.getWriter(),writer);
|
||||
} catch (TransformerException e) {
|
||||
LOG.error("Can not transform feed for service "+this.service.getName(),e);
|
||||
sendNotAvailable(response);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void writeHtml(final Templates template, final Writer writer, final StringWriter source ) throws TransformerException{
|
||||
Transformer transformer = template.newTransformer();
|
||||
Source tranformSource = new StreamSource(new StringReader(source.toString()));
|
||||
transformer.transform(tranformSource,new StreamResult(writer));
|
||||
}
|
||||
|
||||
private void sendNotAvailable(final HttpServletResponse response) throws IOException{
|
||||
response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE, "No transformation stylesheet available");
|
||||
}
|
||||
|
||||
}
|
||||
private static class SyndicateFormatWriter extends FormatWriter{
|
||||
private static final String DEFAUL_NAMESPACE_URI = "http://www.w3.org/2005/Atom";
|
||||
|
||||
private static final Namespace DEFAULT_NAMESPACE = new Namespace("",
|
||||
DEFAUL_NAMESPACE_URI);
|
||||
private final ProvidedService service;
|
||||
private final String encoding;
|
||||
private final OutputFormat format;
|
||||
|
||||
SyndicateFormatWriter(final ProvidedService service,final OutputFormat format, String encoding){
|
||||
this.service = service;
|
||||
this.format = format;
|
||||
this.encoding = encoding;
|
||||
|
||||
}
|
||||
@Override
|
||||
void generateOutputFormat(final BaseFeed feed, final HttpServletResponse response) throws IOException {
|
||||
XmlWriter writer = null;
|
||||
try{
|
||||
writer = createWriter(response.getWriter());
|
||||
if (this.format == OutputFormat.ATOM) {
|
||||
response.setContentType(XMLMIME_ATOM);
|
||||
feed.generateAtom(writer, this.service.getExtensionProfile());
|
||||
} else {
|
||||
response.setContentType(XMLMIME_RSS);
|
||||
feed.generateRss(writer, this.service.getExtensionProfile());
|
||||
}
|
||||
}finally{
|
||||
if(writer != null)
|
||||
writer.close();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
void generateOutputFormat(final BaseEntry entry, final HttpServletResponse response) throws IOException {
|
||||
XmlWriter writer = null;
|
||||
try{
|
||||
writer = createWriter(response.getWriter());
|
||||
if (this.format == OutputFormat.ATOM) {
|
||||
response.setContentType(XMLMIME_ATOM);
|
||||
entry.generateAtom(writer, this.service.getExtensionProfile());
|
||||
} else {
|
||||
response.setContentType(XMLMIME_RSS);
|
||||
entry.generateRss(writer, this.service.getExtensionProfile());
|
||||
}
|
||||
}finally{
|
||||
if(writer != null)
|
||||
writer.close();
|
||||
}
|
||||
}
|
||||
private XmlWriter createWriter(final Writer target) throws IOException {
|
||||
XmlWriter writer = new XmlWriter(target, this.encoding);
|
||||
// set the default namespace to Atom if Atom is the response format
|
||||
if (this.format == OutputFormat.ATOM)
|
||||
writer.setDefaultNamespace(DEFAULT_NAMESPACE);
|
||||
return writer;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
|
@ -1,114 +0,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.
|
||||
*/
|
||||
|
||||
package org.apache.lucene.gdata.server;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.apache.lucene.gdata.data.ServerBaseEntry;
|
||||
import org.apache.lucene.gdata.data.ServerBaseFeed;
|
||||
import org.apache.lucene.gdata.search.GDataSearcher;
|
||||
import org.apache.lucene.gdata.search.SearchComponent;
|
||||
import org.apache.lucene.gdata.search.query.GDataQueryParser;
|
||||
import org.apache.lucene.gdata.server.registry.ComponentType;
|
||||
import org.apache.lucene.gdata.server.registry.GDataServerRegistry;
|
||||
import org.apache.lucene.gdata.server.registry.ProvidedService;
|
||||
import org.apache.lucene.gdata.storage.StorageException;
|
||||
import org.apache.lucene.queryParser.ParseException;
|
||||
import org.apache.lucene.queryParser.QueryParser;
|
||||
import org.apache.lucene.search.Query;
|
||||
|
||||
import com.google.gdata.data.BaseEntry;
|
||||
import com.google.gdata.data.BaseFeed;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class GDataSearchService extends GDataService {
|
||||
private static final Log LOG = LogFactory.getLog(GDataSearchService.class);
|
||||
private static SearchComponent SEARCHCOMPONENT;
|
||||
private GDataSearcher<String> searcher;
|
||||
protected GDataSearchService() throws ServiceException {
|
||||
if(SEARCHCOMPONENT == null)
|
||||
SEARCHCOMPONENT = GDataServerRegistry.getRegistry().lookup(SearchComponent.class,ComponentType.SEARCHCONTROLLER);
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.lucene.gdata.server.GDataService#getFeed(org.apache.lucene.gdata.server.GDataRequest, org.apache.lucene.gdata.server.GDataResponse)
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public BaseFeed getFeed(GDataRequest request, GDataResponse response) throws ServiceException {
|
||||
String translatedQuery = request.getTranslatedQuery();
|
||||
ProvidedService service = request.getConfigurator();
|
||||
|
||||
QueryParser parser = new GDataQueryParser(service.getIndexSchema());
|
||||
Query query;
|
||||
try {
|
||||
query = parser.parse(translatedQuery);
|
||||
|
||||
} catch (ParseException e1) {
|
||||
throw new ServiceException("Search Failed -- Can not parse query",e1,GDataResponse.BAD_REQUEST);
|
||||
}
|
||||
if(LOG.isInfoEnabled())
|
||||
LOG.info("Fire search for user query query: "+query.toString());
|
||||
this.searcher = SEARCHCOMPONENT.getServiceSearcher(service);
|
||||
List<String> result;
|
||||
try {
|
||||
result = this.searcher.search(query,request.getItemsPerPage(),request.getStartIndex(),request.getFeedId());
|
||||
} catch (IOException e) {
|
||||
throw new ServiceException("Search Failed -- Searcher throws IOException",e,GDataResponse.SERVER_ERROR);
|
||||
|
||||
}
|
||||
if(LOG.isInfoEnabled())
|
||||
LOG.info("Fetching results for user query result size: "+result.size());
|
||||
ServerBaseFeed requestFeed = new ServerBaseFeed();
|
||||
requestFeed.setServiceConfig(service);
|
||||
requestFeed.setStartIndex(0);
|
||||
requestFeed.setItemsPerPage(0);
|
||||
requestFeed.setId(request.getFeedId());
|
||||
BaseFeed feed = null;
|
||||
try{
|
||||
feed = this.storage.getFeed(requestFeed);
|
||||
}catch (StorageException e) {
|
||||
throw new ServiceException("Search Failed -- can not get feed, feed not stored ",e,GDataResponse.NOT_FOUND);
|
||||
}
|
||||
for (String entryId : result) {
|
||||
ServerBaseEntry requestEntry = new ServerBaseEntry();
|
||||
requestEntry.setId(entryId);
|
||||
requestEntry.setServiceConfig(service);
|
||||
try{
|
||||
BaseEntry entry = this.storage.getEntry(requestEntry);
|
||||
feed.getEntries().add(entry);
|
||||
}catch (StorageException e) {
|
||||
|
||||
LOG.error("StorageException caught while fetching query results -- skip entry -- "+e.getMessage(),e);
|
||||
}
|
||||
}
|
||||
dynamicElementFeedStragey(feed,request);
|
||||
return feed;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
|
@ -1,450 +0,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.
|
||||
*/
|
||||
package org.apache.lucene.gdata.server;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.apache.lucene.gdata.data.ServerBaseEntry;
|
||||
import org.apache.lucene.gdata.data.ServerBaseFeed;
|
||||
import org.apache.lucene.gdata.server.registry.ComponentType;
|
||||
import org.apache.lucene.gdata.server.registry.EntryEventMediator;
|
||||
import org.apache.lucene.gdata.server.registry.GDataServerRegistry;
|
||||
import org.apache.lucene.gdata.storage.ModificationConflictException;
|
||||
import org.apache.lucene.gdata.storage.ResourceNotFoundException;
|
||||
import org.apache.lucene.gdata.storage.Storage;
|
||||
import org.apache.lucene.gdata.storage.StorageController;
|
||||
import org.apache.lucene.gdata.storage.StorageException;
|
||||
|
||||
import com.google.gdata.data.BaseEntry;
|
||||
import com.google.gdata.data.BaseFeed;
|
||||
import com.google.gdata.data.DateTime;
|
||||
import com.google.gdata.data.Generator;
|
||||
import com.google.gdata.data.Link;
|
||||
import com.google.gdata.util.ParseException;
|
||||
|
||||
/**
|
||||
* default implementation of the {@link org.apache.lucene.gdata.server.Service}
|
||||
* interface.
|
||||
*
|
||||
* @author Simon Willnauer
|
||||
*
|
||||
*/
|
||||
public class GDataService implements Service {
|
||||
private static final Log LOG = LogFactory.getLog(GDataService.class);
|
||||
|
||||
protected Storage storage;
|
||||
|
||||
protected GDataServerRegistry registry = GDataServerRegistry.getRegistry();
|
||||
|
||||
private static final Generator generator;
|
||||
|
||||
private static final String generatorName = "Lucene GData-Server";
|
||||
|
||||
private static final String generatorURI = "http://lucene.apache.org";
|
||||
|
||||
private static final String XMLMIME = "application/atom+xml";
|
||||
|
||||
protected final EntryEventMediator entryEventMediator;
|
||||
static {
|
||||
generator = new Generator();
|
||||
generator.setName(generatorName);
|
||||
generator.setUri(generatorURI);
|
||||
generator.setVersion("0.1");
|
||||
}
|
||||
|
||||
protected GDataService() throws ServiceException {
|
||||
try {
|
||||
StorageController controller = GDataServerRegistry.getRegistry()
|
||||
.lookup(StorageController.class,
|
||||
ComponentType.STORAGECONTROLLER);
|
||||
if (controller == null)
|
||||
throw new StorageException(
|
||||
"StorageController is not registered");
|
||||
this.storage = controller.getStorage();
|
||||
this.entryEventMediator = GDataServerRegistry.getRegistry().getEntryEventMediator();
|
||||
} catch (StorageException e) {
|
||||
LOG
|
||||
.fatal(
|
||||
"Can't get Storage Instance -- can't serve any requests",
|
||||
e);
|
||||
ServiceException ex = new ServiceException(
|
||||
"Can't get Storage instance" + e.getMessage(), e,GDataResponse.SERVER_ERROR);
|
||||
ex.setStackTrace(e.getStackTrace());
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.lucene.gdata.server.Service#createEntry(org.apache.lucene.gdata.server.GDataRequest,
|
||||
* org.apache.lucene.gdata.server.GDataResponse)
|
||||
*/
|
||||
|
||||
public BaseEntry createEntry(GDataRequest request, GDataResponse response)
|
||||
throws ServiceException {
|
||||
|
||||
if (LOG.isInfoEnabled())
|
||||
LOG.info("create Entry for feedId: " + request.getFeedId());
|
||||
|
||||
ServerBaseEntry entry = buildEntry(request, response);
|
||||
entry.setFeedId(request.getFeedId());
|
||||
entry.setServiceConfig(request.getConfigurator());
|
||||
BaseEntry tempEntry = entry.getEntry();
|
||||
tempEntry.setPublished(getCurrentDateTime());
|
||||
tempEntry.setUpdated(getCurrentDateTime());
|
||||
BaseEntry retVal = null;
|
||||
removeDynamicElements(entry.getEntry());
|
||||
try {
|
||||
retVal = this.storage.storeEntry(entry);
|
||||
} catch (Exception e) {
|
||||
|
||||
ServiceException ex = new ServiceException("Could not store entry",
|
||||
e,GDataResponse.SERVER_ERROR);
|
||||
ex.setStackTrace(e.getStackTrace());
|
||||
throw ex;
|
||||
}
|
||||
this.entryEventMediator.entryAdded(entry);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.lucene.gdata.server.Service#deleteEntry(org.apache.lucene.gdata.server.GDataRequest,
|
||||
* org.apache.lucene.gdata.server.GDataResponse)
|
||||
*/
|
||||
|
||||
public BaseEntry deleteEntry(GDataRequest request, GDataResponse response)
|
||||
throws ServiceException {
|
||||
|
||||
ServerBaseEntry entry = new ServerBaseEntry();
|
||||
entry.setServiceConfig(request.getConfigurator());
|
||||
entry.setFeedId(request.getFeedId());
|
||||
entry.setId(request.getEntryId());
|
||||
setVersionId(entry,request,response);
|
||||
if (entry.getId() == null)
|
||||
throw new ServiceException(
|
||||
"entry id is null -- can not delete null entry",GDataResponse.SERVER_ERROR);
|
||||
try {
|
||||
this.storage.deleteEntry(entry);
|
||||
|
||||
} catch (ResourceNotFoundException e) {
|
||||
|
||||
ServiceException ex = new ServiceException(
|
||||
"Could not delete entry", e,GDataResponse.BAD_REQUEST);
|
||||
ex.setStackTrace(e.getStackTrace());
|
||||
throw ex;
|
||||
}catch (ModificationConflictException e) {
|
||||
|
||||
ServiceException ex = new ServiceException(
|
||||
"Could not delete entry - version conflict",e, GDataResponse.CONFLICT);
|
||||
ex.setStackTrace(e.getStackTrace());
|
||||
throw ex;
|
||||
}catch (StorageException e) {
|
||||
|
||||
ServiceException ex = new ServiceException(
|
||||
"Could not delete entry", e,GDataResponse.SERVER_ERROR);
|
||||
ex.setStackTrace(e.getStackTrace());
|
||||
throw ex;
|
||||
}
|
||||
this.entryEventMediator.entryDeleted(entry);
|
||||
//TODO change ret value
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.lucene.gdata.server.Service#updateEntry(org.apache.lucene.gdata.server.GDataRequest,
|
||||
* org.apache.lucene.gdata.server.GDataResponse)
|
||||
*/
|
||||
|
||||
public BaseEntry updateEntry(GDataRequest request, GDataResponse response)
|
||||
throws ServiceException {
|
||||
|
||||
ServerBaseEntry entry = buildEntry(request, response);
|
||||
entry.setFeedId(request.getFeedId());
|
||||
setVersionId(entry,request,response);
|
||||
entry.setServiceConfig(request.getConfigurator());
|
||||
if (LOG.isInfoEnabled())
|
||||
LOG.info("update Entry" + entry.getId() + " for feedId: "
|
||||
+ request.getFeedId());
|
||||
if (entry.getId() == null) {
|
||||
throw new ServiceException("Entry id is null can not update entry",GDataResponse.BAD_REQUEST);
|
||||
}
|
||||
if (!entry.getId().equals(request.getEntryId())) {
|
||||
if (LOG.isInfoEnabled())
|
||||
LOG
|
||||
.info("Entry id in the entry xml does not match the requested resource -- XML-ID:"
|
||||
+ entry.getId()
|
||||
+ "; Requested resource: "
|
||||
+ request.getEntryId());
|
||||
|
||||
throw new ServiceException(
|
||||
"Entry id in the entry xml does not match the requested resource",GDataResponse.BAD_REQUEST);
|
||||
}
|
||||
BaseEntry tempEntry = entry.getEntry();
|
||||
tempEntry.setUpdated(getCurrentDateTime());
|
||||
removeDynamicElements(entry.getEntry());
|
||||
|
||||
BaseEntry retVal = null;
|
||||
|
||||
try {
|
||||
retVal = this.storage.updateEntry(entry);
|
||||
} catch (ResourceNotFoundException e) {
|
||||
|
||||
ServiceException ex = new ServiceException(
|
||||
"Could not update entry", e,GDataResponse.BAD_REQUEST);
|
||||
ex.setStackTrace(e.getStackTrace());
|
||||
throw ex;
|
||||
}catch (ModificationConflictException e) {
|
||||
ServiceException ex = new ServiceException(
|
||||
"Could not update entry - version conflict", e,GDataResponse.CONFLICT);
|
||||
ex.setStackTrace(e.getStackTrace());
|
||||
throw ex;
|
||||
}catch (StorageException e) {
|
||||
|
||||
ServiceException ex = new ServiceException(
|
||||
"Could not update entry", e,GDataResponse.SERVER_ERROR);
|
||||
ex.setStackTrace(e.getStackTrace());
|
||||
throw ex;
|
||||
}
|
||||
this.entryEventMediator.entryUpdated(entry);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.lucene.gdata.server.Service#getFeed(org.apache.lucene.gdata.server.GDataRequest,
|
||||
* org.apache.lucene.gdata.server.GDataResponse)
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public BaseFeed getFeed(GDataRequest request, GDataResponse response)
|
||||
throws ServiceException {
|
||||
|
||||
ServerBaseFeed feed = new ServerBaseFeed();
|
||||
feed.setId(request.getFeedId());
|
||||
feed.setStartIndex(request.getStartIndex());
|
||||
feed.setItemsPerPage(request.getItemsPerPage());
|
||||
feed.setServiceConfig(request.getConfigurator());
|
||||
try {
|
||||
/*
|
||||
* the strategy executes either a search or a direct access.
|
||||
*/
|
||||
BaseFeed retVal = this.storage.getFeed(feed);
|
||||
dynamicElementFeedStragey(retVal, request);
|
||||
|
||||
return retVal;
|
||||
/*
|
||||
* Resource not found will be detected in Gdata request.
|
||||
* the request queries the storage for the feed to get the service for the feed
|
||||
*/
|
||||
} catch (StorageException e) {
|
||||
ServiceException ex = new ServiceException("Could not get feed", e,GDataResponse.NOT_FOUND);
|
||||
ex.setStackTrace(e.getStackTrace());
|
||||
throw ex;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private Link buildLink(String rel, String type, String href) {
|
||||
Link retVal = new Link();
|
||||
retVal.setHref(href);
|
||||
retVal.setRel(rel);
|
||||
retVal.setType(type);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
private ServerBaseEntry buildEntry(final GDataRequest request,
|
||||
final GDataResponse response) throws ServiceException {
|
||||
try {
|
||||
ServerBaseEntry entry = new ServerBaseEntry(GDataEntityBuilder
|
||||
.buildEntry(request));
|
||||
return entry;
|
||||
|
||||
} catch (ParseException e) {
|
||||
ServiceException ex = new ServiceException(
|
||||
"Could not parse entry from incoming request", e, GDataResponse.BAD_REQUEST);
|
||||
ex.setStackTrace(e.getStackTrace());
|
||||
throw ex;
|
||||
} catch (IOException e) {
|
||||
ServiceException ex = new ServiceException(
|
||||
"Could not read or open input stream", e, GDataResponse.BAD_REQUEST);
|
||||
ex.setStackTrace(e.getStackTrace());
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @see org.apache.lucene.gdata.server.Service#getSingleEntry(org.apache.lucene.gdata.server.GDataRequest,
|
||||
* org.apache.lucene.gdata.server.GDataResponse)
|
||||
*/
|
||||
|
||||
public BaseEntry getSingleEntry(GDataRequest request, GDataResponse response)
|
||||
throws ServiceException {
|
||||
|
||||
try {
|
||||
ServerBaseEntry entry = new ServerBaseEntry();
|
||||
entry.setServiceConfig(request.getConfigurator());
|
||||
entry.setFeedId(request.getFeedId());
|
||||
entry.setId(request.getEntryId());
|
||||
|
||||
|
||||
if(entry.getId() == null){
|
||||
throw new ServiceException("entry is null can't get entry", GDataResponse.BAD_REQUEST);
|
||||
}
|
||||
|
||||
BaseEntry retVal = null;
|
||||
retVal = this.storage.getEntry(entry);
|
||||
dynamicElementEntryStragey(retVal, request);
|
||||
return retVal;
|
||||
} catch (ResourceNotFoundException e) {
|
||||
ServiceException ex = new ServiceException(
|
||||
"Could not get entry", e, GDataResponse.BAD_REQUEST);
|
||||
ex.setStackTrace(e.getStackTrace());
|
||||
throw ex;
|
||||
} catch (StorageException e) {
|
||||
ServiceException ex = new ServiceException("Could not get entry", e, GDataResponse.SERVER_ERROR);
|
||||
ex.setStackTrace(e.getStackTrace());
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* adds all dynamic element to the entry
|
||||
*/
|
||||
private void dynamicElementEntryStragey(final BaseEntry entry,
|
||||
final GDataRequest request) {
|
||||
setSelfLink(entry, request.getContextPath());
|
||||
}
|
||||
|
||||
/*
|
||||
* adds all dynamic element to the feed entries
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
protected void dynamicElementFeedStragey(final BaseFeed feed,
|
||||
final GDataRequest request) {
|
||||
buildDynamicFeedElements(request, feed);
|
||||
List<BaseEntry> entryList = feed.getEntries();
|
||||
for (BaseEntry entry : entryList) {
|
||||
String id = new StringBuilder(request.getContextPath()).append(entry.getId()).append("/").toString();
|
||||
setSelfLink(entry, id);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* The selfLink is build from a prefix and the entry id. The prefix is the
|
||||
* context path of the requested feed. This will be used to request the
|
||||
* entry directly
|
||||
*/@SuppressWarnings("unchecked")
|
||||
private BaseEntry setSelfLink(final BaseEntry entry, String id) {
|
||||
Link self = buildLink(Link.Rel.SELF, XMLMIME, id);
|
||||
StringBuilder builder = new StringBuilder(id);
|
||||
builder.append(entry.getVersionId());
|
||||
Link edit = buildLink(Link.Rel.ENTRY_EDIT,XMLMIME,builder.toString());
|
||||
List<Link> list = entry.getLinks();
|
||||
list.add(edit);
|
||||
list.add(self);
|
||||
return entry;
|
||||
}
|
||||
|
||||
/*
|
||||
* build the dynamic elements like self link and next link
|
||||
*/
|
||||
private void buildDynamicFeedElements(final GDataRequest request,
|
||||
final BaseFeed feed) {
|
||||
feed.setGenerator(generator);
|
||||
feed.setItemsPerPage(request.getItemsPerPage());
|
||||
feed.setStartIndex(request.getStartIndex());
|
||||
feed.setId(request.getContextPath());
|
||||
List<Link> links = feed.getLinks();
|
||||
links.add(
|
||||
buildLink(Link.Rel.SELF, Link.Type.ATOM, request.getSelfId()));
|
||||
links.add(
|
||||
buildLink(Link.Rel.NEXT, XMLMIME, request.getNextId()));
|
||||
String prevLink = request.getPreviousId();
|
||||
if(prevLink != null)
|
||||
links.add(buildLink(Link.Rel.PREVIOUS,XMLMIME,prevLink));
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.lucene.gdata.server.Service#close()
|
||||
*/
|
||||
public void close() {
|
||||
this.storage.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.lucene.gdata.server.Service#getFeedLastModified(java.lang.String)
|
||||
*/
|
||||
public Date getFeedLastModified(final String feedId) throws ServiceException {
|
||||
try {
|
||||
return new Date(this.storage.getFeedLastModified(feedId));
|
||||
|
||||
} catch (StorageException e) {
|
||||
ServiceException ex = new ServiceException(
|
||||
"Could not get Last update for feed -- "+feedId, e, GDataResponse.SERVER_ERROR);
|
||||
ex.setStackTrace(e.getStackTrace());
|
||||
throw ex;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.lucene.gdata.server.Service#getEntryLastModified(java.lang.String, java.lang.String)
|
||||
*/
|
||||
public Date getEntryLastModified(final String entryId,final String feedId) throws ServiceException {
|
||||
try {
|
||||
return new Date(this.storage.getEntryLastModified(entryId, feedId));
|
||||
} catch (StorageException e) {
|
||||
ServiceException ex = new ServiceException(
|
||||
"Could not get Last update for entry -- "+entryId, e, GDataResponse.SERVER_ERROR);
|
||||
ex.setStackTrace(e.getStackTrace());
|
||||
throw ex;
|
||||
}
|
||||
|
||||
}
|
||||
private ServerBaseEntry setVersionId(final ServerBaseEntry entry, final GDataRequest request, final GDataResponse response)throws ServiceException{
|
||||
try{
|
||||
entry.setVersion(Integer.parseInt(request.getEntryVersion()));
|
||||
return entry;
|
||||
}catch (Exception e) {
|
||||
LOG.error("Can not parse entry version -- version is not an integer -- versionid: "+request.getEntryVersion(),e);
|
||||
throw new ServiceException("Can not parse entry version -- version is not an integer -- versionid: "+request.getEntryVersion(),e, GDataResponse.BAD_REQUEST);
|
||||
|
||||
}
|
||||
}
|
||||
/*
|
||||
* provide current time to set as published / updated values
|
||||
* always use servertime to prevent client / server time lag
|
||||
* Timezoneshift is 0
|
||||
*/
|
||||
protected DateTime getCurrentDateTime(){
|
||||
return new DateTime(System.currentTimeMillis(),0);
|
||||
}
|
||||
|
||||
private void removeDynamicElements(BaseEntry entry){
|
||||
Link selfLink = entry.getSelfLink();
|
||||
if(selfLink != null)
|
||||
entry.getLinks().remove(selfLink);
|
||||
Link editLink = entry.getEditLink();
|
||||
if(editLink != null)
|
||||
entry.getLinks().remove(editLink);
|
||||
}
|
||||
}
|
|
@ -1,162 +0,0 @@
|
|||
/**
|
||||
* Copyright 2004 The Apache Software Foundation
|
||||
*
|
||||
* Licensed 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.server;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import com.google.gdata.data.BaseEntry;
|
||||
import com.google.gdata.data.BaseFeed;
|
||||
|
||||
|
||||
/**
|
||||
* The Service class represents an interface to access the GData service
|
||||
* componentes of the GData-Server. It encapsulates all interactions with the
|
||||
* GData client.
|
||||
* <p>
|
||||
* This class provides the base level common functionality required to access
|
||||
* the GData components. It is also designed to act as a base class that can be
|
||||
* extended for specific types of underlaying server components as different
|
||||
* indexing or storage components.
|
||||
* </p>
|
||||
* <p>
|
||||
* It could also encapsulate caching mechanismn build on top of the storage to
|
||||
* reduce load on the storage component
|
||||
* </p>
|
||||
*
|
||||
* @author Simon Willnauer
|
||||
*
|
||||
*
|
||||
*/
|
||||
public interface Service {
|
||||
|
||||
/**
|
||||
* Service method to create an entry in an already created and existing
|
||||
* feed. This method will create the entry and passes the entry to the
|
||||
* indexing component to make the new entry accessable via <i>get-queries</i>.
|
||||
* The response and the corresponding http status code will be added to the
|
||||
* given <code>FeedResponse</code>.
|
||||
*
|
||||
* @param request -
|
||||
* the current FeedRequest
|
||||
* @param response -
|
||||
* the current FeedResponse
|
||||
* @return - the entry which has been created
|
||||
* @throws ServiceException -
|
||||
* if the corresponding feed does not exist or the storage can
|
||||
* not be accessed
|
||||
*/
|
||||
public abstract BaseEntry createEntry(final GDataRequest request,
|
||||
final GDataResponse response) throws ServiceException;
|
||||
|
||||
/**
|
||||
* Service Method to delete an entry specified in the given FeedRequest.
|
||||
* This method will remove the entry permanently. There will be no
|
||||
* possiblity to restore the entry. The response and the corresponding http
|
||||
* status code will be added to the given <code>FeedResponse</code>.
|
||||
*
|
||||
* @param request -
|
||||
* the current FeedRequest
|
||||
* @param response -
|
||||
* the current FeedResponse
|
||||
* @return - the entry wich has been deleted
|
||||
* @throws ServiceException -
|
||||
* if the entry does not exist or the storage can not be
|
||||
* accessed
|
||||
*/
|
||||
public abstract BaseEntry deleteEntry(GDataRequest request, final GDataResponse response)
|
||||
throws ServiceException;
|
||||
|
||||
/**
|
||||
* Service method to update an existing entry in a existing feed context.
|
||||
* The entry version will be checked and a <code>ServiceException</code>
|
||||
* will be thrown if the version to update is outdated. The new entry will
|
||||
* be passed to the indexing component to make the version accessable via
|
||||
* <i>get-queries</i>.
|
||||
*
|
||||
* @param request -
|
||||
* the current FeedRequest
|
||||
* @param response -
|
||||
* the current FeedResponse
|
||||
* @return - the entry wich has been updated
|
||||
* @throws ServiceException -
|
||||
* if the corresponding feed does not exist, the storage can not
|
||||
* be accessed or the version to update is out of date.
|
||||
*/
|
||||
public abstract BaseEntry updateEntry(final GDataRequest request,
|
||||
final GDataResponse response) throws ServiceException;
|
||||
|
||||
/**
|
||||
* Service method to retrieve a requested Feed. The feed will also be added to
|
||||
* the given <code>FeedResponse</code> instance and can also be accessed
|
||||
* via the <code>FeedResponse</code> object.
|
||||
*
|
||||
* @param request -
|
||||
* the current FeedRequest
|
||||
* @param response -
|
||||
* the current FeedResponse
|
||||
* @return - the requested feed
|
||||
*
|
||||
* @throws ServiceException -
|
||||
* If the storage can not be accessed or the requested feed does
|
||||
* not exist.
|
||||
*/
|
||||
public abstract BaseFeed getFeed(final GDataRequest request, final GDataResponse response)
|
||||
throws ServiceException;
|
||||
|
||||
/**
|
||||
* Service method to retrieve a requested entry. The entry will also be added to
|
||||
* the given <code>FeedResponse</code> instance and can also be accessed
|
||||
* via the <code>FeedResponse</code> object.
|
||||
*
|
||||
* @param request -
|
||||
* the current FeedRequest
|
||||
* @param response -
|
||||
* the current FeedResponse
|
||||
* @return - the requested entry
|
||||
*
|
||||
* @throws ServiceException -
|
||||
* If the storage can not be accessed or the requested entry does
|
||||
* not exist.
|
||||
*/
|
||||
public abstract BaseEntry getSingleEntry(final GDataRequest request, final GDataResponse response)
|
||||
throws ServiceException;
|
||||
|
||||
/**
|
||||
* will close the Service - service should not be used after this method has been called
|
||||
*/
|
||||
public void close();
|
||||
|
||||
/**
|
||||
* Retruns the date of the last modification for the given feed id
|
||||
* @param feedId - the id of the feed
|
||||
* @return - the last modified date or the current date if the date can not be retrieved
|
||||
* @throws ServiceException - if the storage can not be accessed
|
||||
*/
|
||||
public abstract Date getFeedLastModified(String feedId)throws ServiceException;
|
||||
|
||||
/**
|
||||
* Retruns the date of the last modification for the given entry id
|
||||
* @param entryId - the id of the entry
|
||||
* @param feedId - the feed id this entry belongs to
|
||||
* @return - the last modified date or the current date if the date can not be retrieved
|
||||
* @throws ServiceException - if the storage can not be accessed
|
||||
*/
|
||||
public abstract Date getEntryLastModified(String entryId, String feedId)throws ServiceException;
|
||||
|
||||
|
||||
|
||||
}
|
|
@ -1,85 +0,0 @@
|
|||
/**
|
||||
* Copyright 2004 The Apache Software Foundation
|
||||
*
|
||||
* Licensed 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.server;
|
||||
|
||||
|
||||
/**
|
||||
* The ServiceException is used to encapsulate all {@link java.lang.Exception}
|
||||
* throw by underlying layers of the
|
||||
* {@link org.apache.lucene.gdata.server.Service} layer.
|
||||
*
|
||||
* @author Simon Willnauer
|
||||
*
|
||||
*/
|
||||
public class ServiceException extends Exception {
|
||||
|
||||
private int errorCode;
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = -7099825107871876584L;
|
||||
|
||||
/**
|
||||
* Constructs a new ServiceException
|
||||
* @param errorCode - gdata request error code
|
||||
*/
|
||||
public ServiceException(int errorCode) {
|
||||
super();
|
||||
this.errorCode = errorCode;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new ServiceException
|
||||
* @param arg0 - the exception message
|
||||
* @param errorCode - gdata request error code
|
||||
*/
|
||||
public ServiceException(String arg0,int errorCode) {
|
||||
super(arg0);
|
||||
this.errorCode = errorCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new ServiceException
|
||||
* @param arg0 - the exception message
|
||||
* @param arg1 - the exception cause
|
||||
* @param errorCode - gdata request error code
|
||||
*/
|
||||
public ServiceException(String arg0, Throwable arg1,int errorCode) {
|
||||
super(arg0, arg1);
|
||||
this.errorCode = errorCode;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new ServiceException
|
||||
* @param arg0 - the exception cause
|
||||
* @param errorCode - gdata request error code
|
||||
*/
|
||||
public ServiceException(Throwable arg0,int errorCode) {
|
||||
super(arg0);
|
||||
this.errorCode = errorCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the errorCode.
|
||||
*/
|
||||
public int getErrorCode() {
|
||||
return this.errorCode;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,96 +0,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.
|
||||
*/
|
||||
package org.apache.lucene.gdata.server;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.apache.lucene.gdata.server.administration.AdminService;
|
||||
import org.apache.lucene.gdata.server.administration.GDataAdminService;
|
||||
import org.apache.lucene.gdata.server.registry.Component;
|
||||
import org.apache.lucene.gdata.server.registry.ComponentType;
|
||||
import org.apache.lucene.gdata.server.registry.ServerComponent;
|
||||
|
||||
|
||||
/**
|
||||
* The {@link ServiceFactory} creates {@link Service} implementations to access
|
||||
* the GData - Server components.
|
||||
* This class should not be access directy. The class will be registered in the {@link org.apache.lucene.gdata.server.registry.GDataServerRegistry}.
|
||||
* Use {@link org.apache.lucene.gdata.server.registry.GDataServerRegistry#lookup(Class, ComponentType)}
|
||||
*
|
||||
* @author Simon Willnauer
|
||||
*
|
||||
*/
|
||||
@Component(componentType=ComponentType.SERVICEFACTORY)
|
||||
public class ServiceFactory implements ServerComponent {
|
||||
|
||||
private static final Log LOG = LogFactory.getLog(ServiceFactory.class);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* public constructor to enable loading via the registry
|
||||
* @see org.apache.lucene.gdata.server.registry.Component
|
||||
* @see org.apache.lucene.gdata.server.registry.GDataServerRegistry
|
||||
*/
|
||||
public ServiceFactory() {
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link Service} instance.
|
||||
* @param request - the request for this service
|
||||
*
|
||||
* @return a Service instance
|
||||
*/
|
||||
public Service getService(GDataRequest request) {
|
||||
try{
|
||||
if(request.isSearchRequested())
|
||||
return new GDataSearchService();
|
||||
return new GDataService();
|
||||
}catch (Exception e) {
|
||||
//
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link AdminService} instance
|
||||
* @return a AdminService instance
|
||||
*/
|
||||
public AdminService getAdminService(){
|
||||
try {
|
||||
return new GDataAdminService();
|
||||
} catch (ServiceException e) {
|
||||
LOG.warn("Factory method can not create GDataAdminService returning null-- "+e.getMessage(),e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.lucene.gdata.server.registry.ServerComponent#initialize()
|
||||
*/
|
||||
public void initialize() {
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.lucene.gdata.server.registry.ServerComponent#destroy()
|
||||
*/
|
||||
public void destroy() {
|
||||
//
|
||||
}
|
||||
}
|
|
@ -1,84 +0,0 @@
|
|||
/**
|
||||
* Copyright 2004 The Apache Software Foundation
|
||||
*
|
||||
* Licensed 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.server.administration;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Reader;
|
||||
import java.net.URL;
|
||||
|
||||
|
||||
|
||||
import org.apache.commons.digester.Digester;
|
||||
import org.apache.lucene.gdata.data.GDataAccount;
|
||||
import org.apache.lucene.gdata.utils.SimpleSaxErrorHandler;
|
||||
import org.apache.xerces.parsers.SAXParser;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
/**
|
||||
* Helper class to create {@link org.apache.lucene.gdata.data.GDataAccount}
|
||||
* instances from a xml stream provided via a {@link Reader} instance.
|
||||
*
|
||||
* @author Simon Willnauer
|
||||
*
|
||||
*/
|
||||
public class AccountBuilder {
|
||||
|
||||
/**
|
||||
* Reads the xml from the provided reader and binds the values to the
|
||||
* @param reader - the reader to read the xml from
|
||||
* @return - the GDataAccount
|
||||
* @throws IOException - if an IOException occurs
|
||||
* @throws SAXException - if the xml can not be parsed by the sax reader
|
||||
*/
|
||||
public static GDataAccount buildAccount(final Reader reader) throws IOException,
|
||||
SAXException {
|
||||
if (reader == null)
|
||||
throw new IllegalArgumentException("Reader must not be null");
|
||||
URL resource = AccountBuilder.class.getResource("/gdata-account.xsd");
|
||||
if(resource == null)
|
||||
throw new RuntimeException("can not find xml schema file 'gdata-account.xsd' -- file must be present on the classpath");
|
||||
String schemaFile = resource.getFile();
|
||||
GDataAccount account = null;
|
||||
/*
|
||||
* Force using apache xerces parser for digester
|
||||
*/
|
||||
SAXParser parser = new SAXParser();
|
||||
parser.setFeature("http://apache.org/xml/features/validation/schema-full-checking",true);
|
||||
parser.setFeature("http://apache.org/xml/features/validation/schema",true);
|
||||
parser.setFeature("http://xml.org/sax/features/validation",true);
|
||||
parser.setProperty("http://apache.org/xml/properties/schema/external-noNamespaceSchemaLocation",schemaFile);
|
||||
Digester digester = new Digester(parser);
|
||||
digester.setValidating(true);
|
||||
digester.setErrorHandler(new SimpleSaxErrorHandler());
|
||||
digester.setSchema(schemaFile);
|
||||
digester.addObjectCreate("account", GDataAccount.class);
|
||||
digester.addBeanPropertySetter("account/account-name", "name");
|
||||
digester.addBeanPropertySetter("account/password", "password");
|
||||
digester.addBeanPropertySetter("account/account-role", "rolesAsInt");
|
||||
digester.addBeanPropertySetter("account/account-owner/name",
|
||||
"authorname");
|
||||
digester.addBeanPropertySetter("account/account-owner/email-address",
|
||||
"authorMail");
|
||||
digester.addBeanPropertySetter("account/account-owner/url",
|
||||
"authorLink");
|
||||
|
||||
account = (GDataAccount) digester.parse(reader);
|
||||
return account;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
|
@ -1,123 +0,0 @@
|
|||
/**
|
||||
* Copyright 2004 The Apache Software Foundation
|
||||
*
|
||||
* Licensed 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.server.administration;
|
||||
|
||||
import org.apache.lucene.gdata.data.GDataAccount;
|
||||
import org.apache.lucene.gdata.data.ServerBaseFeed;
|
||||
import org.apache.lucene.gdata.server.Service;
|
||||
import org.apache.lucene.gdata.server.ServiceException;
|
||||
|
||||
/**
|
||||
* The AdminService interface extends the Service interface to serve common
|
||||
* administrator requests. Common users can not create feed or user instances.
|
||||
* This interface provides all actions for create, delete or update Users and
|
||||
* Feeds. Each Feed has an associated Feed - Name which acts as an ID. Feed will
|
||||
* be identified by the feed name e.g. {@link com.google.gdata.data.Source#getId()}
|
||||
* <p>User accounts are supposed to have a unique username attribute as the username acts as a primary key for the storage</p>
|
||||
*
|
||||
*
|
||||
* @author Simon Willnauer
|
||||
*
|
||||
*/
|
||||
public interface AdminService extends Service {
|
||||
|
||||
/**
|
||||
* Creates a new feed instance.
|
||||
*
|
||||
* @param feed -
|
||||
* the feed to create
|
||||
* @param account - the account who own this feed
|
||||
* @throws ServiceException -
|
||||
* if the feed can not be created
|
||||
*/
|
||||
public abstract void createFeed(final ServerBaseFeed feed,
|
||||
final GDataAccount account) throws ServiceException;
|
||||
|
||||
/**
|
||||
* Updates the given feed
|
||||
*
|
||||
* @param feed -
|
||||
* the feed to update
|
||||
* @param account - the account who own this feed
|
||||
*
|
||||
* @throws ServiceException -
|
||||
* if the feed can not be updated or does not exist.
|
||||
*/
|
||||
public abstract void updateFeed(final ServerBaseFeed feed,
|
||||
final GDataAccount account) throws ServiceException;
|
||||
|
||||
/**
|
||||
* Deletes the given feed and all containing entries from the storage. The feed will not be accessable
|
||||
* anymore.
|
||||
*
|
||||
* @param feed -
|
||||
* the feed to deltete
|
||||
*
|
||||
* @throws ServiceException -
|
||||
* if the feed can not be deleted or does not exist
|
||||
*/
|
||||
public abstract void deleteFeed(final ServerBaseFeed feed) throws ServiceException;
|
||||
|
||||
/**
|
||||
* Creates a new account accout.
|
||||
*
|
||||
* @param account -
|
||||
* the account to create
|
||||
* @throws ServiceException -
|
||||
* if the account can not be created or the account does already
|
||||
* exist.
|
||||
*/
|
||||
public abstract void createAccount(final GDataAccount account)
|
||||
throws ServiceException;
|
||||
|
||||
/**
|
||||
* Deletes the given account from the storage. it will also delete all
|
||||
* accociated feeds.
|
||||
*
|
||||
* @param account
|
||||
* the account to delete
|
||||
* @throws ServiceException -
|
||||
* if the account does not exist or the account can not be deleted
|
||||
*/
|
||||
public abstract void deleteAccount(final GDataAccount account)
|
||||
throws ServiceException;
|
||||
|
||||
/**
|
||||
* Updates the given account if the account already exists.
|
||||
*
|
||||
* @param account - the account to update
|
||||
* @throws ServiceException - if the account can not be updated or the account does not exist
|
||||
*/
|
||||
public abstract void updateAccount(final GDataAccount account)
|
||||
throws ServiceException;
|
||||
|
||||
/**
|
||||
* Returns the account for the given account name or <code>null</code> if the account does not exist
|
||||
*
|
||||
* @param account - account name
|
||||
* @return - the account for the given account name or <code>null</code> if the account does not exist
|
||||
* @throws ServiceException - if the account can not be accessed
|
||||
*/
|
||||
public abstract GDataAccount getAccount(String account) throws ServiceException;
|
||||
|
||||
/**
|
||||
* Returns the account associated with the feed for the given feed id
|
||||
* @param feedId - the feed id
|
||||
* @return - the GdataAccount assoziated with the feed for the given feed Id or <code>null</code> if there is no feed for the given feed Id
|
||||
* @throws ServiceException - if the storage can not be accessed
|
||||
*/
|
||||
public abstract GDataAccount getFeedOwningAccount(String feedId) throws ServiceException;
|
||||
}
|
|
@ -1,231 +0,0 @@
|
|||
/**
|
||||
* Copyright 2004 The Apache Software Foundation
|
||||
*
|
||||
* Licensed 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.server.administration;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.apache.lucene.gdata.data.GDataAccount;
|
||||
import org.apache.lucene.gdata.data.ServerBaseFeed;
|
||||
import org.apache.lucene.gdata.server.GDataResponse;
|
||||
import org.apache.lucene.gdata.server.GDataService;
|
||||
import org.apache.lucene.gdata.server.ServiceException;
|
||||
import org.apache.lucene.gdata.server.registry.ProvidedService;
|
||||
import org.apache.lucene.gdata.storage.StorageException;
|
||||
|
||||
/**
|
||||
* default implementation of the
|
||||
* {@link org.apache.lucene.gdata.server.administration.AdminService} interface.
|
||||
*
|
||||
* @author Simon Willnauer
|
||||
*
|
||||
*/
|
||||
public class GDataAdminService extends GDataService implements AdminService {
|
||||
private static final Log LOG = LogFactory.getLog(GDataAdminService.class);
|
||||
|
||||
/**
|
||||
* @throws ServiceException
|
||||
*/
|
||||
public GDataAdminService() throws ServiceException {
|
||||
super();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.lucene.gdata.server.administration.AdminService#createFeed(org.apache.lucene.gdata.data.ServerBaseFeed,
|
||||
* org.apache.lucene.gdata.data.GDataAccount)
|
||||
*/
|
||||
public void createFeed(final ServerBaseFeed feed, final GDataAccount account)
|
||||
throws ServiceException {
|
||||
if (feed == null)
|
||||
throw new ServiceException("Can not create feed -- feed is null",
|
||||
GDataResponse.BAD_REQUEST);
|
||||
if (account == null)
|
||||
throw new ServiceException(
|
||||
"Can not create feed -- account is null",
|
||||
GDataResponse.UNAUTHORIZED);
|
||||
if (feed.getId() == null)
|
||||
throw new ServiceException("Feed ID is null can not create feed",
|
||||
GDataResponse.BAD_REQUEST);
|
||||
if (account.getName() == null)
|
||||
throw new ServiceException(
|
||||
"Account name is null -- can't create feed",
|
||||
GDataResponse.UNAUTHORIZED);
|
||||
try {
|
||||
feed.setUpdated(getCurrentDateTime());
|
||||
feed.setAccount(account);
|
||||
this.storage.storeFeed(feed, account.getName());
|
||||
} catch (StorageException e) {
|
||||
if (LOG.isInfoEnabled())
|
||||
LOG.info("Can not save feed -- " + e.getMessage(), e);
|
||||
throw new ServiceException("Can not save feed", e,
|
||||
GDataResponse.BAD_REQUEST);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.lucene.gdata.server.administration.AdminService#updateFeed(org.apache.lucene.gdata.data.ServerBaseFeed,
|
||||
* org.apache.lucene.gdata.data.GDataAccount)
|
||||
*/
|
||||
public void updateFeed(ServerBaseFeed feed, GDataAccount account)
|
||||
throws ServiceException {
|
||||
if (feed == null)
|
||||
throw new ServiceException("Can not update null feed",
|
||||
GDataResponse.BAD_REQUEST);
|
||||
if (account == null)
|
||||
throw new ServiceException(
|
||||
"Can not update feed -- account is null",
|
||||
GDataResponse.UNAUTHORIZED);
|
||||
if (feed.getId() == null)
|
||||
throw new ServiceException("Feed ID is null can not update feed",
|
||||
GDataResponse.BAD_REQUEST);
|
||||
if (account.getName() == null)
|
||||
throw new ServiceException(
|
||||
"Account name is null -- can't update feed",
|
||||
GDataResponse.UNAUTHORIZED);
|
||||
try {
|
||||
feed.setAccount(account);
|
||||
feed.setUpdated(getCurrentDateTime());
|
||||
this.storage.updateFeed(feed, account.getName());
|
||||
} catch (StorageException e) {
|
||||
if (LOG.isInfoEnabled())
|
||||
LOG.info("Can not update feed -- " + e.getMessage(), e);
|
||||
throw new ServiceException("Can not update feed", e,
|
||||
GDataResponse.BAD_REQUEST);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.lucene.gdata.server.administration.AdminService#deleteFeed(org.apache.lucene.gdata.data.ServerBaseFeed)
|
||||
*/
|
||||
public void deleteFeed(ServerBaseFeed feed) throws ServiceException {
|
||||
if (feed == null)
|
||||
throw new ServiceException("Can not delete null feed",
|
||||
GDataResponse.BAD_REQUEST);
|
||||
if (feed.getId() == null)
|
||||
throw new ServiceException("Feed ID is null can not delete feed",
|
||||
GDataResponse.BAD_REQUEST);
|
||||
String serviceid = null;
|
||||
try {
|
||||
serviceid = this.storage.getServiceForFeed(feed.getId());
|
||||
this.storage.deleteFeed(feed.getId());
|
||||
} catch (StorageException e) {
|
||||
if (LOG.isInfoEnabled())
|
||||
LOG.info("Can not delete feed -- " + e.getMessage(), e);
|
||||
throw new ServiceException("Can not delete feed", e,
|
||||
GDataResponse.BAD_REQUEST);
|
||||
}
|
||||
ProvidedService service = this.registry.getProvidedService(serviceid);
|
||||
feed.setServiceConfig(service);
|
||||
this.entryEventMediator.allEntriesDeleted(feed);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.lucene.gdata.server.administration.AdminService#createAccount(org.apache.lucene.gdata.data.GDataAccount)
|
||||
*/
|
||||
public void createAccount(GDataAccount account) throws ServiceException {
|
||||
if (account == null)
|
||||
throw new ServiceException("Can not save null account",
|
||||
GDataResponse.BAD_REQUEST);
|
||||
try {
|
||||
this.storage.storeAccount(account);
|
||||
} catch (StorageException e) {
|
||||
if (LOG.isInfoEnabled())
|
||||
LOG.info("Can not save account -- " + e.getMessage(), e);
|
||||
throw new ServiceException("Can not save account", e,
|
||||
GDataResponse.BAD_REQUEST);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.lucene.gdata.server.administration.AdminService#deleteAccount(org.apache.lucene.gdata.data.GDataAccount)
|
||||
*/
|
||||
public void deleteAccount(GDataAccount account) throws ServiceException {
|
||||
if (account == null)
|
||||
throw new ServiceException("Can not delete null account",
|
||||
GDataResponse.BAD_REQUEST);
|
||||
try {
|
||||
this.storage.deleteAccount(account.getName());
|
||||
} catch (StorageException e) {
|
||||
if (LOG.isInfoEnabled())
|
||||
LOG.info("Can not save account -- " + e.getMessage(), e);
|
||||
throw new ServiceException("Can not save account", e,
|
||||
GDataResponse.BAD_REQUEST);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.lucene.gdata.server.administration.AdminService#updateAccount(org.apache.lucene.gdata.data.GDataAccount)
|
||||
*/
|
||||
public void updateAccount(GDataAccount account) throws ServiceException {
|
||||
if (account == null)
|
||||
throw new ServiceException("Can not update null account",
|
||||
GDataResponse.BAD_REQUEST);
|
||||
try {
|
||||
this.storage.updateAccount(account);
|
||||
} catch (StorageException e) {
|
||||
if (LOG.isInfoEnabled())
|
||||
LOG.info("Can not save account -- " + e.getMessage(), e);
|
||||
throw new ServiceException("Can not save account", e,
|
||||
GDataResponse.BAD_REQUEST);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.lucene.gdata.server.administration.AdminService#getAccount(java.lang.String)
|
||||
*/
|
||||
public GDataAccount getAccount(String accountName) throws ServiceException {
|
||||
if (accountName == null)
|
||||
throw new ServiceException("Can not get null account",
|
||||
GDataResponse.BAD_REQUEST);
|
||||
try {
|
||||
return this.storage.getAccount(accountName);
|
||||
} catch (StorageException e) {
|
||||
if (LOG.isInfoEnabled())
|
||||
LOG.info("Can not get account -- " + e.getMessage(), e);
|
||||
throw new ServiceException("Can not get account", e,
|
||||
GDataResponse.BAD_REQUEST);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.lucene.gdata.server.administration.AdminService#getFeedOwningAccount(java.lang.String)
|
||||
*/
|
||||
public GDataAccount getFeedOwningAccount(String feedId)
|
||||
throws ServiceException {
|
||||
if (feedId == null)
|
||||
throw new ServiceException(
|
||||
"Can not get account - feed id must not be null",
|
||||
GDataResponse.BAD_REQUEST);
|
||||
try {
|
||||
String accountName = this.storage.getAccountNameForFeedId(feedId);
|
||||
return this.storage.getAccount(accountName);
|
||||
|
||||
} catch (StorageException e) {
|
||||
if (LOG.isInfoEnabled())
|
||||
LOG.info(
|
||||
"Can not get account for feed Id -- " + e.getMessage(),
|
||||
e);
|
||||
throw new ServiceException(
|
||||
"Can not get account for the given feed id", e,
|
||||
GDataResponse.BAD_REQUEST);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,10 +0,0 @@
|
|||
<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<meta name="Author" content="Simon Willnauer">
|
||||
</head>
|
||||
<body>
|
||||
Classes and Services used for user and feed configuration
|
||||
</body>
|
||||
</html>
|
|
@ -1,123 +0,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.
|
||||
*/
|
||||
|
||||
package org.apache.lucene.gdata.server.authentication;
|
||||
|
||||
import org.apache.lucene.gdata.data.GDataAccount;
|
||||
import org.apache.lucene.gdata.data.GDataAccount.AccountRole;
|
||||
import org.apache.lucene.gdata.server.registry.ServerComponent;
|
||||
|
||||
/**
|
||||
* Implementations of the AuthenticationController interface contain all the
|
||||
* logic for processing token based authentification. A token is an encoded
|
||||
* unique <tt>String</tt> value passed back to the client if successfully
|
||||
* authenticated. Clients provide account name, password, the requested service
|
||||
* and the name of the application used for accessing the the gdata service.
|
||||
* <p>
|
||||
* The algorithmn to create and reauthenticate the token can be choosen by the
|
||||
* implementor. <br/> This interface extends
|
||||
* {@link org.apache.lucene.gdata.server.registry.ServerComponent} e.g.
|
||||
* implementing classes can be registered as a
|
||||
* {@link org.apache.lucene.gdata.server.registry.Component} in the
|
||||
* {@link org.apache.lucene.gdata.server.registry.GDataServerRegistry} to be
|
||||
* accessed via the provided lookup service
|
||||
* </p>
|
||||
*
|
||||
* @see org.apache.lucene.gdata.server.authentication.BlowfishAuthenticationController
|
||||
* @author Simon Willnauer
|
||||
*
|
||||
*/
|
||||
public interface AuthenticationController extends ServerComponent {
|
||||
|
||||
/**
|
||||
* The header name containing the authentication token provided by the
|
||||
* client
|
||||
*/
|
||||
public static final String AUTHORIZATION_HEADER = "Authorization";
|
||||
|
||||
/**
|
||||
* Authentication parameter for the account name. Provided by the client to
|
||||
* recieve the auth token.
|
||||
*/
|
||||
public static final String ACCOUNT_PARAMETER = "Email";
|
||||
|
||||
/**
|
||||
* Authentication parameter for the account password. Provided by the client
|
||||
* to recieve the auth token.
|
||||
*/
|
||||
public static final String PASSWORD_PARAMETER = "Passwd";
|
||||
|
||||
/**
|
||||
* Authentication parameter for the requested service. Provided by the
|
||||
* client to recieve the auth token.
|
||||
*/
|
||||
public static final String SERVICE_PARAMETER = "service";
|
||||
|
||||
/**
|
||||
* Authentication parameter for the application name of the clients
|
||||
* application. This is just used for loggin purposes
|
||||
*/
|
||||
public static final String APPLICATION_PARAMETER = "source";
|
||||
|
||||
/**
|
||||
* The key used for respond the auth token to the client. Either as a cookie
|
||||
* (key as cookie name) or as plain response (TOKEN_KEY=TOKEN)
|
||||
*/
|
||||
public final static String TOKEN_KEY = "Auth";
|
||||
|
||||
/**
|
||||
* Creates a authentication token for the given account. The token will be
|
||||
* calculated based on a part of the clients ip address, the account role
|
||||
* and the account name and the time in millisecond at the point of
|
||||
* creation.
|
||||
*
|
||||
* @param account -
|
||||
* the account to create the token for
|
||||
* @param requestIp -
|
||||
* the clients request ip address
|
||||
* @return - a BASE64 encoded authentification token
|
||||
*/
|
||||
public abstract String authenticatAccount(GDataAccount account,
|
||||
String requestIp);
|
||||
|
||||
/**
|
||||
* Authenticates the given auth token and checks the given parameter for
|
||||
* matching the information contained inside the token.
|
||||
* <p>
|
||||
* if the given account name is <code>null</code> the authentication will
|
||||
* ignore the account name and the decision whether the token is valid or
|
||||
* not will be based on the given role compared to the role inside the token
|
||||
* </p>
|
||||
*
|
||||
* @param token -
|
||||
* the token to authenticate
|
||||
* @param requestIp -
|
||||
* the client request IP address
|
||||
* @param role -
|
||||
* the required role
|
||||
* @param accountName -
|
||||
* the name of the account
|
||||
* @return <code>true</code> if the given values match the values inside
|
||||
* the token and if the timestamp plus the configured timeout is
|
||||
* greater than the current time, if one of the values does not
|
||||
* match or the token has timed out it will return
|
||||
* <code>false</code>
|
||||
*/
|
||||
public abstract boolean authenticateToken(final String token,
|
||||
final String requestIp, AccountRole role, String accountName);
|
||||
|
||||
}
|
|
@ -1,71 +0,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.
|
||||
*/
|
||||
|
||||
package org.apache.lucene.gdata.server.authentication;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Simon Willnauer
|
||||
*
|
||||
*/
|
||||
public class AuthenticationException extends Exception {
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = 5467768078178612671L;
|
||||
|
||||
/**
|
||||
* Constructs a new Authentication Exception
|
||||
*/
|
||||
public AuthenticationException() {
|
||||
super();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new Authentication Exception with the specified detail message
|
||||
* @param arg0 - detail message
|
||||
*/
|
||||
public AuthenticationException(String arg0) {
|
||||
super(arg0);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new Authentication Exception with the specified detail message and
|
||||
* nested exception caused this exception.
|
||||
* @param arg0 -
|
||||
* detail message
|
||||
* @param arg1 -
|
||||
* nested exception
|
||||
*/
|
||||
public AuthenticationException(String arg0, Throwable arg1) {
|
||||
super(arg0, arg1);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new Authentication Exception with a nested exception caused this exception
|
||||
* @param arg0 - nested exception
|
||||
*/
|
||||
public AuthenticationException(Throwable arg0) {
|
||||
super(arg0);
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -1,72 +0,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.
|
||||
*/
|
||||
|
||||
package org.apache.lucene.gdata.server.authentication;
|
||||
|
||||
/**
|
||||
* This exception will be thrown by
|
||||
* {@link org.apache.lucene.gdata.server.authentication.AuthenticationController}
|
||||
* implementations if an error while de/encrypting the token occures.
|
||||
*
|
||||
* @author Simon Willnauer
|
||||
*
|
||||
*/
|
||||
public class AuthenticatorException extends RuntimeException {
|
||||
|
||||
private static final long serialVersionUID = -5690495392712564651L;
|
||||
|
||||
/**
|
||||
* Constructs a new Authenticator Exception
|
||||
*/
|
||||
public AuthenticatorException() {
|
||||
super();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new Authenticator Exception with the specified detail message.
|
||||
* @param arg0 - detail message
|
||||
*/
|
||||
public AuthenticatorException(String arg0) {
|
||||
super(arg0);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new Authenticator Exception with the specified detail message and
|
||||
* nested exception.
|
||||
*
|
||||
* @param arg0 -
|
||||
* detail message
|
||||
* @param arg1 -
|
||||
* nested exception
|
||||
*/
|
||||
public AuthenticatorException(String arg0, Throwable arg1) {
|
||||
super(arg0, arg1);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new Authenticator Exception with a nested exception caused this exception.
|
||||
* @param arg0 - nested exception
|
||||
*/
|
||||
public AuthenticatorException(Throwable arg0) {
|
||||
super(arg0);
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -1,277 +0,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.
|
||||
*/
|
||||
|
||||
package org.apache.lucene.gdata.server.authentication;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.security.Provider;
|
||||
import java.security.Security;
|
||||
import java.util.StringTokenizer;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
import javax.crypto.BadPaddingException;
|
||||
import javax.crypto.Cipher;
|
||||
import javax.crypto.IllegalBlockSizeException;
|
||||
import javax.crypto.KeyGenerator;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.apache.lucene.gdata.data.GDataAccount;
|
||||
import org.apache.lucene.gdata.data.GDataAccount.AccountRole;
|
||||
import org.apache.lucene.gdata.server.registry.Component;
|
||||
import org.apache.lucene.gdata.server.registry.ComponentType;
|
||||
import org.apache.lucene.gdata.server.registry.configuration.Requiered;
|
||||
|
||||
import sun.misc.BASE64Decoder;
|
||||
import sun.misc.BASE64Encoder;
|
||||
|
||||
/**
|
||||
* A
|
||||
* {@link org.apache.lucene.gdata.server.authentication.AuthenticationController}
|
||||
* implmentation using a <i>Blowfish</i> algorithmn to en/decrpyt the
|
||||
* authentification token. The <i>Blowfish</i> algorithmn enables a stateless
|
||||
* authetication of the client. The token contains all information to
|
||||
* authenticate the client on possible other hosts.
|
||||
* <p>
|
||||
* The token contains the first 32 bit of the client ip (e.g. 192.168.0),
|
||||
* account name, {@link org.apache.lucene.gdata.data.GDataAccount.AccountRole}
|
||||
* and the cration time as a timestamp. The timestamp will be checked on every
|
||||
* subsequent request. If the timestamp plus the configured timeout is less
|
||||
* than the current time the client has to reauthenticate again.
|
||||
* </p>
|
||||
* <p>
|
||||
* The auth token returned by the
|
||||
* {@link BlowfishAuthenticationController#authenticatAccount(GDataAccount, String)}
|
||||
* method is a BASE64 encoded string.
|
||||
* </p>
|
||||
*
|
||||
* @see javax.crypto.Cipher
|
||||
* @see sun.misc.BASE64Encoder
|
||||
* @see sun.misc.BASE64Decoder
|
||||
* @author Simon Willnauer
|
||||
*
|
||||
*/
|
||||
@Component(componentType = ComponentType.AUTHENTICATIONCONTROLLER)
|
||||
public class BlowfishAuthenticationController implements
|
||||
AuthenticationController {
|
||||
private static final Log LOG = LogFactory
|
||||
.getLog(BlowfishAuthenticationController.class);
|
||||
|
||||
private static final String ALG = "Blowfish";
|
||||
|
||||
private static final String TOKEN_LIMITER = "#";
|
||||
|
||||
private static final String ENCODING = "UTF-8";
|
||||
|
||||
private Cipher deCrypt;
|
||||
|
||||
private Cipher enCrypt;
|
||||
|
||||
private int minuteOffset = 30;
|
||||
|
||||
private long milisecondOffset;
|
||||
|
||||
private BASE64Encoder encoder = new BASE64Encoder();
|
||||
|
||||
private BASE64Decoder decoder = new BASE64Decoder();
|
||||
|
||||
private ReentrantLock lock = new ReentrantLock();
|
||||
|
||||
|
||||
private String key;
|
||||
|
||||
/**
|
||||
* @see org.apache.lucene.gdata.server.authentication.AuthenticationController#initialize()
|
||||
*/
|
||||
public void initialize() {
|
||||
if (this.key == null)
|
||||
throw new IllegalArgumentException("Auth key must not be null");
|
||||
if (this.key.length() < 5 || this.key.length() > 16)
|
||||
throw new IllegalArgumentException(
|
||||
"Auth key length must be greater than 4 and less than 17");
|
||||
|
||||
try {
|
||||
Provider sunJce = new com.sun.crypto.provider.SunJCE();
|
||||
Security.addProvider(sunJce);
|
||||
KeyGenerator kgen = KeyGenerator.getInstance(ALG);
|
||||
kgen.init(448); // 448 Bit^M
|
||||
byte[] raw = this.key.getBytes();
|
||||
SecretKeySpec skeySpec = new SecretKeySpec(raw, ALG);
|
||||
this.deCrypt = Cipher.getInstance(ALG);
|
||||
this.enCrypt = Cipher.getInstance(ALG);
|
||||
this.deCrypt.init(Cipher.DECRYPT_MODE, skeySpec);
|
||||
this.enCrypt.init(Cipher.ENCRYPT_MODE, skeySpec);
|
||||
} catch (Exception e) {
|
||||
throw new AuthenticatorException(
|
||||
"Can't initialize BlowfishAuthenticationController -- "
|
||||
+ e.getMessage(), e);
|
||||
|
||||
}
|
||||
calculateTimeOffset();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.lucene.gdata.server.authentication.AuthenticationController#authenticatAccount(org.apache.lucene.gdata.data.GDataAccount,
|
||||
* java.lang.String)
|
||||
*/
|
||||
public String authenticatAccount(GDataAccount account, String requestIp) {
|
||||
try {
|
||||
String passIp = requestIp.substring(0, requestIp.lastIndexOf('.'));
|
||||
String role = Integer.toString(account.getRolesAsInt());
|
||||
|
||||
return calculateAuthToken(passIp, role, account.getName());
|
||||
} catch (Exception e) {
|
||||
throw new AuthenticatorException("Can not authenticat account -- "
|
||||
+ e.getMessage(), e);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.lucene.gdata.server.authentication.AuthenticationController#authenticateToken(java.lang.String,
|
||||
* java.lang.String,
|
||||
* org.apache.lucene.gdata.data.GDataAccount.AccountRole,
|
||||
* java.lang.String)
|
||||
*/
|
||||
public boolean authenticateToken(final String token,
|
||||
final String requestIp, AccountRole role, String accountName) {
|
||||
if (LOG.isInfoEnabled())
|
||||
LOG.info("authenticate Token " + token + " for requestIp: "
|
||||
+ requestIp);
|
||||
if (token == null || requestIp == null)
|
||||
return false;
|
||||
String passIp = requestIp.substring(0, requestIp.lastIndexOf('.'));
|
||||
String authString = null;
|
||||
try {
|
||||
authString = deCryptAuthToken(token);
|
||||
} catch (Exception e) {
|
||||
throw new AuthenticatorException("Can not decrypt token -- "
|
||||
+ e.getMessage(), e);
|
||||
}
|
||||
if (authString == null)
|
||||
return false;
|
||||
try {
|
||||
StringTokenizer tokenizer = new StringTokenizer(authString,
|
||||
TOKEN_LIMITER);
|
||||
if (!tokenizer.nextToken().equals(passIp))
|
||||
return false;
|
||||
String tempAccountName = tokenizer.nextToken();
|
||||
int intRole = Integer.parseInt(tokenizer.nextToken());
|
||||
/*
|
||||
* Authentication goes either for a account role or a account. For
|
||||
* entry manipulation the account name will be retrieved by the
|
||||
* feedId otherwise it will be null If it is null the authentication
|
||||
* goes against the account role
|
||||
*/
|
||||
if (tempAccountName == null
|
||||
|| (!tempAccountName.equals(accountName) && !GDataAccount
|
||||
.isInRole(intRole, role)))
|
||||
return false;
|
||||
long timeout = Long.parseLong(tokenizer.nextToken());
|
||||
|
||||
return (timeout + this.milisecondOffset) > System
|
||||
.currentTimeMillis();
|
||||
} catch (Exception e) {
|
||||
LOG.error("Error occured while encrypting token " + e.getMessage(),
|
||||
e);
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void calculateTimeOffset() {
|
||||
this.milisecondOffset = this.minuteOffset * 60 * 1000;
|
||||
}
|
||||
|
||||
protected String calculateAuthToken(final String ipAddress,
|
||||
final String role, String accountName)
|
||||
throws IllegalBlockSizeException, BadPaddingException,
|
||||
UnsupportedEncodingException {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append(ipAddress).append(TOKEN_LIMITER);
|
||||
builder.append(accountName).append(TOKEN_LIMITER);
|
||||
builder.append(role).append(TOKEN_LIMITER);
|
||||
builder.append(System.currentTimeMillis());
|
||||
|
||||
this.lock.lock();
|
||||
try {
|
||||
byte[] toencode = builder.toString().getBytes(ENCODING);
|
||||
byte[] result = this.enCrypt.doFinal(toencode);
|
||||
return this.encoder.encode(result);
|
||||
} finally {
|
||||
this.lock.unlock();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
protected String deCryptAuthToken(final String authToken)
|
||||
throws IOException, IllegalBlockSizeException, BadPaddingException {
|
||||
this.lock.lock();
|
||||
try {
|
||||
byte[] input = this.decoder.decodeBuffer(authToken);
|
||||
byte[] result = this.deCrypt.doFinal(input);
|
||||
return new String(result, ENCODING);
|
||||
} finally {
|
||||
this.lock.unlock();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the minuteOffset.
|
||||
*/
|
||||
@Requiered
|
||||
public int getLoginTimeout() {
|
||||
return this.minuteOffset;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param minuteOffset
|
||||
* The minuteOffset to set.
|
||||
*/
|
||||
@Requiered
|
||||
public void setLoginTimeout(int minuteOffset) {
|
||||
this.minuteOffset = minuteOffset;
|
||||
calculateTimeOffset();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the key.
|
||||
*/
|
||||
public String getKey() {
|
||||
return this.key;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param key
|
||||
* The key to set.
|
||||
*/
|
||||
public void setKey(String key) {
|
||||
this.key = key;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.lucene.gdata.server.registry.ServerComponent#destroy()
|
||||
*/
|
||||
public void destroy() {
|
||||
//
|
||||
}
|
||||
|
||||
}
|
|
@ -1,60 +0,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.
|
||||
*/
|
||||
package org.apache.lucene.gdata.server.authentication;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.apache.lucene.gdata.data.GDataAccount.AccountRole;
|
||||
import org.apache.lucene.gdata.server.GDataRequest;
|
||||
|
||||
/**
|
||||
* The GData protocol is based on the widly know REST approach and therefor
|
||||
* client authentication will mostly be provided via a REST interface.
|
||||
* <p>
|
||||
* This interface describes internally used authentication methods to be
|
||||
* implemented by http based authenticator implementations. The GData Server
|
||||
* basically has 2 different REST interfaces need authentication. One is for
|
||||
* altering feed entries and the other for administration actions.
|
||||
* </p>
|
||||
* <p>The interface altering entries work with {@link com.google.gdata.client.Service.GDataRequest} object created by the handler and passed to the {@link org.apache.lucene.gdata.server.Service} instance.
|
||||
* Administration interfaces use the plain {@link javax.servlet.http.HttpServletRequest} inside the handler.
|
||||
* For each type of interface a authentication type a method has to be provided by implementing classes.</p>
|
||||
*
|
||||
* @author Simon Willnauer
|
||||
*
|
||||
*/
|
||||
public interface GDataHttpAuthenticator {
|
||||
|
||||
/**
|
||||
* Authenticates the client request based on the given GdataRequst and required account role
|
||||
* @param request - the gdata request
|
||||
* @param role - the required role for passing the authentication
|
||||
*
|
||||
* @return <code>true</code> if the request successfully authenticates, otherwise <code>false</code>
|
||||
*/
|
||||
public boolean authenticateAccount(final GDataRequest request,
|
||||
AccountRole role);
|
||||
|
||||
/**
|
||||
* Authenticates the client request based on the given requst and required account role
|
||||
* @param request - the client request
|
||||
* @param role - the required role for passing the authentication
|
||||
* @return <code>true</code> if the request successfully authenticates, otherwise <code>false</code>
|
||||
*/
|
||||
public boolean authenticateAccount(final HttpServletRequest request,
|
||||
AccountRole role);
|
||||
}
|
|
@ -1,10 +0,0 @@
|
|||
<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<meta name="Author" content="Simon Willnauer">
|
||||
</head>
|
||||
<body>
|
||||
Classes and Exceptions used for client authentification.
|
||||
</body>
|
||||
</html>
|
|
@ -1,10 +0,0 @@
|
|||
<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<meta name="Author" content="Simon Willnauer">
|
||||
</head>
|
||||
<body>
|
||||
GData-Server classes encapsulation all protocol-level interactions and underlaying GData components.
|
||||
</body>
|
||||
</html>
|
|
@ -1,75 +0,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.
|
||||
*/
|
||||
|
||||
package org.apache.lucene.gdata.server.registry;
|
||||
|
||||
import static java.lang.annotation.ElementType.TYPE;
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* The {@link Component} annotation is used to annotate a class as a
|
||||
* server-component of the GDATA-Server. Annotated class can be configured via
|
||||
* the gdata-config.xml file to be looked up by aribaty classes at runtime via
|
||||
* the
|
||||
* {@link org.apache.lucene.gdata.server.registry.GDataServerRegistry#lookup(Class, ComponentType)}
|
||||
* method.
|
||||
* <p>
|
||||
* Classes annotated with the Component annotation need to provide a default
|
||||
* constructor to be instanciated via reflection. Components of the GData-Server
|
||||
* are definded in the
|
||||
* {@link org.apache.lucene.gdata.server.registry.ComponentType} enumeration.
|
||||
* Each of the enum types are annotated with a
|
||||
* {@link org.apache.lucene.gdata.server.registry.SuperType} annotation. This
|
||||
* annotation specifies the super class or interface of the component. A class
|
||||
* annotated with the Component annotation must implement or extends this
|
||||
* defined super-type. This enables developers to use custom implemetations of
|
||||
* the component like a custom {@link org.apache.lucene.gdata.storage.Storage}.
|
||||
* </p>
|
||||
* <p>
|
||||
* Each ComponentType can only registerd once as the
|
||||
* {@link org.apache.lucene.gdata.server.registry.GDataServerRegistry} does not
|
||||
* provide multipe instances of a ComponentType.
|
||||
* </p>
|
||||
* <p>
|
||||
* This annotation can only annotate types and can be accessed at runtime.
|
||||
* {@link java.lang.annotation.Target} ==
|
||||
* {@link java.lang.annotation.ElementType#TYPE} and
|
||||
* {@link java.lang.annotation.Retention} ==
|
||||
* {@link java.lang.annotation.RetentionPolicy#RUNTIME}.
|
||||
*
|
||||
* @see org.apache.lucene.gdata.server.registry.GDataServerRegistry
|
||||
* @see org.apache.lucene.gdata.server.registry.ComponentType
|
||||
* @see org.apache.lucene.gdata.server.registry.SuperType
|
||||
*
|
||||
*
|
||||
* @author Simon Willnauer
|
||||
*
|
||||
*/
|
||||
@Target( { TYPE })
|
||||
@Retention(value = RUNTIME)
|
||||
public @interface Component {
|
||||
|
||||
/**
|
||||
* @see ComponentType
|
||||
* @return - the component type
|
||||
*/
|
||||
ComponentType componentType();
|
||||
|
||||
}
|
|
@ -1,70 +0,0 @@
|
|||
package org.apache.lucene.gdata.server.registry;
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
import org.apache.lucene.gdata.search.SearchComponent;
|
||||
import org.apache.lucene.gdata.server.ServiceFactory;
|
||||
import org.apache.lucene.gdata.server.authentication.AuthenticationController;
|
||||
import org.apache.lucene.gdata.servlet.handler.RequestHandlerFactory;
|
||||
import org.apache.lucene.gdata.storage.StorageController;
|
||||
|
||||
/**
|
||||
* The enumeration {@link ComponentType} defines the GDATA-Server Components
|
||||
* available via {@link org.apache.lucene.gdata.server.registry.GDataServerRegistry#lookup(Class, ComponentType)}
|
||||
* method.
|
||||
* @see org.apache.lucene.gdata.server.registry.Component
|
||||
* @see org.apache.lucene.gdata.server.registry.GDataServerRegistry
|
||||
* @author Simon Willnauer
|
||||
*
|
||||
*/
|
||||
public enum ComponentType {
|
||||
/**
|
||||
* StorageController Type
|
||||
*
|
||||
* @see StorageController
|
||||
*/
|
||||
@SuperType(superType = StorageController.class)
|
||||
STORAGECONTROLLER,
|
||||
/**
|
||||
* RequestHandlerFactory Type
|
||||
*
|
||||
* @see RequestHandlerFactory
|
||||
*/
|
||||
@SuperType(superType = RequestHandlerFactory.class)
|
||||
REQUESTHANDLERFACTORY,
|
||||
/**
|
||||
* SearchComponent Type
|
||||
* @see SearchComponent
|
||||
*/
|
||||
@SuperType(superType = SearchComponent.class)
|
||||
SEARCHCONTROLLER,
|
||||
/**
|
||||
* ServiceFactory Type
|
||||
*
|
||||
* @see ServiceFactory
|
||||
*/
|
||||
@SuperType(superType = ServiceFactory.class)
|
||||
SERVICEFACTORY,
|
||||
/**
|
||||
* Super type for AuthenticationController implementations
|
||||
* @see AuthenticationController
|
||||
*/
|
||||
@SuperType(superType = AuthenticationController.class)
|
||||
AUTHENTICATIONCONTROLLER
|
||||
|
||||
}
|
|
@ -1,56 +0,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.
|
||||
*/
|
||||
|
||||
package org.apache.lucene.gdata.server.registry;
|
||||
|
||||
import org.apache.lucene.gdata.data.ServerBaseEntry;
|
||||
import org.apache.lucene.gdata.data.ServerBaseFeed;
|
||||
|
||||
/**
|
||||
* The EntryEventListener interface should be implemented by any class needs to be informed about any changes on entries.
|
||||
* To register a class as a EntryEventListener use:
|
||||
* <p>
|
||||
* <tt>
|
||||
* GdataServerRegistry.registerEntryEventListener(EntryEventListener);
|
||||
* <tt>
|
||||
* </p>
|
||||
*
|
||||
*
|
||||
*/
|
||||
public interface EntryEventListener {
|
||||
/**
|
||||
* will be invoked on every successful update on every entry
|
||||
* @param entry the updated entry
|
||||
*/
|
||||
public abstract void fireUpdateEvent(ServerBaseEntry entry);
|
||||
/**
|
||||
* will be invoked on every successful entry insert
|
||||
* @param entry
|
||||
*/
|
||||
public abstract void fireInsertEvent(ServerBaseEntry entry);
|
||||
/**
|
||||
* will be invoked on every successful entry delete
|
||||
* @param entry
|
||||
*/
|
||||
public abstract void fireDeleteEvent(ServerBaseEntry entry);
|
||||
|
||||
/**
|
||||
* will be invoked on every successful feed delete
|
||||
* @param feed - the feed containing the feed id to delete all entries for
|
||||
*/
|
||||
public abstract void fireDeleteAllEntries(ServerBaseFeed feed);
|
||||
}
|
|
@ -1,105 +0,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.
|
||||
*/
|
||||
|
||||
package org.apache.lucene.gdata.server.registry;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.lucene.gdata.data.ServerBaseEntry;
|
||||
import org.apache.lucene.gdata.data.ServerBaseFeed;
|
||||
|
||||
/**
|
||||
* This class will be informed about every successful entry event and
|
||||
* distributes all event to all registered
|
||||
* {@link org.apache.lucene.gdata.server.registry.EntryEventListener}
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
public abstract class EntryEventMediator {
|
||||
|
||||
private final List<EntryEventListener> entryEventListener = new ArrayList<EntryEventListener>(
|
||||
5);
|
||||
|
||||
/**
|
||||
* @return - a entry event mediator instance
|
||||
*/
|
||||
public abstract EntryEventMediator getEntryEventMediator();
|
||||
|
||||
/**
|
||||
* Registers a {@link EntryEventListener}. This listener will be fired if an
|
||||
* entry update, insert or delete occurs
|
||||
*
|
||||
* @param listener -
|
||||
* listener to register
|
||||
*/
|
||||
public void registerEntryEventListener(final EntryEventListener listener) {
|
||||
if (listener == null || this.entryEventListener.contains(listener))
|
||||
return;
|
||||
this.entryEventListener.add(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param entry -
|
||||
* the updated entry
|
||||
*/
|
||||
public void entryUpdated(final ServerBaseEntry entry) {
|
||||
for (EntryEventListener listener : this.entryEventListener) {
|
||||
listener.fireUpdateEvent(entry);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param entry -
|
||||
* the added entry
|
||||
*/
|
||||
public void entryAdded(final ServerBaseEntry entry) {
|
||||
for (EntryEventListener listener : this.entryEventListener) {
|
||||
listener.fireInsertEvent(entry);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param feed - the feed to delete all entries for
|
||||
*/
|
||||
public void allEntriesDeleted(final ServerBaseFeed feed){
|
||||
for (EntryEventListener listener : this.entryEventListener) {
|
||||
listener.fireDeleteAllEntries(feed);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param entry -
|
||||
* the deleted entry
|
||||
*/
|
||||
public void entryDeleted(final ServerBaseEntry entry) {
|
||||
for (EntryEventListener listener : this.entryEventListener) {
|
||||
listener.fireDeleteEvent(entry);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* checks if the listener is already registered.
|
||||
* @param listner - the listener to check
|
||||
* @return <code>true</code> if and only if the given listener is already registered, otherwise <code>false</code>.
|
||||
*/
|
||||
public boolean isListenerRegistered(final EntryEventListener listner){
|
||||
return listner!=null&&this.entryEventListener.contains(listner);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,92 +0,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.
|
||||
*/
|
||||
|
||||
package org.apache.lucene.gdata.server.registry;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.servlet.ServletRequestEvent;
|
||||
import javax.servlet.ServletRequestListener;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.apache.lucene.gdata.server.registry.Scope.ScopeType;
|
||||
|
||||
/**
|
||||
* This <tt>ServletRequestListener</tt> is used by the registry to notify
|
||||
* registered {@link org.apache.lucene.gdata.server.registry.ScopeVisitor}
|
||||
* implementations when a request is initialized e.g destroyed.
|
||||
*
|
||||
*
|
||||
* @see org.apache.lucene.gdata.server.registry.ScopeVisitable
|
||||
* @see javax.servlet.ServletRequestListener
|
||||
*
|
||||
*
|
||||
*/
|
||||
@Scope(scope = ScopeType.REQUEST)
|
||||
public class GDataRequestListener implements ServletRequestListener,
|
||||
ScopeVisitable {
|
||||
private final GDataServerRegistry registry;
|
||||
|
||||
private final List<ScopeVisitor> visitors = new ArrayList<ScopeVisitor>(5);
|
||||
|
||||
private static final Log LOG = LogFactory
|
||||
.getLog(GDataRequestListener.class);
|
||||
|
||||
/**
|
||||
* @throws RegistryException
|
||||
*
|
||||
*/
|
||||
public GDataRequestListener() throws RegistryException {
|
||||
this.registry = GDataServerRegistry.getRegistry();
|
||||
this.registry.registerScopeVisitable(this);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @see javax.servlet.ServletRequestListener#requestDestroyed(javax.servlet.ServletRequestEvent)
|
||||
*/
|
||||
public void requestDestroyed(ServletRequestEvent arg0) {
|
||||
for (ScopeVisitor visitor : this.visitors) {
|
||||
visitor.visiteDestroy();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @see javax.servlet.ServletRequestListener#requestInitialized(javax.servlet.ServletRequestEvent)
|
||||
*/
|
||||
public void requestInitialized(ServletRequestEvent arg0) {
|
||||
for (ScopeVisitor visitor : this.visitors) {
|
||||
visitor.visiteInitialize();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.lucene.gdata.server.registry.ScopeVisitable#accept(org.apache.lucene.gdata.server.registry.ScopeVisitor)
|
||||
*/
|
||||
public void accept(ScopeVisitor visitor) {
|
||||
|
||||
if (!this.visitors.contains(visitor) && visitor != null) {
|
||||
this.visitors.add(visitor);
|
||||
if(LOG.isDebugEnabled())
|
||||
LOG.debug("visitor added -- " + visitor.getClass());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,378 +0,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.
|
||||
*/
|
||||
package org.apache.lucene.gdata.server.registry;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.apache.lucene.gdata.server.registry.configuration.ComponentConfiguration;
|
||||
import org.apache.lucene.gdata.server.registry.configuration.PropertyInjector;
|
||||
import org.apache.lucene.gdata.utils.ReflectionUtils;
|
||||
|
||||
/**
|
||||
*
|
||||
* The GDataServerRegistry represents the registry component of the GData
|
||||
* Server. All provided services and server components will be registered here.
|
||||
* The GData Server serves RSS / ATOM feeds for defined services. Each service
|
||||
* provides <i>n</i> feeds of a defined subclass of
|
||||
* {@link com.google.gdata.data.BaseFeed}. Each feed contains <i>m</i> entries
|
||||
* of a defined subclass of {@link com.google.gdata.data.BaseEntry}. To
|
||||
* generate RSS / ATOM formates a class of the type
|
||||
* {@link com.google.gdata.data.ExtensionProfile} is also defined for a service.
|
||||
* <p>
|
||||
* The entry,feed and the ExtensionProfile classes are defined in the
|
||||
* gdata-config.xml and will be loaded when the server starts up.
|
||||
* </p>
|
||||
* <p>
|
||||
* The components defined in the gdata-config.xml will also be loaded and
|
||||
* instantiated at startup. If a component can not be loaded or an Exception
|
||||
* occurs the server will not start up. To cause of the exception or error will
|
||||
* be logged to the standard server output.
|
||||
* </p>
|
||||
* <p>
|
||||
* The GDataServerRegistry is a Singleton
|
||||
* </p>
|
||||
*
|
||||
*
|
||||
* @author Simon Willnauer
|
||||
*
|
||||
*/
|
||||
public class GDataServerRegistry extends EntryEventMediator{
|
||||
private static GDataServerRegistry INSTANCE;
|
||||
|
||||
private static final Log LOG = LogFactory
|
||||
.getLog(GDataServerRegistry.class);
|
||||
|
||||
private ScopeVisitable requestVisitable;
|
||||
|
||||
private ScopeVisitable sessionVisitable;
|
||||
|
||||
// not available yet
|
||||
private ScopeVisitable contextVisitable;
|
||||
|
||||
private List<ScopeVisitor> visitorBuffer = new ArrayList<ScopeVisitor>(5);
|
||||
|
||||
private final Map<String, ProvidedService> serviceTypeMap = new HashMap<String, ProvidedService>();
|
||||
|
||||
private final Map<ComponentType, ComponentBean> componentMap = new HashMap<ComponentType, ComponentBean>(
|
||||
ComponentType.values().length);
|
||||
|
||||
private GDataServerRegistry() {
|
||||
// private - singleton
|
||||
}
|
||||
|
||||
/**
|
||||
* @return a Singleton registry instance
|
||||
*/
|
||||
public static synchronized GDataServerRegistry getRegistry() {
|
||||
if (INSTANCE == null)
|
||||
INSTANCE = new GDataServerRegistry();
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a {@link ProvidedService}
|
||||
*
|
||||
* @param configurator -
|
||||
* the configurator to register in the registry
|
||||
*/
|
||||
public void registerService(ProvidedService configurator) {
|
||||
if (configurator == null) {
|
||||
LOG.warn("Feed configurator is null -- skip registration");
|
||||
return;
|
||||
}
|
||||
this.serviceTypeMap.put(configurator.getName(), configurator);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param visitor -
|
||||
* the visitor to register
|
||||
* @throws RegistryException
|
||||
*/
|
||||
public synchronized void registerScopeVisitor(final ScopeVisitor visitor)
|
||||
throws RegistryException {
|
||||
if (visitor == null)
|
||||
throw new IllegalArgumentException("visitor must not be null");
|
||||
Scope scope = visitor.getClass().getAnnotation(Scope.class);
|
||||
if (scope == null)
|
||||
throw new RegistryException("Visitor has not Scope");
|
||||
if (LOG.isInfoEnabled())
|
||||
LOG.info("Register scope visitor -- " + visitor.getClass());
|
||||
if (scope.scope().equals(Scope.ScopeType.REQUEST)
|
||||
&& this.requestVisitable != null)
|
||||
this.requestVisitable.accept(visitor);
|
||||
else if (scope.scope() == Scope.ScopeType.SESSION
|
||||
&& this.sessionVisitable != null)
|
||||
this.sessionVisitable.accept(visitor);
|
||||
else if (scope.scope() == Scope.ScopeType.CONTEXT
|
||||
&& this.contextVisitable != null)
|
||||
this.sessionVisitable.accept(visitor);
|
||||
else if (!this.visitorBuffer.contains(visitor))
|
||||
this.visitorBuffer.add(visitor);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param visitable -
|
||||
* the instance to register
|
||||
* @throws RegistryException
|
||||
* @see ScopeVisitable
|
||||
*/
|
||||
public synchronized void registerScopeVisitable(
|
||||
final ScopeVisitable visitable) throws RegistryException {
|
||||
if (visitable == null)
|
||||
throw new IllegalArgumentException("visitable must not be null");
|
||||
|
||||
Scope scope = visitable.getClass().getAnnotation(Scope.class);
|
||||
if (scope == null)
|
||||
throw new RegistryException("Visitable has not Scope");
|
||||
if (LOG.isInfoEnabled())
|
||||
LOG.info("Register scope visitable -- " + visitable.getClass());
|
||||
if (scope.scope() == Scope.ScopeType.REQUEST
|
||||
&& this.requestVisitable == null)
|
||||
this.requestVisitable = visitable;
|
||||
else if (scope.scope() == Scope.ScopeType.SESSION
|
||||
&& this.sessionVisitable == null)
|
||||
this.sessionVisitable = visitable;
|
||||
else if (scope.scope() == Scope.ScopeType.CONTEXT
|
||||
&& this.contextVisitable == null)
|
||||
this.sessionVisitable = visitable;
|
||||
|
||||
if (!this.visitorBuffer.isEmpty()) {
|
||||
|
||||
List<ScopeVisitor> tempList = this.visitorBuffer;
|
||||
this.visitorBuffer = new ArrayList<ScopeVisitor>(5);
|
||||
for (ScopeVisitor visitor : tempList) {
|
||||
registerScopeVisitor(visitor);
|
||||
}
|
||||
tempList.clear();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Looks up the {@link ProvidedServiceConfig} by the given service name.
|
||||
*
|
||||
* @param service
|
||||
* @return - the {@link ProvidedServiceConfig} or <code>null</code> if the
|
||||
* no configuration for this service has been registered
|
||||
*/
|
||||
public ProvidedService getProvidedService(String service) {
|
||||
if (service == null)
|
||||
throw new IllegalArgumentException(
|
||||
"Service is null - must not be null to get registered feed type");
|
||||
return this.serviceTypeMap.get(service);
|
||||
}
|
||||
|
||||
protected void flushRegistry() {
|
||||
Collection<ProvidedService> services = this.serviceTypeMap.values();
|
||||
for (ProvidedService service : services) {
|
||||
service.destroy();
|
||||
}
|
||||
this.serviceTypeMap.clear();
|
||||
this.componentMap.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param service -
|
||||
* the name of the service
|
||||
* @return - <code>true</code> if and only if the service is registered,
|
||||
* otherwise <code>false</code>.
|
||||
*/
|
||||
public boolean isServiceRegistered(String service) {
|
||||
return this.serviceTypeMap.containsKey(service);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroys the registry and release all resources
|
||||
*/
|
||||
public void destroy() {
|
||||
for (ComponentBean component : this.componentMap.values()) {
|
||||
component.getObject().destroy();
|
||||
}
|
||||
|
||||
flushRegistry();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is the main interface to the Component Lookup Service of the
|
||||
* registry. Every GDATA - Server component like STORAGE or the INDEXER
|
||||
* component will be accessible via this method. To get a Component from the
|
||||
* lookup service specify the expected Class as an argument and the
|
||||
* component type of the component to return. For a lookup of the
|
||||
* STORAGECONTORLER the code looks like:
|
||||
* <p>
|
||||
* <code> registryInstance.lookup(StorageController.class,ComponentType.STORAGECONTROLLER);</code>
|
||||
* </p>
|
||||
*
|
||||
* @param <R>
|
||||
* the type of the expected return value
|
||||
* @param clazz -
|
||||
* Class object of the expected return value
|
||||
* @param compType -
|
||||
* The component type
|
||||
* @return the registered component or <code>null</code> if the component
|
||||
* can not looked up.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public <R> R lookup(Class<R> clazz, ComponentType compType) {
|
||||
ComponentBean bean = this.componentMap.get(compType);
|
||||
if (bean == null)
|
||||
return null;
|
||||
if (bean.getSuperType().equals(clazz))
|
||||
return (R) bean.getObject();
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* All registered {@link ServerComponent} registered via this method are
|
||||
* available via the
|
||||
* {@link GDataServerRegistry#lookup(Class, ComponentType)} method. For each
|
||||
* {@link ComponentType} there will be one single instance registered in the
|
||||
* registry.
|
||||
* <p>
|
||||
* Eventually this method invokes the initialize method of the
|
||||
* ServerComponent interface to prepare the component to be available via
|
||||
* the lookup service
|
||||
* </p>
|
||||
*
|
||||
* @param <E> -
|
||||
* The interface of the component to register
|
||||
* @param componentClass -
|
||||
* a implementation of a ServerComponent interface to register in
|
||||
* the registry
|
||||
* @param configuration -
|
||||
* the component configuration {@link ComponentConfiguration}
|
||||
* @throws RegistryException -
|
||||
* if the provided class does not implement the
|
||||
* {@link ServerComponent} interface, if the mandatory
|
||||
* annotations not visible at runtime or not set, if the super
|
||||
* type provided by the {@link ComponentType} for the class to
|
||||
* register is not a super type of the class or if the
|
||||
* invocation of the {@link ServerComponent#initialize()} method
|
||||
* throws an exception.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public <E extends ServerComponent> void registerComponent(
|
||||
final Class<E> componentClass,
|
||||
final ComponentConfiguration configuration)
|
||||
throws RegistryException {
|
||||
|
||||
if (componentClass == null)
|
||||
throw new IllegalArgumentException(
|
||||
"component class must not be null");
|
||||
|
||||
if (!ReflectionUtils.implementsType(componentClass,
|
||||
ServerComponent.class))
|
||||
throw new RegistryException(
|
||||
"can not register component. the given class does not implement ServerComponent interface -- "
|
||||
+ componentClass.getName());
|
||||
try {
|
||||
|
||||
Component annotation = componentClass
|
||||
.getAnnotation(Component.class);
|
||||
if (annotation == null)
|
||||
throw new RegistryException(
|
||||
"can not register component. the given class is not a component -- "
|
||||
+ componentClass.getName());
|
||||
ComponentType type = annotation.componentType();
|
||||
if (this.componentMap.containsKey(type))
|
||||
throw new RegistryException("component already registered -- "
|
||||
+ type.name());
|
||||
Class superType = type.getClass().getField(type.name())
|
||||
.getAnnotation(SuperType.class).superType();
|
||||
if (!ReflectionUtils.isTypeOf(componentClass, superType))
|
||||
throw new RegistryException("Considered super type <"
|
||||
+ superType.getName() + "> is not a super type of <"
|
||||
+ componentClass + ">");
|
||||
ServerComponent comp = componentClass.newInstance();
|
||||
if (configuration == null) {
|
||||
if (LOG.isInfoEnabled())
|
||||
LOG.info("no configuration for ComponentType: "
|
||||
+ type.name());
|
||||
} else
|
||||
configureComponent(comp, type, configuration);
|
||||
comp.initialize();
|
||||
ComponentBean bean = new ComponentBean(comp, superType);
|
||||
|
||||
this.componentMap.put(type, bean);
|
||||
if (ReflectionUtils.implementsType(componentClass,
|
||||
ScopeVisitor.class))
|
||||
this.registerScopeVisitor((ScopeVisitor) comp);
|
||||
} catch (Exception e) {
|
||||
throw new RegistryException("Can not register component -- "
|
||||
+ e.getMessage(), e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Injects the configured properties located in the configuration into the
|
||||
* given server component
|
||||
*/
|
||||
private void configureComponent(final ServerComponent component,
|
||||
final ComponentType type, final ComponentConfiguration configuration) {
|
||||
PropertyInjector injector = new PropertyInjector();
|
||||
injector.setTargetObject(component);
|
||||
injector.injectProperties(configuration);
|
||||
}
|
||||
|
||||
private static class ComponentBean {
|
||||
private final Class superType;
|
||||
|
||||
private final ServerComponent object;
|
||||
|
||||
ComponentBean(final ServerComponent object, final Class superType) {
|
||||
this.superType = superType;
|
||||
this.object = object;
|
||||
}
|
||||
|
||||
ServerComponent getObject() {
|
||||
return this.object;
|
||||
}
|
||||
|
||||
Class getSuperType() {
|
||||
return this.superType;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.lucene.gdata.server.registry.EntryEventMediator#getEntryEventMediator()
|
||||
*/
|
||||
@Override
|
||||
public EntryEventMediator getEntryEventMediator() {
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return - all registered services
|
||||
*/
|
||||
public Collection<ProvidedService> getServices() {
|
||||
|
||||
return this.serviceTypeMap.values();
|
||||
}
|
||||
|
||||
}
|
|
@ -1,65 +0,0 @@
|
|||
/**
|
||||
* Copyright 2004 The Apache Software Foundation
|
||||
*
|
||||
* Licensed 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.server.registry;
|
||||
|
||||
import javax.xml.transform.Templates;
|
||||
|
||||
import org.apache.lucene.gdata.search.config.IndexSchema;
|
||||
|
||||
import com.google.gdata.data.ExtensionProfile;
|
||||
|
||||
/**
|
||||
* This interface describes a service provided by the GData-Server.
|
||||
* @see org.apache.lucene.gdata.server.registry.GDataServerRegistry
|
||||
* @author Simon Willnauer
|
||||
*
|
||||
*/
|
||||
public interface ProvidedService {
|
||||
|
||||
/**
|
||||
* @return Returns the feedType.
|
||||
*/
|
||||
public abstract Class getFeedType();
|
||||
|
||||
/**
|
||||
* @return - the extension profile for this feed
|
||||
*/
|
||||
public abstract ExtensionProfile getExtensionProfile();
|
||||
|
||||
/**
|
||||
* @return the entry Type configured for this Service
|
||||
*/
|
||||
public abstract Class getEntryType();
|
||||
|
||||
/**
|
||||
* @return - the service name
|
||||
*/
|
||||
public abstract String getName();
|
||||
|
||||
/**
|
||||
* releases all dependencies and resources
|
||||
*/
|
||||
public abstract void destroy();
|
||||
/**
|
||||
* @return the index schema configuration for this service
|
||||
*/
|
||||
public abstract IndexSchema getIndexSchema();
|
||||
/**
|
||||
* @return the compiled xslt stylesheet to transform the feed / entry for preview
|
||||
*/
|
||||
public abstract Templates getTransformTemplate();
|
||||
|
||||
}
|
|
@ -1,364 +0,0 @@
|
|||
/**
|
||||
* Copyright 2004 The Apache Software Foundation
|
||||
*
|
||||
* Licensed 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.server.registry;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
|
||||
import javax.xml.transform.Templates;
|
||||
import javax.xml.transform.TransformerConfigurationException;
|
||||
import javax.xml.transform.TransformerFactory;
|
||||
import javax.xml.transform.stream.StreamSource;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.apache.lucene.gdata.search.config.IndexSchema;
|
||||
import org.apache.lucene.gdata.utils.Pool;
|
||||
import org.apache.lucene.gdata.utils.PoolObjectFactory;
|
||||
import org.apache.lucene.gdata.utils.SimpleObjectPool;
|
||||
|
||||
import com.google.gdata.data.BaseEntry;
|
||||
import com.google.gdata.data.BaseFeed;
|
||||
import com.google.gdata.data.ExtensionProfile;
|
||||
|
||||
/**
|
||||
* Standard implementation of
|
||||
* {@link org.apache.lucene.gdata.server.registry.ProvidedService} to be used
|
||||
* inside the
|
||||
* {@link org.apache.lucene.gdata.server.registry.GDataServerRegistry}
|
||||
* <p>
|
||||
* ExtensionProfiles are used to generate and parse xml by the gdata api. For
|
||||
* that case all methods are synchronized. This will slow down the application
|
||||
* when performing lots of xml generation concurrently. For that case the
|
||||
* extensionProfile for a specific service will be pooled and reused.
|
||||
* </p>
|
||||
*
|
||||
*
|
||||
* @author Simon Willnauer
|
||||
*
|
||||
*/
|
||||
@Scope(scope = Scope.ScopeType.REQUEST)
|
||||
public class ProvidedServiceConfig implements ProvidedService, ScopeVisitor {
|
||||
private final static Log LOG = LogFactory
|
||||
.getLog(ProvidedServiceConfig.class);
|
||||
|
||||
private static final int DEFAULT_POOL_SIZE = 5;
|
||||
private IndexSchema indexSchema;
|
||||
/*
|
||||
* To ensure a extension profile instance will not be shared within multiple
|
||||
* threads each thread requesting a config will have one instance for the
|
||||
* entire request.
|
||||
*/
|
||||
protected final ThreadLocal<ExtensionProfile> extProfThreadLocal = new ThreadLocal<ExtensionProfile>();
|
||||
|
||||
/*
|
||||
* ExtensionProfiles are used to generate and parse xml by the gdata api.
|
||||
* For that case all methodes are synchronized. This will slow down the
|
||||
* application when performing lots of xml generation concurrently. for that
|
||||
* case the extensionProfile for a specific service will be pooled and
|
||||
* reused.
|
||||
*/
|
||||
private Pool<ExtensionProfile> profilPool;
|
||||
|
||||
private String serviceName;
|
||||
|
||||
private Class<? extends BaseEntry> entryType;
|
||||
|
||||
private Class<? extends BaseFeed> feedType;
|
||||
|
||||
private ExtensionProfile extensionProfile;
|
||||
|
||||
private int poolSize = DEFAULT_POOL_SIZE;
|
||||
|
||||
private Templates transformerTemplate;
|
||||
|
||||
|
||||
/**
|
||||
* @return Returns the poolSize.
|
||||
*/
|
||||
public int getPoolSize() {
|
||||
return this.poolSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param poolSize
|
||||
* The poolSize to set.
|
||||
*/
|
||||
public void setPoolSize(int poolSize) {
|
||||
|
||||
this.poolSize = poolSize >= DEFAULT_POOL_SIZE ? poolSize
|
||||
: DEFAULT_POOL_SIZE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Default constructor to instantiate via reflection
|
||||
*/
|
||||
public ProvidedServiceConfig() {
|
||||
try {
|
||||
GDataServerRegistry.getRegistry().registerScopeVisitor(this);
|
||||
} catch (RegistryException e) {
|
||||
throw new RuntimeException("Can not register ScopeVisitor -- "
|
||||
+ e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.lucene.gdata.server.registry.ProvidedService#getFeedType()
|
||||
*/
|
||||
public Class getFeedType() {
|
||||
return this.feedType;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param feedType
|
||||
* The feedType to set.
|
||||
*/
|
||||
public void setFeedType(Class feedType) {
|
||||
this.feedType = feedType;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.lucene.gdata.server.registry.ProvidedService#getExtensionProfile()
|
||||
*/
|
||||
public ExtensionProfile getExtensionProfile() {
|
||||
ExtensionProfile ext = this.extProfThreadLocal.get();
|
||||
if (ext != null) {
|
||||
return ext;
|
||||
}
|
||||
if(this.extensionProfile == null)
|
||||
return null;
|
||||
if (this.profilPool == null)
|
||||
createProfilePool();
|
||||
ext = this.profilPool.aquire();
|
||||
this.extProfThreadLocal.set(ext);
|
||||
return ext;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param extensionProfil -
|
||||
* the extension profile for this feed configuration
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public void setExtensionProfile(ExtensionProfile extensionProfil) {
|
||||
if (extensionProfil == null)
|
||||
throw new IllegalArgumentException(
|
||||
"ExtensionProfile must not be null");
|
||||
if (this.extensionProfile != null)
|
||||
return;
|
||||
this.extensionProfile = extensionProfil;
|
||||
|
||||
}
|
||||
|
||||
private void createProfilePool() {
|
||||
if (LOG.isInfoEnabled())
|
||||
LOG.info("Create ExtensionProfile pool with pool size:"
|
||||
+ this.poolSize + " for service " + this.serviceName);
|
||||
this.profilPool = new SimpleObjectPool<ExtensionProfile>(this.poolSize,
|
||||
new ExtensionProfileFactory<ExtensionProfile>(
|
||||
this.extensionProfile.getClass(),this.entryType,this.feedType));
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO add comment
|
||||
*
|
||||
* @param <E>
|
||||
* @param extensionProfileClass
|
||||
* @throws InstantiationException
|
||||
* @throws IllegalAccessException
|
||||
*/
|
||||
public <E extends ExtensionProfile> void setExtensionProfileClass(
|
||||
Class<E> extensionProfileClass) throws InstantiationException,
|
||||
IllegalAccessException {
|
||||
if (extensionProfileClass == null)
|
||||
throw new IllegalArgumentException(
|
||||
"ExtensionProfile class must not be null");
|
||||
|
||||
setExtensionProfile(extensionProfileClass.newInstance());
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.lucene.gdata.server.registry.ProvidedService#getEntryType()
|
||||
*/
|
||||
public Class getEntryType() {
|
||||
return this.entryType;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param entryType
|
||||
*/
|
||||
public void setEntryType(Class entryType) {
|
||||
this.entryType = entryType;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.lucene.gdata.server.registry.ProvidedService#getName()
|
||||
*/
|
||||
public String getName() {
|
||||
return this.serviceName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param serviceName
|
||||
*/
|
||||
public void setName(String serviceName) {
|
||||
this.serviceName = serviceName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.lucene.gdata.server.registry.ProvidedService#destroy()
|
||||
*/
|
||||
public void destroy() {
|
||||
if (this.profilPool != null)
|
||||
this.profilPool.destroy();
|
||||
if (LOG.isInfoEnabled())
|
||||
LOG.info("Destroy Service " + this.serviceName
|
||||
+ " -- release all resources");
|
||||
this.feedType = null;
|
||||
this.entryType = null;
|
||||
this.extensionProfile = null;
|
||||
}
|
||||
|
||||
private static class ExtensionProfileFactory<Type extends ExtensionProfile>
|
||||
implements PoolObjectFactory<Type> {
|
||||
private final Class<? extends ExtensionProfile> clazz;
|
||||
|
||||
private final Constructor<? extends ExtensionProfile> constructor;
|
||||
|
||||
private static final Object[] constArray = new Object[0];
|
||||
|
||||
private BaseEntry entry;
|
||||
private BaseFeed feed;
|
||||
|
||||
ExtensionProfileFactory(Class<? extends ExtensionProfile> clazz, Class<? extends BaseEntry> entryClass, Class<? extends BaseFeed> feedClass) {
|
||||
this.clazz = clazz;
|
||||
try {
|
||||
this.constructor = clazz.getConstructor(new Class[0]);
|
||||
this.entry = entryClass.newInstance();
|
||||
this.feed = feedClass.newInstance();
|
||||
} catch (Exception e) {
|
||||
throw new IllegalArgumentException(
|
||||
"The given class has no default constructor -- can not use as a ExtensionProfile -- "
|
||||
+ this.clazz.getName(), e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.lucene.gdata.utils.PoolObjectFactory#getInstance()
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public Type getInstance() {
|
||||
|
||||
try {
|
||||
Type retValue = (Type) this.constructor.newInstance(constArray);
|
||||
this.entry.declareExtensions(retValue);
|
||||
this.feed.declareExtensions(retValue);
|
||||
return retValue;
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(
|
||||
"Can not instantiate new ExtensionProfile -- ", e);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param type -
|
||||
* the ExtensionProfile to destroy
|
||||
* @see org.apache.lucene.gdata.utils.PoolObjectFactory#destroyInstance(Object)
|
||||
*/
|
||||
public void destroyInstance(Type type) {
|
||||
//
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.lucene.gdata.server.registry.ScopeVisitor#visiteInitialize()
|
||||
*/
|
||||
public void visiteInitialize() {
|
||||
if(this.profilPool == null)
|
||||
createProfilePool();
|
||||
/*
|
||||
* don't set a extension profile for each thread. The current thread
|
||||
* might use another service and does not need the extension profile of
|
||||
* this service
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.lucene.gdata.server.registry.ScopeVisitor#visiteDestroy()
|
||||
*/
|
||||
public void visiteDestroy() {
|
||||
/*
|
||||
* Check every thread after request destroyed to release all profiles to
|
||||
* the pool
|
||||
*/
|
||||
ExtensionProfile ext = this.extProfThreadLocal.get();
|
||||
if (ext == null) {
|
||||
if(LOG.isDebugEnabled())
|
||||
LOG.debug("ThreadLocal owns no ExtensionProfile in requestDestroy for service "
|
||||
+ this.serviceName);
|
||||
return;
|
||||
}
|
||||
this.extProfThreadLocal.set(null);
|
||||
this.profilPool.release(ext);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the indexSchema.
|
||||
*/
|
||||
public IndexSchema getIndexSchema() {
|
||||
return this.indexSchema;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param indexSchema The indexSchema to set.
|
||||
*/
|
||||
public void setIndexSchema(IndexSchema indexSchema) {
|
||||
this.indexSchema = indexSchema;
|
||||
if(this.indexSchema != null)
|
||||
this.indexSchema.setName(this.serviceName);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.lucene.gdata.server.registry.ProvidedService#getTransformTemplate()
|
||||
*/
|
||||
public Templates getTransformTemplate() {
|
||||
|
||||
return this.transformerTemplate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets and creates the preview transformer xslt template to provide a html formate for feeds and entries.
|
||||
* The given file name must be available in the classpath.
|
||||
* @param filename - the name of the file in the classpath
|
||||
*/
|
||||
public void setXsltStylesheet(String filename){
|
||||
if(filename == null || filename.length() == 0){
|
||||
LOG.info("No preview stylesheet configured for service "+this.serviceName);
|
||||
return;
|
||||
}
|
||||
|
||||
TransformerFactory factory = TransformerFactory.newInstance();
|
||||
|
||||
try {
|
||||
this.transformerTemplate = factory.newTemplates(new StreamSource(ProvidedServiceConfig.class.getResourceAsStream(filename.startsWith("/")?filename:"/"+filename)));
|
||||
} catch (TransformerConfigurationException e) {
|
||||
throw new RuntimeException("Can not compile xslt stylesheet path: "+filename,e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -1,154 +0,0 @@
|
|||
/**
|
||||
* Copyright 2004 The Apache Software Foundation
|
||||
*
|
||||
* Licensed 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.server.registry;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.apache.commons.digester.Digester;
|
||||
import org.apache.lucene.gdata.search.config.IndexSchema;
|
||||
import org.apache.lucene.gdata.search.config.IndexSchemaField;
|
||||
import org.apache.lucene.gdata.server.registry.configuration.ComponentConfiguration;
|
||||
import org.apache.lucene.gdata.utils.SimpleSaxErrorHandler;
|
||||
import org.apache.xerces.parsers.SAXParser;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
/**
|
||||
* Reads the configuration file and creates the
|
||||
* {@link org.apache.lucene.gdata.server.registry.GDataServerRegistry} singleton
|
||||
* instance. All services and components will be instantiated and registered in
|
||||
* the registry.
|
||||
*
|
||||
* @author Simon Willnauer
|
||||
*
|
||||
*/
|
||||
class RegistryBuilder {
|
||||
|
||||
/**
|
||||
* builds the {@link GDataServerRegistry} accessible via the
|
||||
* {@link GDataServerRegistry#getRegistry()} method
|
||||
*
|
||||
* @throws IOException -
|
||||
* if an IOException occurs while reading the config file
|
||||
* @throws SAXException -
|
||||
* if the config file can not be parsed
|
||||
*/
|
||||
static void buildRegistry() throws IOException, SAXException {
|
||||
String schemaFile = RegistryBuilder.class.getResource("/gdata-config.xsd").getFile();
|
||||
/*
|
||||
* Force using apache xerces parser for digester
|
||||
*/
|
||||
SAXParser parser = new SAXParser();
|
||||
parser.setFeature("http://apache.org/xml/features/validation/schema-full-checking",true);
|
||||
parser.setFeature("http://apache.org/xml/features/validation/schema",true);
|
||||
parser.setFeature("http://xml.org/sax/features/validation",true);
|
||||
parser.setProperty("http://apache.org/xml/properties/schema/external-noNamespaceSchemaLocation",schemaFile);
|
||||
Digester digester = new Digester(parser);
|
||||
buildFromConfiguration(digester, GDataServerRegistry
|
||||
.getRegistry(),schemaFile);
|
||||
|
||||
}
|
||||
|
||||
private static void buildFromConfiguration(Digester digester,
|
||||
GDataServerRegistry registry, String schemaURL) throws IOException, SAXException {
|
||||
digester.setValidating(true);
|
||||
digester.setSchema(schemaURL);
|
||||
digester.setErrorHandler(new SimpleSaxErrorHandler());
|
||||
digester.push(registry);
|
||||
/*
|
||||
* register services
|
||||
*/
|
||||
digester.addObjectCreate("gdata/service", ProvidedServiceConfig.class);
|
||||
digester.addSetProperties("gdata/service");
|
||||
digester.addSetNext("gdata/service", "registerService");
|
||||
digester.addBeanPropertySetter("gdata/service/feed-class", "feedType");
|
||||
digester.addBeanPropertySetter("gdata/service/entry-class", "entryType");
|
||||
digester.addBeanPropertySetter("gdata/service/extension-profile",
|
||||
"extensionProfileClass");
|
||||
digester.addBeanPropertySetter("gdata/service/previewStyleSheet","xsltStylesheet");
|
||||
addIndexRule(digester);
|
||||
/*
|
||||
* load components and configurations
|
||||
*/
|
||||
digester.addCallMethod("gdata/server-components/component",
|
||||
"registerComponent", 2, new Class[] { Class.class , ComponentConfiguration.class});
|
||||
digester.addCallParam("gdata/server-components/component/class",0);
|
||||
digester.addObjectCreate("gdata/server-components/component/configuration",ComponentConfiguration.class);
|
||||
digester.addCallMethod("gdata/server-components/component/configuration/property","set",2,new Class[]{String.class,String.class});
|
||||
digester.addCallParam("gdata/server-components/component/configuration/property",0,"name");
|
||||
digester.addCallParam("gdata/server-components/component/configuration/property",1);
|
||||
//second parameter on registerComponent -- top of the stack (Component configuration)
|
||||
digester.addCallParam("gdata/server-components/component/configuration",1,0);
|
||||
digester.parse(RegistryBuilder.class
|
||||
.getResourceAsStream("/gdata-config.xml"));
|
||||
|
||||
}
|
||||
|
||||
|
||||
private static void addIndexRule(Digester digester){
|
||||
digester.addObjectCreate("gdata/service/index-schema", IndexSchema.class);
|
||||
digester.addSetNext("gdata/service/index-schema", "setIndexSchema");
|
||||
digester.addSetProperties("gdata/service/index-schema");
|
||||
digester.addSetProperties("gdata/service/index-schema/index");
|
||||
digester.addBeanPropertySetter("gdata/service/index-schema/index/maxMergeDocs");
|
||||
digester.addBeanPropertySetter("gdata/service/index-schema/index/maxBufferedDocs");
|
||||
digester.addBeanPropertySetter("gdata/service/index-schema/index/maxFieldLength");
|
||||
digester.addBeanPropertySetter("gdata/service/index-schema/index/mergeFactor");
|
||||
digester.addBeanPropertySetter("gdata/service/index-schema/index/indexLocation");
|
||||
digester.addBeanPropertySetter("gdata/service/index-schema/index/useCompoundFile");
|
||||
digester.addCallMethod("gdata/service/index-schema/index/defaultAnalyzer", "serviceAnalyzer",1,new Class[]{Class.class});
|
||||
|
||||
//call method on top of the stack addSchemaField
|
||||
digester.addCallMethod("gdata/service/index-schema/field","addSchemaField",1,new Class[]{IndexSchemaField.class});
|
||||
digester.addObjectCreate("gdata/service/index-schema/field",IndexSchemaField.class);
|
||||
//set parameter for method call -- parameter is IndexSchemaField
|
||||
digester.addCallParam("gdata/service/index-schema/field",0,0);
|
||||
digester.addSetProperties("gdata/service/index-schema/field");
|
||||
digester.addBeanPropertySetter("gdata/service/index-schema/field/path");
|
||||
digester.addBeanPropertySetter("gdata/service/index-schema/field/store","storeByName");
|
||||
digester.addBeanPropertySetter("gdata/service/index-schema/field/index","indexByName");
|
||||
digester.addBeanPropertySetter("gdata/service/index-schema/field/analyzer","analyzerClass");
|
||||
|
||||
// call method on top of the stack addSchemaField
|
||||
digester.addCallMethod("gdata/service/index-schema/custom","addSchemaField",1,new Class[]{IndexSchemaField.class});
|
||||
digester.addObjectCreate("gdata/service/index-schema/custom",IndexSchemaField.class);
|
||||
//set parameter for method call -- parameter is IndexSchemaField
|
||||
digester.addCallParam("gdata/service/index-schema/custom",0,0);
|
||||
digester.addSetProperties("gdata/service/index-schema/custom");
|
||||
digester.addBeanPropertySetter("gdata/service/index-schema/custom/path");
|
||||
digester.addBeanPropertySetter("gdata/service/index-schema/custom/store","storeByName");
|
||||
digester.addBeanPropertySetter("gdata/service/index-schema/custom/index","indexByName");
|
||||
digester.addBeanPropertySetter("gdata/service/index-schema/custom/analyzer","analyzerClass");
|
||||
digester.addBeanPropertySetter("gdata/service/index-schema/custom/field-class","fieldClass");
|
||||
// digester.addCallMethod("gdata/service/index-schema/custom/field-class","fieldClass",1,new Class[]{Class.class});
|
||||
|
||||
|
||||
// call method on top of the stack addSchemaField
|
||||
digester.addCallMethod("gdata/service/index-schema/mixed","addSchemaField",1,new Class[]{IndexSchemaField.class});
|
||||
digester.addObjectCreate("gdata/service/index-schema/mixed",IndexSchemaField.class);
|
||||
//set parameter for method call -- parameter is IndexSchemaField
|
||||
digester.addCallParam("gdata/service/index-schema/mixed",0,0);
|
||||
digester.addSetProperties("gdata/service/index-schema/mixed");
|
||||
digester.addBeanPropertySetter("gdata/service/index-schema/mixed","type");
|
||||
digester.addBeanPropertySetter("gdata/service/index-schema/mixed/path");
|
||||
digester.addBeanPropertySetter("gdata/service/index-schema/mixed/store","storeByName");
|
||||
digester.addBeanPropertySetter("gdata/service/index-schema/mixed/index","indexByName");
|
||||
digester.addBeanPropertySetter("gdata/service/index-schema/mixed/contenttype","typePath");
|
||||
digester.addBeanPropertySetter("gdata/service/index-schema/mixed/analyzer","analyzerClass");
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -1,90 +0,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.
|
||||
*/
|
||||
|
||||
package org.apache.lucene.gdata.server.registry;
|
||||
|
||||
import javax.servlet.ServletContextEvent;
|
||||
import javax.servlet.ServletContextListener;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
/**
|
||||
* This Listener creates the
|
||||
* {@link org.apache.lucene.gdata.server.registry.GDataServerRegistry} when the
|
||||
* context is loaded. The registry will be loaded before the
|
||||
* {@link org.apache.lucene.gdata.servlet.RequestControllerServlet} is loaded.
|
||||
* The Registry will be loaded and set up before the REST interface is available.
|
||||
* <p>
|
||||
* This ContextListener has to be configured in the <code>web.xml</code>
|
||||
* deployment descriptor.
|
||||
* </p>
|
||||
* <p>
|
||||
* When the
|
||||
* {@link javax.servlet.ServletContextListener#contextDestroyed(javax.servlet.ServletContextEvent)}
|
||||
* method is called the registry will be destroyed using
|
||||
* {@link org.apache.lucene.gdata.server.registry.GDataServerRegistry#destroy()}
|
||||
* method.
|
||||
*
|
||||
*
|
||||
* @author Simon Willnauer
|
||||
*
|
||||
*/
|
||||
public class RegistryContextListener implements ServletContextListener {
|
||||
private GDataServerRegistry serverRegistry;
|
||||
|
||||
private static final Log LOG = LogFactory
|
||||
.getLog(RegistryContextListener.class);
|
||||
|
||||
/**
|
||||
* @see javax.servlet.ServletContextListener#contextInitialized(javax.servlet.ServletContextEvent)
|
||||
*/
|
||||
public void contextInitialized(ServletContextEvent arg0) {
|
||||
LOG.info("RegistryContextListener has been loaded");
|
||||
|
||||
try {
|
||||
RegistryBuilder.buildRegistry();
|
||||
this.serverRegistry = GDataServerRegistry.getRegistry();
|
||||
/*
|
||||
* catch all exceptions and destroy the registry to release all resources.
|
||||
* some components start lots of threads, the will remain running if the registry is not destroyed
|
||||
*/
|
||||
} catch (Throwable e) {
|
||||
GDataServerRegistry.getRegistry().destroy();
|
||||
LOG.error("can not register required components", e);
|
||||
throw new RuntimeException("Can not register required components",
|
||||
e);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @see javax.servlet.ServletContextListener#contextDestroyed(javax.servlet.ServletContextEvent)
|
||||
*/
|
||||
public void contextDestroyed(ServletContextEvent arg0) {
|
||||
LOG.info("Destroying context");
|
||||
/*
|
||||
* this might be null if startup fails
|
||||
* --> prevent null pointer exception
|
||||
*/
|
||||
if(this.serverRegistry != null)
|
||||
this.serverRegistry.destroy();
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -1,68 +0,0 @@
|
|||
package org.apache.lucene.gdata.server.registry;
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* This exception is thrown by the
|
||||
* {@link org.apache.lucene.gdata.server.registry.GDataServerRegistry} if
|
||||
* registering a service or a component fails.
|
||||
*
|
||||
* @author Simon Willnauer
|
||||
*
|
||||
*/
|
||||
public class RegistryException extends Exception {
|
||||
|
||||
|
||||
private static final long serialVersionUID = -3563720639871194466L;
|
||||
|
||||
/**
|
||||
* Constructs a new Registry Exception.
|
||||
*/
|
||||
public RegistryException() {
|
||||
super();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new Registry Exception with the specified detail message.
|
||||
* @param arg0 - detail message
|
||||
*/
|
||||
public RegistryException(String arg0) {
|
||||
super(arg0);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new Registry Exception with the specified detail message and nested exception.
|
||||
* @param arg0 - detail message
|
||||
* @param arg1 - nested exception
|
||||
*/
|
||||
public RegistryException(String arg0, Throwable arg1) {
|
||||
super(arg0, arg1);
|
||||
|
||||
}
|
||||
|
||||
/** Constructs a new Registry Exception with a nested exception.
|
||||
* @param arg0 - nested exception
|
||||
*/
|
||||
public RegistryException(Throwable arg0) {
|
||||
super(arg0);
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -1,64 +0,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.
|
||||
*/
|
||||
|
||||
package org.apache.lucene.gdata.server.registry;
|
||||
|
||||
import static java.lang.annotation.ElementType.TYPE;
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* The Scope annotation is used in
|
||||
* {@link org.apache.lucene.gdata.server.registry.ScopeVisitable} and
|
||||
* {@link org.apache.lucene.gdata.server.registry.ScopeVisitor} implementations
|
||||
* to indicate which scope should be visited.
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
@Target( { TYPE })
|
||||
@Retention(value = RUNTIME)
|
||||
public @interface Scope {
|
||||
/**
|
||||
* @return - the scope type the class was annotated with
|
||||
*/
|
||||
ScopeType scope();
|
||||
|
||||
/**
|
||||
* Defines a Scope for {@link Scope} annotations
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
public static enum ScopeType {
|
||||
/**
|
||||
* Request scope
|
||||
*/
|
||||
REQUEST,
|
||||
/**
|
||||
* Session scope
|
||||
*/
|
||||
SESSION,
|
||||
/**
|
||||
* Context scope
|
||||
*/
|
||||
CONTEXT
|
||||
|
||||
}
|
||||
}
|
|
@ -1,34 +0,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.
|
||||
*/
|
||||
|
||||
package org.apache.lucene.gdata.server.registry;
|
||||
|
||||
/**
|
||||
* Implementation of this interface accept
|
||||
* {@link org.apache.lucene.gdata.server.registry.ScopeVisitor} objects and call
|
||||
* their methods on the desired action.
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
public interface ScopeVisitable {
|
||||
/**
|
||||
* @param visitor -
|
||||
* the visitor to accept
|
||||
*/
|
||||
public abstract void accept(ScopeVisitor visitor);
|
||||
}
|
|
@ -1,56 +0,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.
|
||||
*/
|
||||
|
||||
package org.apache.lucene.gdata.server.registry;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* <code>ScopeVisitor</code> is used to implement the <code>Visitor</code>
|
||||
* pattern in GDATAServer. An object of this interface can be passed to a
|
||||
* <code>ScopeVistable</code> which will then call its methods. <br/>
|
||||
* {@link org.apache.lucene.gdata.server.registry.Component} Classes registered
|
||||
* in the {@link org.apache.lucene.gdata.server.registry.GDataServerRegistry}
|
||||
* will be added to the Visitableimplementation automatically. Please refer to
|
||||
* the <i>Gang of Four </i> book of Design Patterns for more details on the
|
||||
* <code>Visitor</code> pattern.
|
||||
* </p>
|
||||
* <p>
|
||||
* A scope can be Session, Request or Context if one of the ScopeVisitors for
|
||||
* the desired scope is available by the registry.
|
||||
* </p>
|
||||
* <p>
|
||||
* This <a href="http://www.patterndepot.com/put/8/JavaPatterns.htm">site </a>
|
||||
* has further discussion on design patterns and links to the GOF book. This <a
|
||||
* href="http://www.patterndepot.com/put/8/visitor.pdf">link </a> describes the
|
||||
* Visitor pattern in detail.
|
||||
* </p>
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
public interface ScopeVisitor {
|
||||
/**
|
||||
* Visites the initialization of the scope
|
||||
*/
|
||||
public abstract void visiteInitialize();
|
||||
|
||||
/**
|
||||
* Visites the destory of the scope
|
||||
*
|
||||
*/
|
||||
public abstract void visiteDestroy();
|
||||
}
|
|
@ -1,44 +0,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.
|
||||
*/
|
||||
|
||||
package org.apache.lucene.gdata.server.registry;
|
||||
|
||||
/**
|
||||
* To Register a class as a component in the
|
||||
* {@link org.apache.lucene.gdata.server.registry.GDataServerRegistry} the class
|
||||
* or a super class must implements this interface.
|
||||
* <p>
|
||||
* <tt>ServerComponent</tt> defines a method <tt>initialize</tt> and
|
||||
* <tt>destroy</tt>. <tt>initialize</tt> will be called when the component
|
||||
* is registered and <tt>destroy</tt> when the registry is destroyed (usually
|
||||
* at server shut down).</p>
|
||||
* @see org.apache.lucene.gdata.server.registry.GDataServerRegistry
|
||||
* @author Simon Willnauer
|
||||
*
|
||||
*/
|
||||
public interface ServerComponent {
|
||||
/**
|
||||
* will be call when the component is registered.
|
||||
* if this fails the server must not startup.
|
||||
*/
|
||||
public abstract void initialize();
|
||||
|
||||
/**
|
||||
* will be called when the registry is going down e.g. when the {@link GDataServerRegistry#destroy()} method is called.
|
||||
*/
|
||||
public abstract void destroy();
|
||||
}
|
|
@ -1,45 +0,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.
|
||||
*/
|
||||
|
||||
package org.apache.lucene.gdata.server.registry;
|
||||
|
||||
import static java.lang.annotation.ElementType.FIELD;
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* This Annotation is use to annotate
|
||||
* {@link org.apache.lucene.gdata.server.registry.ComponentType} elements to
|
||||
* specify an interface e.g. super type of a defined component.
|
||||
* <p>This annotation will be visible at runtime</p>
|
||||
* @see org.apache.lucene.gdata.server.registry.Component
|
||||
* @see org.apache.lucene.gdata.server.registry.GDataServerRegistry
|
||||
*
|
||||
* @author Simon Willnauer
|
||||
*
|
||||
*/
|
||||
@Target( { FIELD })
|
||||
@Retention(value = RUNTIME)
|
||||
public @interface SuperType {
|
||||
/**
|
||||
*
|
||||
* @return the specified super type
|
||||
*/
|
||||
Class superType();
|
||||
}
|
|
@ -1,80 +0,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.
|
||||
*/
|
||||
|
||||
package org.apache.lucene.gdata.server.registry.configuration;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Simple configuration class storing properties as key with defined property
|
||||
* values as values in a <code>Map<String,String></code>. As a map cannot
|
||||
* contain duplicate keys the first use of a key can not be replaced. If a key
|
||||
* is used twice a {@link java.lang.IllegalArgumentException} will be thrown.
|
||||
* @see Map
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class ComponentConfiguration {
|
||||
private final Map<String, String> configMap;
|
||||
|
||||
/**
|
||||
* Creates a new ComponentConfiguration object and initializes the internal
|
||||
* map.
|
||||
*/
|
||||
public ComponentConfiguration() {
|
||||
super();
|
||||
this.configMap = new HashMap<String, String>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores a key / value pair as a property. If a key is used twice the first
|
||||
* call will set the key / value pair. Any subsequent calls with a already
|
||||
* set key will throw a IllegalArgumentException.
|
||||
*
|
||||
* @param key -
|
||||
* the property as a key
|
||||
* @param value -
|
||||
* the value for the key
|
||||
*@see Map#put(Object, Object)
|
||||
*/
|
||||
public void set(final String key, final String value) {
|
||||
if (this.configMap.containsKey(key))
|
||||
throw new IllegalArgumentException("key has already been used");
|
||||
this.configMap.put(key, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value of the key or <code>null</code> if the key is not set.
|
||||
* @param key - the key
|
||||
* @return - the value for the key or <code>null</code> if the key is not set.
|
||||
* @see Map#get(java.lang.Object)
|
||||
*/
|
||||
public String get(final String key) {
|
||||
return this.configMap.get(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param key - a string key
|
||||
* @return - <code>true</code> if the key is set, otherwise <code>false</code>
|
||||
* @see Map#containsKey(java.lang.Object)
|
||||
*/
|
||||
public boolean contains(String key) {
|
||||
return this.configMap.containsKey(key);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,78 +0,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.
|
||||
*/
|
||||
|
||||
package org.apache.lucene.gdata.server.registry.configuration;
|
||||
|
||||
/**
|
||||
* Will be throw if an exception occures while injecting properties, a type or
|
||||
* cast exception occures or a
|
||||
* {@link org.apache.lucene.gdata.server.registry.configuration.Requiered}
|
||||
* property is not available.
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class InjectionException extends RuntimeException {
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = 3559845601111510210L;
|
||||
|
||||
/**
|
||||
* Constructs a new InjectionException
|
||||
*/
|
||||
public InjectionException() {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new InjectionException
|
||||
*
|
||||
* @param message -
|
||||
* the exception message
|
||||
*/
|
||||
public InjectionException(String message) {
|
||||
super(message);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new InjectionException
|
||||
*
|
||||
* @param message -
|
||||
* the exception message
|
||||
* @param cause -
|
||||
* the root cause of this exception
|
||||
*/
|
||||
public InjectionException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new InjectionException
|
||||
*
|
||||
* @param cause -
|
||||
* the root cause of this exception
|
||||
*/
|
||||
public InjectionException(Throwable cause) {
|
||||
super(cause);
|
||||
|
||||
}
|
||||
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue