Java tutorial
/** * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.lucene.gdata.server; import java.io.IOException; import java.util.Date; import java.util.List; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.lucene.gdata.data.ServerBaseEntry; import org.apache.lucene.gdata.data.ServerBaseFeed; import org.apache.lucene.gdata.server.registry.ComponentType; import org.apache.lucene.gdata.server.registry.EntryEventMediator; import org.apache.lucene.gdata.server.registry.GDataServerRegistry; import org.apache.lucene.gdata.storage.ModificationConflictException; import org.apache.lucene.gdata.storage.ResourceNotFoundException; import org.apache.lucene.gdata.storage.Storage; import org.apache.lucene.gdata.storage.StorageController; import org.apache.lucene.gdata.storage.StorageException; import com.google.gdata.data.BaseEntry; import com.google.gdata.data.BaseFeed; import com.google.gdata.data.DateTime; import com.google.gdata.data.Generator; import com.google.gdata.data.Link; import com.google.gdata.util.ParseException; /** * default implementation of the {@link org.apache.lucene.gdata.server.Service} * interface. * * @author Simon Willnauer * */ public class GDataService implements Service { private static final Log LOG = LogFactory.getLog(GDataService.class); protected Storage storage; protected GDataServerRegistry registry = GDataServerRegistry.getRegistry(); private static final Generator generator; private static final String generatorName = "Lucene GData-Server"; private static final String generatorURI = "http://lucene.apache.org"; private static final String XMLMIME = "application/atom+xml"; protected final EntryEventMediator entryEventMediator; static { generator = new Generator(); generator.setName(generatorName); generator.setUri(generatorURI); generator.setVersion("0.1"); } protected GDataService() throws ServiceException { try { StorageController controller = GDataServerRegistry.getRegistry().lookup(StorageController.class, ComponentType.STORAGECONTROLLER); if (controller == null) throw new StorageException("StorageController is not registered"); this.storage = controller.getStorage(); this.entryEventMediator = GDataServerRegistry.getRegistry().getEntryEventMediator(); } catch (StorageException e) { LOG.fatal("Can't get Storage Instance -- can't serve any requests", e); ServiceException ex = new ServiceException("Can't get Storage instance" + e.getMessage(), e, GDataResponse.SERVER_ERROR); ex.setStackTrace(e.getStackTrace()); throw ex; } } /** * @see org.apache.lucene.gdata.server.Service#createEntry(org.apache.lucene.gdata.server.GDataRequest, * org.apache.lucene.gdata.server.GDataResponse) */ public BaseEntry createEntry(GDataRequest request, GDataResponse response) throws ServiceException { if (LOG.isInfoEnabled()) LOG.info("create Entry for feedId: " + request.getFeedId()); ServerBaseEntry entry = buildEntry(request, response); entry.setFeedId(request.getFeedId()); entry.setServiceConfig(request.getConfigurator()); BaseEntry tempEntry = entry.getEntry(); tempEntry.setPublished(getCurrentDateTime()); tempEntry.setUpdated(getCurrentDateTime()); BaseEntry retVal = null; removeDynamicElements(entry.getEntry()); try { retVal = this.storage.storeEntry(entry); } catch (Exception e) { ServiceException ex = new ServiceException("Could not store entry", e, GDataResponse.SERVER_ERROR); ex.setStackTrace(e.getStackTrace()); throw ex; } this.entryEventMediator.entryAdded(entry); return retVal; } /** * @see org.apache.lucene.gdata.server.Service#deleteEntry(org.apache.lucene.gdata.server.GDataRequest, * org.apache.lucene.gdata.server.GDataResponse) */ public BaseEntry deleteEntry(GDataRequest request, GDataResponse response) throws ServiceException { ServerBaseEntry entry = new ServerBaseEntry(); entry.setServiceConfig(request.getConfigurator()); entry.setFeedId(request.getFeedId()); entry.setId(request.getEntryId()); setVersionId(entry, request, response); if (entry.getId() == null) throw new ServiceException("entry id is null -- can not delete null entry", GDataResponse.SERVER_ERROR); try { this.storage.deleteEntry(entry); } catch (ResourceNotFoundException e) { ServiceException ex = new ServiceException("Could not delete entry", e, GDataResponse.BAD_REQUEST); ex.setStackTrace(e.getStackTrace()); throw ex; } catch (ModificationConflictException e) { ServiceException ex = new ServiceException("Could not delete entry - version conflict", e, GDataResponse.CONFLICT); ex.setStackTrace(e.getStackTrace()); throw ex; } catch (StorageException e) { ServiceException ex = new ServiceException("Could not delete entry", e, GDataResponse.SERVER_ERROR); ex.setStackTrace(e.getStackTrace()); throw ex; } this.entryEventMediator.entryDeleted(entry); //TODO change ret value return null; } /** * @see org.apache.lucene.gdata.server.Service#updateEntry(org.apache.lucene.gdata.server.GDataRequest, * org.apache.lucene.gdata.server.GDataResponse) */ public BaseEntry updateEntry(GDataRequest request, GDataResponse response) throws ServiceException { ServerBaseEntry entry = buildEntry(request, response); entry.setFeedId(request.getFeedId()); setVersionId(entry, request, response); entry.setServiceConfig(request.getConfigurator()); if (LOG.isInfoEnabled()) LOG.info("update Entry" + entry.getId() + " for feedId: " + request.getFeedId()); if (entry.getId() == null) { throw new ServiceException("Entry id is null can not update entry", GDataResponse.BAD_REQUEST); } if (!entry.getId().equals(request.getEntryId())) { if (LOG.isInfoEnabled()) LOG.info("Entry id in the entry xml does not match the requested resource -- XML-ID:" + entry.getId() + "; Requested resource: " + request.getEntryId()); throw new ServiceException("Entry id in the entry xml does not match the requested resource", GDataResponse.BAD_REQUEST); } BaseEntry tempEntry = entry.getEntry(); tempEntry.setUpdated(getCurrentDateTime()); removeDynamicElements(entry.getEntry()); BaseEntry retVal = null; try { retVal = this.storage.updateEntry(entry); } catch (ResourceNotFoundException e) { ServiceException ex = new ServiceException("Could not update entry", e, GDataResponse.BAD_REQUEST); ex.setStackTrace(e.getStackTrace()); throw ex; } catch (ModificationConflictException e) { ServiceException ex = new ServiceException("Could not update entry - version conflict", e, GDataResponse.CONFLICT); ex.setStackTrace(e.getStackTrace()); throw ex; } catch (StorageException e) { ServiceException ex = new ServiceException("Could not update entry", e, GDataResponse.SERVER_ERROR); ex.setStackTrace(e.getStackTrace()); throw ex; } this.entryEventMediator.entryUpdated(entry); return retVal; } /** * @see org.apache.lucene.gdata.server.Service#getFeed(org.apache.lucene.gdata.server.GDataRequest, * org.apache.lucene.gdata.server.GDataResponse) */ @SuppressWarnings("unchecked") public BaseFeed getFeed(GDataRequest request, GDataResponse response) throws ServiceException { ServerBaseFeed feed = new ServerBaseFeed(); feed.setId(request.getFeedId()); feed.setStartIndex(request.getStartIndex()); feed.setItemsPerPage(request.getItemsPerPage()); feed.setServiceConfig(request.getConfigurator()); try { /* * the strategy executes either a search or a direct access. */ BaseFeed retVal = this.storage.getFeed(feed); dynamicElementFeedStragey(retVal, request); return retVal; /* * Resource not found will be detected in Gdata request. * the request queries the storage for the feed to get the service for the feed */ } catch (StorageException e) { ServiceException ex = new ServiceException("Could not get feed", e, GDataResponse.NOT_FOUND); ex.setStackTrace(e.getStackTrace()); throw ex; } } private Link buildLink(String rel, String type, String href) { Link retVal = new Link(); retVal.setHref(href); retVal.setRel(rel); retVal.setType(type); return retVal; } private ServerBaseEntry buildEntry(final GDataRequest request, final GDataResponse response) throws ServiceException { try { ServerBaseEntry entry = new ServerBaseEntry(GDataEntityBuilder.buildEntry(request)); return entry; } catch (ParseException e) { ServiceException ex = new ServiceException("Could not parse entry from incoming request", e, GDataResponse.BAD_REQUEST); ex.setStackTrace(e.getStackTrace()); throw ex; } catch (IOException e) { ServiceException ex = new ServiceException("Could not read or open input stream", e, GDataResponse.BAD_REQUEST); ex.setStackTrace(e.getStackTrace()); throw ex; } } /** * @see org.apache.lucene.gdata.server.Service#getSingleEntry(org.apache.lucene.gdata.server.GDataRequest, * org.apache.lucene.gdata.server.GDataResponse) */ public BaseEntry getSingleEntry(GDataRequest request, GDataResponse response) throws ServiceException { try { ServerBaseEntry entry = new ServerBaseEntry(); entry.setServiceConfig(request.getConfigurator()); entry.setFeedId(request.getFeedId()); entry.setId(request.getEntryId()); if (entry.getId() == null) { throw new ServiceException("entry is null can't get entry", GDataResponse.BAD_REQUEST); } BaseEntry retVal = null; retVal = this.storage.getEntry(entry); dynamicElementEntryStragey(retVal, request); return retVal; } catch (ResourceNotFoundException e) { ServiceException ex = new ServiceException("Could not get entry", e, GDataResponse.BAD_REQUEST); ex.setStackTrace(e.getStackTrace()); throw ex; } catch (StorageException e) { ServiceException ex = new ServiceException("Could not get entry", e, GDataResponse.SERVER_ERROR); ex.setStackTrace(e.getStackTrace()); throw ex; } } /* * adds all dynamic element to the entry */ private void dynamicElementEntryStragey(final BaseEntry entry, final GDataRequest request) { setSelfLink(entry, request.getContextPath()); } /* * adds all dynamic element to the feed entries */ @SuppressWarnings("unchecked") protected void dynamicElementFeedStragey(final BaseFeed feed, final GDataRequest request) { buildDynamicFeedElements(request, feed); List<BaseEntry> entryList = feed.getEntries(); for (BaseEntry entry : entryList) { String id = new StringBuilder(request.getContextPath()).append(entry.getId()).append("/").toString(); setSelfLink(entry, id); } } /* * The selfLink is build from a prefix and the entry id. The prefix is the * context path of the requested feed. This will be used to request the * entry directly */@SuppressWarnings("unchecked") private BaseEntry setSelfLink(final BaseEntry entry, String id) { Link self = buildLink(Link.Rel.SELF, XMLMIME, id); StringBuilder builder = new StringBuilder(id); builder.append(entry.getVersionId()); Link edit = buildLink(Link.Rel.ENTRY_EDIT, XMLMIME, builder.toString()); List<Link> list = entry.getLinks(); list.add(edit); list.add(self); return entry; } /* * build the dynamic elements like self link and next link */ private void buildDynamicFeedElements(final GDataRequest request, final BaseFeed feed) { feed.setGenerator(generator); feed.setItemsPerPage(request.getItemsPerPage()); feed.setStartIndex(request.getStartIndex()); feed.setId(request.getContextPath()); List<Link> links = feed.getLinks(); links.add(buildLink(Link.Rel.SELF, Link.Type.ATOM, request.getSelfId())); links.add(buildLink(Link.Rel.NEXT, XMLMIME, request.getNextId())); String prevLink = request.getPreviousId(); if (prevLink != null) links.add(buildLink(Link.Rel.PREVIOUS, XMLMIME, prevLink)); } /** * @see org.apache.lucene.gdata.server.Service#close() */ public void close() { this.storage.close(); } /** * @see org.apache.lucene.gdata.server.Service#getFeedLastModified(java.lang.String) */ public Date getFeedLastModified(final String feedId) throws ServiceException { try { return new Date(this.storage.getFeedLastModified(feedId)); } catch (StorageException e) { ServiceException ex = new ServiceException("Could not get Last update for feed -- " + feedId, e, GDataResponse.SERVER_ERROR); ex.setStackTrace(e.getStackTrace()); throw ex; } } /** * @see org.apache.lucene.gdata.server.Service#getEntryLastModified(java.lang.String, java.lang.String) */ public Date getEntryLastModified(final String entryId, final String feedId) throws ServiceException { try { return new Date(this.storage.getEntryLastModified(entryId, feedId)); } catch (StorageException e) { ServiceException ex = new ServiceException("Could not get Last update for entry -- " + entryId, e, GDataResponse.SERVER_ERROR); ex.setStackTrace(e.getStackTrace()); throw ex; } } private ServerBaseEntry setVersionId(final ServerBaseEntry entry, final GDataRequest request, final GDataResponse response) throws ServiceException { try { entry.setVersion(Integer.parseInt(request.getEntryVersion())); return entry; } catch (Exception e) { LOG.error("Can not parse entry version -- version is not an integer -- versionid: " + request.getEntryVersion(), e); throw new ServiceException("Can not parse entry version -- version is not an integer -- versionid: " + request.getEntryVersion(), e, GDataResponse.BAD_REQUEST); } } /* * provide current time to set as published / updated values * always use servertime to prevent client / server time lag * Timezoneshift is 0 */ protected DateTime getCurrentDateTime() { return new DateTime(System.currentTimeMillis(), 0); } private void removeDynamicElements(BaseEntry entry) { Link selfLink = entry.getSelfLink(); if (selfLink != null) entry.getLinks().remove(selfLink); Link editLink = entry.getEditLink(); if (editLink != null) entry.getLinks().remove(editLink); } }