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:
Michael Busch 2007-11-20 00:46:27 +00:00
parent e395be3faf
commit b04703fe8f
348 changed files with 6 additions and 47556 deletions

View File

@ -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 =======================

View File

@ -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*"/>

View File

@ -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 @@

View File

@ -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)

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -1,2 +0,0 @@
AnyObjectId[b1b89c9c921f16af22a88db3ff28975a8e40d886] was removed in git history.
Apache SVN contains full history.

View File

@ -1,2 +0,0 @@
AnyObjectId[75580be255065727b20b41c2d338b14792bb35cd] was removed in git history.
Apache SVN contains full history.

View File

@ -1,2 +0,0 @@
AnyObjectId[1783dbea232ced6db122268f8faa5ce773c7ea42] was removed in git history.
Apache SVN contains full history.

View File

@ -1,2 +0,0 @@
AnyObjectId[2ff9bbd90d63f92cdffea944869ed9bea7ead49c] was removed in git history.
Apache SVN contains full history.

View File

@ -1,2 +0,0 @@
AnyObjectId[311a546765c97a9bc9e60f4c56da07f1246ab3da] was removed in git history.
Apache SVN contains full history.

View File

@ -1,2 +0,0 @@
AnyObjectId[dde9972109dd25f14f732052984b0d3719b17795] was removed in git history.
Apache SVN contains full history.

View File

@ -1,2 +0,0 @@
AnyObjectId[ebd5b4b2a7a1d8b67c1717b364fb9affb35dca1e] was removed in git history.
Apache SVN contains full history.

View File

@ -1,2 +0,0 @@
AnyObjectId[018d6effad3823d0ea59f1b58ab154fc2652f418] was removed in git history.
Apache SVN contains full history.

View File

@ -1,2 +0,0 @@
AnyObjectId[33990e8a1fdf24e15701e4cf8d9f091038394ecd] was removed in git history.
Apache SVN contains full history.

View File

@ -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>

View File

@ -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
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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>

View File

@ -1 +0,0 @@
<html><body>Top-level package.</body></html>

View File

@ -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();
}

View File

@ -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);
}

View File

@ -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();
}
}
}

View File

@ -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);
}
}
}

View File

@ -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);
}
}

View File

@ -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>&lt;category scheme="http://www.example.com/type" term="blog.post"/&gt;<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]);
}
}

View File

@ -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());
}
}

View File

@ -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();
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}
}

View File

@ -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);
}
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}
}

View File

@ -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);
}
}

View File

@ -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>

View File

@ -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;
}
}

View File

@ -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);
}
}

View File

@ -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>

View File

@ -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();
}
}

View File

@ -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);
}
}

View File

@ -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;
}
}
}

View File

@ -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);
}
}

View File

@ -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
}

View File

@ -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;
}
}
}

View File

@ -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();
}

View File

@ -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;
}

View File

@ -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;
}
}

View File

@ -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);
}

View File

@ -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();
}
}

View File

@ -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 {
}
}
}

View File

@ -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();
}
}
}

View File

@ -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);
}
}

View File

@ -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;
}
}

View File

@ -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>

View File

@ -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>

View File

@ -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());
}
}

View File

@ -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()
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}
}
}

View File

@ -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;
}
}

View File

@ -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);
}
}

View File

@ -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;
}

View File

@ -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;
}
}

View File

@ -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() {
//
}
}

View File

@ -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;
}
}

View File

@ -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;
}

View File

@ -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);
}
}
}

View File

@ -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>

View File

@ -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);
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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() {
//
}
}

View File

@ -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);
}

View File

@ -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>

View File

@ -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>

View File

@ -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();
}

View File

@ -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
}

View File

@ -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);
}

View File

@ -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);
}
}

View File

@ -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());
}
}
}

View File

@ -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();
}
}

View File

@ -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();
}

View File

@ -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);
}
}
}

View File

@ -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");
}
}

View File

@ -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();
}
}

View File

@ -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);
}
}

View File

@ -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
}
}

View File

@ -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);
}

View File

@ -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();
}

View File

@ -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();
}

View File

@ -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();
}

View File

@ -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);
}
}

View File

@ -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