mirror of https://github.com/apache/lucene.git
gdata dev update from Simon 2006-06-06
git-svn-id: https://svn.apache.org/repos/asf/lucene/java/trunk@417265 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
6e86efb527
commit
4707eea96c
|
@ -16,7 +16,11 @@
|
|||
<pathelement location="lib/gdata-client-1.0.jar" />
|
||||
<pathelement location="lib/commons-logging-1.1.jar" />
|
||||
<pathelement location="lib/commons-jxpath-1.2.jar" />
|
||||
<pathelement location="lib/je.jar" />
|
||||
<pathelement location="lib/commons-digester-1.7.jar" />
|
||||
<pathelement location="lib/commons-beanutils.jar" />
|
||||
<pathelement location="lib/commons-collections-3.2.jar" />
|
||||
|
||||
|
||||
|
||||
|
||||
</path>
|
||||
|
@ -36,12 +40,16 @@
|
|||
<target name="war-gdata" depends="prepare-dist">
|
||||
<echo>Distributing GData War </echo>
|
||||
<war destfile="${dist.dir}/${gdata.war.name}.war"
|
||||
webxml="webroot/WEB-INF/web.xml">
|
||||
<fileset dir="webroot" excludes="WEB-INF/web.xml"/>
|
||||
webxml="webroot/WEB-INF/web.xml" >
|
||||
<metainf dir="webroot/meta-inf"/>
|
||||
|
||||
|
||||
<fileset dir="webroot" excludes="WEB-INF/web.xml"/>
|
||||
<lib dir="${gdata.lib.dir}" includes="commons-logging-1.1.jar"/>
|
||||
<lib dir="${gdata.lib.dir}" includes="gdata-client-1.0.jar"/>
|
||||
|
||||
<lib dir="${gdata.lib.dir}" includes="commons-digester-1.7.jar" />
|
||||
<lib dir="${gdata.lib.dir}" includes="commons-beanutils.jar" />
|
||||
<lib dir="${gdata.lib.dir}" includes="commons-collections-3.2.jar" />
|
||||
<lib dir="${build.dir}" includes="${final.name}.jar"/>
|
||||
<lib file="${lucene.jar}" />
|
||||
</war>
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
AnyObjectId[b1b89c9c921f16af22a88db3ff28975a8e40d886] was removed in git history.
|
||||
Apache SVN contains full history.
|
|
@ -0,0 +1,2 @@
|
|||
AnyObjectId[75580be255065727b20b41c2d338b14792bb35cd] was removed in git history.
|
||||
Apache SVN contains full history.
|
|
@ -0,0 +1,2 @@
|
|||
AnyObjectId[1783dbea232ced6db122268f8faa5ce773c7ea42] was removed in git history.
|
||||
Apache SVN contains full history.
|
|
@ -1,11 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
|
||||
<properties>
|
||||
<comment>Lucene Storage Properties</comment>
|
||||
<entry key="gdata.server.storage.lucene.buffersize">20</entry>
|
||||
<entry key="gdata.server.storage.lucene.optimizeInterval">20</entry>
|
||||
<entry key="gdata.server.storage.lucene.persistFactor">20</entry>
|
||||
<entry key="gdata.server.storage.lucene.directory">/tmp/storage/</entry>
|
||||
<entry key="gdata.server.storage.lucene.recover">true</entry>
|
||||
<entry key="gdata.server.storage.lucene.recover.keepFiles">false</entry>
|
||||
</properties>
|
|
@ -18,13 +18,10 @@ package org.apache.lucene.gdata.server;
|
|||
import java.io.IOException;
|
||||
import java.io.Reader;
|
||||
|
||||
import org.apache.lucene.gdata.server.registry.DataBuilderException;
|
||||
import org.apache.lucene.gdata.server.registry.FeedInstanceConfigurator;
|
||||
import org.apache.lucene.gdata.server.registry.GDataServerRegistry;
|
||||
import org.apache.lucene.gdata.server.registry.ProvidedService;
|
||||
|
||||
import com.google.gdata.data.BaseEntry;
|
||||
import com.google.gdata.data.BaseFeed;
|
||||
import com.google.gdata.data.ExtensionProfile;
|
||||
import com.google.gdata.util.ParseException;
|
||||
|
||||
/**
|
||||
|
@ -36,15 +33,17 @@ import com.google.gdata.util.ParseException;
|
|||
* 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.
|
||||
* {@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 {
|
||||
private static final GDataServerRegistry REGISTRY = GDataServerRegistry.getRegistry(); // TODO find another way for getting the registered feeds
|
||||
|
||||
/**
|
||||
* Builds a {@link BaseFeed} instance from the {@link Reader} provided by
|
||||
|
@ -53,51 +52,42 @@ public class GDataEntityBuilder {
|
|||
* @param request -
|
||||
* the request to build the instance from
|
||||
* @return - a BaseFeed instance
|
||||
* @throws FeedNotFoundException -
|
||||
* if the feed is not registered
|
||||
*
|
||||
* @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 FeedNotFoundException, IOException, ParseException {
|
||||
throws IOException, ParseException {
|
||||
if (request == null)
|
||||
throw new IllegalArgumentException("request must not be null");
|
||||
return buildFeed(request.getFeedId(), request.getReader(),request.getExtensionProfile());
|
||||
ProvidedService config = request.getConfigurator();
|
||||
return buildFeed(request.getReader(), config);
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a {@link BaseFeed} from the provided {@link Reader}
|
||||
*
|
||||
* @param feedId -
|
||||
* the feed ID to request the feed type from the registry
|
||||
*
|
||||
* @param reader -
|
||||
* the reader to build the feed from
|
||||
* @param profile - extension profile to parse the resource
|
||||
* @param config -
|
||||
* the feed instance config containing the extension profile to
|
||||
* parse the resource
|
||||
* @return - a BaseFeed instance
|
||||
* @throws FeedNotFoundException -
|
||||
* if the feed is not registered
|
||||
*
|
||||
* @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 String feedId, final Reader reader,final ExtensionProfile profile)
|
||||
throws FeedNotFoundException, ParseException, IOException {
|
||||
public static BaseFeed buildFeed(final Reader reader,
|
||||
final ProvidedService config) throws ParseException, IOException {
|
||||
|
||||
BaseFeed retVal = null;
|
||||
try {
|
||||
retVal = (BaseFeed) createEntityInstance(feedId);
|
||||
} catch (FeedNotFoundException e) {
|
||||
throw e;
|
||||
} catch (Exception e) {
|
||||
DataBuilderException ex = new DataBuilderException(
|
||||
"Could not build Feed for Feed class ", e);
|
||||
ex.setStackTrace(e.getStackTrace());
|
||||
throw ex;
|
||||
}
|
||||
retVal.parseAtom(profile, reader);
|
||||
retVal = createEntityInstance(config);
|
||||
retVal.parseAtom(config.getExtensionProfile(), reader);
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
@ -109,63 +99,73 @@ public class GDataEntityBuilder {
|
|||
* @param request -
|
||||
* the request to build the instance from
|
||||
* @return - a BaseEntry instance
|
||||
* @throws FeedNotFoundException -
|
||||
* if the feed, requested by the client is not registered
|
||||
*
|
||||
* @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 FeedNotFoundException, IOException, ParseException {
|
||||
throws IOException, ParseException {
|
||||
if (request == null)
|
||||
throw new IllegalArgumentException("request must not be null");
|
||||
return buildEntry(request.getFeedId(), request.getReader(),request.getExtensionProfile());
|
||||
ProvidedService config = request.getConfigurator();
|
||||
return buildEntry(request.getReader(), config);
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a {@link BaseFeed} instance from the {@link Reader} provided by
|
||||
* the {@link GDataRequest}
|
||||
* @param feedId -
|
||||
* the feed ID to request the feed type from the registry
|
||||
*
|
||||
* @param reader -
|
||||
* the reader to build the feed from
|
||||
* @param profile - extension profile to parse the resource
|
||||
* @param config -
|
||||
* the instance config containing the extension profile to parse
|
||||
* the resource
|
||||
* @return - a BaseFeed instance
|
||||
* @throws FeedNotFoundException -
|
||||
* if the feed is not registered
|
||||
*
|
||||
* @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 String feedId, final Reader reader,final ExtensionProfile profile)
|
||||
throws FeedNotFoundException, ParseException, IOException {
|
||||
public static BaseEntry buildEntry(final Reader reader,
|
||||
final ProvidedService config) throws ParseException, IOException {
|
||||
|
||||
BaseEntry retVal = null;
|
||||
try {
|
||||
retVal = ((BaseFeed) createEntityInstance(feedId)).createEntry();
|
||||
} catch (FeedNotFoundException e) {
|
||||
throw e;
|
||||
} catch (Exception e) {
|
||||
DataBuilderException ex = new DataBuilderException(
|
||||
"Could not build Entry for Entry class ", e);
|
||||
ex.setStackTrace(e.getStackTrace());
|
||||
throw ex;
|
||||
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);
|
||||
}
|
||||
retVal.parseAtom(new ExtensionProfile(), reader);
|
||||
return retVal;
|
||||
}
|
||||
static class EntityBuilderException extends RuntimeException{
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = 7224011324202237951L;
|
||||
|
||||
EntityBuilderException(String arg0) {
|
||||
super(arg0);
|
||||
|
||||
private static Object createEntityInstance(String feedId)
|
||||
throws FeedNotFoundException, InstantiationException,
|
||||
IllegalAccessException {
|
||||
FeedInstanceConfigurator config = REGISTRY.getFeedConfigurator(feedId);
|
||||
if (config == null)
|
||||
throw new FeedNotFoundException(
|
||||
"No feed for requested feed ID found - " + feedId);
|
||||
Class feedClass = config.getFeedType();
|
||||
return feedClass.newInstance();
|
||||
}
|
||||
|
||||
EntityBuilderException(String arg0, Throwable arg1) {
|
||||
super(arg0, arg1);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,13 +22,17 @@ 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.server.authentication.AuthenticationController;
|
||||
import org.apache.lucene.gdata.server.registry.ComponentType;
|
||||
import org.apache.lucene.gdata.server.registry.ProvidedService;
|
||||
import org.apache.lucene.gdata.server.registry.GDataServerRegistry;
|
||||
|
||||
import com.google.gdata.data.ExtensionProfile;
|
||||
import org.apache.lucene.gdata.storage.Storage;
|
||||
import org.apache.lucene.gdata.storage.StorageController;
|
||||
|
||||
/**
|
||||
* The GDataRequest Class wraps the incoming HttpServletRequest. Needed
|
||||
|
@ -68,6 +72,10 @@ public class GDataRequest {
|
|||
@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";
|
||||
|
||||
// Atom is the default resopnse format
|
||||
private OutputFormat responseFormat = OutputFormat.ATOM;
|
||||
|
||||
|
@ -77,7 +85,7 @@ public class GDataRequest {
|
|||
|
||||
private String entryId = null;
|
||||
|
||||
private ExtensionProfile extensionProfile= null;
|
||||
private ProvidedService configurator = null;
|
||||
|
||||
private String entryVersion = null;
|
||||
|
||||
|
@ -112,12 +120,31 @@ public class GDataRequest {
|
|||
public void initializeRequest() throws GDataRequestException {
|
||||
generateIdentificationProperties();
|
||||
setOutputFormat();
|
||||
// TODO remove this dependency
|
||||
StorageController controller = GDataServerRegistry.getRegistry()
|
||||
.lookup(StorageController.class,
|
||||
ComponentType.STORAGECONTROLLER);
|
||||
try {
|
||||
|
||||
Storage storage = controller.getStorage();
|
||||
|
||||
String service = storage.getServiceForFeed(this.feedId);
|
||||
/*
|
||||
* ExtensionProfile is used for building the Entry / Feed Instances from an inputstream or reader
|
||||
* ExtensionProfile and the type is used for building the Entry /
|
||||
* Feed Instances from an inputstream or reader
|
||||
*
|
||||
*/
|
||||
this.extensionProfile = GDataServerRegistry.getRegistry().getExtensionProfile(this.feedId);
|
||||
if(this.extensionProfile == null)
|
||||
throw new GDataRequestException("feed is not registered or extension profile could not be created");
|
||||
this.configurator = GDataServerRegistry.getRegistry()
|
||||
.getProvidedService(service);
|
||||
if (this.configurator == null)
|
||||
throw new GDataRequestException(
|
||||
"feed is not registered or extension profile could not be created");
|
||||
|
||||
} catch (Exception e) {
|
||||
throw new GDataRequestException(
|
||||
"feed is not registered or extension profile could not be created");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -231,6 +258,7 @@ public class GDataRequest {
|
|||
LOG.warn("Intems per page could not be parsed - " + e.getMessage(),
|
||||
e);
|
||||
}
|
||||
|
||||
return retval < 0 ? DEFAULT_ITEMS_PER_PAGE : retval;
|
||||
}
|
||||
|
||||
|
@ -263,7 +291,7 @@ public class GDataRequest {
|
|||
public String getSelfId() {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append(buildRequestIDString(false));
|
||||
|
||||
builder.append("?");
|
||||
builder.append(getQueryString());
|
||||
|
||||
return builder.toString();
|
||||
|
@ -275,42 +303,48 @@ public class GDataRequest {
|
|||
* @return the id of the next page
|
||||
*/
|
||||
public String getNextId() {
|
||||
// StringBuilder builder = new StringBuilder();
|
||||
// builder.append(buildRequestIDString());
|
||||
//
|
||||
// builder.append(getQueryString());
|
||||
//
|
||||
// if(this.request.getParameter(START_INDEX_NEXT_PAGE_PARAMETER)==
|
||||
// null){
|
||||
// builder.append("&").append(START_INDEX_NEXT_PAGE_PARAMETER).append("=");
|
||||
// builder.append(DEFAULT_ITEMS_PER_PAGE+1);
|
||||
// }
|
||||
// else{
|
||||
//
|
||||
// int next = 0;
|
||||
// try{
|
||||
// next =
|
||||
// Integer.parseInt(this.request.getParameter(START_INDEX_NEXT_PAGE_PARAMETER));
|
||||
// }catch (Exception e) {
|
||||
// //
|
||||
// }
|
||||
//
|
||||
// if(next < 0)
|
||||
// builder.append(DEFAULT_ITEMS_PER_PAGE+1);
|
||||
// else
|
||||
// builder.append(next+DEFAULT_ITEMS_PER_PAGE);
|
||||
// int pos = builder.indexOf(START_INDEX_NEXT_PAGE_PARAMETER);
|
||||
// boolean end = builder.lastIndexOf("&",pos) < pos;
|
||||
// builder.replace(pos+START_INDEX_NEXT_PAGE_PARAMETER.length()+1,pos+START_INDEX_NEXT_PAGE_PARAMETER.length()+3,""+next);
|
||||
//
|
||||
//
|
||||
// System.out.println(end);
|
||||
// }
|
||||
//
|
||||
//
|
||||
//
|
||||
// return builder.toString();
|
||||
return buildRequestIDString(false);
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append(buildRequestIDString(false));
|
||||
builder.append("?");
|
||||
|
||||
Enumeration parameters = this.request.getParameterNames();
|
||||
while (parameters.hasMoreElements()) {
|
||||
String element = (String) parameters.nextElement();
|
||||
String[] values = this.request.getParameterValues(element);
|
||||
for (int i = 0; i < values.length; i++) {
|
||||
|
||||
builder.append(element).append("=");
|
||||
if (element.equals(START_INDEX_NEXT_PAGE_PARAMETER)) {
|
||||
int tempVal = DEFAULT_START_INDEX;
|
||||
try {
|
||||
tempVal = Integer.parseInt(values[i]);
|
||||
} catch (Exception e) {
|
||||
LOG.info("Can not parse StartIndex -- use defaut");
|
||||
}
|
||||
builder.append(tempVal + getItemsPerPage());
|
||||
break;
|
||||
}
|
||||
|
||||
builder.append(values[i]);
|
||||
|
||||
}
|
||||
if (parameters.hasMoreElements())
|
||||
builder.append("&");
|
||||
|
||||
}
|
||||
if (this.request.getParameter(ITEMS_PER_PAGE_PARAMETER) == null) {
|
||||
if (builder.charAt(builder.length() - 1) != '?')
|
||||
builder.append('&');
|
||||
builder.append(ITEMS_PER_PAGE_PARAMETER).append("=").append(
|
||||
DEFAULT_ITEMS_PER_PAGE);
|
||||
}
|
||||
if (this.request.getParameter(START_INDEX_NEXT_PAGE_PARAMETER) == null) {
|
||||
builder.append('&');
|
||||
builder.append(START_INDEX_NEXT_PAGE_PARAMETER).append("=");
|
||||
builder.append(DEFAULT_ITEMS_PER_PAGE + 1);
|
||||
}
|
||||
|
||||
return builder.toString();
|
||||
|
||||
}
|
||||
|
||||
|
@ -340,9 +374,9 @@ public class GDataRequest {
|
|||
|
||||
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);
|
||||
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;
|
||||
|
||||
|
@ -412,31 +446,92 @@ public class GDataRequest {
|
|||
}
|
||||
|
||||
/**
|
||||
* If the reuquest is a {@link GDataRequestType#GET} request and there is
|
||||
* no entry id specified, the requested resource is a feed.
|
||||
* If the reuquest 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
|
||||
* @return - <code>true</code> if an only if the requested resource is a
|
||||
* feed
|
||||
*/
|
||||
public boolean isFeedRequested() {
|
||||
|
||||
return (this.type.equals(GDataRequestType.GET) && (this.entryId == null|| this.entryId.length() == 0|| (this.entryId.equals('/'))));
|
||||
return (this.type.equals(GDataRequestType.GET) && (this.entryId == null
|
||||
|| this.entryId.length() == 0 || (this.entryId.equals('/'))));
|
||||
}
|
||||
|
||||
/**
|
||||
* * If the reuquest 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
|
||||
* @return - <code>true</code> if an only if the requested resource is an
|
||||
* entry
|
||||
*/
|
||||
public boolean isEntryRequested() {
|
||||
return !this.isFeedRequested();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return - the extensionProfile for the requested resource
|
||||
* @return the configuration for this request
|
||||
*/
|
||||
public ExtensionProfile getExtensionProfile() {
|
||||
return this.extensionProfile;
|
||||
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 underlaying HttpServletRequest.
|
||||
*/
|
||||
public Cookie[] getCookies() {
|
||||
return this.request.getCookies();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return - the cookie set instead of the authentication token or
|
||||
* <code>null</code> if not 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 underlaying HttpServletRequest
|
||||
*/
|
||||
public HttpServletRequest getHttpServletRequest() {
|
||||
|
||||
return this.request;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,13 +18,16 @@ package org.apache.lucene.gdata.server;
|
|||
|
||||
import java.io.IOException;
|
||||
import java.io.Writer;
|
||||
import java.util.Date;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.apache.lucene.gdata.server.GDataRequest.OutputFormat;
|
||||
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;
|
||||
|
@ -50,6 +53,13 @@ import com.google.gdata.util.common.xml.XmlWriter.Namespace;
|
|||
* {@link org.apache.lucene.gdata.server.GDataResponse#sendResponse(BaseEntry, ExtensionProfile)}
|
||||
* 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>
|
||||
*
|
||||
*
|
||||
*
|
||||
|
@ -68,11 +78,17 @@ public class GDataResponse {
|
|||
|
||||
private final HttpServletResponse response;
|
||||
|
||||
protected static final String XMLMIME_ATOM = "text/xml";
|
||||
|
||||
protected static final String XMLMIME_RSS = "text/xml";
|
||||
|
||||
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 static final String HEADER_LASTMODIFIED = "Last-Modified";
|
||||
|
||||
/**
|
||||
* Creates a new GDataResponse
|
||||
*
|
||||
|
@ -83,7 +99,7 @@ public class GDataResponse {
|
|||
if (response == null)
|
||||
throw new IllegalArgumentException("response must not be null");
|
||||
this.response = response;
|
||||
this.response.setContentType("text/xml");
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -96,14 +112,18 @@ public class GDataResponse {
|
|||
this.isError = true;
|
||||
this.error = errorCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the status of the underlaying response
|
||||
*
|
||||
* @see HttpServletResponse
|
||||
* @param responseCode - the status of the response
|
||||
* @param responseCode -
|
||||
* the status of the response
|
||||
*/
|
||||
public void setResponseCode(int responseCode){
|
||||
public void setResponseCode(int responseCode) {
|
||||
this.response.setStatus(responseCode);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method sends the specified error to the user if set
|
||||
*
|
||||
|
@ -113,6 +133,7 @@ public class GDataResponse {
|
|||
public void sendError() throws IOException {
|
||||
if (this.isError)
|
||||
this.response.sendError(this.error);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -141,22 +162,31 @@ public class GDataResponse {
|
|||
throws IOException {
|
||||
if (feed == null)
|
||||
throw new IllegalArgumentException("feed must not be null");
|
||||
if(profile == null)
|
||||
throw new IllegalArgumentException("extension profil must not be null");
|
||||
if (profile == null)
|
||||
throw new IllegalArgumentException(
|
||||
"extension profil must not be null");
|
||||
DateTime time = feed.getUpdated();
|
||||
if (time != null)
|
||||
setLastModifiedHeader(time.getValue());
|
||||
XmlWriter writer = createWriter();
|
||||
|
||||
if (this.outputFormat.equals(OutputFormat.ATOM))
|
||||
if (this.outputFormat.equals(OutputFormat.ATOM)) {
|
||||
this.response.setContentType(XMLMIME_ATOM);
|
||||
feed.generateAtom(writer, profile);
|
||||
else
|
||||
} else {
|
||||
this.response.setContentType(XMLMIME_RSS);
|
||||
feed.generateRss(writer, profile);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Sends a response for an update, insert or delete request. This method
|
||||
* must not invoked in a case of an error performing the requeste action.
|
||||
* If the specified response format is ATOM the default namespace will be set to ATOM.
|
||||
* must not invoked in a case of an error performing the requeste 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 profile -
|
||||
|
@ -169,8 +199,12 @@ public class GDataResponse {
|
|||
throws IOException {
|
||||
if (entry == null)
|
||||
throw new IllegalArgumentException("entry must not be null");
|
||||
if(profile == null)
|
||||
throw new IllegalArgumentException("extension profil must not be null");
|
||||
if (profile == null)
|
||||
throw new IllegalArgumentException(
|
||||
"extension profil must not be null");
|
||||
DateTime time = entry.getUpdated();
|
||||
if (time != null)
|
||||
setLastModifiedHeader(time.getValue());
|
||||
XmlWriter writer = createWriter();
|
||||
if (this.outputFormat.equals(OutputFormat.ATOM))
|
||||
entry.generateAtom(writer, profile);
|
||||
|
@ -181,7 +215,7 @@ public class GDataResponse {
|
|||
private XmlWriter createWriter() throws IOException {
|
||||
XmlWriter writer = new XmlWriter(getWriter(), this.encoding);
|
||||
// set the default namespace to Atom if Atom is the response format
|
||||
if(this.outputFormat.equals(OutputFormat.ATOM))
|
||||
if (this.outputFormat.equals(OutputFormat.ATOM))
|
||||
writer.setDefaultNamespace(DEFAULT_NAMESPACE);
|
||||
return writer;
|
||||
}
|
||||
|
@ -224,11 +258,12 @@ public class GDataResponse {
|
|||
public void setOutputFormat(OutputFormat outputFormat) {
|
||||
this.outputFormat = outputFormat;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see Object#toString()
|
||||
*/
|
||||
@Override
|
||||
public String toString(){
|
||||
public String toString() {
|
||||
StringBuilder builder = new StringBuilder(" GDataResponse: ");
|
||||
builder.append("Error: ").append(this.error);
|
||||
builder.append(" outputFormat: ").append(getOutputFormat());
|
||||
|
@ -236,7 +271,20 @@ public class GDataResponse {
|
|||
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -16,14 +16,21 @@
|
|||
package org.apache.lucene.gdata.server;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
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.GDataServerRegistry;
|
||||
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 org.apache.lucene.gdata.storage.StorageFactory;
|
||||
|
||||
import com.google.gdata.data.BaseEntry;
|
||||
import com.google.gdata.data.BaseFeed;
|
||||
|
@ -33,21 +40,26 @@ 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 extends Service {
|
||||
public class GDataService implements Service {
|
||||
private static final Log LOGGER = LogFactory.getLog(GDataService.class);
|
||||
|
||||
private Storage storage;
|
||||
protected Storage storage;
|
||||
|
||||
private GDataServerRegistry registry = GDataServerRegistry.getRegistry();
|
||||
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";
|
||||
static {
|
||||
generator = new Generator();
|
||||
generator.setName(generatorName);
|
||||
|
@ -57,7 +69,13 @@ public class GDataService extends Service {
|
|||
|
||||
protected GDataService() throws ServiceException {
|
||||
try {
|
||||
this.storage = StorageFactory.getStorage();
|
||||
StorageController controller = GDataServerRegistry.getRegistry()
|
||||
.lookup(StorageController.class,
|
||||
ComponentType.STORAGECONTROLLER);
|
||||
if (controller == null)
|
||||
throw new StorageException(
|
||||
"StorageController is not registered");
|
||||
this.storage = controller.getStorage();
|
||||
|
||||
} catch (StorageException e) {
|
||||
LOGGER
|
||||
|
@ -75,40 +93,55 @@ public class GDataService extends Service {
|
|||
* @see org.apache.lucene.gdata.server.Service#createEntry(org.apache.lucene.gdata.server.GDataRequest,
|
||||
* org.apache.lucene.gdata.server.GDataResponse)
|
||||
*/
|
||||
@Override
|
||||
|
||||
public BaseEntry createEntry(GDataRequest request, GDataResponse response)
|
||||
throws ServiceException {
|
||||
|
||||
checkFeedIsRegisterd(request);
|
||||
if (LOGGER.isInfoEnabled())
|
||||
LOGGER.info("create Entry for feedId: " + request.getFeedId());
|
||||
BaseEntry entry = buildEntry(request);
|
||||
setUpdateTime(entry);
|
||||
try {
|
||||
|
||||
this.storage.storeEntry(entry, request.getFeedId());
|
||||
ServerBaseEntry entry = buildEntry(request, response);
|
||||
entry.setFeedId(request.getFeedId());
|
||||
entry.setServiceConfig(request.getConfigurator());
|
||||
setTimeStamps(entry.getEntry());
|
||||
BaseEntry retVal = null;
|
||||
try {
|
||||
retVal = this.storage.storeEntry(entry);
|
||||
} catch (Exception e) {
|
||||
response.setError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
|
||||
ServiceException ex = new ServiceException("Could not store entry",
|
||||
e);
|
||||
ex.setStackTrace(e.getStackTrace());
|
||||
throw ex;
|
||||
}
|
||||
return entry;
|
||||
return retVal;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.lucene.gdata.server.Service#deleteEntry(org.apache.lucene.gdata.server.GDataRequest,
|
||||
* org.apache.lucene.gdata.server.GDataResponse)
|
||||
*/
|
||||
@Override
|
||||
|
||||
public BaseEntry deleteEntry(GDataRequest request, GDataResponse response)
|
||||
throws ServiceException {
|
||||
checkFeedIsRegisterd(request);
|
||||
String entryid = request.getEntryId();
|
||||
String feedid = request.getFeedId();
|
||||
|
||||
ServerBaseEntry entry = new ServerBaseEntry();
|
||||
entry.setServiceConfig(request.getConfigurator());
|
||||
entry.setFeedId(request.getFeedId());
|
||||
entry.setId(request.getEntryId());
|
||||
if (entry.getId() == null)
|
||||
throw new ServiceException(
|
||||
"entry id is null -- can not delete null entry");
|
||||
try {
|
||||
this.storage.deleteEntry(entryid, feedid);
|
||||
this.storage.deleteEntry(entry);
|
||||
} catch (ResourceNotFoundException e) {
|
||||
response.setError(HttpServletResponse.SC_BAD_REQUEST);
|
||||
ServiceException ex = new ServiceException(
|
||||
"Could not delete entry", e);
|
||||
ex.setStackTrace(e.getStackTrace());
|
||||
throw ex;
|
||||
} catch (Exception e) {
|
||||
response.setError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
|
||||
ServiceException ex = new ServiceException(
|
||||
"Could not delete entry", e);
|
||||
ex.setStackTrace(e.getStackTrace());
|
||||
|
@ -121,26 +154,50 @@ public class GDataService extends Service {
|
|||
* @see org.apache.lucene.gdata.server.Service#updateEntry(org.apache.lucene.gdata.server.GDataRequest,
|
||||
* org.apache.lucene.gdata.server.GDataResponse)
|
||||
*/
|
||||
@Override
|
||||
|
||||
public BaseEntry updateEntry(GDataRequest request, GDataResponse response)
|
||||
throws ServiceException {
|
||||
checkFeedIsRegisterd(request);
|
||||
|
||||
BaseEntry entry = buildEntry(request);
|
||||
String feedid = request.getFeedId();
|
||||
ServerBaseEntry entry = buildEntry(request, response);
|
||||
entry.setFeedId(request.getFeedId());
|
||||
|
||||
entry.setServiceConfig(request.getConfigurator());
|
||||
if (LOGGER.isInfoEnabled())
|
||||
LOGGER.info("update Entry" + entry.getId() + " for feedId: "
|
||||
+ feedid);
|
||||
setUpdateTime(entry);
|
||||
+ request.getFeedId());
|
||||
if (entry.getId() == null) {
|
||||
response.setError(HttpServletResponse.SC_BAD_REQUEST);
|
||||
throw new ServiceException("Entry id is null can not update entry");
|
||||
}
|
||||
if (!entry.getId().equals(request.getEntryId())) {
|
||||
if (LOGGER.isInfoEnabled())
|
||||
LOGGER
|
||||
.info("Entry id in the entry xml does not match the requested resource -- XML-ID:"
|
||||
+ entry.getId()
|
||||
+ "; Requested resource: "
|
||||
+ request.getEntryId());
|
||||
response.setError(HttpServletResponse.SC_BAD_REQUEST);
|
||||
throw new ServiceException(
|
||||
"Entry id in the entry xml does not match the requested resource");
|
||||
}
|
||||
setTimeStamps(entry.getEntry());
|
||||
BaseEntry retVal = null;
|
||||
try {
|
||||
this.storage.updateEntry(entry, feedid);
|
||||
retVal = this.storage.updateEntry(entry);
|
||||
} catch (ResourceNotFoundException e) {
|
||||
response.setError(HttpServletResponse.SC_BAD_REQUEST);
|
||||
ServiceException ex = new ServiceException(
|
||||
"Could not update entry", e);
|
||||
ex.setStackTrace(e.getStackTrace());
|
||||
throw ex;
|
||||
} catch (StorageException e) {
|
||||
response.setError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
|
||||
ServiceException ex = new ServiceException(
|
||||
"Could not update entry", e);
|
||||
ex.setStackTrace(e.getStackTrace());
|
||||
throw ex;
|
||||
}
|
||||
return entry;
|
||||
return retVal;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -148,21 +205,25 @@ public class GDataService extends Service {
|
|||
* org.apache.lucene.gdata.server.GDataResponse)
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public BaseFeed getFeed(GDataRequest request, GDataResponse response)
|
||||
throws ServiceException {
|
||||
checkFeedIsRegisterd(request);
|
||||
|
||||
ServerBaseFeed feed = new ServerBaseFeed();
|
||||
feed.setId(request.getFeedId());
|
||||
feed.setStartIndex(request.getStartIndex());
|
||||
feed.setItemsPerPage(request.getItemsPerPage());
|
||||
feed.setServiceConfig(request.getConfigurator());
|
||||
try {
|
||||
// TODO remove when storing feeds is implemented just for
|
||||
// development
|
||||
BaseFeed feed = this.storage.getFeed(request.getFeedId(), request
|
||||
.getStartIndex(), request.getItemsPerPage());
|
||||
buildDynamicFeedElements(request, feed);
|
||||
List<BaseEntry> list = feed.getEntries();
|
||||
addContextPath(list, request.getContextPath());
|
||||
return feed;
|
||||
BaseFeed retVal = this.storage.getFeed(feed);
|
||||
dynamicElementFeedStragey(retVal, request);
|
||||
|
||||
return retVal;
|
||||
/*
|
||||
* resouce not found will be detected in Gdata request.
|
||||
* the request queries the storage for the feed to get the serivce for the feed
|
||||
*/
|
||||
} catch (StorageException e) {
|
||||
response.setError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
|
||||
ServiceException ex = new ServiceException("Could not get feed", e);
|
||||
ex.setStackTrace(e.getStackTrace());
|
||||
throw ex;
|
||||
|
@ -170,18 +231,6 @@ public class GDataService extends Service {
|
|||
|
||||
}
|
||||
|
||||
/*
|
||||
* 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.getLinks().add(
|
||||
buildLink(Link.Rel.SELF, Link.Type.ATOM, request.getSelfId()));
|
||||
// TODO add next link
|
||||
}
|
||||
|
||||
private Link buildLink(String rel, String type, String href) {
|
||||
Link retVal = new Link();
|
||||
retVal.setHref(href);
|
||||
|
@ -190,41 +239,21 @@ public class GDataService extends Service {
|
|||
return retVal;
|
||||
}
|
||||
|
||||
/*
|
||||
* every entry has an ID which has to have a prefix. The prefix is the
|
||||
* context path of the requested feed. This will be used to request the
|
||||
* entry directly
|
||||
*/
|
||||
private void addContextPath(List<BaseEntry> list, final String contextPath) {
|
||||
for (BaseEntry entry : list) {
|
||||
addcontextPath(entry, contextPath);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private BaseEntry addcontextPath(final BaseEntry entry,
|
||||
final String contextPath) {
|
||||
String id = contextPath + entry.getId();
|
||||
entry.setId(id);
|
||||
Link self = new Link();
|
||||
self.setRel("self");
|
||||
self.setHref(id);
|
||||
self.setType("application/atom+xml");
|
||||
entry.getLinks().add(self);
|
||||
return entry;
|
||||
}
|
||||
|
||||
private BaseEntry buildEntry(final GDataRequest request)
|
||||
throws ServiceException {
|
||||
private ServerBaseEntry buildEntry(final GDataRequest request,
|
||||
final GDataResponse response) throws ServiceException {
|
||||
try {
|
||||
return GDataEntityBuilder.buildEntry(request);
|
||||
ServerBaseEntry entry = new ServerBaseEntry(GDataEntityBuilder
|
||||
.buildEntry(request));
|
||||
return entry;
|
||||
|
||||
} catch (ParseException e) {
|
||||
response.setError(HttpServletResponse.SC_BAD_REQUEST);
|
||||
ServiceException ex = new ServiceException(
|
||||
"Could not parse entry from incoming request", e);
|
||||
ex.setStackTrace(e.getStackTrace());
|
||||
throw ex;
|
||||
} catch (IOException e) {
|
||||
response.setError(HttpServletResponse.SC_BAD_REQUEST);
|
||||
ServiceException ex = new ServiceException(
|
||||
"Could not read or open input stream", e);
|
||||
ex.setStackTrace(e.getStackTrace());
|
||||
|
@ -232,20 +261,11 @@ public class GDataService extends Service {
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* checks whether the reqeuested feed is registered
|
||||
*/
|
||||
private void checkFeedIsRegisterd(final GDataRequest request)
|
||||
throws FeedNotFoundException {
|
||||
if (!this.registry.isFeedRegistered(request.getFeedId()))
|
||||
throw new FeedNotFoundException(
|
||||
"Feed could not be found - is not registed - Feed ID:"
|
||||
+ request.getFeedId());
|
||||
this.storage.setExtensionProfile(request.getExtensionProfile());
|
||||
}
|
||||
|
||||
private BaseEntry setUpdateTime(final BaseEntry entry) {
|
||||
private BaseEntry setTimeStamps(final BaseEntry entry) {
|
||||
if (entry.getUpdated() == null)
|
||||
entry.setUpdated(DateTime.now());
|
||||
if (entry.getPublished() == null)
|
||||
entry.setPublished(DateTime.now());
|
||||
return entry;
|
||||
}
|
||||
|
||||
|
@ -253,18 +273,30 @@ public class GDataService extends Service {
|
|||
* @see org.apache.lucene.gdata.server.Service#getSingleEntry(org.apache.lucene.gdata.server.GDataRequest,
|
||||
* org.apache.lucene.gdata.server.GDataResponse)
|
||||
*/
|
||||
@Override
|
||||
|
||||
public BaseEntry getSingleEntry(GDataRequest request, GDataResponse response)
|
||||
throws ServiceException {
|
||||
checkFeedIsRegisterd(request);
|
||||
|
||||
try {
|
||||
BaseEntry entry = this.storage.getEntry(request.getEntryId(),
|
||||
request.getFeedId());
|
||||
if(entry == null)
|
||||
return null;
|
||||
addcontextPath(entry, request.getContextPath());
|
||||
return entry;
|
||||
ServerBaseEntry entry = new ServerBaseEntry();
|
||||
entry.setServiceConfig(request.getConfigurator());
|
||||
entry.setFeedId(request.getFeedId());
|
||||
entry.setId(request.getEntryId());
|
||||
if(entry.getId() == null){
|
||||
response.setError(HttpServletResponse.SC_BAD_REQUEST);
|
||||
throw new ServiceException("entry is null can't get entry");
|
||||
}
|
||||
|
||||
BaseEntry retVal = null;
|
||||
retVal = this.storage.getEntry(entry);
|
||||
dynamicElementEntryStragey(retVal, request);
|
||||
return retVal;
|
||||
} catch (ResourceNotFoundException e) {
|
||||
response.setError(HttpServletResponse.SC_BAD_REQUEST);
|
||||
ServiceException ex = new ServiceException(
|
||||
"Could not get entry", e);
|
||||
ex.setStackTrace(e.getStackTrace());
|
||||
throw ex;
|
||||
} catch (StorageException e) {
|
||||
ServiceException ex = new ServiceException("Could not get feed", e);
|
||||
ex.setStackTrace(e.getStackTrace());
|
||||
|
@ -272,4 +304,95 @@ public class GDataService extends Service {
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* 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")
|
||||
private void dynamicElementFeedStragey(final BaseFeed feed,
|
||||
final GDataRequest request) {
|
||||
buildDynamicFeedElements(request, feed);
|
||||
List<BaseEntry> entryList = feed.getEntries();
|
||||
for (BaseEntry entry : entryList) {
|
||||
String id = request.getContextPath() + entry.getId();
|
||||
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);
|
||||
entry.getLinks().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());
|
||||
feed.getLinks().add(
|
||||
buildLink(Link.Rel.SELF, Link.Type.ATOM, request.getSelfId()));
|
||||
feed.getLinks().add(
|
||||
buildLink(Link.Rel.NEXT, XMLMIME, request.getNextId()));
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @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);
|
||||
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);
|
||||
ex.setStackTrace(e.getStackTrace());
|
||||
throw ex;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -16,6 +16,8 @@
|
|||
|
||||
package org.apache.lucene.gdata.server;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import com.google.gdata.data.BaseEntry;
|
||||
import com.google.gdata.data.BaseFeed;
|
||||
|
||||
|
@ -39,7 +41,7 @@ import com.google.gdata.data.BaseFeed;
|
|||
*
|
||||
*
|
||||
*/
|
||||
public abstract class Service {
|
||||
public interface Service {
|
||||
|
||||
/**
|
||||
* Service method to create an entry in an already created and existing
|
||||
|
@ -133,6 +135,27 @@ public abstract class Service {
|
|||
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;
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -17,6 +17,10 @@
|
|||
package org.apache.lucene.gdata.server;
|
||||
|
||||
/**
|
||||
* The ServiceException is used to encapsulate all {@link java.lang.Exception}
|
||||
* throw by underlaying layers of the
|
||||
* {@link org.apache.lucene.gdata.server.Service} layer.
|
||||
*
|
||||
* @author Simon Willnauer
|
||||
*
|
||||
*/
|
||||
|
@ -28,7 +32,7 @@ public class ServiceException extends Exception {
|
|||
private static final long serialVersionUID = -7099825107871876584L;
|
||||
|
||||
/**
|
||||
*
|
||||
* Constructs a new ServiceException
|
||||
*/
|
||||
public ServiceException() {
|
||||
super();
|
||||
|
@ -36,7 +40,8 @@ public class ServiceException extends Exception {
|
|||
}
|
||||
|
||||
/**
|
||||
* @param arg0
|
||||
* Constructs a new ServiceException
|
||||
* @param arg0 - the exception message
|
||||
*/
|
||||
public ServiceException(String arg0) {
|
||||
super(arg0);
|
||||
|
@ -44,8 +49,9 @@ public class ServiceException extends Exception {
|
|||
}
|
||||
|
||||
/**
|
||||
* @param arg0
|
||||
* @param arg1
|
||||
* Constructs a new ServiceException
|
||||
* @param arg0 - the exceptin message
|
||||
* @param arg1 - the exception cause
|
||||
*/
|
||||
public ServiceException(String arg0, Throwable arg1) {
|
||||
super(arg0, arg1);
|
||||
|
@ -53,7 +59,8 @@ public class ServiceException extends Exception {
|
|||
}
|
||||
|
||||
/**
|
||||
* @param arg0
|
||||
* Constructs a new ServiceException
|
||||
* @param arg0 - the exception cause
|
||||
*/
|
||||
public ServiceException(Throwable arg0) {
|
||||
super(arg0);
|
||||
|
|
|
@ -15,36 +15,44 @@
|
|||
*/
|
||||
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
|
||||
*
|
||||
*/
|
||||
public class ServiceFactory {
|
||||
@Component(componentType=ComponentType.SERVICEFACTORY)
|
||||
public class ServiceFactory implements ServerComponent {
|
||||
|
||||
private static final Log LOG = LogFactory.getLog(ServiceFactory.class);
|
||||
|
||||
|
||||
private static ServiceFactory INSTANCE = null;
|
||||
|
||||
/**
|
||||
* @return - a Singleton Instance of the factory
|
||||
* 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 static synchronized ServiceFactory getInstance() {
|
||||
if (INSTANCE == null)
|
||||
INSTANCE = new ServiceFactory();
|
||||
return INSTANCE;
|
||||
|
||||
}
|
||||
|
||||
private ServiceFactory() {
|
||||
// private constructor --> singleton
|
||||
public ServiceFactory() {
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link Service} implementation.
|
||||
* Creates a {@link Service} instance.
|
||||
*
|
||||
* @return a Service Implementation
|
||||
* @return a Service instance
|
||||
*/
|
||||
public Service getService() {
|
||||
try{
|
||||
|
@ -54,4 +62,31 @@ public class ServiceFactory {
|
|||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link AdminService} instance
|
||||
* @return a AdminService instance
|
||||
*/
|
||||
public AdminService getAdminService(){
|
||||
try {
|
||||
return new GDataAdminService();
|
||||
} catch (ServiceException e) {
|
||||
LOG.warn("Factory method can not create GDataAdminService returning null-- "+e.getMessage(),e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.lucene.gdata.server.registry.ServerComponent#initialize()
|
||||
*/
|
||||
public void initialize() {
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.lucene.gdata.server.registry.ServerComponent#destroy()
|
||||
*/
|
||||
public void destroy() {
|
||||
//
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,62 +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;
|
||||
|
||||
/**
|
||||
* @author Simon Willnauer
|
||||
*
|
||||
*/
|
||||
public class DataBuilderException extends RuntimeException {
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = -3802958802500735198L;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public DataBuilderException() {
|
||||
super();
|
||||
// TODO Auto-generated constructor stub
|
||||
}
|
||||
|
||||
/**
|
||||
* @param message
|
||||
*/
|
||||
public DataBuilderException(String message) {
|
||||
super(message);
|
||||
// TODO Auto-generated constructor stub
|
||||
}
|
||||
|
||||
/**
|
||||
* @param message
|
||||
* @param cause
|
||||
*/
|
||||
public DataBuilderException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
// TODO Auto-generated constructor stub
|
||||
}
|
||||
|
||||
/**
|
||||
* @param cause
|
||||
*/
|
||||
public DataBuilderException(Throwable cause) {
|
||||
super(cause);
|
||||
// TODO Auto-generated constructor stub
|
||||
}
|
||||
|
||||
}
|
|
@ -1,66 +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;
|
||||
|
||||
/**
|
||||
* @author Simon Willnauer
|
||||
*
|
||||
*/
|
||||
public class FeedInstanceConfigurator {
|
||||
private Class feedType;
|
||||
private String feedId;
|
||||
private Class extensionProfileClass;
|
||||
/**
|
||||
* @return Returns the feedType.
|
||||
*/
|
||||
public Class getFeedType() {
|
||||
return this.feedType;
|
||||
}
|
||||
/**
|
||||
* @param feedType The feedType to set.
|
||||
*/
|
||||
public void setFeedType(Class feedType) {
|
||||
this.feedType = feedType;
|
||||
}
|
||||
/**
|
||||
* @return Returns the feedURL.
|
||||
*/
|
||||
public String getFeedId() {
|
||||
return this.feedId;
|
||||
}
|
||||
/**
|
||||
* @param feedURL The feedURL to set.
|
||||
*/
|
||||
public void setFeedId(String feedURL) {
|
||||
this.feedId = feedURL;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return - the extension profile for this feed
|
||||
*/
|
||||
public Class getExtensionProfilClass(){
|
||||
return this.extensionProfileClass;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param extensionProfilClass
|
||||
*/
|
||||
public void setExtensionProfileClass(Class extensionProfilClass){
|
||||
this.extensionProfileClass = extensionProfilClass;
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -20,23 +20,29 @@ import java.util.Map;
|
|||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.apache.lucene.gdata.storage.StorageController;
|
||||
|
||||
import com.google.gdata.data.ExtensionProfile;
|
||||
|
||||
/**
|
||||
*
|
||||
* The FeedRegistry represents the registry component of the GData Server. All
|
||||
* feed configurations will be registered here. Feed configurations contain
|
||||
* several informationsa about GData feed like:
|
||||
* <ol>
|
||||
* <li>the feed id - where the feed can be accessed via http methodes</li>
|
||||
* <li>the feed type - feed types are implementations of the abstract
|
||||
* {@link com.google.gdata.data.BaseFeed}</li>
|
||||
* </ol>
|
||||
* The registry will be set up at start up of the server application and can be
|
||||
* accessed from other components to get configurations according to incoming
|
||||
* requests.
|
||||
* 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
|
||||
* instanciated at startup. If a component can not be loaded or an Exception
|
||||
* occures the server will not start up. To cause of the exception or error will
|
||||
* be logged to the standart server output.
|
||||
* </p>
|
||||
* <p>The GDataServerRegistry is a Singleton</p>
|
||||
*
|
||||
*
|
||||
* @author Simon Willnauer
|
||||
*
|
||||
|
@ -44,12 +50,13 @@ import com.google.gdata.data.ExtensionProfile;
|
|||
public class GDataServerRegistry {
|
||||
private static GDataServerRegistry INSTANCE;
|
||||
|
||||
private StorageController storageInstance;
|
||||
|
||||
private static final Log LOGGER = LogFactory
|
||||
.getLog(GDataServerRegistry.class);
|
||||
|
||||
private final Map<String, FeedInstanceConfigurator> feedTypMap = new HashMap<String, FeedInstanceConfigurator>();
|
||||
private final Map<String, ProvidedService> serviceTypeMap = new HashMap<String, ProvidedService>();
|
||||
|
||||
private final Map<ComponentType, ComponentBean> componentMap = new HashMap<ComponentType, ComponentBean>(
|
||||
10);
|
||||
|
||||
private GDataServerRegistry() {
|
||||
// private - singleton
|
||||
|
@ -65,90 +72,183 @@ public class GDataServerRegistry {
|
|||
}
|
||||
|
||||
/**
|
||||
* Registers a {@link FeedInstanceConfigurator}
|
||||
* Registers a {@link ProvidedService}
|
||||
*
|
||||
* @param configurator -
|
||||
* the configurator to register in the registry
|
||||
*/
|
||||
public void registerFeed(FeedInstanceConfigurator configurator) {
|
||||
public void registerService(ProvidedService configurator) {
|
||||
if (configurator == null) {
|
||||
LOGGER.warn("Feedconfigurator is null -- skip registration");
|
||||
return;
|
||||
}
|
||||
this.feedTypMap.put(configurator.getFeedId(), configurator);
|
||||
this.serviceTypeMap.put(configurator.getName(), configurator);
|
||||
}
|
||||
|
||||
/**
|
||||
* Looks up the {@link FeedInstanceConfigurator} by the given feed id.
|
||||
* Looks up the {@link ProvidedServiceConfig} by the given service name.
|
||||
*
|
||||
* @param feedId
|
||||
* @return - the {@link FeedInstanceConfigurator} or <code>null</code> if
|
||||
* the no configuration for this feed has been registered
|
||||
* @param service
|
||||
* @return - the {@link ProvidedServiceConfig} or <code>null</code> if the
|
||||
* no configuration for this service has been registered
|
||||
*/
|
||||
public FeedInstanceConfigurator getFeedConfigurator(String feedId) {
|
||||
if (feedId == null)
|
||||
public ProvidedService getProvidedService(String service) {
|
||||
if (service == null)
|
||||
throw new IllegalArgumentException(
|
||||
"Feed URL is null - must not be null to get registered feedtype");
|
||||
return this.feedTypMap.get(feedId);
|
||||
"Service is null - must not be null to get registered feedtype");
|
||||
return this.serviceTypeMap.get(service);
|
||||
}
|
||||
|
||||
protected void flushRegistry() {
|
||||
this.feedTypMap.clear();
|
||||
this.serviceTypeMap.clear();
|
||||
this.componentMap.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param feedId -
|
||||
* the id of the feed as the feed is registered
|
||||
* @return - <code>true</code> if and only if the feed is registered,
|
||||
* @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 isFeedRegistered(String feedId) {
|
||||
return this.feedTypMap.containsKey(feedId);
|
||||
public boolean isServiceRegistered(String service) {
|
||||
return this.serviceTypeMap.containsKey(service);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param storage
|
||||
*/
|
||||
public void registerStorage(StorageController storage) {
|
||||
if (this.storageInstance != null)
|
||||
throw new IllegalStateException(
|
||||
"Storage already registered -- Instance of "
|
||||
+ this.storageInstance.getClass());
|
||||
this.storageInstance = storage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroys the registry and release all resources
|
||||
*/
|
||||
public void destroy() {
|
||||
for (ComponentBean component : this.componentMap.values()) {
|
||||
component.getObject().destroy();
|
||||
}
|
||||
flushRegistry();
|
||||
this.storageInstance.destroy();
|
||||
this.storageInstance = null;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the {@link ExtensionProfile} for a registered feed
|
||||
* @param feedId - the feed id
|
||||
* @return - the extension profil for this feed of <code>null</code> if
|
||||
* the feed is not registered or the extension profile could not be
|
||||
* instanciated
|
||||
* 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.
|
||||
*/
|
||||
public ExtensionProfile getExtensionProfile(final String feedId) {
|
||||
FeedInstanceConfigurator configurator = this.feedTypMap.get(feedId);
|
||||
if (configurator == null)
|
||||
@SuppressWarnings("unchecked")
|
||||
public <R> R lookup(Class<R> clazz, ComponentType compType) {
|
||||
ComponentBean bean = this.componentMap.get(compType);
|
||||
if (bean == null)
|
||||
return null;
|
||||
Class clazz = configurator.getExtensionProfilClass();
|
||||
if (bean.getSuperType().equals(clazz))
|
||||
return (R) bean.getObject();
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param <E>
|
||||
* @param componentClass
|
||||
* @throws RegistryException
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public <E extends ServerComponent> void registerComponent(final Class<E> componentClass)
|
||||
throws RegistryException {
|
||||
|
||||
if (componentClass == null)
|
||||
throw new IllegalArgumentException(
|
||||
"component class must not be null");
|
||||
|
||||
if(!checkImplementsServerComponent(componentClass))
|
||||
throw new RegistryException("can not register component. the given class does not implement ServerComponent interface -- "+componentClass.getName());
|
||||
try {
|
||||
return (ExtensionProfile) clazz.newInstance();
|
||||
|
||||
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 (!checkSuperType(componentClass, superType))
|
||||
throw new RegistryException("Considered Supertype <"
|
||||
+ superType.getName() + "> is not a super type of <"
|
||||
+ componentClass + ">");
|
||||
ServerComponent comp = componentClass.newInstance();
|
||||
comp.initialize();
|
||||
ComponentBean bean = new ComponentBean(comp, superType);
|
||||
|
||||
this.componentMap.put(type, bean);
|
||||
|
||||
} catch (Exception e) {
|
||||
LOGGER
|
||||
.error("Can not create instance of ExtensionProfil for class: "
|
||||
+ clazz + " -- feedId: " + feedId);
|
||||
throw new RegistryException("Can not register component -- "
|
||||
+ e.getMessage(), e);
|
||||
}
|
||||
|
||||
}
|
||||
return null;
|
||||
|
||||
private static boolean checkImplementsServerComponent(Class type){
|
||||
if(type == null)
|
||||
return false;
|
||||
if(type.equals(Object.class))
|
||||
return false;
|
||||
if(type.equals(ServerComponent.class))
|
||||
return true;
|
||||
Class[] compInterfaces = type.getInterfaces();
|
||||
for (int i = 0; i < compInterfaces.length; i++) {
|
||||
if(checkImplementsServerComponent(compInterfaces[i]))
|
||||
return true;
|
||||
}
|
||||
return checkImplementsServerComponent(type.getSuperclass());
|
||||
|
||||
}
|
||||
|
||||
private static boolean checkSuperType(Class type, Class consideredSuperType) {
|
||||
|
||||
if (type.equals(Object.class))
|
||||
return false;
|
||||
if (type.equals(consideredSuperType))
|
||||
return true;
|
||||
Class[] interfaces = type.getInterfaces();
|
||||
for (int i = 0; i < interfaces.length; i++) {
|
||||
if (interfaces[i].equals(consideredSuperType))
|
||||
return true;
|
||||
}
|
||||
return checkSuperType(type.getSuperclass(), consideredSuperType);
|
||||
}
|
||||
|
||||
private 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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -15,27 +15,56 @@
|
|||
*/
|
||||
package org.apache.lucene.gdata.server.registry;
|
||||
|
||||
import com.google.gdata.data.ExtensionProfile;
|
||||
import com.google.gdata.data.Feed;
|
||||
import java.io.IOException;
|
||||
|
||||
import org.apache.commons.digester.Digester;
|
||||
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 instanciated and registered in
|
||||
* the registry.
|
||||
*
|
||||
* @author Simon Willnauer
|
||||
*
|
||||
*/
|
||||
public class RegistryBuilder {
|
||||
class RegistryBuilder {
|
||||
|
||||
/**
|
||||
* builds the {@link GDataServerRegistry} accessible via the
|
||||
* {@link GDataServerRegistry#getRegistry()} method
|
||||
*
|
||||
* @throws IOException -
|
||||
* if an IOException occures while reading the config file
|
||||
* @throws SAXException -
|
||||
* if the config file can not be parsed
|
||||
*/
|
||||
public static void buildRegistry(){
|
||||
// TODO Implement this!! -- just for develping purposes
|
||||
GDataServerRegistry reg = GDataServerRegistry.getRegistry();
|
||||
FeedInstanceConfigurator configurator = new FeedInstanceConfigurator();
|
||||
configurator.setFeedType(Feed.class);
|
||||
configurator.setFeedId("weblog");
|
||||
configurator.setExtensionProfileClass(ExtensionProfile.class);
|
||||
reg.registerFeed(configurator);
|
||||
static void buildRegistry() throws IOException, SAXException {
|
||||
|
||||
buildFromConfiguration(new Digester(), GDataServerRegistry
|
||||
.getRegistry());
|
||||
|
||||
}
|
||||
|
||||
private static void buildFromConfiguration(Digester digester,
|
||||
GDataServerRegistry registry) throws IOException, SAXException {
|
||||
|
||||
digester.setValidating(false);
|
||||
digester.push(registry);
|
||||
digester.addCallMethod("gdata/server-components/component",
|
||||
"registerComponent", 0, new Class[] { Class.class });
|
||||
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.parse(RegistryBuilder.class
|
||||
.getResourceAsStream("/gdata-config.xml"));
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -30,7 +30,14 @@ import org.apache.commons.logging.LogFactory;
|
|||
* The Registry will be loaded and set up befor the REST interface is available.
|
||||
* <p>
|
||||
* This ContextListener has to be configured in the <code>web.xml</code>
|
||||
* deployment descriptor.</p>
|
||||
* 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
|
||||
|
@ -42,15 +49,23 @@ public class RegistryContextListener implements ServletContextListener {
|
|||
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 (Exception e) {
|
||||
this.serverRegistry.destroy();
|
||||
LOG.error("can not register requiered components", e);
|
||||
throw new RuntimeException("Can not register required components",
|
||||
e);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -5,6 +5,6 @@
|
|||
<meta name="Author" content="Simon Willnauer">
|
||||
</head>
|
||||
<body>
|
||||
Internal registry - registering feeds and configurations
|
||||
Internal registry - registering services and server components
|
||||
</body>
|
||||
</html>
|
|
@ -18,11 +18,16 @@ package org.apache.lucene.gdata.servlet;
|
|||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.servlet.ServletConfig;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.apache.lucene.gdata.server.registry.ComponentType;
|
||||
import org.apache.lucene.gdata.server.registry.GDataServerRegistry;
|
||||
import org.apache.lucene.gdata.servlet.handler.RequestHandlerFactory;
|
||||
|
||||
/**
|
||||
*
|
||||
* Provides an abstract class to be subclassed to create an GDATA servlet
|
||||
|
@ -44,6 +49,8 @@ public abstract class AbstractGdataServlet extends HttpServlet {
|
|||
|
||||
private static final String METHOD_PUT = "PUT";
|
||||
|
||||
protected static RequestHandlerFactory HANDLER_FACTORY = null;
|
||||
|
||||
/**
|
||||
* This overwrites the protected <code>service</code> method to dispatch
|
||||
* the request to the correponding <code>do</code> method. There is
|
||||
|
@ -94,4 +101,15 @@ public abstract class AbstractGdataServlet extends HttpServlet {
|
|||
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @see javax.servlet.GenericServlet#init(javax.servlet.ServletConfig)
|
||||
*/
|
||||
public void init(ServletConfig arg0) throws ServletException {
|
||||
HANDLER_FACTORY = GDataServerRegistry.getRegistry().lookup(RequestHandlerFactory.class,ComponentType.REQUESTHANDLERFACTORY);
|
||||
if(HANDLER_FACTORY == null)
|
||||
throw new ServletException("service not available");
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -18,16 +18,13 @@ package org.apache.lucene.gdata.servlet;
|
|||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.servlet.ServletConfig;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.apache.lucene.gdata.servlet.handler.DefaultRequestHandlerFactory;
|
||||
import org.apache.lucene.gdata.servlet.handler.GDataRequestHandler;
|
||||
import org.apache.lucene.gdata.servlet.handler.RequestHandlerFactory;
|
||||
|
||||
/**
|
||||
* Provides a clean basic interface for GDATA Client API and requests to the
|
||||
|
@ -39,7 +36,6 @@ import org.apache.lucene.gdata.servlet.handler.RequestHandlerFactory;
|
|||
*
|
||||
*/
|
||||
public class RequestControllerServlet extends AbstractGdataServlet {
|
||||
private static RequestHandlerFactory HANDLER_FACTORY = null;
|
||||
private static final Log LOGGER = LogFactory.getLog(RequestControllerServlet.class);
|
||||
|
||||
/**
|
||||
|
@ -56,7 +52,7 @@ public class RequestControllerServlet extends AbstractGdataServlet {
|
|||
@Override
|
||||
protected void doDelete(HttpServletRequest arg0, HttpServletResponse arg1)
|
||||
throws ServletException, IOException {
|
||||
GDataRequestHandler hanlder = HANDLER_FACTORY.getDeleteHandler();
|
||||
GDataRequestHandler hanlder = HANDLER_FACTORY.getEntryDeleteHandler();
|
||||
if(LOGGER.isInfoEnabled())
|
||||
LOGGER.info("Process DELETE request");
|
||||
|
||||
|
@ -70,10 +66,9 @@ public class RequestControllerServlet extends AbstractGdataServlet {
|
|||
@Override
|
||||
protected void doGet(HttpServletRequest arg0, HttpServletResponse arg1)
|
||||
throws ServletException, IOException {
|
||||
GDataRequestHandler hanlder = HANDLER_FACTORY.getQueryHandler();
|
||||
GDataRequestHandler hanlder = HANDLER_FACTORY.getFeedQueryHandler();
|
||||
if(LOGGER.isInfoEnabled())
|
||||
LOGGER.info("Process GET request");
|
||||
|
||||
hanlder.processRequest(arg0, arg1);
|
||||
}
|
||||
|
||||
|
@ -84,7 +79,7 @@ public class RequestControllerServlet extends AbstractGdataServlet {
|
|||
@Override
|
||||
protected void doPost(HttpServletRequest arg0, HttpServletResponse arg1)
|
||||
throws ServletException, IOException {
|
||||
GDataRequestHandler hanlder = HANDLER_FACTORY.getInsertHandler();
|
||||
GDataRequestHandler hanlder = HANDLER_FACTORY.getEntryInsertHandler();
|
||||
if(LOGGER.isInfoEnabled())
|
||||
LOGGER.info("Process POST request");
|
||||
hanlder.processRequest(arg0, arg1);
|
||||
|
@ -97,26 +92,11 @@ public class RequestControllerServlet extends AbstractGdataServlet {
|
|||
@Override
|
||||
protected void doPut(HttpServletRequest arg0, HttpServletResponse arg1)
|
||||
throws ServletException, IOException {
|
||||
GDataRequestHandler hanlder = HANDLER_FACTORY.getUpdateHandler();
|
||||
GDataRequestHandler hanlder = HANDLER_FACTORY.getEntryUpdateHandler();
|
||||
if(LOGGER.isInfoEnabled())
|
||||
LOGGER.info("Process PUT request");
|
||||
hanlder.processRequest(arg0, arg1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see javax.servlet.GenericServlet#init(javax.servlet.ServletConfig)
|
||||
*/
|
||||
@Override
|
||||
public void init(ServletConfig arg0) {
|
||||
/*
|
||||
* The Factory implementation could be configured as an initial
|
||||
* parameter or by an external config file.
|
||||
*
|
||||
*/
|
||||
HANDLER_FACTORY = RequestHandlerFactory
|
||||
.getInstance(DefaultRequestHandlerFactory.class);
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -30,17 +30,19 @@ import org.apache.lucene.gdata.server.GDataResponse;
|
|||
import org.apache.lucene.gdata.server.Service;
|
||||
import org.apache.lucene.gdata.server.ServiceFactory;
|
||||
import org.apache.lucene.gdata.server.GDataRequest.GDataRequestType;
|
||||
import org.apache.lucene.gdata.server.registry.ComponentType;
|
||||
import org.apache.lucene.gdata.server.registry.GDataServerRegistry;
|
||||
|
||||
/**
|
||||
* @author Simon Willnauer
|
||||
*
|
||||
*/
|
||||
public abstract class AbstractGdataRequestHandler implements
|
||||
public abstract class AbstractGdataRequestHandler extends RequestAuthenticator implements
|
||||
GDataRequestHandler {
|
||||
private final static Log LOG = LogFactory
|
||||
.getLog(AbstractGdataRequestHandler.class);
|
||||
|
||||
|
||||
protected Service service;
|
||||
protected GDataRequest feedRequest;
|
||||
protected GDataResponse feedResponse;
|
||||
|
||||
|
@ -52,9 +54,10 @@ public abstract class AbstractGdataRequestHandler implements
|
|||
HttpServletResponse response) throws ServletException, IOException;
|
||||
|
||||
protected void initializeRequestHandler(final HttpServletRequest request, final HttpServletResponse response, final GDataRequestType type)
|
||||
throws GDataRequestException {
|
||||
throws GDataRequestException, ServletException {
|
||||
this.feedRequest = new GDataRequest(request, type);
|
||||
this.feedResponse = new GDataResponse(response);
|
||||
getService();
|
||||
try {
|
||||
this.feedRequest.initializeRequest();
|
||||
} catch (GDataRequestException e) {
|
||||
|
@ -83,12 +86,17 @@ public abstract class AbstractGdataRequestHandler implements
|
|||
this.feedResponse.setError(error);
|
||||
}
|
||||
|
||||
protected Service getService() throws ServletException {
|
||||
ServiceFactory serviceFactory = ServiceFactory.getInstance();
|
||||
Service service = serviceFactory.getService();
|
||||
if(service == null)
|
||||
private void getService() throws ServletException {
|
||||
GDataServerRegistry registry = GDataServerRegistry.getRegistry();
|
||||
ServiceFactory serviceFactory = registry.lookup(ServiceFactory.class,ComponentType.SERVICEFACTORY);
|
||||
this.service = serviceFactory.getService();
|
||||
if(this.service == null)
|
||||
throw new ServletException("Service not available");
|
||||
return service;
|
||||
|
||||
}
|
||||
|
||||
protected void closeService(){
|
||||
this.service.close();
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -23,9 +23,8 @@ import javax.servlet.http.HttpServletResponse;
|
|||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.apache.lucene.gdata.server.FeedNotFoundException;
|
||||
import org.apache.lucene.gdata.data.GDataAccount.AccountRole;
|
||||
import org.apache.lucene.gdata.server.GDataRequestException;
|
||||
import org.apache.lucene.gdata.server.Service;
|
||||
import org.apache.lucene.gdata.server.ServiceException;
|
||||
import org.apache.lucene.gdata.server.GDataRequest.GDataRequestType;
|
||||
|
||||
|
@ -63,21 +62,21 @@ public class DefaultDeleteHandler extends AbstractGdataRequestHandler {
|
|||
sendError();
|
||||
return;
|
||||
}
|
||||
|
||||
Service service = getService();
|
||||
try {
|
||||
service.deleteEntry(this.feedRequest, this.feedResponse);
|
||||
} catch (FeedNotFoundException e) {
|
||||
LOG.error("Could not process DeleteFeed request Feed Not Found- "
|
||||
+ e.getMessage(), e);
|
||||
setError(HttpServletResponse.SC_NOT_FOUND);
|
||||
if(!authenticateAccount(request,AccountRole.ENTRYAMINISTRATOR)){
|
||||
setError(HttpServletResponse.SC_UNAUTHORIZED);
|
||||
sendError();
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
this.service.deleteEntry(this.feedRequest, this.feedResponse);
|
||||
|
||||
} catch (ServiceException e) {
|
||||
LOG.error("Could not process DeleteFeed request - "
|
||||
+ e.getMessage(), e);
|
||||
setError(HttpServletResponse.SC_BAD_REQUEST);
|
||||
sendError();
|
||||
}
|
||||
closeService();
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
package org.apache.lucene.gdata.servlet.handler;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Date;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
@ -28,6 +29,7 @@ import org.apache.lucene.gdata.server.GDataRequestException;
|
|||
import org.apache.lucene.gdata.server.Service;
|
||||
import org.apache.lucene.gdata.server.ServiceException;
|
||||
import org.apache.lucene.gdata.server.GDataRequest.GDataRequestType;
|
||||
import org.apache.lucene.gdata.utils.DateFormater;
|
||||
|
||||
import com.google.gdata.data.BaseEntry;
|
||||
import com.google.gdata.data.BaseFeed;
|
||||
|
@ -42,6 +44,13 @@ import com.google.gdata.data.BaseFeed;
|
|||
* {@link org.apache.lucene.gdata.server.GDataRequest} instance passed to the
|
||||
* {@link Service} class.
|
||||
* </p>
|
||||
* <p>
|
||||
* The DefaultGetHandler supports HTTP Conditional GET. It set the Last-Modified
|
||||
* response header based upon the value of the <atom:updated> element in the
|
||||
* returned feed or entry. A client can send this value back as the value of the
|
||||
* If-Modified-Since 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
|
||||
|
@ -63,42 +72,67 @@ public class DefaultGetHandler extends AbstractGdataRequestHandler {
|
|||
sendError();
|
||||
return;
|
||||
}
|
||||
Service service = getService();
|
||||
|
||||
try {
|
||||
String modifiedSince = this.feedRequest.getModifiedSince();
|
||||
if (!checkIsModified(modifiedSince)) {
|
||||
this.feedResponse
|
||||
.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
|
||||
return;
|
||||
}
|
||||
if (LOG.isInfoEnabled())
|
||||
LOG.info("Requested output formate: "
|
||||
+ this.feedRequest.getRequestedResponseFormat());
|
||||
this.feedResponse.setOutputFormat(this.feedRequest
|
||||
.getRequestedResponseFormat());
|
||||
if(this.feedRequest.isFeedRequested()){
|
||||
BaseFeed feed = service
|
||||
.getFeed(this.feedRequest, this.feedResponse);
|
||||
if (this.feedRequest.isFeedRequested()) {
|
||||
BaseFeed feed = this.service.getFeed(this.feedRequest,
|
||||
this.feedResponse);
|
||||
|
||||
this.feedResponse.sendResponse(feed, this.feedRequest.getExtensionProfile());
|
||||
}else{
|
||||
BaseEntry entry = service.getSingleEntry(this.feedRequest,this.feedResponse);
|
||||
if(entry == null){
|
||||
this.feedResponse.setError(HttpServletResponse.SC_NOT_FOUND);
|
||||
sendError();
|
||||
}
|
||||
this.feedResponse.sendResponse(entry, this.feedRequest.getExtensionProfile());
|
||||
this.feedResponse.sendResponse(feed, this.feedRequest
|
||||
.getConfigurator().getExtensionProfile());
|
||||
} else {
|
||||
BaseEntry entry = this.service.getSingleEntry(this.feedRequest,
|
||||
this.feedResponse);
|
||||
this.feedResponse.sendResponse(entry, this.feedRequest
|
||||
.getConfigurator().getExtensionProfile());
|
||||
}
|
||||
|
||||
|
||||
} catch (ServiceException e) { // TODO handle exceptions to send exact
|
||||
// response
|
||||
} catch (ServiceException e) {
|
||||
LOG.error("Could not process GetFeed request - " + e.getMessage(),
|
||||
e);
|
||||
this.feedResponse.setError(HttpServletResponse.SC_BAD_REQUEST); // TODO
|
||||
// change
|
||||
// this
|
||||
sendError();
|
||||
}
|
||||
|
||||
|
||||
closeService();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* returns true if the resource has been modified since the specified
|
||||
* reqeust header value
|
||||
*/
|
||||
private boolean checkIsModified(String lastModified)
|
||||
throws ServiceException {
|
||||
if (lastModified == null)
|
||||
return true;
|
||||
try {
|
||||
Date clientDate = DateFormater.parseDate(lastModified,DateFormater.HTTP_HEADER_DATE_FORMAT,DateFormater.HTTP_HEADER_DATE_FORMAT_TIME_OFFSET);
|
||||
Date entityDate;
|
||||
if (this.feedRequest.isFeedRequested())
|
||||
entityDate = this.service.getFeedLastModified(this.feedRequest
|
||||
.getFeedId());
|
||||
else
|
||||
entityDate = this.service.getEntryLastModified(this.feedRequest
|
||||
.getEntryId(),this.feedRequest.getFeedId());
|
||||
if(LOG.isInfoEnabled())
|
||||
LOG.info("comparing date clientDate: "+clientDate+"; lastmodified: "+entityDate);
|
||||
return (entityDate.getTime()-clientDate.getTime() > 1000);
|
||||
} catch (java.text.ParseException e) {
|
||||
LOG.info("Couldn't parse Last-Modified header -- "+lastModified,e);
|
||||
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -24,8 +24,8 @@ import javax.servlet.http.HttpServletResponse;
|
|||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.apache.lucene.gdata.data.GDataAccount.AccountRole;
|
||||
import org.apache.lucene.gdata.server.GDataRequestException;
|
||||
import org.apache.lucene.gdata.server.Service;
|
||||
import org.apache.lucene.gdata.server.ServiceException;
|
||||
import org.apache.lucene.gdata.server.GDataRequest.GDataRequestType;
|
||||
|
||||
|
@ -63,20 +63,23 @@ public class DefaultInsertHandler extends AbstractGdataRequestHandler {
|
|||
sendError();
|
||||
return;
|
||||
}
|
||||
if(!authenticateAccount(this.feedRequest,AccountRole.ENTRYAMINISTRATOR)){
|
||||
setError(HttpServletResponse.SC_UNAUTHORIZED);
|
||||
sendError();
|
||||
return;
|
||||
}
|
||||
|
||||
Service service = getService();
|
||||
try{
|
||||
BaseEntry entry = service.createEntry(this.feedRequest,this.feedResponse);
|
||||
BaseEntry entry = this.service.createEntry(this.feedRequest,this.feedResponse);
|
||||
setFeedResponseFormat();
|
||||
setFeedResponseStatus(HttpServletResponse.SC_CREATED);
|
||||
this.feedResponse.sendResponse(entry, this.feedRequest.getExtensionProfile());
|
||||
this.feedResponse.sendResponse(entry, this.feedRequest.getConfigurator().getExtensionProfile());
|
||||
|
||||
}catch (ServiceException e) {
|
||||
LOG.error("Could not process GetFeed request - "+e.getMessage(),e);
|
||||
setError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
|
||||
this.feedResponse.sendError();
|
||||
}
|
||||
|
||||
closeService();
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -16,54 +16,134 @@
|
|||
|
||||
package org.apache.lucene.gdata.servlet.handler;
|
||||
|
||||
import org.apache.lucene.gdata.server.registry.Component;
|
||||
import org.apache.lucene.gdata.server.registry.ComponentType;
|
||||
|
||||
/**
|
||||
* Default implementation for RequestHandlerFactory Builds the
|
||||
* {@link org.apache.lucene.gdata.servlet.handler.GDataRequestHandler}
|
||||
* instances.
|
||||
* 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.REQUESTHANDLERFACTORY)
|
||||
public class DefaultRequestHandlerFactory extends RequestHandlerFactory {
|
||||
|
||||
DefaultRequestHandlerFactory() {
|
||||
|
||||
/**
|
||||
* 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 DefaultRequestHandlerFactory() {
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.lucene.gdata.servlet.handler.RequestHandlerFactory#getUpdateHandler()
|
||||
* @see org.apache.lucene.gdata.servlet.handler.RequestHandlerFactory#getEntryUpdateHandler()
|
||||
*/
|
||||
@Override
|
||||
public GDataRequestHandler getUpdateHandler() {
|
||||
public GDataRequestHandler getEntryUpdateHandler() {
|
||||
|
||||
return new DefaultUpdateHandler();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.lucene.gdata.servlet.handler.RequestHandlerFactory#getDeleteHandler()
|
||||
* @see org.apache.lucene.gdata.servlet.handler.RequestHandlerFactory#getEntryDeleteHandler()
|
||||
*/
|
||||
@Override
|
||||
public GDataRequestHandler getDeleteHandler() {
|
||||
public GDataRequestHandler getEntryDeleteHandler() {
|
||||
|
||||
return new DefaultDeleteHandler();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.lucene.gdata.servlet.handler.RequestHandlerFactory#getQueryHandler()
|
||||
* @see org.apache.lucene.gdata.servlet.handler.RequestHandlerFactory#getFeedQueryHandler()
|
||||
*/
|
||||
@Override
|
||||
public GDataRequestHandler getQueryHandler() {
|
||||
public GDataRequestHandler getFeedQueryHandler() {
|
||||
|
||||
return new DefaultGetHandler();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.lucene.gdata.servlet.handler.RequestHandlerFactory#getInsertHandler()
|
||||
* @see org.apache.lucene.gdata.servlet.handler.RequestHandlerFactory#getEntryInsertHandler()
|
||||
*/
|
||||
@Override
|
||||
public GDataRequestHandler getInsertHandler() {
|
||||
public GDataRequestHandler getEntryInsertHandler() {
|
||||
|
||||
return new DefaultInsertHandler();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.lucene.gdata.servlet.handler.RequestHandlerFactory#getInsertAccountHandler()
|
||||
*/
|
||||
@Override
|
||||
public GDataRequestHandler getInsertAccountHandler() {
|
||||
|
||||
return new InsertAccountStrategy();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.lucene.gdata.servlet.handler.RequestHandlerFactory#getDeleteAccountHandler()
|
||||
*/
|
||||
@Override
|
||||
public GDataRequestHandler getDeleteAccountHandler() {
|
||||
|
||||
return new DeleteAccountStrategy();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.lucene.gdata.servlet.handler.RequestHandlerFactory#getUpdateAccountHandler()
|
||||
*/
|
||||
@Override
|
||||
public GDataRequestHandler getUpdateAccountHandler() {
|
||||
|
||||
return new UpdataAccountStrategy();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.lucene.gdata.servlet.handler.RequestHandlerFactory#getInsertFeedHandler()
|
||||
*/
|
||||
@Override
|
||||
public GDataRequestHandler getInsertFeedHandler() {
|
||||
|
||||
return new InsertFeedHandler();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.lucene.gdata.servlet.handler.RequestHandlerFactory#getUpdateFeedHandler()
|
||||
*/
|
||||
@Override
|
||||
public GDataRequestHandler getUpdateFeedHandler() {
|
||||
|
||||
return new UpdateFeedHandler();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.lucene.gdata.servlet.handler.RequestHandlerFactory#getDeleteFeedHandler()
|
||||
*/
|
||||
@Override
|
||||
public GDataRequestHandler getDeleteFeedHandler() {
|
||||
|
||||
return new DeleteFeedHandler();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.lucene.gdata.server.registry.ServerComponent#initialize()
|
||||
*/
|
||||
public void initialize() {
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.lucene.gdata.server.registry.ServerComponent#destroy()
|
||||
*/
|
||||
public void destroy() {
|
||||
//
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -23,9 +23,8 @@ import javax.servlet.http.HttpServletResponse;
|
|||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.apache.lucene.gdata.server.FeedNotFoundException;
|
||||
import org.apache.lucene.gdata.data.GDataAccount.AccountRole;
|
||||
import org.apache.lucene.gdata.server.GDataRequestException;
|
||||
import org.apache.lucene.gdata.server.Service;
|
||||
import org.apache.lucene.gdata.server.ServiceException;
|
||||
import org.apache.lucene.gdata.server.GDataRequest.GDataRequestType;
|
||||
|
||||
|
@ -62,33 +61,29 @@ public class DefaultUpdateHandler extends AbstractGdataRequestHandler {
|
|||
try {
|
||||
initializeRequestHandler(request, response,GDataRequestType.UPDATE);
|
||||
} catch (GDataRequestException e) {
|
||||
setError(HttpServletResponse.SC_UNAUTHORIZED);
|
||||
sendError();
|
||||
return;
|
||||
}
|
||||
if(!authenticateAccount(request,AccountRole.ENTRYAMINISTRATOR)){
|
||||
sendError();
|
||||
return;
|
||||
}
|
||||
|
||||
Service service = getService();
|
||||
try {
|
||||
BaseEntry entry = service.updateEntry(this.feedRequest,
|
||||
BaseEntry entry = this.service.updateEntry(this.feedRequest,
|
||||
this.feedResponse);
|
||||
setFeedResponseFormat();
|
||||
setFeedResponseStatus(HttpServletResponse.SC_OK);
|
||||
this.feedResponse.sendResponse(entry, this.feedRequest.getExtensionProfile());
|
||||
}catch (FeedNotFoundException e) {
|
||||
LOG.error("Could not process UpdateFeed request - "
|
||||
+ e.getMessage(), e);
|
||||
setError(HttpServletResponse.SC_NOT_FOUND);
|
||||
this.feedResponse.sendResponse(entry, this.feedRequest.getConfigurator().getExtensionProfile());
|
||||
|
||||
sendError();
|
||||
}
|
||||
catch (ServiceException e) {
|
||||
|
||||
LOG.error("Could not process UpdateFeed request - "
|
||||
+ e.getMessage(), e);
|
||||
setError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
|
||||
|
||||
sendError();
|
||||
}
|
||||
|
||||
closeService();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -16,107 +16,83 @@
|
|||
|
||||
package org.apache.lucene.gdata.servlet.handler;
|
||||
|
||||
import org.apache.lucene.gdata.server.registry.ServerComponent;
|
||||
|
||||
/**
|
||||
* Abstract Superclass for RequestHandlerFactories
|
||||
* @author Simon Willnauer
|
||||
*
|
||||
*/
|
||||
public abstract class RequestHandlerFactory {
|
||||
public abstract class RequestHandlerFactory implements ServerComponent {
|
||||
|
||||
|
||||
|
||||
private static RequestHandlerFactory INSTANCE = null;
|
||||
|
||||
/**
|
||||
* This method creates a singleton instance of the given type. The fist call
|
||||
* will create an instance of the given class which will be returned in
|
||||
* every subsequent call. Any subsequent call to this method will ignore the
|
||||
* given class object.
|
||||
*
|
||||
* @param factoryImplementation -
|
||||
* the factory implementation (must be a subtype of this Class)
|
||||
*
|
||||
* @return - a singleton instance of the given type
|
||||
*
|
||||
* 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 static synchronized RequestHandlerFactory getInstance(
|
||||
Class factoryImplementation) {
|
||||
if (INSTANCE == null) {
|
||||
|
||||
INSTANCE = createInstance(factoryImplementation);
|
||||
}
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Singleton - Pattern using private constructor
|
||||
*
|
||||
*/
|
||||
RequestHandlerFactory() {
|
||||
public RequestHandlerFactory() {
|
||||
super();
|
||||
|
||||
}
|
||||
|
||||
private static RequestHandlerFactory createInstance(
|
||||
final Class qualifiedClass) {
|
||||
if (qualifiedClass == null)
|
||||
throw new IllegalArgumentException(
|
||||
"Factory class is null -- must be a implementation of org.apache.lucene.gdata.servlet.handler.RequestHandlerFactory");
|
||||
try {
|
||||
return (RequestHandlerFactory) qualifiedClass.newInstance();
|
||||
} catch (Exception e) {
|
||||
FactoryImplementationException ex = new FactoryImplementationException(
|
||||
"Factory implementation could not be created", e.getCause());
|
||||
ex.setStackTrace(e.getStackTrace());
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a UpdateHandler which processes a GDATA UPDATE request.
|
||||
* @return - an RequestHandlerInstance
|
||||
* Creates a EntryUpdateHandler which processes a GDATA UPDATE request.
|
||||
* @return - a RequestHandlerInstance
|
||||
*/
|
||||
public abstract GDataRequestHandler getUpdateHandler();
|
||||
public abstract GDataRequestHandler getEntryUpdateHandler();
|
||||
|
||||
/**
|
||||
* Creates a DeleteHandler which processes a GDATA DELETE request.
|
||||
* @return - an RequestHandlerInstance
|
||||
* Creates a EntryDeleteHandler which processes a GDATA DELETE request.
|
||||
* @return - a RequestHandlerInstance
|
||||
*/
|
||||
public abstract GDataRequestHandler getDeleteHandler();
|
||||
public abstract GDataRequestHandler getEntryDeleteHandler();
|
||||
|
||||
/**
|
||||
* Creates a QueryHandler which processes a GDATA Query / Get request.
|
||||
* @return - an RequestHandlerInstance
|
||||
* Creates a FeedQueryHandler which processes a GDATA Query / Get request.
|
||||
* @return - a RequestHandlerInstance
|
||||
*/
|
||||
public abstract GDataRequestHandler getQueryHandler();
|
||||
public abstract GDataRequestHandler getFeedQueryHandler();
|
||||
|
||||
/**
|
||||
* Creates a InsertHandler which processes a GDATA Insert request.
|
||||
* @return - an RequestHandlerInstance
|
||||
* Creates a EntryInsertHandler which processes a GDATA Insert request.
|
||||
* @return - a RequestHandlerInstance
|
||||
*/
|
||||
public abstract GDataRequestHandler getInsertHandler();
|
||||
|
||||
|
||||
|
||||
private static class FactoryImplementationException extends
|
||||
RuntimeException {
|
||||
|
||||
public abstract GDataRequestHandler getEntryInsertHandler();
|
||||
/**
|
||||
*
|
||||
* Creates a InsertAccountHandler which processes a Account Insert request.
|
||||
* @return - a RequestHandlerInstance
|
||||
*/
|
||||
private static final long serialVersionUID = 3166033278825112569L;
|
||||
|
||||
public abstract GDataRequestHandler getInsertAccountHandler();
|
||||
/**
|
||||
* Constructs a new FactoryImplementationException with the specified
|
||||
* cause and message
|
||||
*
|
||||
* @param arg0 -
|
||||
* the detail message
|
||||
* @param arg1 -
|
||||
* the throw cause
|
||||
* Creates a DeleteAccountHandler which processes a Account Delete request.
|
||||
* @return - a RequestHandlerInstance
|
||||
*/
|
||||
public FactoryImplementationException(String arg0, Throwable arg1) {
|
||||
super(arg0, arg1);
|
||||
public abstract GDataRequestHandler getDeleteAccountHandler();
|
||||
/**
|
||||
* Creates a UpdateAccountHandler which processes a Account Update request.
|
||||
* @return - a RequestHandlerInstance
|
||||
*/
|
||||
public abstract GDataRequestHandler getUpdateAccountHandler();
|
||||
/**
|
||||
* Creates a InsertFeedHandler which processes a Feed Insert request.
|
||||
* @return - a RequestHandlerInstance
|
||||
*/
|
||||
public abstract GDataRequestHandler getInsertFeedHandler();
|
||||
/**
|
||||
* Creates a UpdateFeedHandler which processes a Feed Insert request.
|
||||
* @return - a RequestHandlerInstance
|
||||
*/
|
||||
public abstract GDataRequestHandler getUpdateFeedHandler();
|
||||
/**
|
||||
* Creates a DeleteFeedHandler which processes a Feed Insert request.
|
||||
* @return - a RequestHandlerInstance
|
||||
*/
|
||||
public abstract GDataRequestHandler getDeleteFeedHandler();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -53,6 +53,8 @@ public class IDGenerator {
|
|||
|
||||
protected static final Log LOGGER = LogFactory.getLog(IDGenerator.class);
|
||||
|
||||
private static final String RUNNER_THREAD_NAME = "GDATA-ID Generator";
|
||||
|
||||
/**
|
||||
* Constructs a new ID generator. with a fixed capacity of prebuild ids. The
|
||||
* default capacity is 10. Every given parameter less than 10 will be
|
||||
|
@ -92,6 +94,8 @@ public class IDGenerator {
|
|||
UIDProducer producer = new UIDProducer(this.blockingQueue,
|
||||
this.secureRandom, this.mdigest);
|
||||
this.runner = new Thread(producer);
|
||||
this.runner.setDaemon(true);
|
||||
this.runner.setName(RUNNER_THREAD_NAME);
|
||||
this.runner.start();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,86 +15,260 @@
|
|||
*/
|
||||
package org.apache.lucene.gdata.storage;
|
||||
|
||||
import java.util.List;
|
||||
import org.apache.lucene.gdata.data.GDataAccount;
|
||||
import org.apache.lucene.gdata.data.ServerBaseEntry;
|
||||
import org.apache.lucene.gdata.data.ServerBaseFeed;
|
||||
|
||||
import com.google.gdata.data.BaseEntry;
|
||||
import com.google.gdata.data.BaseFeed;
|
||||
import com.google.gdata.data.ExtensionProfile;
|
||||
|
||||
/**
|
||||
* This is the main storage interface. The Storage represents the internal
|
||||
* server storage. It acts as a Database to persist the feed data.
|
||||
* This inferface is not public yet!!
|
||||
* A interface every storage implementation must provide to access the
|
||||
* <tt>Storage</tt>. It describes all access methodes needed to store,
|
||||
* retrieve and look up data stored in the <tt>Storage</tt> component. This
|
||||
* interface acts as a <tt>Facade</tt> to hide the storage implementation from
|
||||
* the user.
|
||||
* <p>
|
||||
* This could also act as a proxy for a remote storage. It also removes any
|
||||
* restrictions from custom storage implementations.
|
||||
* </p>
|
||||
*
|
||||
*
|
||||
* @author Simon Willnauer
|
||||
*
|
||||
*/
|
||||
/*
|
||||
* not final yet
|
||||
*/
|
||||
public interface Storage {
|
||||
|
||||
/**
|
||||
* This stores an incoming entry for a later retrival.
|
||||
* The Entry will be associated with the feedid.
|
||||
* @param entry - the entry
|
||||
* @param feedId - the feedID
|
||||
* @return - the stored Entry
|
||||
* @throws StorageException
|
||||
*
|
||||
* Stores the given entry. The ServerBaseEntry must provide a feed id and
|
||||
* the service type. configuration for the entry.
|
||||
*
|
||||
* @param entry -
|
||||
* the entry to store
|
||||
*
|
||||
* @return - the stored Entry for the server response
|
||||
* @throws StorageException -
|
||||
* if the entry can not be stored or required field are not set.
|
||||
*/
|
||||
public abstract BaseEntry storeEntry(BaseEntry entry, String feedId)
|
||||
public abstract BaseEntry storeEntry(ServerBaseEntry entry)
|
||||
throws StorageException;
|
||||
|
||||
/**
|
||||
* @param entryId
|
||||
* @param feedId
|
||||
* @throws StorageException
|
||||
* Deletes the given entry. The ServerBaseEntry just hase to provide the
|
||||
* entry id to be deleted.
|
||||
*
|
||||
* @param entry -
|
||||
* the entry to delete from the storage
|
||||
* @throws StorageException -
|
||||
* if the entry can not be deleted or the entry does not exist
|
||||
* or required field are not set.
|
||||
*/
|
||||
public abstract void deleteEntry(String entryId, String feedId)
|
||||
public abstract void deleteEntry(ServerBaseEntry entry)
|
||||
throws StorageException;
|
||||
|
||||
/**
|
||||
* @param entry
|
||||
* @param feedId
|
||||
* @return
|
||||
* @throws StorageException
|
||||
* Updates the given entry. The ServerBaseEntry must provide a feed id,
|
||||
* service id and the
|
||||
* {@link org.apache.lucene.gdata.server.registry.ProvidedService}
|
||||
*
|
||||
* @param entry -
|
||||
* the entry to update
|
||||
*
|
||||
* @return - the updated entry for server response.
|
||||
* @throws StorageException -
|
||||
* if the entry can not be updated or does not exist or required
|
||||
* field are not set.
|
||||
*/
|
||||
public abstract BaseEntry updateEntry(BaseEntry entry, String feedId)
|
||||
public abstract BaseEntry updateEntry(ServerBaseEntry entry)
|
||||
throws StorageException;
|
||||
|
||||
/**
|
||||
* @param feedId
|
||||
* @param startIndex
|
||||
* @param resultCount
|
||||
* @return
|
||||
* @throws StorageException
|
||||
* Retrieves the requested feed from the storage. The given ServerBaseFeed
|
||||
* must provide information about the feed id, max-result count and the
|
||||
* start index. To create feeds and entries also the service type must be
|
||||
* provided.
|
||||
*
|
||||
* @param feed -
|
||||
* the to retieve from the storage
|
||||
* @return the requested feed
|
||||
* @throws StorageException -
|
||||
* the feed does not exist or can not be retrieved or required
|
||||
* field are not set.
|
||||
*/
|
||||
public abstract BaseFeed getFeed(String feedId, int startIndex,
|
||||
int resultCount) throws StorageException;
|
||||
|
||||
/**
|
||||
* @param entryId
|
||||
* @param feedId
|
||||
* @return
|
||||
* @throws StorageException
|
||||
*/
|
||||
public abstract BaseEntry getEntry(String entryId, String feedId)
|
||||
public abstract BaseFeed getFeed(ServerBaseFeed feed)
|
||||
throws StorageException;
|
||||
|
||||
/**
|
||||
* @param entryIdList
|
||||
* @param feedId
|
||||
* @return
|
||||
* @throws StorageException
|
||||
* Retrieves the requested entry from the storage. The given entry must
|
||||
* provide information about the entry id and service type.
|
||||
*
|
||||
* @param entry -
|
||||
* the entry to retrieve
|
||||
* @return - the requested entry
|
||||
* @throws StorageException -
|
||||
* if the entry does not exist or can not be created or required
|
||||
* field are not set.
|
||||
*/
|
||||
public abstract List<BaseEntry> getEntries(List<String> entryIdList,
|
||||
String feedId) throws StorageException;
|
||||
public abstract BaseEntry getEntry(ServerBaseEntry entry)
|
||||
throws StorageException;
|
||||
|
||||
/**
|
||||
* @param profile
|
||||
* Saves a new account. Required attributes to set are <tt>password</tt>
|
||||
* and <tt>accountname</tt>
|
||||
*
|
||||
* @param account -
|
||||
* the account to save
|
||||
* @throws StorageException -
|
||||
* if the account can not be stored or the account already
|
||||
* exists or required field are not set.
|
||||
*/
|
||||
public abstract void setExtensionProfile(final ExtensionProfile profile);
|
||||
public abstract void storeAccount(final GDataAccount account)
|
||||
throws StorageException;
|
||||
|
||||
/**
|
||||
* close this storage instance
|
||||
* Updates an existing account. Required attributes to set are
|
||||
* <tt>password</tt> and <tt>accountname</tt>
|
||||
*
|
||||
* @param account -
|
||||
* the account to update
|
||||
* @throws StorageException -
|
||||
* if the account does not exist or required field are not set.
|
||||
*/
|
||||
public abstract void updateAccount(final GDataAccount account)
|
||||
throws StorageException;
|
||||
|
||||
/**
|
||||
* Deletes the account for the given account name. All feeds and entries
|
||||
* referencing this account will be deleted as well!
|
||||
*
|
||||
* @param accountname -
|
||||
* the name of the account to delete
|
||||
* @throws StorageException -
|
||||
* if the account does not exist
|
||||
*/
|
||||
public abstract void deleteAccount(final String accountname)
|
||||
throws StorageException;
|
||||
|
||||
/**
|
||||
* Stores a new feed for a existing account. The Feed must provide
|
||||
* information about the service type to store the feed for and the feed id
|
||||
* used for accessing and retrieving the feed from the storage. Each feed is
|
||||
* associated with a provided service. This method does check wheather a
|
||||
* feed with the same feed id as the given feed does already exists.
|
||||
*
|
||||
* @see org.apache.lucene.gdata.server.registry.ProvidedService
|
||||
* @param feed -
|
||||
* the feed to create
|
||||
* @param accountname -
|
||||
* the account name belongs to the feed
|
||||
* @throws StorageException -
|
||||
* if the feed already exists or the feed can not be stored
|
||||
*/
|
||||
public abstract void storeFeed(final ServerBaseFeed feed, String accountname)
|
||||
throws StorageException;
|
||||
|
||||
/**
|
||||
* Deletes the feed for the given feed id. All Entries referencing the given
|
||||
* feed id will be deleted as well.
|
||||
*
|
||||
* @param feedId -
|
||||
* the feed id for the feed to delete.
|
||||
* @throws StorageException -
|
||||
* if the feed for the feed id does not exist or the feed can
|
||||
* not be deleted
|
||||
*/
|
||||
public abstract void deleteFeed(final String feedId)
|
||||
throws StorageException;
|
||||
|
||||
/**
|
||||
* Updates a stored feed. The Feed must provide information about the
|
||||
* service type to store the feed for and the feed id used for accessing and
|
||||
* retrieving the feed from the storage.
|
||||
*
|
||||
* @param feed -
|
||||
* the feed to update
|
||||
* @param accountname -
|
||||
* the account name belongs to the feed
|
||||
* @throws StorageException -
|
||||
* if the feed does not exist or the feed can not be updated
|
||||
*/
|
||||
public abstract void updateFeed(final ServerBaseFeed feed,
|
||||
String accountname) throws StorageException;
|
||||
|
||||
/**
|
||||
* Retrieves the service name for a stored feed
|
||||
*
|
||||
* @param feedId -
|
||||
* the feed id
|
||||
* @return - the name of the service
|
||||
* @throws StorageException -
|
||||
* if no feed for the provided id is stored
|
||||
*/
|
||||
public abstract String getServiceForFeed(String feedId)
|
||||
throws StorageException;
|
||||
|
||||
/**
|
||||
* @param accountName -
|
||||
* the name of the requested account
|
||||
* @return - a {@link GDataAccount} instance for the requested account name
|
||||
* @throws StorageException -
|
||||
* if no account for the account name is stored
|
||||
*
|
||||
*/
|
||||
public abstract GDataAccount getAccount(String accountName)
|
||||
throws StorageException;
|
||||
|
||||
/**
|
||||
* close this storage instance. This method will be called by clients after
|
||||
* use.
|
||||
*/
|
||||
public abstract void close();
|
||||
|
||||
/**
|
||||
* Each feed belongs to one specific account. This method retrieves the
|
||||
* account name for
|
||||
*
|
||||
* @param feedId -
|
||||
* the id of the feed to retrieve the accountname
|
||||
* @return - the name / id of the account associated with the feed for the
|
||||
* given feed id
|
||||
* @throws StorageException -
|
||||
* if the feed is not stored or the storage can not be accessed
|
||||
*/
|
||||
public String getAccountNameForFeedId(String feedId)
|
||||
throws StorageException;
|
||||
|
||||
/**
|
||||
* Retrieves the date of the last modification for the given id
|
||||
*
|
||||
* @param entryId -
|
||||
* the entry Id
|
||||
* @param feedId -
|
||||
* the feed which contains the entry
|
||||
* @return - The date of the last modifiaction in milliseconds or
|
||||
* <code>new Long(0)</code> if the resource can not be found eg.
|
||||
* the time can not be accessed
|
||||
* @throws StorageException -
|
||||
* if the storage can not be accessed
|
||||
*/
|
||||
public Long getEntryLastModified(String entryId, String feedId)
|
||||
throws StorageException;
|
||||
|
||||
/**
|
||||
* Retrieves the date of the last modification for the given id
|
||||
*
|
||||
* @param feedId -
|
||||
* the feed Id
|
||||
* @return - The date of the last modifiaction in milliseconds or
|
||||
* <code>new Long(0)</code> if the resource can not be found eg.
|
||||
* the time can not be accessed
|
||||
* @throws StorageException -
|
||||
* if the storage can not be accessed
|
||||
*/
|
||||
public Long getFeedLastModified(String feedId) throws StorageException;
|
||||
|
||||
}
|
||||
|
|
|
@ -15,13 +15,47 @@
|
|||
*/
|
||||
package org.apache.lucene.gdata.storage;
|
||||
|
||||
import org.apache.lucene.gdata.server.registry.ServerComponent;
|
||||
|
||||
/**
|
||||
* An interface to define a central storage controller acting as a
|
||||
* <tt>Stroage</tt> Factory. The <tt>StroageController</tt> manages the
|
||||
* storage logic. Subclasses of {@link StorageController} can be registered as
|
||||
* {@link org.apache.lucene.gdata.server.registry.Component} in the
|
||||
* {@link org.apache.lucene.gdata.server.registry.GDataServerRegistry}. A
|
||||
* single instance of the contorller will be loaded and passed to clients via
|
||||
* the lookup service.
|
||||
* <p>
|
||||
* This instances, registered in the registry must be thread save as they are
|
||||
* shared between several clients
|
||||
* </p>
|
||||
* <p>
|
||||
* Each StroageController implementation must provide a super user
|
||||
* {@link org.apache.lucene.gdata.data.GDataAccount} with all
|
||||
* {@link org.apache.lucene.gdata.data.GDataAccount.AccountRole} set. This
|
||||
* account must have the defined name <i>administrator</i> and a default
|
||||
* password <i>password</i>. The password has to be updated by the server
|
||||
* administrator before production use.
|
||||
* To get the predefinded GDataAccount use {@link org.apache.lucene.gdata.data.GDataAccount#createAdminAccount()}
|
||||
* </p>
|
||||
*
|
||||
*
|
||||
* @author Simon Willnauer
|
||||
*
|
||||
*/
|
||||
public interface StorageController {
|
||||
/**
|
||||
* Destroys the controller
|
||||
public interface StorageController extends ServerComponent {
|
||||
/**
|
||||
* Destroys the controller - this method is called by the registry when the
|
||||
* context will be destroyed
|
||||
*/
|
||||
public abstract void destroy();
|
||||
public abstract void destroy();
|
||||
|
||||
/**
|
||||
* Creates Storage instances to access the underlaying storage component
|
||||
*
|
||||
* @return a storage instance
|
||||
* @throws StorageException -
|
||||
* if the storage instance can not be created
|
||||
*/
|
||||
public abstract Storage getStorage() throws StorageException;
|
||||
}
|
||||
|
|
|
@ -1,44 +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.storage;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.apache.lucene.gdata.storage.lucenestorage.StorageImplementation;
|
||||
|
||||
/**
|
||||
*TODO document me
|
||||
* @author Simon Willnauer
|
||||
*
|
||||
*/
|
||||
public class StorageFactory {
|
||||
/**
|
||||
* Creates a {@link Storage} instance
|
||||
* @return - a storage instance
|
||||
* @throws StorageException - if the storage can not be created
|
||||
*/
|
||||
public static Storage getStorage()throws StorageException{
|
||||
try {
|
||||
return new StorageImplementation();
|
||||
} catch (IOException e) {
|
||||
StorageException ex = new StorageException("Can't create Storage instance -- "
|
||||
+ e.getMessage(), e);
|
||||
ex.setStackTrace(e.getStackTrace());
|
||||
throw ex;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
|
@ -20,8 +20,11 @@ import java.util.ArrayList;
|
|||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import java.util.concurrent.locks.ReadWriteLock;
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||
|
@ -30,6 +33,10 @@ import org.apache.commons.logging.Log;
|
|||
import org.apache.commons.logging.LogFactory;
|
||||
import org.apache.lucene.gdata.storage.lucenestorage.StorageEntryWrapper.StorageOperation;
|
||||
|
||||
import com.google.gdata.data.BaseEntry;
|
||||
import com.google.gdata.data.ExtensionProfile;
|
||||
import com.google.gdata.data.Link;
|
||||
|
||||
/**
|
||||
* The StorageBuffer is used to buffer incoming updates, deletes and inserts to
|
||||
* the storage. The storage uses an lucene index to store the enries. As
|
||||
|
@ -57,6 +64,8 @@ public class StorageBuffer {
|
|||
|
||||
private final Map<String, Map<String, StorageEntryWrapper>> bufferMap;
|
||||
|
||||
private final Map<String, Long> modifiyMap;
|
||||
|
||||
private final List<String> excludeList;
|
||||
|
||||
private final ReadWriteLock lock = new ReentrantReadWriteLock(true);
|
||||
|
@ -86,6 +95,9 @@ public class StorageBuffer {
|
|||
this.excludeList = new ArrayList<String>(
|
||||
expectedBufferCount < DEFAULT_BUFFER_COUNT ? DEFAULT_BUFFER_COUNT
|
||||
: expectedBufferCount);
|
||||
this.modifiyMap = new HashMap<String, Long>(
|
||||
expectedBufferCount < DEFAULT_BUFFER_COUNT ? DEFAULT_BUFFER_COUNT
|
||||
: expectedBufferCount);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -114,7 +126,9 @@ public class StorageBuffer {
|
|||
20);
|
||||
newFeedMap.put(wrapper.getEntryId(), wrapper);
|
||||
this.bufferMap.put(feedId, newFeedMap);
|
||||
|
||||
}
|
||||
addLastModified(wrapper.getFeedId(),wrapper.getTimestamp());
|
||||
} finally {
|
||||
/*
|
||||
* add all to exclude from searches doc will be available via the
|
||||
|
@ -125,6 +139,22 @@ public class StorageBuffer {
|
|||
}
|
||||
}
|
||||
|
||||
private void addLastModified(final String feedId,Long timestamp){
|
||||
if(this.modifiyMap.containsKey(feedId))
|
||||
this.modifiyMap.remove(feedId);
|
||||
this.modifiyMap.put(feedId,timestamp);
|
||||
|
||||
}
|
||||
|
||||
protected Long getFeedLastModified(final String feedId){
|
||||
return this.modifiyMap.get(feedId);
|
||||
}
|
||||
protected Set<Entry<String,Long>> getLastModified(){
|
||||
return this.modifiyMap.entrySet();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns all entries for the given feed id sorted by the update timestamp
|
||||
* desc.
|
||||
|
@ -173,6 +203,7 @@ public class StorageBuffer {
|
|||
if (tempMap == null)
|
||||
return;
|
||||
tempMap.remove(entryId);
|
||||
this.addLastModified(feedId,new Long(System.currentTimeMillis()));
|
||||
} finally {
|
||||
this.writeLock.unlock();
|
||||
|
||||
|
@ -230,6 +261,7 @@ public class StorageBuffer {
|
|||
private void clearBuffer() {
|
||||
this.bufferMap.clear();
|
||||
this.excludeList.clear();
|
||||
this.modifiyMap.clear();
|
||||
|
||||
}
|
||||
|
||||
|
@ -246,4 +278,35 @@ public class StorageBuffer {
|
|||
|
||||
}
|
||||
|
||||
|
||||
static class BufferableEntry extends BaseEntry{
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public BufferableEntry() {
|
||||
super();
|
||||
this.links = new LinkedList<Link>();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param arg0
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public BufferableEntry(BaseEntry arg0) {
|
||||
super(arg0);
|
||||
this.links = new LinkedList<Link>();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see com.google.gdata.data.BaseEntry#declareExtensions(com.google.gdata.data.ExtensionProfile)
|
||||
*/
|
||||
@Override
|
||||
public void declareExtensions(ExtensionProfile arg0) {
|
||||
//
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -6,145 +6,174 @@ 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.server.registry.GDataServerRegistry;
|
||||
import org.apache.lucene.gdata.data.GDataAccount;
|
||||
import org.apache.lucene.gdata.server.registry.Component;
|
||||
import org.apache.lucene.gdata.server.registry.ComponentType;
|
||||
import org.apache.lucene.gdata.storage.IDGenerator;
|
||||
import org.apache.lucene.gdata.storage.Storage;
|
||||
import org.apache.lucene.gdata.storage.StorageController;
|
||||
import org.apache.lucene.gdata.storage.StorageException;
|
||||
import org.apache.lucene.gdata.storage.lucenestorage.configuration.StorageConfigurator;
|
||||
import org.apache.lucene.gdata.storage.lucenestorage.util.ReferenceCounter;
|
||||
import org.apache.lucene.index.IndexModifier;
|
||||
import org.apache.lucene.index.IndexWriter;
|
||||
import org.apache.lucene.search.IndexSearcher;
|
||||
import org.apache.lucene.store.Directory;
|
||||
import org.apache.lucene.store.FSDirectory;
|
||||
import org.apache.lucene.store.RAMDirectory;
|
||||
|
||||
/**
|
||||
* TODO document this
|
||||
*
|
||||
*
|
||||
* @author Simon Willnauer
|
||||
*
|
||||
*/
|
||||
public class StorageCoreController implements StorageController{
|
||||
protected static final Log LOG = LogFactory.getLog(StorageCoreController.class);
|
||||
@Component(componentType = ComponentType.STORAGECONTROLLER)
|
||||
public class StorageCoreController implements StorageController {
|
||||
protected static final Log LOG = LogFactory
|
||||
.getLog(StorageCoreController.class);
|
||||
|
||||
private IndexSearcher searcher;
|
||||
private static StorageCoreController coreController;
|
||||
|
||||
private final Directory storageDir;
|
||||
|
||||
private final StorageModifier modifier;
|
||||
|
||||
private ReferenceCounter<StorageQuery> storageQuery;
|
||||
|
||||
private StorageBuffer currentBuffer;
|
||||
|
||||
private Object storageControllerLock = new Object();
|
||||
|
||||
private static final int DEFAULT_STORAGE_BUFFER_SIZE = 10;
|
||||
|
||||
private static final int DEFAULT_STORAGE_PERSIST_FACTOR = 10;
|
||||
|
||||
private static final String STORAGELOG = ".lucenestorage";
|
||||
|
||||
private int storageBufferSize;
|
||||
|
||||
private int storagePersistFactor;
|
||||
|
||||
private StorageConfigurator configurator;
|
||||
|
||||
private IDGenerator idGenerator;
|
||||
|
||||
private int indexOptimizeInterval;
|
||||
|
||||
private StorageCoreController()throws IOException, StorageException{
|
||||
this(null);
|
||||
}
|
||||
// private RecoverController recoverController;
|
||||
|
||||
|
||||
|
||||
|
||||
private StorageCoreController(final Directory dir) throws IOException, StorageException {
|
||||
/**
|
||||
* Creates a new <tt>StoragCoreController</tt> and sets up the storage
|
||||
* environment reading the configuration file.
|
||||
*
|
||||
*
|
||||
*
|
||||
* @throws IOException -
|
||||
* if an IOException occures
|
||||
* @throws StorageException -
|
||||
* if the storage lock can not be created or the
|
||||
* {@link IDGenerator} can not be loaded
|
||||
*/
|
||||
public StorageCoreController() throws IOException, StorageException {
|
||||
synchronized (StorageCoreController.class) {
|
||||
try{
|
||||
try {
|
||||
this.idGenerator = new IDGenerator(10);
|
||||
}catch (Exception e) {
|
||||
throw new StorageException("Can't create ID Generator",e);
|
||||
} catch (Exception e) {
|
||||
throw new StorageException("Can't create ID Generator", e);
|
||||
}
|
||||
|
||||
boolean createNewStorage = false;
|
||||
|
||||
if(dir == null){
|
||||
this.configurator = StorageConfigurator.getStorageConfigurator();
|
||||
if (!this.configurator.isRamDirectory()) {
|
||||
|
||||
String storageDirPath = this.configurator.getStorageDirectory();
|
||||
File storeDir = new File(storageDirPath);
|
||||
File storageLog = new File(storeDir.getAbsolutePath()+System.getProperty("file.separator")+STORAGELOG);
|
||||
try{
|
||||
if(storeDir.isDirectory() && !storageLog.exists()){
|
||||
File storageLog = new File(storeDir.getAbsolutePath()
|
||||
+ System.getProperty("file.separator") + STORAGELOG);
|
||||
try {
|
||||
if (storeDir.isDirectory() && !storageLog.exists()) {
|
||||
|
||||
if(createLuceneStorageLog(storeDir)){
|
||||
this.storageDir = FSDirectory.getDirectory(storeDir,true);
|
||||
if (createLuceneStorageLog(storeDir)) {
|
||||
this.storageDir = FSDirectory.getDirectory(
|
||||
storeDir, true);
|
||||
createNewStorage = true;
|
||||
}
|
||||
else
|
||||
throw new StorageException("could not create storage log file in "+storageDirPath);
|
||||
} else
|
||||
throw new StorageException(
|
||||
"could not create storage lock file in "
|
||||
+ storageDirPath);
|
||||
|
||||
}else
|
||||
this.storageDir = FSDirectory.getDirectory(storeDir,false);
|
||||
}catch (IOException e) {
|
||||
} else
|
||||
this.storageDir = FSDirectory.getDirectory(storeDir,
|
||||
false);
|
||||
} catch (IOException e) {
|
||||
storageLog.delete();
|
||||
throw e;
|
||||
}
|
||||
this.indexOptimizeInterval = this.configurator.getIndexOptimizeInterval();
|
||||
this.storageBufferSize = this.configurator.getStorageBufferSize() < DEFAULT_STORAGE_BUFFER_SIZE?DEFAULT_STORAGE_BUFFER_SIZE:this.configurator.getStorageBufferSize();
|
||||
this.storagePersistFactor = this.configurator.getStoragepersistFactor() < DEFAULT_STORAGE_PERSIST_FACTOR? DEFAULT_STORAGE_PERSIST_FACTOR:this.configurator.getStoragepersistFactor();
|
||||
this.indexOptimizeInterval = this.configurator
|
||||
.getIndexOptimizeInterval();
|
||||
this.storageBufferSize = this.configurator
|
||||
.getStorageBufferSize() < DEFAULT_STORAGE_BUFFER_SIZE ? DEFAULT_STORAGE_BUFFER_SIZE
|
||||
: this.configurator.getStorageBufferSize();
|
||||
this.storagePersistFactor = this.configurator
|
||||
.getStoragepersistFactor() < DEFAULT_STORAGE_PERSIST_FACTOR ? DEFAULT_STORAGE_PERSIST_FACTOR
|
||||
: this.configurator.getStoragepersistFactor();
|
||||
|
||||
}
|
||||
else
|
||||
this.storageDir = dir;
|
||||
} else
|
||||
this.storageDir = getRamDirectory();
|
||||
|
||||
this.currentBuffer = new StorageBuffer(this.storageBufferSize);
|
||||
this.modifier = createStorageModifier(createNewStorage);
|
||||
this.searcher = new IndexSearcher(this.storageDir);
|
||||
|
||||
|
||||
GDataServerRegistry.getRegistry().registerStorage(this);// TODO reverse dependency here
|
||||
|
||||
|
||||
// this.recoverController = new RecoverController(null,this.configurator.isRecover(),this.configurator.isKeepRecoveredFiles());
|
||||
if(createNewStorage)
|
||||
createAdminAccount();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
private StorageModifier createStorageModifier(boolean create) throws IOException{
|
||||
IndexModifier indexModifier = new IndexModifier(this.storageDir,new StandardAnalyzer(),create);
|
||||
return new StorageModifier(indexModifier,this.currentBuffer,this.storagePersistFactor,this.indexOptimizeInterval);
|
||||
|
||||
private StorageModifier createStorageModifier(boolean create)
|
||||
throws IOException {
|
||||
IndexModifier indexModifier = new IndexModifier(this.storageDir,
|
||||
new StandardAnalyzer(), create);
|
||||
return new StorageModifier(this, indexModifier, this.currentBuffer,
|
||||
this.storagePersistFactor, this.indexOptimizeInterval);
|
||||
}
|
||||
/**TODO document this
|
||||
* @return
|
||||
|
||||
/**
|
||||
* returns the current storage modifier
|
||||
*
|
||||
* @return - the current storage modifier
|
||||
*/
|
||||
public StorageModifier getStorageModifier(){
|
||||
protected StorageModifier getStorageModifier() {
|
||||
return this.modifier;
|
||||
}
|
||||
|
||||
/**TODO document this
|
||||
* @return
|
||||
* @throws IOException
|
||||
* @throws StorageException
|
||||
/**
|
||||
* returns a <tt>StorageQuery</tt> to query the storage index. The
|
||||
* returned object is a reference counter to keep track of the references to
|
||||
* the <tt>StorageQuery</tt>. The reference is already incremented before
|
||||
* returned from this method.
|
||||
* <p>
|
||||
* if the reference counter has no remaining references the resource e.g.
|
||||
* the <tt>StorageQuery</tt> will be closed. This ensures that a
|
||||
* <tt>StorageQuery</tt> instance will be arround as long as needed and
|
||||
* the resources will be released. The reference counter should be
|
||||
* decremented by clients after finished using the query instance.
|
||||
* </p>
|
||||
*
|
||||
* @return a {@link ReferenceCounter} instance holding the StorageQuery as a
|
||||
* resource.
|
||||
*
|
||||
*/
|
||||
public static StorageCoreController getStorageCoreController() throws IOException, StorageException{
|
||||
synchronized (StorageCoreController.class) {
|
||||
if(coreController == null)
|
||||
coreController = new StorageCoreController();
|
||||
return coreController;
|
||||
}
|
||||
}
|
||||
/**TODO document this
|
||||
* @param dir
|
||||
* @return
|
||||
* @throws IOException
|
||||
* @throws StorageException
|
||||
*/
|
||||
protected static StorageCoreController getStorageCoreController(final Directory dir) throws IOException, StorageException{
|
||||
synchronized (StorageCoreController.class) {
|
||||
if(coreController == null)
|
||||
coreController = new StorageCoreController(dir);
|
||||
return coreController;
|
||||
}
|
||||
}
|
||||
|
||||
/**TODO document this
|
||||
* @return
|
||||
* @throws IOException
|
||||
*/
|
||||
public ReferenceCounter<StorageQuery> getStorageQuery() throws IOException {
|
||||
protected ReferenceCounter<StorageQuery> getStorageQuery() {
|
||||
synchronized (this.storageControllerLock) {
|
||||
|
||||
if(this.storageQuery == null){
|
||||
this.storageQuery = getNewStorageQueryHolder(new StorageQuery(this.currentBuffer,this.searcher));
|
||||
if(LOG.isInfoEnabled())
|
||||
if (this.storageQuery == null) {
|
||||
this.storageQuery = getNewStorageQueryHolder(new StorageQuery(
|
||||
this.currentBuffer, this.searcher));
|
||||
if (LOG.isInfoEnabled())
|
||||
LOG.info("Relese new StorageQuery");
|
||||
}
|
||||
this.storageQuery.increamentReference();
|
||||
|
@ -152,15 +181,19 @@ public class StorageCoreController implements StorageController{
|
|||
}
|
||||
}
|
||||
|
||||
private ReferenceCounter<StorageQuery> getNewStorageQueryHolder(final StorageQuery query){
|
||||
ReferenceCounter<StorageQuery> holder = new ReferenceCounter<StorageQuery>(query){
|
||||
public void close(){
|
||||
try{
|
||||
if(LOG.isInfoEnabled())
|
||||
LOG.info("close StorageQuery -- zero references remaining");
|
||||
private ReferenceCounter<StorageQuery> getNewStorageQueryHolder(
|
||||
final StorageQuery query) {
|
||||
ReferenceCounter<StorageQuery> holder = new ReferenceCounter<StorageQuery>(
|
||||
query) {
|
||||
public void close() {
|
||||
try {
|
||||
if (LOG.isInfoEnabled())
|
||||
LOG
|
||||
.info("close StorageQuery -- zero references remaining");
|
||||
this.resource.close();
|
||||
}catch (IOException e) {
|
||||
LOG.warn("Error during close call on StorageQuery"+e.getMessage(),e);
|
||||
} catch (IOException e) {
|
||||
LOG.warn("Error during close call on StorageQuery"
|
||||
+ e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -168,13 +201,19 @@ public class StorageCoreController implements StorageController{
|
|||
return holder;
|
||||
}
|
||||
|
||||
|
||||
|
||||
protected void registerNewStorageQuery() throws IOException{
|
||||
if(LOG.isInfoEnabled())
|
||||
/**
|
||||
* Forces the controller to register a new <tt>StorageQuery</tt> instance.
|
||||
* This method will be called after an index has been modified to make the
|
||||
* changes available for searching.
|
||||
*
|
||||
* @throws IOException -
|
||||
* if an IO exception occures
|
||||
*/
|
||||
protected void registerNewStorageQuery() throws IOException {
|
||||
if (LOG.isInfoEnabled())
|
||||
LOG.info("new StorageQuery requested -- create new storage buffer");
|
||||
synchronized (this.storageControllerLock) {
|
||||
if(this.storageQuery != null)
|
||||
if (this.storageQuery != null)
|
||||
this.storageQuery.decrementRef();
|
||||
this.searcher = new IndexSearcher(this.storageDir);
|
||||
this.storageQuery = null;
|
||||
|
@ -184,103 +223,176 @@ public class StorageCoreController implements StorageController{
|
|||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new StorageBuffer
|
||||
*
|
||||
* @return the new StorageBuffer
|
||||
*/
|
||||
protected StorageBuffer releaseNewStorageBuffer() {
|
||||
synchronized (this.storageControllerLock) {
|
||||
return this.currentBuffer;
|
||||
}
|
||||
}
|
||||
|
||||
/**TODO document this
|
||||
* @return
|
||||
* @throws IOException
|
||||
/**
|
||||
* Creates a new IndexModifier on the storage index
|
||||
*
|
||||
* @return - a new modifier
|
||||
* @throws IOException -
|
||||
* if an IO exception occures
|
||||
*/
|
||||
public IndexModifier createIndexModifier() throws IOException {
|
||||
if(LOG.isInfoEnabled())
|
||||
protected IndexModifier createIndexModifier() throws IOException {
|
||||
if (LOG.isInfoEnabled())
|
||||
LOG.info("new IndexModifier created - release to StorageModifier");
|
||||
synchronized (this.storageControllerLock) {
|
||||
return new IndexModifier(this.storageDir,new StandardAnalyzer(),false);
|
||||
return new IndexModifier(this.storageDir, new StandardAnalyzer(),
|
||||
false);
|
||||
}
|
||||
}
|
||||
|
||||
private void close() throws IOException{
|
||||
private void close() throws IOException {
|
||||
synchronized (this.storageControllerLock) {
|
||||
if(LOG.isInfoEnabled())
|
||||
LOG.info("StorageController has been closed -- server is shutting down -- release all resources");
|
||||
if(this.storageQuery != null)
|
||||
if (LOG.isInfoEnabled())
|
||||
LOG
|
||||
.info("StorageController has been closed -- server is shutting down -- release all resources");
|
||||
if (this.storageQuery != null)
|
||||
this.storageQuery.decrementRef();
|
||||
coreController = null;
|
||||
this.modifier.close();
|
||||
//TODO make sure all resources will be released
|
||||
// TODO make sure all resources will be released
|
||||
}
|
||||
}
|
||||
/**TODO document this
|
||||
* @return
|
||||
|
||||
/**
|
||||
* The size of the <tt>StorageBuffer</tt>.
|
||||
*
|
||||
* @return - storage buffer size
|
||||
*/
|
||||
public int getStorageBufferSize() {
|
||||
return this.storageBufferSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* The size of the <tt>StorageBuffer</tt>. This size should be at least
|
||||
* as big as the persist factor to prevent the <tt>StorageBuffer</tt> from
|
||||
* resizing
|
||||
*
|
||||
* @param storageBufferSize
|
||||
*/
|
||||
public void setStorageBufferSize(int storageBufferSize) {
|
||||
this.storageBufferSize = storageBufferSize;
|
||||
}
|
||||
/**TODO document this
|
||||
* @return
|
||||
|
||||
/**
|
||||
* An integer value after how many changes to the StorageModifier the
|
||||
* buffered changes will be persisted / wirtten to the index
|
||||
*
|
||||
* @return - the persist factor
|
||||
*/
|
||||
public int getStoragePersistFactor() {
|
||||
return this.storagePersistFactor;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param storagePersistFactor
|
||||
*/
|
||||
public void setStoragePersistFactor(int storagePersistFactor) {
|
||||
this.storagePersistFactor = storagePersistFactor;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws IOException
|
||||
* @throws StorageException
|
||||
* Forces the StorageModifier to write all buffered changes.
|
||||
*
|
||||
* @throws IOException -
|
||||
* if an IO exception occures
|
||||
*
|
||||
*/
|
||||
public void forceWrite()throws IOException, StorageException{
|
||||
public void forceWrite() throws IOException {
|
||||
this.modifier.forceWrite();
|
||||
}
|
||||
|
||||
|
||||
private boolean createLuceneStorageLog(File storageDirectory) throws IOException{
|
||||
if(storageDirectory.isDirectory() && !storageDirectory.exists()){
|
||||
private boolean createLuceneStorageLog(File storageDirectory)
|
||||
throws IOException {
|
||||
if (storageDirectory.isDirectory() && !storageDirectory.exists()) {
|
||||
storageDirectory.createNewFile();
|
||||
}
|
||||
File file = new File(storageDirectory.getAbsolutePath()+System.getProperty("file.separator")+STORAGELOG);
|
||||
File file = new File(storageDirectory.getAbsolutePath()
|
||||
+ System.getProperty("file.separator") + STORAGELOG);
|
||||
return file.createNewFile();
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**TODO document this
|
||||
* @return
|
||||
* @throws StorageException
|
||||
/**
|
||||
* Creates a unique ID to store as an id for
|
||||
* {@link org.apache.lucene.gdata.data.ServerBaseEntry} instances
|
||||
*
|
||||
* @return - a unique id
|
||||
* @throws StorageException -
|
||||
* if no id can be released
|
||||
*/
|
||||
public synchronized String releaseID() throws StorageException{
|
||||
try{
|
||||
public synchronized String releaseID() throws StorageException {
|
||||
try {
|
||||
return this.idGenerator.getUID();
|
||||
}catch (InterruptedException e) {
|
||||
throw new StorageException("Can't release new ID",e);
|
||||
} catch (InterruptedException e) {
|
||||
throw new StorageException("Can't release new ID", e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @see org.apache.lucene.gdata.storage.StorageController#destroy()
|
||||
*/
|
||||
public void destroy() {
|
||||
try{
|
||||
try {
|
||||
close();
|
||||
}catch (Exception e) {
|
||||
LOG.error("Closing StorageCoreController failed -- "+e.getMessage(),e);
|
||||
} catch (Exception e) {
|
||||
LOG.error("Closing StorageCoreController failed -- "
|
||||
+ e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return - the lucene directory used as a storage
|
||||
*/
|
||||
protected Directory getDirectory() {
|
||||
return this.storageDir;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.lucene.gdata.storage.StorageController#getStorage()
|
||||
*/
|
||||
public Storage getStorage() throws StorageException {
|
||||
try {
|
||||
return new StorageImplementation();
|
||||
} catch (StorageException e) {
|
||||
StorageException ex = new StorageException(
|
||||
"Can't create Storage instance -- " + e.getMessage(), e);
|
||||
ex.setStackTrace(e.getStackTrace());
|
||||
throw ex;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// TODO Try to remove this --> testcases
|
||||
private RAMDirectory getRamDirectory() throws IOException {
|
||||
IndexWriter writer;
|
||||
RAMDirectory retVal = new RAMDirectory();
|
||||
writer = new IndexWriter(retVal, new StandardAnalyzer(), true);
|
||||
writer.close();
|
||||
return retVal;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.lucene.gdata.server.registry.ServerComponent#initialize()
|
||||
*/
|
||||
public void initialize() {
|
||||
//
|
||||
}
|
||||
|
||||
private void createAdminAccount() throws StorageException{
|
||||
GDataAccount adminAccount = GDataAccount.createAdminAccount();
|
||||
StorageAccountWrapper wrapper = new StorageAccountWrapper(adminAccount);
|
||||
this.getStorageModifier().createAccount(wrapper);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -21,20 +21,27 @@ import java.io.StringWriter;
|
|||
|
||||
import org.apache.lucene.document.Document;
|
||||
import org.apache.lucene.document.Field;
|
||||
import org.apache.lucene.gdata.data.ServerBaseEntry;
|
||||
import org.apache.lucene.gdata.server.registry.ProvidedService;
|
||||
import org.apache.lucene.gdata.server.registry.ProvidedServiceConfig;
|
||||
import org.apache.lucene.gdata.storage.lucenestorage.StorageBuffer.BufferableEntry;
|
||||
|
||||
import com.google.gdata.data.BaseEntry;
|
||||
import com.google.gdata.data.ExtensionProfile;
|
||||
import com.google.gdata.util.common.xml.XmlWriter;
|
||||
|
||||
/**
|
||||
* This immutable class wrapps Entries for an internal Storage representation of
|
||||
* an entry. This class also acts as a Documentfactory for lucene documents to
|
||||
* be stored inside the index.
|
||||
* This immutable class wrapps <tt>ServerBaseEntry</tt> for an internal
|
||||
* Storage representation of an entry. This class also acts as a Documentfactory
|
||||
* for lucene documents to be stored inside the index.
|
||||
*
|
||||
* @author Simon Willnauer
|
||||
*
|
||||
*/
|
||||
public class StorageEntryWrapper implements Comparable<StorageEntryWrapper> {
|
||||
public class StorageEntryWrapper implements Comparable<StorageEntryWrapper>,
|
||||
StorageWrapper {
|
||||
|
||||
private static final long serialVersionUID = -4619985652059888526L;
|
||||
|
||||
private static final String INTERNAL_ENCODING = "UTF-8";
|
||||
|
||||
/**
|
||||
|
@ -45,7 +52,7 @@ public class StorageEntryWrapper implements Comparable<StorageEntryWrapper> {
|
|||
/**
|
||||
* lucene field name feed id
|
||||
*/
|
||||
public final static String FIELD_FEED_ID = "feedId";
|
||||
public final static String FIELD_FEED_REFERENCE = "feedReference";
|
||||
|
||||
/**
|
||||
* lucene field name entry content
|
||||
|
@ -61,67 +68,73 @@ public class StorageEntryWrapper implements Comparable<StorageEntryWrapper> {
|
|||
|
||||
private final String feedId;
|
||||
|
||||
private final String content;
|
||||
private String content;
|
||||
|
||||
private final transient BaseEntry entry;
|
||||
private final ServerBaseEntry entry;
|
||||
|
||||
private final Long timestamp;
|
||||
private Long timestamp;
|
||||
|
||||
private transient Document document;
|
||||
|
||||
private StorageOperation operation;
|
||||
|
||||
private final ExtensionProfile profile;
|
||||
private ProvidedService config;
|
||||
|
||||
/**
|
||||
* Creates a new StorageEntryWrapper.
|
||||
*
|
||||
* @param entry -
|
||||
* the entry to wrap
|
||||
* @param feedId -
|
||||
* the feed id
|
||||
*
|
||||
* @param operation -
|
||||
* the StorageOperation
|
||||
* @param profile -
|
||||
* the ExtensionProfil for the given entry
|
||||
*
|
||||
* @throws IOException -
|
||||
* if the entry content can not be generated
|
||||
*/
|
||||
protected StorageEntryWrapper(final BaseEntry entry, final String feedId,
|
||||
StorageOperation operation, final ExtensionProfile profile)
|
||||
throws IOException {
|
||||
public StorageEntryWrapper(final ServerBaseEntry entry,
|
||||
StorageOperation operation) throws IOException {
|
||||
|
||||
this.entry = entry;
|
||||
this.operation = operation;
|
||||
this.entryId = entry.getId();
|
||||
this.feedId = feedId;
|
||||
this.profile = profile;
|
||||
this.feedId = entry.getFeedId();
|
||||
if (operation != StorageOperation.DELETE) {
|
||||
this.config = entry.getServiceConfig();
|
||||
this.content = buildContent();
|
||||
this.timestamp = new Long(System.currentTimeMillis());
|
||||
|
||||
}
|
||||
this.timestamp = new Long(
|
||||
this.entry.getUpdated() != null ? this.entry.getUpdated()
|
||||
.getValue() : System.currentTimeMillis());
|
||||
|
||||
|
||||
}
|
||||
|
||||
private String buildContent() throws IOException {
|
||||
StringWriter writer = new StringWriter();
|
||||
XmlWriter xmlWriter = new XmlWriter(writer, INTERNAL_ENCODING);
|
||||
this.entry.generateAtom(xmlWriter, this.profile);
|
||||
this.entry.generateAtom(xmlWriter, this.config.getExtensionProfile());
|
||||
return writer.toString();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @return - the lucene document representing the entry
|
||||
* @see org.apache.lucene.gdata.storage.lucenestorage.StorageWrapper#getLuceneDocument()
|
||||
*/
|
||||
public Document getLuceneDocument() {
|
||||
if(this.operation == StorageOperation.DELETE)
|
||||
return null;
|
||||
if (this.document != null)
|
||||
return this.document;
|
||||
this.document = new Document();
|
||||
this.document.add(new Field("entryId", this.entryId, Field.Store.YES,
|
||||
Field.Index.UN_TOKENIZED));
|
||||
this.document.add(new Field("feedId", this.feedId, Field.Store.YES,
|
||||
Field.Index.UN_TOKENIZED));
|
||||
this.document.add(new Field("content", this.content,
|
||||
Field.Store.COMPRESS, Field.Index.UN_TOKENIZED));
|
||||
this.document.add(new Field("timestamp", this.timestamp.toString(),
|
||||
this.document.add(new Field(FIELD_ENTRY_ID, this.entryId,
|
||||
Field.Store.YES, Field.Index.UN_TOKENIZED));
|
||||
this.document.add(new Field(FIELD_FEED_REFERENCE, this.feedId,
|
||||
Field.Store.YES, Field.Index.UN_TOKENIZED));
|
||||
this.document.add(new Field(FIELD_CONTENT, this.content,
|
||||
Field.Store.COMPRESS, Field.Index.NO));
|
||||
this.document.add(new Field(FIELD_TIMESTAMP, this.timestamp.toString(),
|
||||
Field.Store.YES, Field.Index.UN_TOKENIZED));
|
||||
|
||||
return this.document;
|
||||
|
@ -132,7 +145,11 @@ public class StorageEntryWrapper implements Comparable<StorageEntryWrapper> {
|
|||
* @return - the wrapped entry
|
||||
*/
|
||||
public BaseEntry getEntry() {
|
||||
return this.entry;
|
||||
/*
|
||||
* this wrapps the entry again. BufferableEntry creates a new instance
|
||||
* for the dynamic element like links.
|
||||
*/
|
||||
return new BufferableEntry(this.entry.getEntry());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -178,11 +195,32 @@ public class StorageEntryWrapper implements Comparable<StorageEntryWrapper> {
|
|||
}
|
||||
|
||||
/**
|
||||
* @see java.lang.Comparable#compareTo(T)
|
||||
* This compare method compares the timestamps of the wrapper instances.
|
||||
*
|
||||
* @param arg0 -
|
||||
* the wrapper to compare
|
||||
* @par
|
||||
* @return - 0 if the wrappers timestamp are the same, an integer > 0 if the
|
||||
* given wrapper is after this wrapper
|
||||
*
|
||||
*/
|
||||
public int compareTo(StorageEntryWrapper arg0) {
|
||||
return arg0.timestamp == this.timestamp ? 0
|
||||
: (arg0.timestamp > this.timestamp ? 1 : -1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return - the specified {@link ProvidedServiceConfig}
|
||||
*/
|
||||
public ProvidedService getConfigurator() {
|
||||
return this.config;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the timestamp.
|
||||
*/
|
||||
public Long getTimestamp() {
|
||||
return this.timestamp;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -17,19 +17,23 @@
|
|||
package org.apache.lucene.gdata.storage.lucenestorage;
|
||||
|
||||
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.GDataAccount;
|
||||
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.GDataServerRegistry;
|
||||
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 org.apache.lucene.gdata.storage.lucenestorage.StorageEntryWrapper.StorageOperation;
|
||||
import org.apache.lucene.gdata.storage.lucenestorage.util.ReferenceCounter;
|
||||
|
||||
import com.google.gdata.data.BaseEntry;
|
||||
import com.google.gdata.data.BaseFeed;
|
||||
import com.google.gdata.data.ExtensionProfile;
|
||||
import com.google.gdata.data.Feed;
|
||||
|
||||
/**
|
||||
* This is an implementation of the
|
||||
|
@ -47,8 +51,6 @@ import com.google.gdata.data.Feed;
|
|||
public class StorageImplementation implements Storage {
|
||||
private final StorageCoreController controller;
|
||||
|
||||
private ExtensionProfile profile;
|
||||
|
||||
private static final Log LOG = LogFactory
|
||||
.getLog(StorageImplementation.class);
|
||||
|
||||
|
@ -56,40 +58,36 @@ public class StorageImplementation implements Storage {
|
|||
* Creates a new StorageImplementation
|
||||
*
|
||||
* @throws StorageException -
|
||||
* if the
|
||||
* {@link org.apache.lucene.gdata.storage.StorageController} can
|
||||
* not be created
|
||||
* @throws IOException -
|
||||
* if the
|
||||
* {@link org.apache.lucene.gdata.storage.StorageController} can
|
||||
* not be created
|
||||
* @see StorageCoreController#getStorageCoreController()
|
||||
* if the storage controller can not be obtained
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
public StorageImplementation() throws IOException, StorageException {
|
||||
this.controller = StorageCoreController.getStorageCoreController();
|
||||
public StorageImplementation() throws StorageException {
|
||||
this.controller = (StorageCoreController) GDataServerRegistry
|
||||
.getRegistry().lookup(StorageController.class,
|
||||
ComponentType.STORAGECONTROLLER);
|
||||
if (this.controller == null)
|
||||
throw new StorageException("Can't get registered StorageController");
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.lucene.gdata.storage.Storage#storeEntry(com.google.gdata.data.BaseEntry,
|
||||
* java.lang.String)
|
||||
* @see org.apache.lucene.gdata.storage.Storage#storeEntry(org.apache.lucene.gdata.data.ServerBaseEntry)
|
||||
*/
|
||||
public BaseEntry storeEntry(BaseEntry entry, String feedId)
|
||||
public BaseEntry storeEntry(final ServerBaseEntry entry)
|
||||
throws StorageException {
|
||||
if (this.profile == null)
|
||||
throw new StorageException(
|
||||
"Can process ExtensionProfile not set -- is null");
|
||||
if (feedId == null)
|
||||
throw new StorageException("No feed ID specified -- is null");
|
||||
|
||||
if (entry == null)
|
||||
throw new StorageException("entry is null");
|
||||
StorageModifier modifier = this.controller.getStorageModifier();
|
||||
String id = this.controller.releaseID();
|
||||
entry.setId(feedId + id);
|
||||
entry.setId(entry.getFeedId() + id);
|
||||
if (LOG.isInfoEnabled())
|
||||
LOG.info("Store entry " + id + " -- feed: " + feedId);
|
||||
LOG.info("Store entry " + id + " -- feed: " + entry.getFeedId());
|
||||
|
||||
try {
|
||||
StorageEntryWrapper wrapper = new StorageEntryWrapper(entry,
|
||||
feedId, StorageOperation.INSERT, this.profile);
|
||||
StorageOperation.INSERT);
|
||||
modifier.insertEntry(wrapper);
|
||||
} catch (IOException e) {
|
||||
StorageException ex = new StorageException("Can't create Entry -- "
|
||||
|
@ -99,53 +97,63 @@ public class StorageImplementation implements Storage {
|
|||
|
||||
}
|
||||
|
||||
return entry;
|
||||
return entry.getEntry();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.lucene.gdata.storage.Storage#deleteEntry(java.lang.String,
|
||||
* java.lang.String)
|
||||
* @see org.apache.lucene.gdata.storage.Storage#deleteEntry(org.apache.lucene.gdata.data.ServerBaseEntry)
|
||||
*/
|
||||
public void deleteEntry(String entryId, String feedId)
|
||||
public void deleteEntry(final ServerBaseEntry entry)
|
||||
throws StorageException {
|
||||
if (this.profile == null)
|
||||
throw new StorageException(
|
||||
"Can process ExtensionProfile not set -- is null");
|
||||
if (feedId == null)
|
||||
throw new StorageException("No feed ID specified -- is null");
|
||||
if (entryId == null)
|
||||
throw new StorageException("No entry ID specified -- is null");
|
||||
if (LOG.isInfoEnabled())
|
||||
LOG.info("delete entry " + entryId + " -- feed: " + feedId);
|
||||
StorageModifier modifier = this.controller.getStorageModifier();
|
||||
modifier.deleteEntry(entryId, feedId);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.lucene.gdata.storage.Storage#updateEntry(com.google.gdata.data.BaseEntry,
|
||||
* java.lang.String)
|
||||
*/
|
||||
public BaseEntry updateEntry(BaseEntry entry, String feedId)
|
||||
throws StorageException {
|
||||
if (this.profile == null)
|
||||
throw new StorageException(
|
||||
"Can process ExtensionProfile not set -- is null");
|
||||
if (feedId == null)
|
||||
throw new StorageException("No feed ID specified -- is null");
|
||||
if (entry == null)
|
||||
throw new StorageException("enrty is null");
|
||||
if (entry.getId() == null)
|
||||
throw new StorageException("No entry ID specified -- is null");
|
||||
if (LOG.isInfoEnabled())
|
||||
LOG.info("update entry " + entry.getId() + " -- feed: " + feedId);
|
||||
StorageModifier modifier = this.controller.getStorageModifier();
|
||||
throw new StorageException("Entry is null");
|
||||
|
||||
if (LOG.isInfoEnabled())
|
||||
LOG.info("delete entry " + entry.getId() + " -- feed: "
|
||||
+ entry.getFeedId());
|
||||
StorageModifier modifier = this.controller.getStorageModifier();
|
||||
ReferenceCounter<StorageQuery> query = this.controller.getStorageQuery();
|
||||
try{
|
||||
if(query.get().isEntryStored(entry.getId(),entry.getFeedId())){
|
||||
|
||||
modifier.deleteEntry(new StorageEntryWrapper(entry,StorageOperation.DELETE));
|
||||
}
|
||||
else
|
||||
throw new ResourceNotFoundException("Entry for entry id: "+entry.getId()+" is not stored");
|
||||
}catch (IOException e) {
|
||||
throw new StorageException("Can not access storage");
|
||||
}finally{
|
||||
query.decrementRef();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.lucene.gdata.storage.Storage#updateEntry(org.apache.lucene.gdata.data.ServerBaseEntry)
|
||||
*/
|
||||
public BaseEntry updateEntry(ServerBaseEntry entry) throws StorageException {
|
||||
|
||||
if (entry == null)
|
||||
throw new StorageException("entry is null");
|
||||
if(entry.getId() == null)
|
||||
throw new StorageException("entry id is null");
|
||||
if(entry.getFeedId() == null)
|
||||
throw new StorageException("feed id is null");
|
||||
if (LOG.isInfoEnabled())
|
||||
LOG.info("update entry " + entry.getId() + " -- feed: "
|
||||
+ entry.getFeedId());
|
||||
StorageModifier modifier = this.controller.getStorageModifier();
|
||||
ReferenceCounter<StorageQuery> query = this.controller.getStorageQuery();
|
||||
try {
|
||||
StorageEntryWrapper wrapper = new StorageEntryWrapper(entry,
|
||||
feedId, StorageOperation.UPDATE, this.profile);
|
||||
StorageOperation.UPDATE);
|
||||
if(query.get().isEntryStored(entry.getId(),entry.getFeedId()))
|
||||
modifier.updateEntry(wrapper);
|
||||
else
|
||||
throw new ResourceNotFoundException("Entry for entry id: "+entry.getId()+" is not stored");
|
||||
|
||||
} catch (IOException e) {
|
||||
LOG.error("Can't update entry for feedID: " + feedId
|
||||
LOG.error("Can't update entry for feedID: " + entry.getFeedId()
|
||||
+ "; entryId: " + entry.getId() + " -- " + e.getMessage(),
|
||||
e);
|
||||
StorageException ex = new StorageException("Can't create Entry -- "
|
||||
|
@ -155,36 +163,32 @@ public class StorageImplementation implements Storage {
|
|||
|
||||
}
|
||||
|
||||
return entry;
|
||||
return entry.getEntry();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.lucene.gdata.storage.Storage#getFeed(java.lang.String,
|
||||
* int, int)
|
||||
* @see org.apache.lucene.gdata.storage.Storage#getFeed(org.apache.lucene.gdata.data.ServerBaseFeed)
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public BaseFeed getFeed(String feedId, int startIndex, int resultCount)
|
||||
throws StorageException {
|
||||
if (this.profile == null)
|
||||
throw new StorageException(
|
||||
"Can process ExtensionProfile not set -- is null");
|
||||
if (feedId == null)
|
||||
throw new StorageException("No feed ID specified -- is null");
|
||||
public BaseFeed getFeed(final ServerBaseFeed feed) throws StorageException {
|
||||
|
||||
if (feed == null)
|
||||
throw new StorageException("feed is null");
|
||||
if (LOG.isInfoEnabled())
|
||||
LOG.info("get feed: " + feedId + " startindex: " + startIndex
|
||||
+ " resultCount: " + resultCount);
|
||||
LOG.info("get feed: " + feed.getId() + " startindex: "
|
||||
+ feed.getStartIndex() + " resultCount: "
|
||||
+ feed.getItemsPerPage());
|
||||
ReferenceCounter<StorageQuery> query = null;
|
||||
try {
|
||||
query = this.controller.getStorageQuery();
|
||||
List<BaseEntry> resultList = query.get().getLatestFeedQuery(feedId,
|
||||
resultCount, startIndex, this.profile);
|
||||
BaseFeed feed = new Feed();
|
||||
feed.getEntries().addAll(resultList);
|
||||
return feed;
|
||||
BaseFeed retVal = query.get().getLatestFeedQuery(feed.getId(),
|
||||
feed.getItemsPerPage(), feed.getStartIndex(),
|
||||
feed.getServiceConfig());
|
||||
return retVal;
|
||||
} catch (Exception e) {
|
||||
LOG.error("Can't get latest feed for feedID: " + feedId + " -- "
|
||||
+ e.getMessage(), e);
|
||||
LOG.error("Can't get latest feed for feedID: " + feed.getId()
|
||||
+ " -- " + e.getMessage(), e);
|
||||
StorageException ex = new StorageException("Can't create Entry -- "
|
||||
+ e.getMessage(), e);
|
||||
ex.setStackTrace(e.getStackTrace());
|
||||
|
@ -198,27 +202,28 @@ public class StorageImplementation implements Storage {
|
|||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.lucene.gdata.storage.Storage#getEntry(java.lang.String,
|
||||
* java.lang.String)
|
||||
* @see org.apache.lucene.gdata.storage.Storage#getEntry(org.apache.lucene.gdata.data.ServerBaseEntry)
|
||||
*/
|
||||
public BaseEntry getEntry(String entryId, String feedId)
|
||||
public BaseEntry getEntry(final ServerBaseEntry entry)
|
||||
throws StorageException {
|
||||
if (this.profile == null)
|
||||
throw new StorageException(
|
||||
"Can process ExtensionProfile not set -- is null");
|
||||
if (feedId == null)
|
||||
throw new StorageException("No feed ID specified -- is null");
|
||||
if (entryId == null)
|
||||
throw new StorageException("No entry ID specified -- is null");
|
||||
|
||||
if (entry == null)
|
||||
throw new StorageException("No entry specified -- is null");
|
||||
if (LOG.isInfoEnabled())
|
||||
LOG.info("get entry " + entryId + " -- feed: " + feedId);
|
||||
LOG.info("get entry " + entry.getId() + " -- feed: "
|
||||
+ entry.getFeedId());
|
||||
ReferenceCounter<StorageQuery> query = null;
|
||||
try {
|
||||
query = this.controller.getStorageQuery();
|
||||
return query.get().singleEntryQuery(entryId, feedId, this.profile);
|
||||
BaseEntry retVal = query.get().singleEntryQuery(entry.getId(),
|
||||
entry.getFeedId(), entry.getServiceConfig());
|
||||
if(retVal == null)
|
||||
throw new ResourceNotFoundException("can not get entry for entry ID "+entry.getId());
|
||||
return retVal;
|
||||
} catch (Exception e) {
|
||||
LOG.error("Can't get entry for feedID: " + feedId + "; entryId: "
|
||||
+ entryId + " -- " + e.getMessage(), e);
|
||||
LOG.error("Can't get entry for feedID: " + entry.getFeedId()
|
||||
+ "; entryId: " + entry.getId() + " -- " + e.getMessage(),
|
||||
e);
|
||||
StorageException ex = new StorageException("Can't create Entry -- "
|
||||
+ e.getMessage(), e);
|
||||
ex.setStackTrace(e.getStackTrace());
|
||||
|
@ -231,17 +236,6 @@ public class StorageImplementation implements Storage {
|
|||
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.lucene.gdata.storage.Storage#getEntries(java.util.List,
|
||||
* java.lang.String)
|
||||
*/
|
||||
public List<BaseEntry> getEntries(List<String> entryIdList, String feedId)
|
||||
throws StorageException {
|
||||
throw new StorageException("not implemented yet");
|
||||
// TODO implement this
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.lucene.gdata.storage.Storage#close()
|
||||
*/
|
||||
|
@ -250,10 +244,283 @@ public class StorageImplementation implements Storage {
|
|||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.lucene.gdata.storage.Storage#setExtensionProfile(com.google.gdata.data.ExtensionProfile)
|
||||
* @see org.apache.lucene.gdata.storage.Storage#storeAccount(org.apache.lucene.gdata.data.GDataAccount)
|
||||
*/
|
||||
public void setExtensionProfile(ExtensionProfile profile) {
|
||||
this.profile = profile;
|
||||
public void storeAccount(GDataAccount Account) throws StorageException {
|
||||
if (Account == null)
|
||||
throw new StorageException("Can not save null Account");
|
||||
ReferenceCounter<StorageQuery> query = null;
|
||||
try {
|
||||
query = this.controller.getStorageQuery();
|
||||
if (query.get().getUser(Account.getName()) != null)
|
||||
throw new StorageException("Account already exists");
|
||||
StorageModifier modifier = this.controller.getStorageModifier();
|
||||
StorageAccountWrapper wrapper = new StorageAccountWrapper(Account);
|
||||
modifier.createAccount(wrapper);
|
||||
} catch (Exception e) {
|
||||
LOG.error("Can't save Account -- " + e.getMessage(), e);
|
||||
StorageException ex = new StorageException("Can't save Account -- "
|
||||
+ e.getMessage(), e);
|
||||
ex.setStackTrace(e.getStackTrace());
|
||||
throw ex;
|
||||
|
||||
} finally {
|
||||
if (query != null)
|
||||
query.decrementRef();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.lucene.gdata.storage.Storage#updateAccount(org.apache.lucene.gdata.data.GDataAccount)
|
||||
*/
|
||||
public void updateAccount(GDataAccount Account) throws StorageException {
|
||||
if (Account == null)
|
||||
throw new StorageException("Can not update null Account");
|
||||
ReferenceCounter<StorageQuery> query = null;
|
||||
try {
|
||||
query = this.controller.getStorageQuery();
|
||||
if (query.get().getUser(Account.getName()) == null)
|
||||
throw new StorageException("Account does not exist");
|
||||
StorageModifier modifier = this.controller.getStorageModifier();
|
||||
StorageAccountWrapper wrapper = new StorageAccountWrapper(Account);
|
||||
modifier.updateAccount(wrapper);
|
||||
} catch (Exception e) {
|
||||
LOG.error("Can't update Account -- " + e.getMessage(), e);
|
||||
StorageException ex = new StorageException(
|
||||
"Can't update Account -- " + e.getMessage(), e);
|
||||
ex.setStackTrace(e.getStackTrace());
|
||||
throw ex;
|
||||
|
||||
} finally {
|
||||
if (query != null)
|
||||
query.decrementRef();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.lucene.gdata.storage.Storage#deleteAccount(java.lang.String)
|
||||
*/
|
||||
public void deleteAccount(String Accountname) throws StorageException {
|
||||
if (Accountname == null)
|
||||
throw new StorageException("can not delete null Account");
|
||||
ReferenceCounter<StorageQuery> query = null;
|
||||
try {
|
||||
query = this.controller.getStorageQuery();
|
||||
if (query.get().getUser(Accountname) == null)
|
||||
throw new StorageException("Account does not exist");
|
||||
StorageModifier modifier = this.controller.getStorageModifier();
|
||||
modifier.deleteAccount(Accountname);
|
||||
} catch (Exception e) {
|
||||
LOG.error("Can't update Account -- " + e.getMessage(), e);
|
||||
StorageException ex = new StorageException(
|
||||
"Can't update Account -- " + e.getMessage(), e);
|
||||
ex.setStackTrace(e.getStackTrace());
|
||||
throw ex;
|
||||
|
||||
} finally {
|
||||
if (query != null)
|
||||
query.decrementRef();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.lucene.gdata.storage.Storage#storeFeed(org.apache.lucene.gdata.data.ServerBaseFeed,
|
||||
* java.lang.String)
|
||||
*/
|
||||
public void storeFeed(ServerBaseFeed feed, String accountName)
|
||||
throws StorageException {
|
||||
if (feed == null)
|
||||
throw new StorageException("can not insert null feed");
|
||||
if (accountName == null)
|
||||
throw new StorageException("accountName must not be null");
|
||||
ReferenceCounter<StorageQuery> query = null;
|
||||
try {
|
||||
query = this.controller.getStorageQuery();
|
||||
if (query.get().isFeedStored(feed.getId()))
|
||||
throw new StorageException("feed with feedID " + feed.getId()
|
||||
+ " is already stored");
|
||||
StorageModifier modifier = this.controller.getStorageModifier();
|
||||
StorageFeedWrapper wrapper = new StorageFeedWrapper(feed,
|
||||
accountName);
|
||||
modifier.createFeed(wrapper);
|
||||
|
||||
} catch (Exception e) {
|
||||
LOG.error("Can't create feed -- " + e.getMessage(), e);
|
||||
StorageException ex = new StorageException("Can't create feed -- "
|
||||
+ e.getMessage(), e);
|
||||
ex.setStackTrace(e.getStackTrace());
|
||||
throw ex;
|
||||
|
||||
} finally {
|
||||
if (query != null)
|
||||
query.decrementRef();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.lucene.gdata.storage.Storage#deleteFeed(java.lang.String)
|
||||
*/
|
||||
public void deleteFeed(String feedId) throws StorageException {
|
||||
if (feedId == null)
|
||||
throw new StorageException("can not delete feed id is null ");
|
||||
ReferenceCounter<StorageQuery> query = null;
|
||||
try {
|
||||
query = this.controller.getStorageQuery();
|
||||
if (!query.get().isFeedStored(feedId))
|
||||
throw new StorageException("Account does not exist");
|
||||
StorageModifier modifier = this.controller.getStorageModifier();
|
||||
|
||||
modifier.deleteFeed(feedId);
|
||||
|
||||
} catch (Exception e) {
|
||||
LOG.error("Can't delete feed -- " + e.getMessage(), e);
|
||||
StorageException ex = new StorageException("Can't create feed -- "
|
||||
+ e.getMessage(), e);
|
||||
ex.setStackTrace(e.getStackTrace());
|
||||
throw ex;
|
||||
|
||||
} finally {
|
||||
if (query == null)
|
||||
query.decrementRef();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.lucene.gdata.storage.Storage#updateFeed(org.apache.lucene.gdata.data.ServerBaseFeed,
|
||||
* java.lang.String)
|
||||
*/
|
||||
public void updateFeed(ServerBaseFeed feed, String accountName)
|
||||
throws StorageException {
|
||||
if (feed == null)
|
||||
throw new StorageException("can not update null feed");
|
||||
if (accountName == null)
|
||||
throw new StorageException("accountName must not be null");
|
||||
ReferenceCounter<StorageQuery> query = null;
|
||||
try {
|
||||
query = this.controller.getStorageQuery();
|
||||
if (!query.get().isFeedStored(feed.getId()))
|
||||
throw new StorageException("Account does not exist");
|
||||
StorageModifier modifier = this.controller.getStorageModifier();
|
||||
StorageFeedWrapper wrapper = new StorageFeedWrapper(feed,
|
||||
accountName);
|
||||
modifier.updateFeed(wrapper);
|
||||
|
||||
} catch (Exception e) {
|
||||
LOG.error("Can't create feed -- " + e.getMessage(), e);
|
||||
StorageException ex = new StorageException("Can't create feed -- "
|
||||
+ e.getMessage(), e);
|
||||
ex.setStackTrace(e.getStackTrace());
|
||||
throw ex;
|
||||
|
||||
} finally {
|
||||
if (query == null)
|
||||
query.decrementRef();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.lucene.gdata.storage.Storage#getServiceForFeed(java.lang.String)
|
||||
*/
|
||||
public String getServiceForFeed(String feedId) throws StorageException {
|
||||
if (feedId == null)
|
||||
throw new StorageException("no feed for the feedID == null");
|
||||
ReferenceCounter<StorageQuery> query = null;
|
||||
try {
|
||||
query = this.controller.getStorageQuery();
|
||||
String type = query.get().getService(feedId);
|
||||
if (type == null)
|
||||
throw new StorageException("no feed for the feedID == "
|
||||
+ feedId + " found");
|
||||
return type;
|
||||
} catch (Exception e) {
|
||||
throw new StorageException("Can not access storage", e);
|
||||
} finally {
|
||||
if (query != null)
|
||||
query.decrementRef();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.lucene.gdata.storage.Storage#getAccount(java.lang.String)
|
||||
*/
|
||||
public GDataAccount getAccount(String accountName) throws StorageException {
|
||||
if (accountName == null)
|
||||
throw new StorageException("account name must not be null");
|
||||
ReferenceCounter<StorageQuery> query = null;
|
||||
try {
|
||||
query = this.controller.getStorageQuery();
|
||||
return query.get().getUser(accountName);
|
||||
} catch (Exception e) {
|
||||
throw new StorageException("Can not access storage", e);
|
||||
} finally {
|
||||
if (query != null)
|
||||
query.decrementRef();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.lucene.gdata.storage.Storage#getAccountNameForFeedId(java.lang.String)
|
||||
*/
|
||||
public String getAccountNameForFeedId(String feedId)
|
||||
throws StorageException {
|
||||
if (feedId == null)
|
||||
throw new StorageException("feedid must not be null");
|
||||
ReferenceCounter<StorageQuery> query = null;
|
||||
try {
|
||||
query = this.controller.getStorageQuery();
|
||||
String accountName = query.get().getAccountNameForFeedId(feedId);
|
||||
if (accountName == null)
|
||||
throw new StorageException("no feed for feedId " + feedId
|
||||
+ " found");
|
||||
return accountName;
|
||||
} catch (IOException e) {
|
||||
throw new StorageException("Can not access storage - "
|
||||
+ e.getMessage(), e);
|
||||
} finally {
|
||||
if (query != null)
|
||||
query.decrementRef();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.lucene.gdata.storage.Storage#getEntryLastModified(java.lang.String, java.lang.String)
|
||||
*/
|
||||
public Long getEntryLastModified(String entryId,String feedId) throws StorageException {
|
||||
ReferenceCounter<StorageQuery> query = null;
|
||||
try {
|
||||
query = this.controller.getStorageQuery();
|
||||
return new Long(query.get().getEntryLastModified(entryId,feedId));
|
||||
} catch (IOException e) {
|
||||
throw new StorageException("Can not access storage - "
|
||||
+ e.getMessage(), e);
|
||||
} finally {
|
||||
if (query != null)
|
||||
query.decrementRef();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.lucene.gdata.storage.Storage#getFeedLastModified(java.lang.String)
|
||||
*/
|
||||
public Long getFeedLastModified(String feedId) throws StorageException {
|
||||
ReferenceCounter<StorageQuery> query = null;
|
||||
try {
|
||||
query = this.controller.getStorageQuery();
|
||||
return new Long(query.get().getFeedLastModified(feedId));
|
||||
} catch (IOException e) {
|
||||
throw new StorageException("Can not access storage - "
|
||||
+ e.getMessage(), e);
|
||||
} finally {
|
||||
if (query != null)
|
||||
query.decrementRef();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package org.apache.lucene.gdata.storage.lucenestorage;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
|
@ -13,11 +14,32 @@ import org.apache.commons.logging.Log;
|
|||
import org.apache.commons.logging.LogFactory;
|
||||
import org.apache.lucene.document.Document;
|
||||
import org.apache.lucene.gdata.storage.StorageException;
|
||||
import org.apache.lucene.gdata.storage.lucenestorage.StorageEntryWrapper.StorageOperation;
|
||||
import org.apache.lucene.index.IndexModifier;
|
||||
import org.apache.lucene.index.Term;
|
||||
|
||||
/**
|
||||
* TODO document this
|
||||
* The StorageModifier is the a Singleton component of the LuceneStorage. There
|
||||
* is one single instance of this class modifying the index used to store all
|
||||
* the gdata Entities as Entries, Feeds and Users. This class contains an
|
||||
* instance of {@link org.apache.lucene.index.IndexModifier} used to manage all
|
||||
* delete and add actions to the storage.
|
||||
* <p>
|
||||
* To prevent the storage component from opening and closing the
|
||||
* {@link org.apache.lucene.index.IndexModifier} for every modifying operation
|
||||
* the incoming entry actions (DELETE, UPDATE, INSERT) will be buffered in a
|
||||
* registered instance of
|
||||
* {@link org.apache.lucene.gdata.storage.lucenestorage.StorageBuffer}. When a
|
||||
* certain amout (specified as the persistfactor in the configuration file) of
|
||||
* modifications have been executed the StorageModifier will persist the
|
||||
* buffered entries.
|
||||
* </p>
|
||||
* <p>
|
||||
* Feed and User operations won't be buffered. These actions occure not very
|
||||
* often compared to entry actions. Every call of an user / feed modifying
|
||||
* operation forces all changes to be written to the storage index.
|
||||
* </p>
|
||||
*
|
||||
* @author Simon Willnauer
|
||||
*
|
||||
*/
|
||||
|
@ -25,10 +47,14 @@ public class StorageModifier {
|
|||
protected static final Log LOG = LogFactory.getLog(StorageModifier.class);
|
||||
|
||||
private final List<Term> deletedDocumentQueue;
|
||||
|
||||
private final List<Term> deletedForUpdateDocumentQueue;
|
||||
|
||||
private final Map<String,Document> documentMap;
|
||||
private final Map<String, Document> documentMap;
|
||||
|
||||
private final List<Document> forceWriteDocuments;
|
||||
|
||||
private final List<Term> forceWriteTerms;
|
||||
|
||||
private volatile int persistFactor;
|
||||
|
||||
|
@ -45,44 +71,70 @@ public class StorageModifier {
|
|||
private Lock readLock = this.lock.readLock();
|
||||
|
||||
private Lock writeLock = this.lock.writeLock();
|
||||
|
||||
private final static int DEFAULT_OPTIMIZE_INTERVAL = 10;
|
||||
|
||||
private final int optimizeInterval;
|
||||
private int optimizeCounter = 0;
|
||||
|
||||
private volatile int optimizeCounter = 0;
|
||||
|
||||
private final StorageCoreController controller;
|
||||
|
||||
/**
|
||||
* TODO document this
|
||||
* @param modifier
|
||||
* @param buffer
|
||||
* @param persitsFactor
|
||||
* @param optimizeInterval
|
||||
* Creates a new StorageModifier
|
||||
*
|
||||
* @param controller -
|
||||
* the registered StorageController
|
||||
* @param modifier -
|
||||
* the IndexModifier
|
||||
* @param buffer -
|
||||
* the StorageBuffer
|
||||
* @param persitsFactor -
|
||||
* the factor when the changes will be persisted to the storage
|
||||
* index
|
||||
* @param optimizeInterval -
|
||||
* after how many storage operations the index will be optimized
|
||||
*/
|
||||
public StorageModifier(final IndexModifier modifier,
|
||||
final StorageBuffer buffer, int persitsFactor,int optimizeInterval) {
|
||||
protected StorageModifier(final StorageCoreController controller,
|
||||
final IndexModifier modifier, final StorageBuffer buffer,
|
||||
int persitsFactor, int optimizeInterval) {
|
||||
this.deletedDocumentQueue = new LinkedList<Term>();
|
||||
this.deletedForUpdateDocumentQueue = new LinkedList<Term>();
|
||||
this.documentMap = new HashMap<String,Document>(persitsFactor);
|
||||
this.documentMap = new HashMap<String, Document>(persitsFactor);
|
||||
this.forceWriteDocuments = new ArrayList<Document>(5);
|
||||
this.forceWriteTerms = new ArrayList<Term>(5);
|
||||
this.buffer = buffer;
|
||||
this.controller = controller;
|
||||
|
||||
this.persistFactor = persitsFactor > 0 ? persitsFactor
|
||||
: DEFAULT_PERSIST_FACTOR;
|
||||
this.modifier = modifier;
|
||||
this.optimizeInterval = optimizeInterval < DEFAULT_OPTIMIZE_INTERVAL?DEFAULT_OPTIMIZE_INTERVAL:optimizeInterval;
|
||||
this.optimizeInterval = optimizeInterval < DEFAULT_OPTIMIZE_INTERVAL ? DEFAULT_OPTIMIZE_INTERVAL
|
||||
: optimizeInterval;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO document this
|
||||
* @param wrapper
|
||||
* @throws StorageException
|
||||
* Updates the given entry. First the alredy persisted entry will be
|
||||
* removed, after marking as deleted the new Entry will be written.
|
||||
*
|
||||
* @param wrapper -
|
||||
* the wrapper containing the entry
|
||||
* @throws StorageException -
|
||||
* if the entry can not be stored
|
||||
*/
|
||||
public void updateEntry(StorageEntryWrapper wrapper)
|
||||
throws StorageException {
|
||||
try {
|
||||
if(wrapper.getOperation() != StorageOperation.UPDATE)
|
||||
throw new StorageException("Illegal method call -- updateEntry does not accept other storageOperations than update");
|
||||
this.readLock.lock();
|
||||
Term tempTerm = new Term(StorageEntryWrapper.FIELD_ENTRY_ID, wrapper.getEntryId());
|
||||
this.buffer.addEntry(wrapper);
|
||||
try {
|
||||
Term tempTerm = new Term(StorageEntryWrapper.FIELD_ENTRY_ID,
|
||||
wrapper.getEntryId());
|
||||
this.documentMap.put(wrapper.getEntryId(), wrapper
|
||||
.getLuceneDocument());
|
||||
this.deletedForUpdateDocumentQueue.add(tempTerm);
|
||||
this.documentMap.put(wrapper.getEntryId(),wrapper.getLuceneDocument());
|
||||
this.buffer.addEntry(wrapper);
|
||||
storageModified();
|
||||
} finally {
|
||||
this.readLock.unlock();
|
||||
|
@ -90,16 +142,22 @@ public class StorageModifier {
|
|||
}
|
||||
|
||||
/**
|
||||
* TODO document this
|
||||
* @param wrapper
|
||||
* @throws StorageException
|
||||
* Inserts a new Entry to the Lucene index storage
|
||||
*
|
||||
* @param wrapper -
|
||||
* the wrapper containing the entry
|
||||
* @throws StorageException -
|
||||
* if the entry can not be stored
|
||||
*/
|
||||
public void insertEntry(StorageEntryWrapper wrapper) throws StorageException {
|
||||
public void insertEntry(StorageEntryWrapper wrapper)
|
||||
throws StorageException {
|
||||
if(wrapper.getOperation() != StorageOperation.INSERT)
|
||||
throw new StorageException("Illegal method call -- insertEntry does not accept other storage operations than insert");
|
||||
this.readLock.lock();
|
||||
try {
|
||||
|
||||
this.documentMap.put(wrapper.getEntryId(), wrapper
|
||||
.getLuceneDocument());
|
||||
this.buffer.addEntry(wrapper);
|
||||
this.documentMap.put(wrapper.getEntryId(),wrapper.getLuceneDocument());
|
||||
storageModified();
|
||||
} finally {
|
||||
this.readLock.unlock();
|
||||
|
@ -107,18 +165,149 @@ public class StorageModifier {
|
|||
}
|
||||
|
||||
/**
|
||||
*TODO document this
|
||||
* @param entryId
|
||||
* @param feedId
|
||||
* @throws StorageException
|
||||
* Deletes the entry for the given entry id.
|
||||
* @param wrapper - the wrapper containing the information to delete
|
||||
*
|
||||
* @throws StorageException -
|
||||
* if the entry can not be deleted
|
||||
*
|
||||
*/
|
||||
public void deleteEntry(final String entryId, final String feedId) throws StorageException {
|
||||
try {
|
||||
public void deleteEntry(final StorageEntryWrapper wrapper)
|
||||
throws StorageException {
|
||||
if(wrapper.getOperation() != StorageOperation.DELETE)
|
||||
throw new StorageException("Illegal method call -- insertEntry does not accept other storage operations than delete");
|
||||
this.readLock.lock();
|
||||
Term tempTerm = new Term(StorageEntryWrapper.FIELD_ENTRY_ID, entryId);
|
||||
this.buffer.addDeleted(entryId, feedId);
|
||||
try {
|
||||
Term tempTerm = new Term(StorageEntryWrapper.FIELD_ENTRY_ID,
|
||||
wrapper.getEntryId());
|
||||
this.deletedDocumentQueue.add(tempTerm);
|
||||
this.buffer.addDeleted(wrapper.getEntryId(), wrapper.getFeedId());
|
||||
storageModified();
|
||||
} finally {
|
||||
this.readLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a new Feed to the storage. Feed action will be not buffered. Call to
|
||||
* this method forces the index to be written.
|
||||
*
|
||||
* @param wrapper -
|
||||
* the wrapper containing the feed;
|
||||
* @throws StorageException -
|
||||
* if the feed can not be written
|
||||
*/
|
||||
public void createFeed(StorageFeedWrapper wrapper) throws StorageException {
|
||||
this.readLock.lock();
|
||||
try {
|
||||
this.forceWriteDocuments.add(wrapper.getLuceneDocument());
|
||||
storageModified();
|
||||
} finally {
|
||||
this.readLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a new accountr to the storage. User action will be not buffered. Call to
|
||||
* this method forces the index to be written.
|
||||
*
|
||||
* @param account
|
||||
* -the wrapper containig the user to be persisted
|
||||
* @throws StorageException -
|
||||
* if the user can not be persisted.
|
||||
*/
|
||||
public void createAccount(StorageAccountWrapper account) throws StorageException {
|
||||
this.readLock.lock();
|
||||
try {
|
||||
this.forceWriteDocuments.add(account.getLuceneDocument());
|
||||
storageModified();
|
||||
} finally {
|
||||
this.readLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes the user with the given username. User action will be not
|
||||
* buffered. Call to this method forces the index to be written.
|
||||
*
|
||||
* @param accountName -
|
||||
* the user to be deleted
|
||||
* @throws StorageException -
|
||||
* If the user could not be deleted
|
||||
*/
|
||||
public void deleteAccount(String accountName) throws StorageException {
|
||||
this.readLock.lock();
|
||||
try {
|
||||
//TODO delete all feeds and entries of this account
|
||||
this.forceWriteTerms.add(new Term(
|
||||
StorageAccountWrapper.FIELD_ACCOUNTNAME, accountName));
|
||||
storageModified();
|
||||
} finally {
|
||||
this.readLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* User action will be not buffered. Call to this method forces the index to
|
||||
* be written.
|
||||
*
|
||||
* @param user
|
||||
* -the wrapper containig the user to be persisted
|
||||
* @throws StorageException -
|
||||
* if the user can not be persisted.
|
||||
*/
|
||||
public void updateAccount(final StorageAccountWrapper user)
|
||||
throws StorageException {
|
||||
this.readLock.lock();
|
||||
try {
|
||||
this.forceWriteTerms.add(new Term(
|
||||
StorageAccountWrapper.FIELD_ACCOUNTNAME, user.getUser()
|
||||
.getName()));
|
||||
this.forceWriteDocuments.add(user.getLuceneDocument());
|
||||
storageModified();
|
||||
} finally {
|
||||
this.readLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Feed action will be not buffered. Call to this method forces the index to
|
||||
* be written.
|
||||
*
|
||||
* @param wrapper -
|
||||
* the wrapper containig the feed
|
||||
* @throws StorageException -
|
||||
* if the feed can not be persisted
|
||||
*/
|
||||
public void updateFeed(final StorageFeedWrapper wrapper)
|
||||
throws StorageException {
|
||||
this.readLock.lock();
|
||||
try {
|
||||
this.forceWriteTerms.add(new Term(StorageFeedWrapper.FIELD_FEED_ID,
|
||||
wrapper.getFeed().getId()));
|
||||
this.forceWriteDocuments.add(wrapper.getLuceneDocument());
|
||||
storageModified();
|
||||
} finally {
|
||||
this.readLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes the feed with the given feed id Feed action will be not buffered.
|
||||
* Call to this method forces the index to be written.
|
||||
* All entries referencing the given feed id will be deleted as well!
|
||||
* @param feedId -
|
||||
* the id of the feed to delete
|
||||
* @throws StorageException -
|
||||
* if the feed can not be deleted
|
||||
*/
|
||||
public void deleteFeed(final String feedId) throws StorageException {
|
||||
this.readLock.lock();
|
||||
try {
|
||||
this.deletedDocumentQueue.add(new Term(StorageEntryWrapper.FIELD_FEED_REFERENCE,feedId));
|
||||
this.forceWriteTerms.add(new Term(StorageFeedWrapper.FIELD_FEED_ID,
|
||||
feedId));
|
||||
|
||||
storageModified();
|
||||
} finally {
|
||||
this.readLock.unlock();
|
||||
|
@ -131,7 +320,9 @@ public class StorageModifier {
|
|||
|
||||
try {
|
||||
incrementCounter();
|
||||
if (this.persistFactor > this.modifiedCounter)
|
||||
if (this.persistFactor > this.modifiedCounter
|
||||
&& this.forceWriteDocuments.size() <= 0
|
||||
&& this.forceWriteTerms.size() <= 0)
|
||||
return;
|
||||
|
||||
if (LOG.isInfoEnabled())
|
||||
|
@ -142,7 +333,10 @@ public class StorageModifier {
|
|||
|
||||
this.modifiedCounter = 0;
|
||||
} catch (IOException e) {
|
||||
|
||||
LOG.error("Writing persistent index failed - Recovering", e);
|
||||
throw new StorageException("could not write to storage index -- "+e.getMessage(),e);
|
||||
|
||||
} finally {
|
||||
this.readLock.lock();
|
||||
this.writeLock.unlock();
|
||||
|
@ -150,7 +344,7 @@ public class StorageModifier {
|
|||
|
||||
}
|
||||
|
||||
protected void forceWrite() throws IOException, StorageException {
|
||||
protected void forceWrite() throws IOException {
|
||||
this.writeLock.lock();
|
||||
try {
|
||||
if (LOG.isInfoEnabled())
|
||||
|
@ -164,22 +358,27 @@ public class StorageModifier {
|
|||
}
|
||||
}
|
||||
|
||||
private void requestNewIndexModifier() throws IOException, StorageException {
|
||||
StorageCoreController controller = StorageCoreController
|
||||
.getStorageCoreController();
|
||||
controller.registerNewStorageQuery();
|
||||
this.buffer = controller.releaseNewStorageBuffer();
|
||||
this.modifier = controller.createIndexModifier();
|
||||
private void requestNewIndexModifier() throws IOException {
|
||||
|
||||
this.controller.registerNewStorageQuery();
|
||||
this.buffer = this.controller.releaseNewStorageBuffer();
|
||||
this.modifier = this.controller.createIndexModifier();
|
||||
}
|
||||
|
||||
private void writePersistentIndex(final boolean optimize) throws IOException {
|
||||
private void writePersistentIndex(final boolean optimize)
|
||||
throws IOException {
|
||||
try {
|
||||
|
||||
/*
|
||||
* first delete all updated documents
|
||||
*/
|
||||
for(Term entryIdTerm : this.deletedForUpdateDocumentQueue) {
|
||||
for (Term entryIdTerm : this.deletedForUpdateDocumentQueue) {
|
||||
this.modifier.deleteDocuments(entryIdTerm);
|
||||
}
|
||||
|
||||
for (Term term : this.forceWriteTerms) {
|
||||
this.modifier.deleteDocuments(term);
|
||||
}
|
||||
/*
|
||||
* add all documents
|
||||
*/
|
||||
|
@ -187,34 +386,44 @@ public class StorageModifier {
|
|||
for (Document doc : documents) {
|
||||
this.modifier.addDocument(doc);
|
||||
}
|
||||
/*
|
||||
* write all users or feeds
|
||||
*/
|
||||
for (Document docs : this.forceWriteDocuments) {
|
||||
this.modifier.addDocument(docs);
|
||||
}
|
||||
|
||||
/*
|
||||
* delete all documents marked as deleted. As the DocumentIDs are
|
||||
* unique the document marked as deleted must not persist after the
|
||||
* index has been written.
|
||||
* In the case of an update of a document and a previous delete the concurrency component will not allow an update.
|
||||
* new inserted entries can not be deleted accidently-
|
||||
* index has been written. In the case of an update of a document
|
||||
* and a previous delete the concurrency component will not allow an
|
||||
* update. new inserted entries can not be deleted accidently-
|
||||
*/
|
||||
for (Term entryIdTerm : this.deletedDocumentQueue) {
|
||||
this.modifier.deleteDocuments(entryIdTerm);
|
||||
}
|
||||
this.modifier.flush();
|
||||
if(optimize){
|
||||
if(LOG.isInfoEnabled())
|
||||
LOG.info("Optimizing index -- optimize interval "+this.optimizeInterval);
|
||||
if (optimize) {
|
||||
if (LOG.isInfoEnabled())
|
||||
LOG.info("Optimizing index -- optimize interval "
|
||||
+ this.optimizeInterval);
|
||||
this.modifier.optimize();
|
||||
}
|
||||
|
||||
} finally {
|
||||
if(optimize)
|
||||
if (optimize)
|
||||
this.optimizeCounter = 0;
|
||||
this.modifier.close();
|
||||
this.deletedForUpdateDocumentQueue.clear();
|
||||
this.deletedDocumentQueue.clear();
|
||||
this.documentMap.clear();
|
||||
this.forceWriteDocuments.clear();
|
||||
this.forceWriteTerms.clear();
|
||||
}
|
||||
}
|
||||
|
||||
protected void close()throws IOException{
|
||||
protected void close() throws IOException {
|
||||
this.writeLock.lock();
|
||||
try {
|
||||
if (LOG.isInfoEnabled())
|
||||
|
@ -228,7 +437,7 @@ public class StorageModifier {
|
|||
}
|
||||
}
|
||||
|
||||
private void incrementCounter(){
|
||||
private void incrementCounter() {
|
||||
this.optimizeCounter++;
|
||||
this.modifiedCounter++;
|
||||
}
|
||||
|
|
|
@ -22,9 +22,13 @@ import java.util.ArrayList;
|
|||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.apache.lucene.document.Document;
|
||||
import org.apache.lucene.gdata.server.FeedNotFoundException;
|
||||
import org.apache.lucene.gdata.data.GDataAccount;
|
||||
import org.apache.lucene.gdata.server.GDataEntityBuilder;
|
||||
import org.apache.lucene.gdata.server.registry.ProvidedService;
|
||||
import org.apache.lucene.gdata.storage.StorageException;
|
||||
import org.apache.lucene.index.Term;
|
||||
import org.apache.lucene.search.BooleanClause;
|
||||
import org.apache.lucene.search.BooleanQuery;
|
||||
|
@ -37,20 +41,22 @@ import org.apache.lucene.search.TermQuery;
|
|||
import org.apache.lucene.search.BooleanClause.Occur;
|
||||
|
||||
import com.google.gdata.data.BaseEntry;
|
||||
import com.google.gdata.data.ExtensionProfile;
|
||||
import com.google.gdata.data.BaseFeed;
|
||||
import com.google.gdata.data.DateTime;
|
||||
import com.google.gdata.util.ParseException;
|
||||
|
||||
/**
|
||||
* StorageQuery wrapps a Lucene {@link org.apache.lucene.search.IndexSearcher}
|
||||
* and a {@link org.apache.lucene.gdata.storage.lucenestorage.StorageBuffer} to
|
||||
* perform all request on the lucene storage.
|
||||
* The wrapped components are thread - safe.
|
||||
* perform all request on the lucene storage. The wrapped components are thread -
|
||||
* safe.
|
||||
* <p>
|
||||
* An instance of this class will serve all client requests. To obtain the
|
||||
* current instance of the {@link StorageQuery} the method
|
||||
* {@link org.apache.lucene.gdata.storage.lucenestorage.StorageCoreController#getStorageQuery()}
|
||||
* has to be invoked. This method will release the current StorageQuery.
|
||||
* </p>
|
||||
*
|
||||
* @see org.apache.lucene.search.IndexSearcher
|
||||
* @see org.apache.lucene.gdata.storage.lucenestorage.StorageCoreController
|
||||
* @see org.apache.lucene.gdata.storage.lucenestorage.StorageBuffer
|
||||
|
@ -59,6 +65,7 @@ import com.google.gdata.util.ParseException;
|
|||
*
|
||||
*/
|
||||
public class StorageQuery {
|
||||
private static final Log LOG = LogFactory.getLog(StorageQuery.class);
|
||||
private final StorageBuffer buffer;
|
||||
|
||||
private final Searcher searcher;
|
||||
|
@ -66,8 +73,8 @@ public class StorageQuery {
|
|||
/*
|
||||
* Sort the result by timestamp desc
|
||||
*/
|
||||
private final Sort timeStampSort = new Sort(new SortField(StorageEntryWrapper.FIELD_TIMESTAMP,
|
||||
SortField.STRING, true));
|
||||
private final Sort timeStampSort = new Sort(new SortField(
|
||||
StorageEntryWrapper.FIELD_TIMESTAMP, SortField.STRING, true));
|
||||
|
||||
/**
|
||||
* Creates a new StorageQuery
|
||||
|
@ -107,7 +114,8 @@ public class StorageQuery {
|
|||
*/
|
||||
private Hits storageFeedQuery(final String feedId, final Sort sort)
|
||||
throws IOException {
|
||||
TermQuery query = new TermQuery(new Term(StorageEntryWrapper.FIELD_FEED_ID, feedId));
|
||||
TermQuery query = new TermQuery(new Term(
|
||||
StorageEntryWrapper.FIELD_FEED_REFERENCE, feedId));
|
||||
return this.searcher.search(query, new ModifiedEntryFilter(this.buffer
|
||||
.getExculdList()), sort);
|
||||
|
||||
|
@ -154,44 +162,55 @@ public class StorageQuery {
|
|||
* how many entries are requested
|
||||
* @param startIndex -
|
||||
* the offset of the entriy to start from.
|
||||
* @param profil -
|
||||
* the extension profile used to create the entriy instances
|
||||
* @param config -
|
||||
* the FeedInstanceConfiguration contaning extension profile used
|
||||
* to create the entriy instances
|
||||
* @return - an ordered list of {@link BaseEntry} objects, or an empty list
|
||||
* if no entries could be found
|
||||
* @throws IOException -
|
||||
* if the index could not be queries or the entries could not be
|
||||
* build
|
||||
* @throws FeedNotFoundException -
|
||||
* if the requested feed is not registered
|
||||
* @throws ParseException -
|
||||
* if an entry could not be parsed while building it from the
|
||||
* Lucene Document.
|
||||
*/
|
||||
// TODO check input parameter
|
||||
public List<BaseEntry> getLatestFeedQuery(final String feedId,
|
||||
@SuppressWarnings("unchecked")
|
||||
public BaseFeed getLatestFeedQuery(final String feedId,
|
||||
final int resultCount, final int startIndex,
|
||||
final ExtensionProfile profil) throws IOException,
|
||||
FeedNotFoundException, ParseException {
|
||||
final ProvidedService config) throws IOException,
|
||||
ParseException {
|
||||
DateTime updated = null;
|
||||
Hits feedHits = storageFeedQuery(feedId);
|
||||
if(feedHits.length() == 0)
|
||||
return null;
|
||||
BaseFeed retVal = buildFeedFromLuceneDocument(feedHits.doc(0),config);
|
||||
|
||||
List<BaseEntry> returnList = new ArrayList<BaseEntry>(resultCount);
|
||||
List<StorageEntryWrapper> bufferedWrapperList = this.buffer
|
||||
.getSortedEntries(feedId);
|
||||
int alreadyAdded = 0;
|
||||
int offset = startIndex - 1;
|
||||
|
||||
if (bufferedWrapperList != null
|
||||
&& bufferedWrapperList.size() >= startIndex) {
|
||||
|
||||
updated = bufferedWrapperList.get(0).getEntry().getUpdated();
|
||||
for (; alreadyAdded < resultCount; alreadyAdded++) {
|
||||
if ((bufferedWrapperList.size() - offset) > 0) {
|
||||
StorageEntryWrapper wrappedEntry = bufferedWrapperList
|
||||
.get(offset++);
|
||||
returnList.add(wrappedEntry.getEntry());
|
||||
returnList
|
||||
.add(wrappedEntry.getEntry());
|
||||
} else
|
||||
break;
|
||||
}
|
||||
// reset offset
|
||||
offset = startIndex - 1;
|
||||
if (alreadyAdded == resultCount)
|
||||
return returnList;
|
||||
if (alreadyAdded == resultCount){
|
||||
retVal.getEntries().addAll(returnList);
|
||||
retVal.setUpdated(updated);
|
||||
return retVal;
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* if the buffersize is less than the startindex the buffersize must
|
||||
|
@ -207,12 +226,22 @@ public class StorageQuery {
|
|||
|
||||
for (; (offset < hits.length()) && (alreadyAdded < resultCount); offset++, alreadyAdded++) {
|
||||
Document doc = hits.doc(offset);
|
||||
BaseEntry entry = buildEntryFromLuceneDocument(doc, profil);
|
||||
BaseEntry entry = buildEntryFromLuceneDocument(doc, config);
|
||||
returnList.add(entry);
|
||||
}
|
||||
|
||||
if(updated == null){
|
||||
try{
|
||||
long updatedTimeStamp = Long.parseLong(hits.doc(0).get(StorageEntryWrapper.FIELD_TIMESTAMP));
|
||||
updated = new DateTime(updatedTimeStamp);
|
||||
}catch (Exception e) {
|
||||
LOG.warn("could not create DateTime -- "+e.getMessage(),e);
|
||||
updated = buildEntryFromLuceneDocument(hits.doc(0),config).getUpdated();
|
||||
}
|
||||
return returnList;
|
||||
}
|
||||
}
|
||||
retVal.setUpdated(updated);
|
||||
retVal.getEntries().addAll(returnList);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -228,22 +257,21 @@ public class StorageQuery {
|
|||
* the entry to fetch
|
||||
* @param feedId -
|
||||
* the feedid eg. feed context
|
||||
* @param profil -
|
||||
* the extension profile used to create the entriy instances
|
||||
* @param config -
|
||||
* the FeedInstanceConfiguration contaning extension profile used
|
||||
* to create the entriy instances
|
||||
* @return - the requested {@link BaseEntry} or <code>null</code> if the
|
||||
* entry can not be found
|
||||
* @throws IOException -
|
||||
* if the index could not be queries or the entries could not be
|
||||
* build
|
||||
* @throws FeedNotFoundException -
|
||||
* if the requested feed is not registered
|
||||
* @throws ParseException -
|
||||
* if an entry could not be parsed while building it from the
|
||||
* Lucene Document.
|
||||
*/
|
||||
public BaseEntry singleEntryQuery(final String entryId,
|
||||
final String feedId, final ExtensionProfile profil)
|
||||
throws IOException, FeedNotFoundException, ParseException {
|
||||
final String feedId, final ProvidedService config)
|
||||
throws IOException, ParseException {
|
||||
StorageEntryWrapper wrapper = this.buffer.getEntry(entryId, feedId);
|
||||
|
||||
if (wrapper == null) {
|
||||
|
@ -252,8 +280,13 @@ public class StorageQuery {
|
|||
return null;
|
||||
Document doc = hits.doc(0);
|
||||
|
||||
return buildEntryFromLuceneDocument(doc, profil);
|
||||
return buildEntryFromLuceneDocument(doc, config);
|
||||
}
|
||||
/*
|
||||
* ServerBaseEntry enables the dynamic element of the entry like the
|
||||
* links to be dynamic. BufferedEntries will be reused until they are
|
||||
* written.
|
||||
*/
|
||||
return wrapper.getEntry();
|
||||
|
||||
}
|
||||
|
@ -274,21 +307,21 @@ public class StorageQuery {
|
|||
* the entriy ids to fetch.
|
||||
* @param feedId -
|
||||
* the feed id eg. feed context.
|
||||
* @param profil -
|
||||
* the extension profile used to create the entry instances.
|
||||
* @param config -
|
||||
* the FeedInstanceConfiguration contaning extension profile used
|
||||
* to create the entriy instances
|
||||
*
|
||||
* @return - the list of entries corresponding to the given entry id list.
|
||||
* @throws IOException -
|
||||
* if the index could not be queries or the entries could not be
|
||||
* build
|
||||
* @throws FeedNotFoundException -
|
||||
* if the requested feed is not registered
|
||||
* @throws ParseException -
|
||||
* if an entry could not be parsed while building it from the
|
||||
* Lucene Document.
|
||||
*/
|
||||
public List<BaseEntry> entryQuery(List<String> entryIds,
|
||||
final String feedId, final ExtensionProfile profil)
|
||||
throws IOException, FeedNotFoundException, ParseException {
|
||||
final String feedId, final ProvidedService config)
|
||||
throws IOException, ParseException {
|
||||
List<BaseEntry> resultList = new ArrayList<BaseEntry>(entryIds.size());
|
||||
List<String> searchList = new ArrayList<String>(entryIds.size());
|
||||
for (String entry : entryIds) {
|
||||
|
@ -308,7 +341,7 @@ public class StorageQuery {
|
|||
while (hitIterator.hasNext()) {
|
||||
Hit hit = (Hit) hitIterator.next();
|
||||
Document doc = hit.getDocument();
|
||||
BaseEntry entry = buildEntryFromLuceneDocument(doc, profil);
|
||||
BaseEntry entry = buildEntryFromLuceneDocument(doc, config);
|
||||
resultList.add(entry);
|
||||
|
||||
}
|
||||
|
@ -318,15 +351,44 @@ public class StorageQuery {
|
|||
}
|
||||
|
||||
private BaseEntry buildEntryFromLuceneDocument(final Document doc,
|
||||
final ExtensionProfile profil) throws FeedNotFoundException,
|
||||
ParseException, IOException {
|
||||
StringReader reader = new StringReader(doc.getField(StorageEntryWrapper.FIELD_CONTENT)
|
||||
.stringValue());
|
||||
return GDataEntityBuilder.buildEntry(doc.getField(StorageEntryWrapper.FIELD_FEED_ID)
|
||||
.stringValue(), reader, profil);
|
||||
final ProvidedService config) throws ParseException,
|
||||
IOException {
|
||||
StringReader reader = new StringReader(doc.getField(
|
||||
StorageEntryWrapper.FIELD_CONTENT).stringValue());
|
||||
return GDataEntityBuilder.buildEntry( reader, config);
|
||||
|
||||
}
|
||||
|
||||
private BaseFeed buildFeedFromLuceneDocument(final Document doc,
|
||||
final ProvidedService config) throws ParseException,
|
||||
IOException {
|
||||
StringReader reader = new StringReader(doc.getField(
|
||||
StorageFeedWrapper.FIELD_CONTENT).stringValue());
|
||||
return GDataEntityBuilder
|
||||
.buildFeed(reader, config);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Queries the storage for an user instance
|
||||
*
|
||||
* @param username -
|
||||
* the username (primary key)
|
||||
* @return - the user instance if found or <code>null</code> if not exists
|
||||
* @throws IOException -
|
||||
* if the storage can not be accessed.
|
||||
*/
|
||||
public GDataAccount getUser(final String username) throws IOException {
|
||||
if (username == null)
|
||||
return null;
|
||||
TermQuery query = new TermQuery(new Term(
|
||||
StorageAccountWrapper.FIELD_ACCOUNTNAME, username));
|
||||
Hits h = this.searcher.search(query);
|
||||
if (h.length() == 0)
|
||||
return null;
|
||||
return StorageAccountWrapper.buildEntity(h.doc(0));
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes all resources used in the {@link StorageQuery}. The instance can
|
||||
* not be reused after invoking this method.
|
||||
|
@ -339,4 +401,92 @@ public class StorageQuery {
|
|||
this.buffer.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether a feed for the given feedID is stored
|
||||
* @param feedId - the feed ID
|
||||
* @return <code>true</code> if and only if a feed is stored for the provided feed ID, <code>false</code> if no feed for the given id is stored
|
||||
* @throws IOException
|
||||
*/
|
||||
public boolean isFeedStored(String feedId)throws IOException{
|
||||
Hits h = storageFeedQuery(feedId);
|
||||
return (h.length() > 0);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Looks up the feedtype for the given feed ID
|
||||
* @param feedID - the feed ID
|
||||
* @return - the feed type
|
||||
* @throws IOException - if the storage can not be accessed
|
||||
*/
|
||||
public String getService(String feedID) throws IOException {
|
||||
Hits hits = storageFeedQuery(feedID);
|
||||
if (hits.length() <= 0)
|
||||
return null;
|
||||
Document doc = hits.doc(0);
|
||||
String feedType = doc.get(StorageFeedWrapper.FIELD_SERVICE_ID);
|
||||
return feedType;
|
||||
}
|
||||
private Hits storageFeedQuery(String feedId) throws IOException {
|
||||
TermQuery query = new TermQuery(new Term(
|
||||
StorageFeedWrapper.FIELD_FEED_ID, feedId));
|
||||
return this.searcher.search(query);
|
||||
}
|
||||
|
||||
/**
|
||||
* Looks up the account reference for the given feed id
|
||||
* @param feedId - id of the feed
|
||||
* @return - the name of the account associated with the feed for the given feed id, or <code>null</code> if the feed is not stored
|
||||
* @throws IOException - if the storage can not be accessed
|
||||
*/
|
||||
public String getAccountNameForFeedId(String feedId) throws IOException {
|
||||
Hits h = storageFeedQuery(feedId);
|
||||
if(h.length() == 0)
|
||||
return null;
|
||||
Document doc = h.doc(0);
|
||||
return doc.get(StorageFeedWrapper.FIELD_ACCOUNTREFERENCE);
|
||||
|
||||
}
|
||||
protected long getEntryLastModified(final String entryId,final String feedId) throws IOException, StorageException{
|
||||
StorageEntryWrapper wrapper = this.buffer.getEntry(entryId,feedId);
|
||||
if(wrapper != null)
|
||||
return wrapper.getTimestamp();
|
||||
|
||||
Hits h = storageQuery(entryId);
|
||||
if(h.length() > 0)
|
||||
try{
|
||||
return Long.parseLong(h.doc(0).get(StorageEntryWrapper.FIELD_TIMESTAMP));
|
||||
}catch (Exception e) {
|
||||
LOG.warn("Can not parse timestamp from entry -- "+h.doc(0).get(StorageEntryWrapper.FIELD_TIMESTAMP));
|
||||
}
|
||||
else
|
||||
throw new StorageException("Entry not found");
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
protected long getFeedLastModified(final String feedId)throws IOException{
|
||||
Long bufferedTime = this.buffer.getFeedLastModified(feedId);
|
||||
if(bufferedTime != null)
|
||||
return bufferedTime;
|
||||
Hits entryHits = storageFeedQuery(feedId,this.timeStampSort);
|
||||
if(entryHits.length() > 0){
|
||||
try{
|
||||
return Long.parseLong(entryHits.doc(0).getField(StorageEntryWrapper.FIELD_TIMESTAMP).stringValue());
|
||||
}catch (Exception e) {
|
||||
LOG.warn("Can not parse timestamp from entry -- "+entryHits.doc(0).get(StorageEntryWrapper.FIELD_TIMESTAMP));
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
||||
}
|
||||
protected boolean isEntryStored(String entryId,String feedId) throws IOException{
|
||||
if(this.buffer.getEntry(entryId,feedId)!=null)
|
||||
return true;
|
||||
|
||||
Hits h = storageQuery(entryId);
|
||||
if(h.length() > 0)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,6 +38,7 @@ public class StorageConfigurator {
|
|||
|
||||
private final boolean recover;
|
||||
|
||||
private final boolean ramDirectory;
|
||||
private static StorageConfigurator INSTANCE = null;
|
||||
|
||||
private final int indexOptimizeInterval;
|
||||
|
@ -64,7 +65,8 @@ public class StorageConfigurator {
|
|||
.getProperty("gdata.server.storage.lucene.directory");
|
||||
this.indexOptimizeInterval = Integer.parseInt(properties
|
||||
.getProperty("gdata.server.storage.lucene.optimizeInterval"));
|
||||
|
||||
this.ramDirectory = Boolean.parseBoolean(properties
|
||||
.getProperty("gdata.server.storage.lucene.directory.ramDirectory"));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -141,4 +143,11 @@ public class StorageConfigurator {
|
|||
return this.indexOptimizeInterval;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the ramDirectory.
|
||||
*/
|
||||
public boolean isRamDirectory() {
|
||||
return this.ramDirectory;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -21,13 +21,13 @@ import junit.framework.TestCase;
|
|||
|
||||
import org.apache.lucene.gdata.server.GDataRequest.GDataRequestType;
|
||||
import org.apache.lucene.gdata.server.GDataRequest.OutputFormat;
|
||||
import org.apache.lucene.gdata.server.registry.FeedInstanceConfigurator;
|
||||
import org.apache.lucene.gdata.server.registry.GDataServerRegistry;
|
||||
import org.apache.lucene.gdata.server.registry.ProvidedService;
|
||||
import org.apache.lucene.gdata.server.registry.RegistryException;
|
||||
import org.apache.lucene.gdata.utils.ProvidedServiceStub;
|
||||
import org.apache.lucene.gdata.utils.StorageStub;
|
||||
import org.easymock.MockControl;
|
||||
|
||||
import com.google.gdata.data.ExtensionProfile;
|
||||
import com.google.gdata.data.Feed;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Simon Willnauer
|
||||
|
@ -39,14 +39,21 @@ public class TestGDataRequest extends TestCase {
|
|||
private MockControl control;
|
||||
|
||||
private GDataRequest feedRequest;
|
||||
static{
|
||||
try {
|
||||
GDataServerRegistry.getRegistry().registerComponent(StorageStub.class);
|
||||
} catch (RegistryException e) {
|
||||
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
FeedInstanceConfigurator configurator = new FeedInstanceConfigurator();
|
||||
configurator.setFeedType(Feed.class);
|
||||
configurator.setFeedId("feed");
|
||||
configurator.setExtensionProfileClass(ExtensionProfile.class);
|
||||
GDataServerRegistry.getRegistry().registerFeed(configurator);
|
||||
ProvidedService configurator = new ProvidedServiceStub();
|
||||
GDataServerRegistry.getRegistry().registerService(configurator);
|
||||
|
||||
|
||||
this.control = MockControl.createControl(HttpServletRequest.class);
|
||||
this.request = (HttpServletRequest) this.control.getMock();
|
||||
this.feedRequest = new GDataRequest(this.request,GDataRequestType.GET);
|
||||
|
@ -216,7 +223,7 @@ public class TestGDataRequest extends TestCase {
|
|||
public void testGetSelfId() throws GDataRequestException{
|
||||
String host = "www.apache.org";
|
||||
String feedAndEntryID = "/feed/entryid";
|
||||
String queryString = "?max-results=25";
|
||||
String queryString = "max-results=25";
|
||||
this.control.expectAndDefaultReturn(this.request.getHeader("Host"),host);
|
||||
this.control.expectAndDefaultReturn(this.request.getRequestURI(),"/host/feed/entryId/15");
|
||||
this.control.expectAndDefaultReturn(this.request.getPathInfo(),"/feed/entryId/15");
|
||||
|
@ -227,13 +234,13 @@ public class TestGDataRequest extends TestCase {
|
|||
queryString);
|
||||
this.control.replay();
|
||||
this.feedRequest.initializeRequest();
|
||||
String selfID = "http://"+host+"/host/feed/entryId/15"+queryString;
|
||||
String selfID = "http://"+host+"/host/feed/entryId/15?"+queryString;
|
||||
|
||||
assertEquals("Self ID",selfID,this.feedRequest.getSelfId());
|
||||
this.control.reset();
|
||||
|
||||
|
||||
queryString = "?alt=rss&max-results=25";
|
||||
queryString = "alt=rss&max-results=25";
|
||||
this.control.expectAndDefaultReturn(this.request.getHeader("Host"),host);
|
||||
this.control.expectAndDefaultReturn(this.request.getRequestURI(),"/host/feed/entryId/15");
|
||||
this.control.expectAndDefaultReturn(this.request.getPathInfo(),"/feed/entryId/15");
|
||||
|
@ -244,7 +251,7 @@ public class TestGDataRequest extends TestCase {
|
|||
queryString);
|
||||
this.control.replay();
|
||||
this.feedRequest.initializeRequest();
|
||||
selfID = "http://"+host+"/host/feed/entryId/15"+queryString;
|
||||
selfID = "http://"+host+"/host/feed/entryId/15?"+queryString;
|
||||
|
||||
assertEquals("Self ID",selfID,this.feedRequest.getSelfId());
|
||||
this.control.reset();
|
||||
|
@ -296,7 +303,7 @@ public class TestGDataRequest extends TestCase {
|
|||
queryString);
|
||||
this.control.replay();
|
||||
|
||||
assertEquals("?"+maxResults,this.feedRequest.getQueryString());
|
||||
assertEquals(maxResults,this.feedRequest.getQueryString());
|
||||
this.control.reset();
|
||||
|
||||
}
|
||||
|
@ -342,7 +349,11 @@ public class TestGDataRequest extends TestCase {
|
|||
|
||||
|
||||
}
|
||||
public void testIsEntryRequest(){
|
||||
public void testgetAuthToken(){
|
||||
this.control.expectAndDefaultReturn(this.request.getHeader("Authentication"),"GoogleLogin auth=bla");
|
||||
this.control.replay();
|
||||
assertEquals("bla",this.feedRequest.getAuthToken());
|
||||
this.control.verify();
|
||||
|
||||
}
|
||||
|
||||
|
@ -352,7 +363,8 @@ public class TestGDataRequest extends TestCase {
|
|||
// String queryString = "?max-results=25";
|
||||
// String startIndex = "&start-index=26";
|
||||
// this.control.expectAndDefaultReturn(this.request.getHeader("Host"),host);
|
||||
// this.control.expectAndDefaultReturn(this.request.getPathInfo(),"/feed/entryId/15");
|
||||
// this.control.expectAndDefaultReturn(this.request.getRequestURI(),"/feed/");
|
||||
// this.control.expectAndDefaultReturn(this.request.getPathInfo(),"/feed/");
|
||||
// this.control.expectAndReturn(this.request.getParameter("max-results"),"25",2);
|
||||
// this.control.expectAndReturn(this.request.getParameter("start-index"),null);
|
||||
// this.control.expectAndDefaultReturn(this.request.getParameter("alt"),
|
||||
|
@ -361,22 +373,27 @@ public class TestGDataRequest extends TestCase {
|
|||
// queryString);
|
||||
// this.control.replay();
|
||||
// this.feedRequest.initializeRequest();
|
||||
// String nextID = "http://"+host+"/feed"+queryString+startIndex;
|
||||
// String nextID = "http://"+host+"/feed/"+queryString+startIndex;
|
||||
//
|
||||
// assertEquals("Next ID",nextID,this.feedRequest.getNextId());
|
||||
// this.control.reset();
|
||||
//
|
||||
//
|
||||
|
||||
|
||||
// queryString = "?alt=rss&max-results=25";
|
||||
//
|
||||
// this.control.expectAndDefaultReturn(this.request.getHeader("Host"),host);
|
||||
// this.control.expectAndDefaultReturn(this.request.getPathInfo(),"/feed/entryId/15");
|
||||
// this.control.expectAndDefaultReturn(this.request.getRequestURI(),"/feed/");
|
||||
// this.control.expectAndDefaultReturn(this.request.getPathInfo(),"/feed/");
|
||||
// this.control.expectAndReturn(this.request.getParameter("max-results"),"25",2);
|
||||
// this.control.expectAndReturn(this.request.getParameter("start-index"),"26",2);
|
||||
// this.control.expectAndDefaultReturn(this.request.getParameter("alt"),
|
||||
// null);
|
||||
// this.control.expectAndDefaultReturn(this.request.getQueryString(),
|
||||
// queryString+startIndex);
|
||||
// Enumeration e =
|
||||
// this.control.expectAndDefaultReturn(this.request.getParameterNames(),)
|
||||
//
|
||||
//
|
||||
// this.control.replay();
|
||||
// this.feedRequest.initializeRequest();
|
||||
// startIndex = "&start-index=51";
|
||||
|
@ -395,7 +412,7 @@ public class TestGDataRequest extends TestCase {
|
|||
// null);
|
||||
// this.control.replay();
|
||||
// this.feedRequest.initializeRequest();
|
||||
// selfID = "http://"+host+"/feed"+"?max-results=25";
|
||||
// String selfID = "http://"+host+"/feed"+"?max-results=25";
|
||||
//
|
||||
// assertEquals("Self ID",selfID,this.feedRequest.getSelfId());
|
||||
// this.control.reset();
|
||||
|
|
|
@ -71,11 +71,11 @@ public class TestGDataResponse extends TestCase {
|
|||
PrintWriter writer = new PrintWriter(stringWriter);
|
||||
|
||||
this.control.expectAndReturn(this.httpResponse.getWriter(),writer);
|
||||
this.httpResponse.setContentType(GDataResponse.XMLMIME_ATOM);
|
||||
this.response.setOutputFormat(OutputFormat.ATOM);
|
||||
this.control.replay();
|
||||
|
||||
this.response.sendResponse(createFeed(),new ExtensionProfile
|
||||
());
|
||||
this.response.sendResponse(createFeed(),new ExtensionProfile());
|
||||
assertEquals("Simple XML representation",stringWriter.toString(),generatedFeedAtom);
|
||||
this.control.reset();
|
||||
|
||||
|
@ -84,6 +84,7 @@ public class TestGDataResponse extends TestCase {
|
|||
|
||||
this.control.expectAndReturn(this.httpResponse.getWriter(),writer);
|
||||
this.response.setOutputFormat(OutputFormat.RSS);
|
||||
this.httpResponse.setContentType(GDataResponse.XMLMIME_RSS);
|
||||
this.control.replay();
|
||||
|
||||
this.response.sendResponse(createFeed(),new ExtensionProfile
|
||||
|
|
|
@ -15,6 +15,13 @@
|
|||
*/
|
||||
package org.apache.lucene.gdata.server.registry;
|
||||
|
||||
import org.apache.lucene.gdata.server.ServiceFactory;
|
||||
import org.apache.lucene.gdata.servlet.handler.DefaultRequestHandlerFactory;
|
||||
import org.apache.lucene.gdata.servlet.handler.RequestHandlerFactory;
|
||||
import org.apache.lucene.gdata.storage.StorageController;
|
||||
import org.apache.lucene.gdata.storage.lucenestorage.StorageCoreController;
|
||||
|
||||
import com.google.gdata.data.Entry;
|
||||
import com.google.gdata.data.Feed;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
@ -25,11 +32,13 @@ import junit.framework.TestCase;
|
|||
*/
|
||||
public class TestFeedRegistry extends TestCase {
|
||||
private GDataServerRegistry reg;
|
||||
private FeedInstanceConfigurator configurator;
|
||||
private ProvidedServiceConfig configurator;
|
||||
@Override
|
||||
protected void setUp(){
|
||||
this.reg = GDataServerRegistry.getRegistry();
|
||||
this.configurator = new FeedInstanceConfigurator();
|
||||
this.configurator = new ProvidedServiceConfig();
|
||||
this.configurator.setEntryType(Entry.class);
|
||||
this.configurator.setFeedType(Feed.class);
|
||||
}
|
||||
/**
|
||||
* @see junit.framework.TestCase#tearDown()
|
||||
|
@ -50,13 +59,13 @@ public class TestFeedRegistry extends TestCase {
|
|||
/**
|
||||
* Test method for 'org.apache.lucene.gdata.server.registry.FeedRegistry.registerFeed(FeedInstanceConfigurator)'
|
||||
*/
|
||||
public void testRegisterFeed() {
|
||||
String feedURL = "myFeed";
|
||||
registerFeed(feedURL);
|
||||
assertEquals("Registered Configurator",this.configurator,this.reg.getFeedConfigurator(feedURL));
|
||||
assertNull("not registered Configurator",this.reg.getFeedConfigurator("somethingElse"));
|
||||
public void testRegisterService() {
|
||||
String service = "service";
|
||||
registerService(service);
|
||||
assertEquals("Registered Configurator",this.configurator,this.reg.getProvidedService(service));
|
||||
assertNull("not registered Configurator",this.reg.getProvidedService("something"));
|
||||
try{
|
||||
this.reg.getFeedConfigurator(null);
|
||||
this.reg.getProvidedService(null);
|
||||
fail("Exception expected");
|
||||
}catch (IllegalArgumentException e) {
|
||||
//
|
||||
|
@ -67,11 +76,12 @@ public class TestFeedRegistry extends TestCase {
|
|||
* Test method for 'org.apache.lucene.gdata.server.registry.FeedRegistry.getFeedConfigurator(String)'
|
||||
*/
|
||||
public void testFlushRegistry() {
|
||||
String feedURL = "testFeed";
|
||||
registerFeed(feedURL);
|
||||
assertEquals("Registered Configurator",this.configurator,this.reg.getFeedConfigurator(feedURL));
|
||||
String service = "service";
|
||||
registerService(service);
|
||||
|
||||
assertEquals("Registered Configurator",this.configurator,this.reg.getProvidedService(service));
|
||||
this.reg.flushRegistry();
|
||||
assertNull("Registry flushed",this.reg.getFeedConfigurator(feedURL));
|
||||
assertNull("Registry flushed",this.reg.getProvidedService(service));
|
||||
|
||||
|
||||
}
|
||||
|
@ -80,19 +90,43 @@ public class TestFeedRegistry extends TestCase {
|
|||
*
|
||||
*/
|
||||
public void testIsFeedRegistered(){
|
||||
String myFeed = "myFeed";
|
||||
registerFeed(myFeed);
|
||||
assertTrue("Feed is registerd",this.reg.isFeedRegistered(myFeed));
|
||||
assertFalse("null Feed is not registerd",this.reg.isFeedRegistered(null));
|
||||
assertFalse("Feed is not registerd",this.reg.isFeedRegistered("someOtherFeed"));
|
||||
String service = "service";
|
||||
registerService(service);
|
||||
assertTrue("Feed is registerd",this.reg.isServiceRegistered(service));
|
||||
assertFalse("null Feed is not registerd",this.reg.isServiceRegistered(null));
|
||||
assertFalse("Feed is not registerd",this.reg.isServiceRegistered("something"));
|
||||
|
||||
}
|
||||
|
||||
private void registerFeed(String feedURL){
|
||||
private void registerService(String servicename){
|
||||
|
||||
this.configurator.setName(servicename);
|
||||
this.reg.registerService(this.configurator);
|
||||
}
|
||||
|
||||
public void testRegisterComponent() throws RegistryException{
|
||||
try {
|
||||
this.reg.registerComponent(StorageController.class);
|
||||
fail("RegistryException expected");
|
||||
} catch (RegistryException e) {
|
||||
//
|
||||
}
|
||||
this.reg.registerComponent(StorageCoreController.class);
|
||||
|
||||
this.reg.registerComponent(DefaultRequestHandlerFactory.class);
|
||||
RequestHandlerFactory factory = this.reg.lookup(RequestHandlerFactory.class,ComponentType.REQUESTHANDLERFACTORY);
|
||||
try{
|
||||
this.reg.registerComponent(DefaultRequestHandlerFactory.class);
|
||||
fail("RegistryException expected");
|
||||
} catch (RegistryException e) {
|
||||
//
|
||||
}
|
||||
this.reg.registerComponent(ServiceFactory.class);
|
||||
ServiceFactory servicefactory = this.reg.lookup(ServiceFactory.class,ComponentType.SERVICEFACTORY);
|
||||
assertNotNull(servicefactory);
|
||||
assertNotNull(factory);
|
||||
|
||||
|
||||
this.configurator.setFeedType(Feed.class);
|
||||
this.configurator.setFeedId(feedURL);
|
||||
this.reg.registerFeed(this.configurator);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -22,7 +22,8 @@ import java.io.Reader;
|
|||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.apache.lucene.gdata.server.FeedNotFoundException;
|
||||
import org.apache.lucene.gdata.data.ServerBaseEntry;
|
||||
import org.apache.lucene.gdata.data.ServerBaseFeed;
|
||||
import org.apache.lucene.gdata.server.GDataEntityBuilder;
|
||||
|
||||
import com.google.gdata.data.BaseEntry;
|
||||
|
@ -30,6 +31,7 @@ import com.google.gdata.data.BaseFeed;
|
|||
import com.google.gdata.data.Entry;
|
||||
import com.google.gdata.data.ExtensionProfile;
|
||||
import com.google.gdata.data.Feed;
|
||||
import com.google.gdata.data.Source;
|
||||
import com.google.gdata.util.ParseException;
|
||||
|
||||
/**
|
||||
|
@ -44,8 +46,9 @@ public class TestGDataEntityBuilder extends TestCase {
|
|||
private static GDataServerRegistry reg = GDataServerRegistry.getRegistry();
|
||||
private Reader reader;
|
||||
private static String feedID = "myFeed";
|
||||
private ExtensionProfile profile;
|
||||
private ProvidedServiceConfig config;
|
||||
private static Class feedType = Feed.class;
|
||||
private static Class entryType = Entry.class;
|
||||
|
||||
|
||||
/**
|
||||
|
@ -53,11 +56,12 @@ public class TestGDataEntityBuilder extends TestCase {
|
|||
*/
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
FeedInstanceConfigurator config = new FeedInstanceConfigurator();
|
||||
config.setFeedId(feedID);
|
||||
config.setFeedType(feedType);
|
||||
this.profile = new ExtensionProfile();
|
||||
reg.registerFeed(config);
|
||||
this.config = new ProvidedServiceConfig();
|
||||
|
||||
this.config.setFeedType(feedType);
|
||||
this.config.setEntryType(entryType);
|
||||
this.config.setExtensionProfile(new ExtensionProfile());
|
||||
reg.registerService(this.config);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -72,24 +76,27 @@ public class TestGDataEntityBuilder extends TestCase {
|
|||
/**
|
||||
* Test method for 'org.apache.lucene.gdata.data.GDataEntityBuilder.buildFeed(String, Reader)'
|
||||
*/
|
||||
public void testBuildFeedStringReader() throws FeedNotFoundException, ParseException, IOException {
|
||||
public void testBuildFeedStringReader() throws ParseException, IOException {
|
||||
this.reader = new FileReader(incomingFeed);
|
||||
BaseFeed feed = GDataEntityBuilder.buildFeed(feedID,this.reader,this.profile);
|
||||
BaseFeed feed = GDataEntityBuilder.buildFeed(this.reader,this.config);
|
||||
assertNotNull(feed);
|
||||
assertEquals("feed title",feed.getTitle().getPlainText(), feedTitleFromXML);
|
||||
assertTrue( feed instanceof Feed);
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
/**
|
||||
* Test method for 'org.apache.lucene.gdata.data.GDataEntityBuilder.buildEntry(String, Reader)'
|
||||
*/
|
||||
public void testBuildEntryStringReader() throws FeedNotFoundException, ParseException, IOException {
|
||||
public void testBuildEntryStringReader() throws ParseException, IOException {
|
||||
this.reader = new FileReader(incomingEntry);
|
||||
BaseEntry entry = GDataEntityBuilder.buildEntry(feedID,this.reader,this.profile);
|
||||
BaseEntry entry = GDataEntityBuilder.buildEntry(this.reader,this.config);
|
||||
assertNotNull(entry);
|
||||
assertEquals("entry summary",entry.getSummary().getPlainText(),entrySummaryFromXML);
|
||||
assertTrue(entry instanceof Entry);
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -1,81 +1,72 @@
|
|||
package org.apache.lucene.gdata.storage.lucenestorage;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Date;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.apache.lucene.analysis.standard.StandardAnalyzer;
|
||||
import org.apache.lucene.gdata.server.FeedNotFoundException;
|
||||
import org.apache.lucene.gdata.server.registry.FeedInstanceConfigurator;
|
||||
import org.apache.lucene.gdata.data.GDataAccount;
|
||||
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.GDataServerRegistry;
|
||||
import org.apache.lucene.gdata.server.registry.RegistryBuilder;
|
||||
import org.apache.lucene.gdata.server.registry.ProvidedService;
|
||||
import org.apache.lucene.gdata.storage.StorageController;
|
||||
import org.apache.lucene.gdata.storage.StorageException;
|
||||
import org.apache.lucene.gdata.storage.lucenestorage.StorageCoreController;
|
||||
import org.apache.lucene.gdata.storage.lucenestorage.StorageEntryWrapper;
|
||||
import org.apache.lucene.gdata.storage.lucenestorage.StorageModifier;
|
||||
import org.apache.lucene.gdata.storage.lucenestorage.StorageQuery;
|
||||
import org.apache.lucene.gdata.storage.lucenestorage.StorageEntryWrapper.StorageOperation;
|
||||
import org.apache.lucene.gdata.storage.lucenestorage.util.ReferenceCounter;
|
||||
import org.apache.lucene.index.IndexWriter;
|
||||
import org.apache.lucene.gdata.utils.ProvidedServiceStub;
|
||||
import org.apache.lucene.index.Term;
|
||||
import org.apache.lucene.search.BooleanClause;
|
||||
import org.apache.lucene.search.BooleanQuery;
|
||||
import org.apache.lucene.search.Hits;
|
||||
import org.apache.lucene.search.IndexSearcher;
|
||||
import org.apache.lucene.search.Query;
|
||||
import org.apache.lucene.search.TermQuery;
|
||||
import org.apache.lucene.store.Directory;
|
||||
import org.apache.lucene.store.RAMDirectory;
|
||||
|
||||
import com.google.gdata.data.BaseEntry;
|
||||
import com.google.gdata.data.DateTime;
|
||||
import com.google.gdata.data.Entry;
|
||||
import com.google.gdata.data.ExtensionProfile;
|
||||
import com.google.gdata.data.Feed;
|
||||
import com.google.gdata.data.PlainTextConstruct;
|
||||
import com.google.gdata.data.TextConstruct;
|
||||
import com.google.gdata.data.TextContent;
|
||||
import com.google.gdata.util.ParseException;
|
||||
|
||||
public class TestStorageModifier extends TestCase {
|
||||
private StorageModifier modifier;
|
||||
|
||||
private int count = 1;
|
||||
|
||||
private ExtensionProfile profile;
|
||||
private ProvidedService configurator;
|
||||
|
||||
private Directory dir;
|
||||
|
||||
private StorageCoreController controller;
|
||||
|
||||
private static String feedId = "myFeed";
|
||||
|
||||
private static String username = "simon";
|
||||
|
||||
private static String password = "test";
|
||||
private static String service = "myService";
|
||||
|
||||
protected void setUp() throws Exception {
|
||||
FeedInstanceConfigurator configurator = new FeedInstanceConfigurator();
|
||||
configurator.setFeedType(Feed.class);
|
||||
configurator.setFeedId(feedId);
|
||||
configurator.setExtensionProfileClass(ExtensionProfile.class);
|
||||
GDataServerRegistry.getRegistry().registerFeed(configurator);
|
||||
dir = new RAMDirectory();
|
||||
this.profile = new ExtensionProfile();
|
||||
IndexWriter writer;
|
||||
|
||||
writer = new IndexWriter(dir,new StandardAnalyzer(),true);
|
||||
writer.close();
|
||||
modifier = StorageCoreController.getStorageCoreController(dir).getStorageModifier();
|
||||
|
||||
GDataServerRegistry.getRegistry().registerComponent(
|
||||
StorageCoreController.class);
|
||||
this.configurator = new ProvidedServiceStub();
|
||||
GDataServerRegistry.getRegistry().registerService(this.configurator);
|
||||
this.controller = (StorageCoreController) GDataServerRegistry
|
||||
.getRegistry().lookup(StorageController.class,
|
||||
ComponentType.STORAGECONTROLLER);
|
||||
this.modifier = this.controller.getStorageModifier();
|
||||
this.dir = this.controller.getDirectory();
|
||||
|
||||
}
|
||||
|
||||
protected void tearDown() throws Exception {
|
||||
this.count = 1;
|
||||
// destroy all resources
|
||||
GDataServerRegistry.getRegistry().destroy();//TODO remove dependency here
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Test method for
|
||||
* 'org.apache.lucene.storage.lucenestorage.StorageModifier.StorageModifier(Directory,
|
||||
* int)'
|
||||
*/
|
||||
public void testStorageModifier() {
|
||||
GDataServerRegistry.getRegistry().destroy();// TODO remove dependency
|
||||
// here
|
||||
|
||||
}
|
||||
|
||||
|
@ -83,75 +74,91 @@ public class TestStorageModifier extends TestCase {
|
|||
* Test method for
|
||||
* 'org.apache.lucene.storage.lucenestorage.StorageModifier.updateEntry(StroageEntryWrapper)'
|
||||
*/
|
||||
public void testUpdateEntry() throws IOException, InterruptedException, FeedNotFoundException, ParseException, StorageException {
|
||||
public void testUpdateEntry() throws IOException, InterruptedException,
|
||||
ParseException, StorageException {
|
||||
testInsertEntry();
|
||||
for(int i = 1; i < this.count; i++){
|
||||
for (int i = 1; i < this.count; i++) {
|
||||
Entry e = new Entry();
|
||||
e.setId(""+i);
|
||||
String insertString = "Hello world"+i;
|
||||
e.setId("" + i);
|
||||
String insertString = "Hello world" + i;
|
||||
e.setTitle(new PlainTextConstruct(insertString));
|
||||
StorageEntryWrapper wrapper = new StorageEntryWrapper(e,feedId,StorageOperation.UPDATE,this.profile);
|
||||
ServerBaseEntry en = getServerEntry(e);
|
||||
StorageEntryWrapper wrapper = new StorageEntryWrapper(en,
|
||||
StorageOperation.UPDATE);
|
||||
this.modifier.updateEntry(wrapper);
|
||||
ReferenceCounter<StorageQuery> innerQuery = StorageCoreController.getStorageCoreController().getStorageQuery();
|
||||
BaseEntry fetchedEntry = innerQuery.get().singleEntryQuery(""+i,feedId,this.profile);
|
||||
assertEquals("updated Title:",insertString,fetchedEntry.getTitle().getPlainText());
|
||||
ReferenceCounter<StorageQuery> innerQuery = this.controller
|
||||
.getStorageQuery();
|
||||
BaseEntry fetchedEntry = innerQuery.get().singleEntryQuery("" + i,
|
||||
feedId, this.configurator);
|
||||
assertEquals("updated Title:", insertString, fetchedEntry
|
||||
.getTitle().getPlainText());
|
||||
}
|
||||
// double updates
|
||||
for(int i = 1; i < this.count; i++){
|
||||
for (int i = 1; i < this.count; i++) {
|
||||
Entry e = new Entry();
|
||||
e.setId(""+i);
|
||||
String insertString = "Hello world"+i;
|
||||
e.setId("" + i);
|
||||
String insertString = "Hello world" + i;
|
||||
e.setTitle(new PlainTextConstruct(insertString));
|
||||
StorageEntryWrapper wrapper = new StorageEntryWrapper(e,feedId,StorageOperation.UPDATE,this.profile);
|
||||
ServerBaseEntry en = getServerEntry(e);
|
||||
StorageEntryWrapper wrapper = new StorageEntryWrapper(en,
|
||||
StorageOperation.UPDATE);
|
||||
this.modifier.updateEntry(wrapper);
|
||||
|
||||
e = new Entry();
|
||||
e.setId(""+i);
|
||||
insertString = "Foo Bar"+i;
|
||||
e.setId("" + i);
|
||||
insertString = "Foo Bar" + i;
|
||||
e.setTitle(new PlainTextConstruct(insertString));
|
||||
wrapper = new StorageEntryWrapper(e,feedId,StorageOperation.UPDATE,this.profile);
|
||||
en = getServerEntry(e);
|
||||
wrapper = new StorageEntryWrapper(en,
|
||||
StorageOperation.UPDATE);
|
||||
this.modifier.updateEntry(wrapper);
|
||||
|
||||
ReferenceCounter<StorageQuery> innerQuery = StorageCoreController.getStorageCoreController().getStorageQuery();
|
||||
ReferenceCounter<StorageQuery> innerQuery = this.controller
|
||||
.getStorageQuery();
|
||||
|
||||
BaseEntry fetchedEntry = innerQuery.get().singleEntryQuery(""+i,feedId,this.profile);
|
||||
assertEquals("updated Title:",insertString,fetchedEntry.getTitle().getPlainText());
|
||||
BaseEntry fetchedEntry = innerQuery.get().singleEntryQuery("" + i,
|
||||
feedId, this.configurator);
|
||||
assertEquals("updated Title:", insertString, fetchedEntry
|
||||
.getTitle().getPlainText());
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Test method for
|
||||
* 'org.apache.lucene.storage.lucenestorage.StorageModifier.insertEntry(StroageEntryWrapper)'
|
||||
*/
|
||||
public void testInsertEntry() throws IOException, InterruptedException, FeedNotFoundException, ParseException, StorageException {
|
||||
public void testInsertEntry() throws IOException, InterruptedException,
|
||||
ParseException, StorageException {
|
||||
|
||||
Thread a = getRunnerThread(this.count);
|
||||
a.start();
|
||||
|
||||
Thread b = getRunnerThread((this.count+=10));
|
||||
Thread b = getRunnerThread((this.count += 10));
|
||||
b.start();
|
||||
a.join();
|
||||
for (int i = 1; i < this.count ; i++) {
|
||||
ReferenceCounter<StorageQuery> innerQuery = StorageCoreController.getStorageCoreController().getStorageQuery();
|
||||
BaseEntry e = innerQuery.get().singleEntryQuery(""+i,feedId,this.profile);
|
||||
assertEquals("get entry for id"+i,""+i,e.getId());
|
||||
|
||||
for (int i = 1; i < this.count; i++) {
|
||||
ReferenceCounter<StorageQuery> innerQuery = this.controller
|
||||
.getStorageQuery();
|
||||
BaseEntry e = innerQuery.get().singleEntryQuery("" + i, feedId,
|
||||
this.configurator);
|
||||
assertEquals("get entry for id" + i, "" + i, e.getId());
|
||||
|
||||
}
|
||||
b.join();
|
||||
ReferenceCounter<StorageQuery> query = StorageCoreController.getStorageCoreController().getStorageQuery();
|
||||
ReferenceCounter<StorageQuery> query = this.controller
|
||||
.getStorageQuery();
|
||||
|
||||
this.count+=10;
|
||||
for (int i = 1; i < this.count ; i++) {
|
||||
BaseEntry e = query.get().singleEntryQuery(""+i,feedId,this.profile);
|
||||
assertEquals("get entry for id"+i,""+i,e.getId());
|
||||
this.count += 10;
|
||||
for (int i = 1; i < this.count; i++) {
|
||||
BaseEntry e = query.get().singleEntryQuery("" + i, feedId,
|
||||
this.configurator);
|
||||
assertEquals("get entry for id" + i, "" + i, e.getId());
|
||||
}
|
||||
|
||||
BaseEntry e = query.get().singleEntryQuery(""+this.count,feedId,this.profile);
|
||||
assertNull("not entry for ID",e);
|
||||
BaseEntry e = query.get().singleEntryQuery("" + this.count, feedId,
|
||||
this.configurator);
|
||||
assertNull("not entry for ID", e);
|
||||
query.decrementRef();
|
||||
|
||||
}
|
||||
|
@ -160,70 +167,196 @@ public class TestStorageModifier extends TestCase {
|
|||
* Test method for
|
||||
* 'org.apache.lucene.storage.lucenestorage.StorageModifier.deleteEntry(String)'
|
||||
*/
|
||||
public void testDeleteEntry() throws IOException, InterruptedException, FeedNotFoundException, ParseException, StorageException {
|
||||
public void testDeleteEntry() throws IOException, InterruptedException,
|
||||
ParseException, StorageException {
|
||||
testInsertEntry();
|
||||
for (int i = 1; i < this.count ; i++) {
|
||||
if(i%2 == 0 || i< 10){
|
||||
this.modifier.deleteEntry(""+i,feedId);
|
||||
for (int i = 1; i < this.count; i++) {
|
||||
if (i % 2 == 0 || i < 10) {
|
||||
ServerBaseEntry entry = new ServerBaseEntry();
|
||||
entry.setId("" + i);
|
||||
entry.setFeedId(feedId);
|
||||
this.modifier.deleteEntry(new StorageEntryWrapper(entry,StorageOperation.DELETE));
|
||||
}
|
||||
ReferenceCounter<StorageQuery> query = StorageCoreController.getStorageCoreController().getStorageQuery();
|
||||
if(i%2 == 0 || i< 10){
|
||||
assertNull(query.get().singleEntryQuery(""+i,feedId,this.profile));
|
||||
}
|
||||
else
|
||||
assertEquals(""+i,query.get().singleEntryQuery(""+i,feedId,this.profile).getId());
|
||||
ReferenceCounter<StorageQuery> query = this.controller
|
||||
.getStorageQuery();
|
||||
if (i % 2 == 0 || i < 10) {
|
||||
assertNull(query.get().singleEntryQuery("" + i, feedId,
|
||||
this.configurator));
|
||||
} else
|
||||
assertEquals("" + i, query.get().singleEntryQuery("" + i,
|
||||
feedId, this.configurator).getId());
|
||||
query.decrementRef();
|
||||
}
|
||||
|
||||
StorageCoreController.getStorageCoreController().forceWrite();
|
||||
this.controller.forceWrite();
|
||||
IndexSearcher searcher = new IndexSearcher(this.dir);
|
||||
|
||||
for (int i = 1; i < this.count ; i++) {
|
||||
Query luceneQuery = new TermQuery(new Term(StorageEntryWrapper.FIELD_ENTRY_ID,""+i));
|
||||
for (int i = 1; i < this.count; i++) {
|
||||
Query luceneQuery = new TermQuery(new Term(
|
||||
StorageEntryWrapper.FIELD_ENTRY_ID, "" + i));
|
||||
Hits hits = searcher.search(luceneQuery);
|
||||
if(i%2 == 0 || i< 10){
|
||||
if (i % 2 == 0 || i < 10) {
|
||||
|
||||
assertEquals(0,hits.length());
|
||||
}
|
||||
else
|
||||
assertEquals(1,hits.length());
|
||||
assertEquals(0, hits.length());
|
||||
} else
|
||||
assertEquals(1, hits.length());
|
||||
}
|
||||
searcher.close();
|
||||
|
||||
}
|
||||
|
||||
public void testSaveUser() throws StorageException, IOException {
|
||||
|
||||
private Thread getRunnerThread(int idIndex){
|
||||
GDataAccount user = new GDataAccount();
|
||||
user.setName(username);
|
||||
user.setPassword(password);
|
||||
StorageAccountWrapper wrapper = new StorageAccountWrapper(user);
|
||||
this.modifier.createAccount(wrapper);
|
||||
IndexSearcher searcher = new IndexSearcher(this.dir);
|
||||
Query q = new TermQuery(new Term(StorageAccountWrapper.FIELD_ACCOUNTNAME,
|
||||
username));
|
||||
Hits h = searcher.search(q);
|
||||
assertEquals("length == 1", 1, h.length());
|
||||
GDataAccount storedUser = StorageAccountWrapper.buildEntity(h.doc(0));
|
||||
assertTrue(storedUser.equals(user));
|
||||
searcher.close();
|
||||
}
|
||||
|
||||
public void testDeleteUser() throws StorageException, IOException {
|
||||
testSaveUser();
|
||||
this.modifier.deleteAccount(username);
|
||||
IndexSearcher searcher = new IndexSearcher(this.dir);
|
||||
Query q = new TermQuery(new Term(StorageAccountWrapper.FIELD_ACCOUNTNAME,
|
||||
username));
|
||||
Hits h = searcher.search(q);
|
||||
assertEquals("length == 0", 0, h.length());
|
||||
searcher.close();
|
||||
}
|
||||
|
||||
public void testUpdateUser() throws StorageException, IOException {
|
||||
testSaveUser();
|
||||
GDataAccount user = new GDataAccount();
|
||||
user.setName(username);
|
||||
user.setPassword("newPass");
|
||||
StorageAccountWrapper wrapper = new StorageAccountWrapper(user);
|
||||
this.modifier.updateAccount(wrapper);
|
||||
IndexSearcher searcher = new IndexSearcher(this.dir);
|
||||
Query q = new TermQuery(new Term(StorageAccountWrapper.FIELD_ACCOUNTNAME,
|
||||
username));
|
||||
Hits h = searcher.search(q);
|
||||
assertEquals("length == 1", 1, h.length());
|
||||
GDataAccount storedUser = StorageAccountWrapper.buildEntity(h.doc(0));
|
||||
assertTrue(storedUser.equals(user));
|
||||
|
||||
assertFalse(storedUser.getPassword().equals(password));
|
||||
searcher.close();
|
||||
}
|
||||
|
||||
public void testSaveFeed() throws IOException, StorageException {
|
||||
String title = "myTitle";
|
||||
ServerBaseFeed feed = new ServerBaseFeed();
|
||||
feed.setId(feedId);
|
||||
feed.setTitle(new PlainTextConstruct(title));
|
||||
feed.setServiceType(service);
|
||||
feed.setServiceConfig(this.configurator);
|
||||
StorageFeedWrapper wrapper = new StorageFeedWrapper(feed,username);
|
||||
this.modifier.createFeed(wrapper);
|
||||
|
||||
IndexSearcher searcher = new IndexSearcher(this.dir);
|
||||
Query q = new TermQuery(new Term(StorageFeedWrapper.FIELD_FEED_ID,
|
||||
feedId));
|
||||
Hits h = searcher.search(q);
|
||||
assertEquals("length == 1", 1, h.length());
|
||||
searcher.close();
|
||||
|
||||
}
|
||||
|
||||
public void testDeleteFeed() throws IOException, StorageException {
|
||||
testSaveFeed();
|
||||
Entry e = new Entry();
|
||||
e.setTitle(new PlainTextConstruct("hello world"));
|
||||
ServerBaseEntry entry = new ServerBaseEntry(e);
|
||||
entry.setFeedId(feedId);
|
||||
entry.setId("testme");
|
||||
entry.setServiceConfig(this.configurator);
|
||||
StorageEntryWrapper entryWrapper = new StorageEntryWrapper(entry,StorageOperation.INSERT);
|
||||
this.modifier.insertEntry(entryWrapper);
|
||||
this.modifier.forceWrite();
|
||||
this.modifier.deleteFeed(feedId);
|
||||
IndexSearcher searcher = new IndexSearcher(this.dir);
|
||||
Query q = new TermQuery(new Term(StorageFeedWrapper.FIELD_FEED_ID,
|
||||
feedId));
|
||||
Query q1 = new TermQuery(new Term(StorageEntryWrapper.FIELD_FEED_REFERENCE,
|
||||
feedId));
|
||||
BooleanQuery boolQuery = new BooleanQuery();
|
||||
boolQuery.add(q,BooleanClause.Occur.SHOULD);
|
||||
boolQuery.add(q1,BooleanClause.Occur.SHOULD);
|
||||
Hits h = searcher.search(boolQuery);
|
||||
assertEquals("length == 0", 0, h.length());
|
||||
searcher.close();
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws IOException
|
||||
* @throws StorageException
|
||||
*/
|
||||
public void testUpdateFeed() throws IOException, StorageException {
|
||||
testSaveFeed();
|
||||
ServerBaseFeed feed = new ServerBaseFeed();
|
||||
String title = "myTitle";
|
||||
String newusername = "doug";
|
||||
feed.setTitle(new PlainTextConstruct(title));
|
||||
feed.setId(feedId);
|
||||
feed.setServiceType(service);
|
||||
feed.setServiceConfig(this.configurator);
|
||||
StorageFeedWrapper wrapper = new StorageFeedWrapper(feed,newusername);
|
||||
this.modifier.updateFeed(wrapper);
|
||||
IndexSearcher searcher = new IndexSearcher(this.dir);
|
||||
Query q = new TermQuery(new Term(StorageFeedWrapper.FIELD_FEED_ID,
|
||||
feedId));
|
||||
Hits h = searcher.search(q);
|
||||
assertEquals("length == 1", 1, h.length());
|
||||
assertTrue(h.doc(0).get(StorageFeedWrapper.FIELD_ACCOUNTREFERENCE).equals(newusername));
|
||||
searcher.close();
|
||||
|
||||
}
|
||||
|
||||
private Thread getRunnerThread(int idIndex) {
|
||||
Thread t = new Thread(new Runner(idIndex));
|
||||
return t;
|
||||
}
|
||||
|
||||
private class Runner implements Runnable{
|
||||
private class Runner implements Runnable {
|
||||
private int idIndex;
|
||||
public Runner(int idIndex){
|
||||
|
||||
public Runner(int idIndex) {
|
||||
this.idIndex = idIndex;
|
||||
}
|
||||
public void run() {
|
||||
for (int i = idIndex; i < idIndex+10; i++) {
|
||||
|
||||
BaseEntry e = buildEntry(""+i);
|
||||
public void run() {
|
||||
for (int i = idIndex; i < idIndex + 10; i++) {
|
||||
|
||||
BaseEntry e = buildEntry("" + i);
|
||||
try {
|
||||
StorageEntryWrapper wrapper = new StorageEntryWrapper(e,feedId,StorageOperation.INSERT,new ExtensionProfile());
|
||||
ServerBaseEntry en = new ServerBaseEntry(e);
|
||||
en.setFeedId(feedId);
|
||||
en.setServiceConfig(configurator);
|
||||
StorageEntryWrapper wrapper = new StorageEntryWrapper(en,
|
||||
StorageOperation.INSERT);
|
||||
modifier.insertEntry(wrapper);
|
||||
} catch (Exception e1) {
|
||||
|
||||
e1.printStackTrace();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
}// end run
|
||||
|
||||
}//end run
|
||||
|
||||
private BaseEntry buildEntry(String id){
|
||||
private BaseEntry buildEntry(String id) {
|
||||
Entry e = new Entry();
|
||||
e.setId(id);
|
||||
e.setTitle(new PlainTextConstruct("Monty Python"));
|
||||
|
@ -231,12 +364,12 @@ public class TestStorageModifier extends TestCase {
|
|||
e.setPublished(DateTime.now());
|
||||
|
||||
e.setUpdated(DateTime.now());
|
||||
String content = "1st soldier with a keen interest in birds: Who goes there?" +
|
||||
"King Arthur: It is I, Arthur, son of Uther Pendragon, from the castle of Camelot. King of the Britons, defeater of the Saxons, Sovereign of all England!" +
|
||||
"1st soldier with a keen interest in birds: Pull the other one!" +
|
||||
"King Arthur: I am, and this is my trusty servant Patsy. We have ridden the length and breadth of the land in search of knights who will join me in my court at Camelot. I must speak with your lord and master." +
|
||||
"1st soldier with a keen interest in birds: What? Ridden on a horse?" +
|
||||
"King Arthur: Yes!";
|
||||
String content = "1st soldier with a keen interest in birds: Who goes there?"
|
||||
+ "King Arthur: It is I, Arthur, son of Uther Pendragon, from the castle of Camelot. King of the Britons, defeater of the Saxons, Sovereign of all England!"
|
||||
+ "1st soldier with a keen interest in birds: Pull the other one!"
|
||||
+ "King Arthur: I am, and this is my trusty servant Patsy. We have ridden the length and breadth of the land in search of knights who will join me in my court at Camelot. I must speak with your lord and master."
|
||||
+ "1st soldier with a keen interest in birds: What? Ridden on a horse?"
|
||||
+ "King Arthur: Yes!";
|
||||
e.setContent(new TextContent(new PlainTextConstruct(content)));
|
||||
e.setSummary(new PlainTextConstruct("The Holy Grail"));
|
||||
return e;
|
||||
|
@ -244,4 +377,11 @@ public class TestStorageModifier extends TestCase {
|
|||
|
||||
}
|
||||
|
||||
private ServerBaseEntry getServerEntry(BaseEntry e){
|
||||
ServerBaseEntry en = new ServerBaseEntry(e);
|
||||
en.setFeedId(feedId);
|
||||
en.setServiceConfig(this.configurator);
|
||||
return en;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,74 +1,85 @@
|
|||
package org.apache.lucene.gdata.storage.lucenestorage;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.apache.lucene.analysis.standard.StandardAnalyzer;
|
||||
import org.apache.lucene.gdata.server.FeedNotFoundException;
|
||||
import org.apache.lucene.gdata.server.registry.FeedInstanceConfigurator;
|
||||
import org.apache.lucene.gdata.data.GDataAccount;
|
||||
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.GDataServerRegistry;
|
||||
import org.apache.lucene.gdata.server.registry.RegistryBuilder;
|
||||
import org.apache.lucene.gdata.server.registry.ProvidedService;
|
||||
import org.apache.lucene.gdata.storage.StorageController;
|
||||
import org.apache.lucene.gdata.storage.StorageException;
|
||||
import org.apache.lucene.gdata.storage.lucenestorage.StorageCoreController;
|
||||
import org.apache.lucene.gdata.storage.lucenestorage.StorageEntryWrapper;
|
||||
import org.apache.lucene.gdata.storage.lucenestorage.StorageModifier;
|
||||
import org.apache.lucene.gdata.storage.lucenestorage.StorageQuery;
|
||||
import org.apache.lucene.gdata.storage.lucenestorage.StorageEntryWrapper.StorageOperation;
|
||||
import org.apache.lucene.gdata.storage.lucenestorage.util.ReferenceCounter;
|
||||
import org.apache.lucene.index.IndexWriter;
|
||||
import org.apache.lucene.gdata.utils.ProvidedServiceStub;
|
||||
import org.apache.lucene.store.Directory;
|
||||
import org.apache.lucene.store.RAMDirectory;
|
||||
|
||||
import com.google.gdata.data.BaseEntry;
|
||||
import com.google.gdata.data.BaseFeed;
|
||||
import com.google.gdata.data.DateTime;
|
||||
import com.google.gdata.data.Entry;
|
||||
import com.google.gdata.data.ExtensionProfile;
|
||||
import com.google.gdata.data.Feed;
|
||||
import com.google.gdata.util.ParseException;
|
||||
|
||||
public class TestStorageQuery extends TestCase {
|
||||
private StorageModifier modifier;
|
||||
private int count = 30;
|
||||
private ReferenceCounter<StorageQuery> query;
|
||||
private ExtensionProfile profile;
|
||||
|
||||
private ProvidedService configurator;
|
||||
private StorageCoreController controller;
|
||||
private Directory dir;
|
||||
private static String feedId = "myFeed";
|
||||
private static String accountName = "simon";
|
||||
private static String service = ProvidedServiceStub.SERVICE_NAME;
|
||||
protected void setUp() throws Exception {
|
||||
FeedInstanceConfigurator configurator = new FeedInstanceConfigurator();
|
||||
configurator.setFeedType(Feed.class);
|
||||
configurator.setFeedId(feedId);
|
||||
configurator.setExtensionProfileClass(ExtensionProfile.class);
|
||||
GDataServerRegistry.getRegistry().registerFeed(configurator);
|
||||
this.profile = new ExtensionProfile();
|
||||
this.dir = new RAMDirectory();
|
||||
IndexWriter writer;
|
||||
writer = new IndexWriter(this.dir,new StandardAnalyzer(),true);
|
||||
writer.close();
|
||||
this.modifier = StorageCoreController.getStorageCoreController(this.dir).getStorageModifier();
|
||||
GDataServerRegistry.getRegistry().registerComponent(StorageCoreController.class);
|
||||
this.configurator = new ProvidedServiceStub();
|
||||
|
||||
|
||||
GDataServerRegistry.getRegistry().registerService(this.configurator);
|
||||
this.controller = (StorageCoreController)GDataServerRegistry.getRegistry().lookup(StorageController.class,ComponentType.STORAGECONTROLLER);
|
||||
this.modifier = this.controller.getStorageModifier();
|
||||
this.dir = this.controller.getDirectory();
|
||||
ServerBaseFeed feed = new ServerBaseFeed();
|
||||
feed.setId(feedId);
|
||||
feed.setServiceType(service);
|
||||
feed.setServiceConfig(this.configurator);
|
||||
|
||||
StorageFeedWrapper wrapper = new StorageFeedWrapper(feed,accountName);
|
||||
this.modifier.createFeed(wrapper);
|
||||
insertEntries(this.count);
|
||||
this.query = StorageCoreController.getStorageCoreController().getStorageQuery();
|
||||
this.query = this.controller.getStorageQuery();
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
public void insertEntries(int count) throws IOException,InterruptedException, StorageException{
|
||||
/**
|
||||
* @param entrycount
|
||||
* @throws IOException
|
||||
* @throws InterruptedException
|
||||
* @throws StorageException
|
||||
*/
|
||||
public void insertEntries(int entrycount) throws IOException,InterruptedException, StorageException{
|
||||
List<StorageEntryWrapper> tempList = new ArrayList<StorageEntryWrapper>();
|
||||
for (int i = 0; i <= count ; i++) {
|
||||
Entry entry = new Entry();
|
||||
for (int i = 0; i <= entrycount ; i++) {
|
||||
ServerBaseEntry entry = new ServerBaseEntry(new Entry());
|
||||
entry.setId(""+i);
|
||||
|
||||
entry.setServiceConfig(this.configurator);
|
||||
entry.setUpdated(new DateTime(System.currentTimeMillis(),0));
|
||||
StorageEntryWrapper wrapper = new StorageEntryWrapper(entry,feedId,StorageOperation.INSERT,this.profile);
|
||||
entry.setFeedId(feedId);
|
||||
StorageEntryWrapper wrapper = new StorageEntryWrapper(entry,StorageOperation.INSERT);
|
||||
tempList.add(i,wrapper);
|
||||
|
||||
// force different timestamps --> DateTime 2006-06-05T13:37:55.724Z
|
||||
Thread.sleep(50);
|
||||
Thread.sleep(10);
|
||||
|
||||
}
|
||||
for (StorageEntryWrapper entry : tempList) {
|
||||
|
@ -82,24 +93,33 @@ public class TestStorageQuery extends TestCase {
|
|||
|
||||
protected void tearDown() throws Exception {
|
||||
this.query.decrementRef();
|
||||
GDataServerRegistry.getRegistry().destroy();//TODO remove dependency here
|
||||
GDataServerRegistry.getRegistry().destroy();
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
*/
|
||||
public void testAccountNameQuery() throws IOException, StorageException{
|
||||
ReferenceCounter<StorageQuery> query = this.controller.getStorageQuery();
|
||||
assertEquals(accountName,query.get().getAccountNameForFeedId(feedId));
|
||||
assertNull(query.get().getAccountNameForFeedId("someId"));
|
||||
}
|
||||
|
||||
/*
|
||||
* Test method for 'org.apache.lucene.storage.lucenestorage.StorageQuery.feedQuery(String, int, int)'
|
||||
*/
|
||||
public void testFeedQuery() throws IOException, FeedNotFoundException, ParseException, StorageException {
|
||||
FeedQueryHelper(this.query);
|
||||
StorageCoreController.getStorageCoreController().forceWrite();
|
||||
ReferenceCounter<StorageQuery> queryAssureWritten = StorageCoreController.getStorageCoreController().getStorageQuery();
|
||||
public void testFeedQuery() throws IOException, ParseException, StorageException {
|
||||
feedQueryHelper(this.query);
|
||||
this.controller.forceWrite();
|
||||
ReferenceCounter<StorageQuery> queryAssureWritten = this.controller.getStorageQuery();
|
||||
|
||||
assertNotSame(queryAssureWritten,this.query);
|
||||
FeedQueryHelper(queryAssureWritten);
|
||||
feedQueryHelper(queryAssureWritten);
|
||||
queryAssureWritten.decrementRef();
|
||||
}
|
||||
private void FeedQueryHelper(ReferenceCounter<StorageQuery> currentQuery) throws IOException, FeedNotFoundException, ParseException{
|
||||
List<BaseEntry> entryList = currentQuery.get().getLatestFeedQuery(feedId,25,1,this.profile);
|
||||
|
||||
private void feedQueryHelper(ReferenceCounter<StorageQuery> currentQuery) throws IOException, ParseException{
|
||||
BaseFeed feed = currentQuery.get().getLatestFeedQuery(feedId,25,1,this.configurator);
|
||||
List<BaseEntry> entryList = feed.getEntries();
|
||||
assertTrue("listSize: "+entryList.size(),entryList.size() == 25);
|
||||
|
||||
BaseEntry tempEntry = null;
|
||||
|
@ -116,7 +136,8 @@ public class TestStorageQuery extends TestCase {
|
|||
// test sub retrieve sublist
|
||||
int offset = 15;
|
||||
int resultCount = 5;
|
||||
List<BaseEntry> entrySubList = currentQuery.get().getLatestFeedQuery(feedId,resultCount,offset,this.profile);
|
||||
feed = currentQuery.get().getLatestFeedQuery(feedId,resultCount,offset,this.configurator);
|
||||
List<BaseEntry> entrySubList = feed.getEntries();
|
||||
|
||||
assertTrue("listSize: "+entrySubList.size(),entrySubList.size() == resultCount);
|
||||
offset--;
|
||||
|
@ -134,9 +155,9 @@ public class TestStorageQuery extends TestCase {
|
|||
/*
|
||||
* Test method for 'org.apache.lucene.storage.lucenestorage.StorageQuery.singleEntryQuery(String, String)'
|
||||
*/
|
||||
public void testSingleEntryQuery() throws FeedNotFoundException, ParseException, IOException {
|
||||
public void testSingleEntryQuery() throws ParseException, IOException {
|
||||
for (int i = 1; i <= this.count; i++) {
|
||||
BaseEntry entry = this.query.get().singleEntryQuery(""+i,feedId,this.profile);
|
||||
BaseEntry entry = this.query.get().singleEntryQuery(""+i,feedId,this.configurator);
|
||||
assertEquals(""+i,entry.getId());
|
||||
}
|
||||
|
||||
|
@ -145,24 +166,92 @@ public class TestStorageQuery extends TestCase {
|
|||
/*
|
||||
* Test method for 'org.apache.lucene.storage.lucenestorage.StorageQuery.entryQuery(List<String>, String)'
|
||||
*/
|
||||
public void testEntryQuery() throws FeedNotFoundException, ParseException, IOException, StorageException {
|
||||
public void testEntryQuery() throws ParseException, IOException, StorageException {
|
||||
entryQueryHelper(this.query);
|
||||
StorageCoreController.getStorageCoreController().forceWrite();
|
||||
ReferenceCounter<StorageQuery> queryAssureWritten = StorageCoreController.getStorageCoreController().getStorageQuery();
|
||||
this.controller.forceWrite();
|
||||
ReferenceCounter<StorageQuery> queryAssureWritten = this.controller.getStorageQuery();
|
||||
|
||||
assertNotSame(queryAssureWritten,query);
|
||||
entryQueryHelper(queryAssureWritten);
|
||||
queryAssureWritten.decrementRef();
|
||||
}
|
||||
public void testGetUser() throws StorageException, IOException{
|
||||
this.modifier.forceWrite();
|
||||
GDataAccount user = new GDataAccount();
|
||||
user.setName("simon");
|
||||
user.setPassword("pass");
|
||||
user.setAuthorname("simon willnauer");
|
||||
user.setAuthorMail("simon@apache.org");
|
||||
user.setAuthorLink(new URL("http://www.apache.org"));
|
||||
|
||||
|
||||
private void entryQueryHelper(ReferenceCounter<StorageQuery> currentQuery) throws IOException, FeedNotFoundException, ParseException{
|
||||
|
||||
this.modifier.createAccount(new StorageAccountWrapper(user));
|
||||
GDataAccount queriedUser = this.query.get().getUser("simon");
|
||||
assertNull(queriedUser);
|
||||
ReferenceCounter<StorageQuery> tempQuery = this.controller.getStorageQuery();
|
||||
queriedUser = tempQuery.get().getUser("simon");
|
||||
assertTrue(queriedUser.equals(user));
|
||||
assertTrue(queriedUser.getAuthorMail().equals(user.getAuthorMail()));
|
||||
assertTrue(queriedUser.getAuthorLink().equals(user.getAuthorLink()));
|
||||
assertTrue(queriedUser.getAuthorname().equals(user.getAuthorname()));
|
||||
assertTrue(queriedUser.getPassword().equals(user.getPassword()));
|
||||
}
|
||||
|
||||
public void testIsEntryStored() throws IOException{
|
||||
|
||||
assertTrue(this.query.get().isEntryStored(""+(this.count-1),feedId));
|
||||
assertFalse(this.query.get().isEntryStored("someOther",feedId));
|
||||
this.modifier.forceWrite();
|
||||
assertTrue(this.query.get().isEntryStored(""+(this.count-1),feedId));
|
||||
this.query = this.controller.getStorageQuery();
|
||||
assertTrue(this.query.get().isEntryStored(""+(this.count-1),feedId));
|
||||
assertFalse(this.query.get().isEntryStored("someOther",feedId));
|
||||
}
|
||||
|
||||
public void testGetEntryLastModied() throws IOException, StorageException{
|
||||
ServerBaseEntry entry = new ServerBaseEntry(new Entry());
|
||||
entry.setId("test");
|
||||
entry.setServiceConfig(this.configurator);
|
||||
entry.setUpdated(new DateTime(System.currentTimeMillis(),0));
|
||||
entry.setFeedId(feedId);
|
||||
StorageEntryWrapper wrapper = new StorageEntryWrapper(entry,StorageOperation.INSERT);
|
||||
|
||||
this.modifier.insertEntry(wrapper);
|
||||
assertEquals(entry.getUpdated().getValue(),this.query.get().getEntryLastModified("test",feedId));
|
||||
this.modifier.forceWrite();
|
||||
assertEquals(entry.getUpdated().getValue(),this.query.get().getEntryLastModified("test",feedId));
|
||||
this.query = this.controller.getStorageQuery();
|
||||
assertEquals(entry.getUpdated().getValue(),this.query.get().getEntryLastModified("test",feedId));
|
||||
try{
|
||||
this.query.get().getEntryLastModified("some",feedId);
|
||||
fail("exception expected");
|
||||
}catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void testGetFeedLastModified() throws StorageException, IOException{
|
||||
ServerBaseEntry entry = new ServerBaseEntry(new Entry());
|
||||
entry.setId("test");
|
||||
entry.setServiceConfig(this.configurator);
|
||||
entry.setUpdated(new DateTime(System.currentTimeMillis(),0));
|
||||
entry.setFeedId(feedId);
|
||||
StorageEntryWrapper wrapper = new StorageEntryWrapper(entry,StorageOperation.INSERT);
|
||||
this.modifier.insertEntry(wrapper);
|
||||
assertEquals(entry.getUpdated().getValue(),this.query.get().getFeedLastModified(feedId));
|
||||
this.modifier.forceWrite();
|
||||
assertEquals(entry.getUpdated().getValue(),this.query.get().getFeedLastModified(feedId));
|
||||
this.query = this.controller.getStorageQuery();
|
||||
assertEquals(entry.getUpdated().getValue(),this.query.get().getFeedLastModified(feedId));
|
||||
}
|
||||
private void entryQueryHelper(ReferenceCounter<StorageQuery> currentQuery) throws IOException, ParseException{
|
||||
|
||||
List<String> entryIdList = new ArrayList<String>();
|
||||
for (int i = 1; i <= this.count; i++) {
|
||||
entryIdList.add(""+i);
|
||||
}
|
||||
List<BaseEntry> entryList = currentQuery.get().entryQuery(entryIdList,feedId,this.profile);
|
||||
List<BaseEntry> entryList = currentQuery.get().entryQuery(entryIdList,feedId,this.configurator);
|
||||
assertEquals(entryIdList.size(),entryList.size());
|
||||
List<String> entryIdCompare = new ArrayList<String>();
|
||||
for (BaseEntry entry : entryList) {
|
||||
|
@ -172,4 +261,6 @@ public class TestStorageQuery extends TestCase {
|
|||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -9,7 +9,9 @@
|
|||
- Lucene
|
||||
</description>
|
||||
<listener>
|
||||
<listener-class> org.apache.lucene.gdata.server.registry.RegistryContextListener</listener-class>
|
||||
<listener-class>
|
||||
org.apache.lucene.gdata.server.registry.RegistryContextListener
|
||||
</listener-class>
|
||||
</listener>
|
||||
<servlet>
|
||||
<servlet-name>ControllerServlet</servlet-name>
|
||||
|
@ -21,4 +23,35 @@
|
|||
<servlet-name>ControllerServlet</servlet-name>
|
||||
<url-pattern>/*</url-pattern>
|
||||
</servlet-mapping>
|
||||
<servlet>
|
||||
<servlet-name>AuthenticationServlet</servlet-name>
|
||||
<servlet-class>
|
||||
org.apache.lucene.gdata.servlet.AuthenticationServlet
|
||||
</servlet-class>
|
||||
</servlet>
|
||||
<servlet-mapping>
|
||||
<servlet-name>AuthenticationServlet</servlet-name>
|
||||
<url-pattern>/accounts/ClientLogin</url-pattern>
|
||||
</servlet-mapping>
|
||||
<servlet>
|
||||
<servlet-name>FeedAdminServlet</servlet-name>
|
||||
<servlet-class>
|
||||
org.apache.lucene.gdata.servlet.FeedAdministrationServlet
|
||||
</servlet-class>
|
||||
</servlet>
|
||||
<servlet-mapping>
|
||||
<servlet-name>FeedAdminServlet</servlet-name>
|
||||
<url-pattern>/admin/feed</url-pattern>
|
||||
</servlet-mapping>
|
||||
<servlet>
|
||||
<servlet-name>AccountAdminServlet</servlet-name>
|
||||
<servlet-class>
|
||||
org.apache.lucene.gdata.servlet.AccountAdministrationServlet
|
||||
</servlet-class>
|
||||
</servlet>
|
||||
<servlet-mapping>
|
||||
<servlet-name>AccountAdminServlet</servlet-name>
|
||||
<url-pattern>/admin/account</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
</web-app>
|
Loading…
Reference in New Issue