[seam-commits] Seam SVN: r8272 - trunk/examples/wiki/src/main/org/jboss/seam/wiki/core/ui.
seam-commits at lists.jboss.org
seam-commits at lists.jboss.org
Fri May 23 12:09:51 EDT 2008
Author: christian.bauer at jboss.com
Date: 2008-05-23 12:09:51 -0400 (Fri, 23 May 2008)
New Revision: 8272
Modified:
trunk/examples/wiki/src/main/org/jboss/seam/wiki/core/ui/FeedServlet.java
trunk/examples/wiki/src/main/org/jboss/seam/wiki/core/ui/FileServlet.java
Log:
Optimized custom servlets for feeds and files
Modified: trunk/examples/wiki/src/main/org/jboss/seam/wiki/core/ui/FeedServlet.java
===================================================================
--- trunk/examples/wiki/src/main/org/jboss/seam/wiki/core/ui/FeedServlet.java 2008-05-23 15:15:55 UTC (rev 8271)
+++ trunk/examples/wiki/src/main/org/jboss/seam/wiki/core/ui/FeedServlet.java 2008-05-23 16:09:51 UTC (rev 8272)
@@ -8,10 +8,8 @@
import com.sun.syndication.feed.synd.*;
import com.sun.syndication.io.SyndFeedOutput;
+import com.sun.syndication.io.FeedException;
import org.jboss.seam.Component;
-import org.jboss.seam.transaction.Transaction;
-import org.jboss.seam.web.Session;
-import org.jboss.seam.security.Identity;
import org.jboss.seam.international.Messages;
import org.jboss.seam.wiki.core.feeds.FeedDAO;
import org.jboss.seam.wiki.core.model.*;
@@ -31,7 +29,6 @@
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
-import javax.transaction.UserTransaction;
import java.io.IOException;
import java.util.*;
@@ -79,6 +76,7 @@
// Allow unit testing
public FeedServlet() {}
+ // TODO: All data access in this method runs with auto-commit mode, see http://jira.jboss.com/jira/browse/JBSEAM-957
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
@@ -95,7 +93,6 @@
if (!feedTypes.containsKey(pathInfo)) {
log.debug("can not render this feed type, returning BAD REQUEST");
response.sendError(HttpServletResponse.SC_BAD_REQUEST, "Unsupported feed type " + pathInfo);
- invalidateSessionIfPossible(request);
return;
}
SyndFeedType syndFeedType = feedTypes.get(pathInfo);
@@ -120,181 +117,168 @@
tag = tagParam;
}
- // TODO: Seam should use its transaction interceptor for java beans: http://jira.jboss.com/jira/browse/JBSEAM-957
- // and that would allow us to break up this gigantic if/then/else clause easily...
- UserTransaction userTx = null;
- boolean startedTx = false;
- try {
- userTx = Transaction.instance();
- if (userTx.getStatus() != javax.transaction.Status.STATUS_ACTIVE) {
- startedTx = true;
- userTx.begin();
- }
+ Feed feed = resolveFeed(aggregateParam, feedIdParam, areaNameParam, nodeNameParam);
- Feed feed = null;
+ if (feed == null) {
+ log.debug("feed not found, returning NOT FOUND");
+ response.sendError(HttpServletResponse.SC_NOT_FOUND, "Feed");
+ return;
+ }
- // Find the feed, depending on variations of request parameters
- if (aggregateParam != null && aggregateParam.length() > 0) {
-
- log.debug("trying to retrieve aggregated feed from cache: " + aggregateParam);
-
- FeedAggregateCache aggregateCache = (FeedAggregateCache)Component.getInstance(FeedAggregateCache.class);
- List<FeedEntryDTO> result = aggregateCache.get(aggregateParam);
- if (result != null) {
- feed = new Feed();
- feed.setAuthor(Messages.instance().get("lacewiki.msg.AutomaticallyGeneratedFeed"));
- feed.setTitle(Messages.instance().get("lacewiki.msg.AutomaticallyGeneratedFeed") + ": " + aggregateParam);
- feed.setPublishedDate(new Date());
- // We are lying here, we don't really have an alternate representation link for this resource
- feed.setLink( Preferences.instance().get(WikiPreferences.class).getBaseUrl() );
- for (FeedEntryDTO feedEntryDTO : result) {
- feed.getFeedEntries().add(feedEntryDTO.getFeedEntry());
- }
- }
-
- } else if (feedIdParam != null && feedIdParam.length() >0) {
- try {
-
- log.debug("trying to retrieve feed for id: " + feedIdParam);
- Long feedId = Long.valueOf(feedIdParam);
- FeedDAO feedDAO = (FeedDAO)Component.getInstance(FeedDAO.class);
- feed = feedDAO.findFeed(feedId);
- } catch (NumberFormatException ex) {
- log.debug("feed identifier couldn't be converted to java.lang.Long");
- response.sendError(HttpServletResponse.SC_NOT_FOUND, "Feed " + feedIdParam);
- }
-
-
- } else if (areaNameParam != null && areaNameParam.matches("^[A-Z0-9]+.*")) {
- log.debug("trying to retrieve area: " + areaNameParam);
- WikiNodeDAO nodeDAO = (WikiNodeDAO)Component.getInstance(WikiNodeDAO.class);
- WikiDirectory area = nodeDAO.findAreaUnrestricted(areaNameParam);
- if (area != null && (nodeNameParam == null || !nodeNameParam.matches("^[A-Z0-9]+.*")) && area.getFeed() != null) {
- log.debug("using feed of area, no node requested: " + area);
- feed = area.getFeed();
- } else if (area != null && nodeNameParam != null && nodeNameParam.matches("^[A-Z0-9]+.*")) {
- log.debug("trying to retrieve node: " + nodeNameParam);
- WikiDirectory nodeDir = nodeDAO.findWikiDirectoryInAreaUnrestricted(area.getAreaNumber(), nodeNameParam);
- if (nodeDir != null && nodeDir.getFeed() != null) {
- log.debug("using feed of node: " + nodeDir);
- feed = nodeDir.getFeed();
- } else {
- log.debug("node not found or node has no feed");
- }
- } else {
- log.debug("area not found or area has no feed");
- }
- } else {
- log.debug("neither feed id nor area name requested, getting wikiRoot feed");
- WikiNodeFactory factory = (WikiNodeFactory)Component.getInstance(WikiNodeFactory.class);
- feed = factory.loadWikiRoot().getFeed();
- }
-
- if (feed == null) {
- log.debug("feed not found, returning NOT FOUND");
- response.sendError(HttpServletResponse.SC_NOT_FOUND, "Feed");
- if (startedTx) userTx.commit();
- invalidateSessionIfPossible(request);
+ log.debug("checking permissions of " + feed);
+ // Authenticate and authorize, first with current user (session) then with basic HTTP authentication
+ Integer currentAccessLevel = (Integer)Component.getInstance("currentAccessLevel");
+ if (feed.getReadAccessLevel() > currentAccessLevel) {
+ boolean loggedIn = ((Authenticator)Component.getInstance(Authenticator.class)).authenticateBasicHttp(request);
+ currentAccessLevel = (Integer)Component.getInstance("currentAccessLevel");
+ if (!loggedIn || feed.getReadAccessLevel() > currentAccessLevel) {
+ log.debug("requiring authentication, feed has higher access level than current");
+ response.setHeader("WWW-Authenticate", "Basic realm=\"" + feed.getTitle().replace("\"", "'") + "\"");
+ response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
return;
}
+ }
- log.debug("checking permissions of " + feed);
- // Authenticate and authorize, first with current user (session) then with basic HTTP authentication
- Integer currentAccessLevel = (Integer)Component.getInstance("currentAccessLevel");
- if (feed.getReadAccessLevel() > currentAccessLevel) {
- boolean loggedIn = ((Authenticator)Component.getInstance(Authenticator.class)).authenticateBasicHttp(request);
- currentAccessLevel = (Integer)Component.getInstance("currentAccessLevel");
- if (!loggedIn || feed.getReadAccessLevel() > currentAccessLevel) {
- log.debug("requiring authentication, feed has higher access level than current");
- response.setHeader("WWW-Authenticate", "Basic realm=\"" + feed.getTitle().replace("\"", "'") + "\"");
- response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
- if (startedTx) userTx.commit();
- invalidateSessionIfPossible(request);
- return;
- }
+ Date lastFeedEntryDate = null;
+ if (feed.getId() != null) {
+
+ // Ask the database what the latest feed entry is for that feed, then use its updated timestamp hash
+ FeedDAO feedDAO = (FeedDAO)Component.getInstance(FeedDAO.class);
+ List<FeedEntry> result = feedDAO.findLastFeedEntries(feed.getId(), 1);
+ if (result.size() > 0) {
+ lastFeedEntryDate = result.get(0).getUpdatedDate();
}
- Date lastFeedEntryDate = null;
- if (feed.getId() != null) {
+ } else {
- // Ask the database what the latest feed entry is for that feed, then use its updated timestamp hash
- FeedDAO feedDAO = (FeedDAO)Component.getInstance(FeedDAO.class);
- List<FeedEntry> result = feedDAO.findLastFeedEntries(feed.getId(), 1);
- if (result.size() > 0) {
- lastFeedEntryDate = result.get(0).getUpdatedDate();
- }
-
- } else {
-
- // Get the first (latest) entry of the aggregated feed and use its published timestamp hash (ignoring updates!)
- // There is a wrinkle hidden here: What if a feed entry is updated? Then the published timestamp should also
- // be different because the "first latest" feed entry in the list is sorted by both published and updated
- // timestamps. So even though we only use published timestamp hash as an ETag, this timestamp also changes
- // when a feed entry is updated because the collection order changes as well.
- if (feed.getFeedEntries().size() > 0) {
- lastFeedEntryDate = feed.getFeedEntries().iterator().next().getPublishedDate();
- }
+ // Get the first (latest) entry of the aggregated feed and use its published timestamp hash (ignoring updates!)
+ // There is a wrinkle hidden here: What if a feed entry is updated? Then the published timestamp should also
+ // be different because the "first latest" feed entry in the list is sorted by both published and updated
+ // timestamps. So even though we only use published timestamp hash as an ETag, this timestamp also changes
+ // when a feed entry is updated because the collection order changes as well.
+ if (feed.getFeedEntries().size() > 0) {
+ lastFeedEntryDate = feed.getFeedEntries().iterator().next().getPublishedDate();
}
- if (lastFeedEntryDate != null) {
- String etag = calculateEtag(lastFeedEntryDate);
- log.debug("setting etag header: " + etag);
- response.setHeader("ETag", etag);
- String previousToken = request.getHeader("If-None-Match");
- if (previousToken != null && previousToken.equals(etag)) {
- log.debug("found matching etag in request header, returning 304 Not Modified");
- response.sendError(HttpServletResponse.SC_NOT_MODIFIED);
- if (startedTx) userTx.commit();
- invalidateSessionIfPossible(request);
- return;
- }
+ }
+ if (lastFeedEntryDate != null) {
+ String etag = calculateEtag(lastFeedEntryDate);
+ log.debug("setting etag header: " + etag);
+ response.setHeader("ETag", etag);
+ String previousToken = request.getHeader("If-None-Match");
+ if (previousToken != null && previousToken.equals(etag)) {
+ log.debug("found matching etag in request header, returning 304 Not Modified");
+ response.sendError(HttpServletResponse.SC_NOT_MODIFIED);
+ return;
}
+ }
- // TODO: Refactor this parameter mess a little
- log.debug("finally rendering feed");
- SyndFeed syndFeed =
- createSyndFeed(
- request.getRequestURL().toString(),
- syndFeedType,
- feed,
- currentAccessLevel,
- tag,
- comments,
- aggregateParam
- );
+ // TODO: Refactor this parameter mess a little
+ log.debug("finally rendering feed");
+ SyndFeed syndFeed =
+ createSyndFeed(
+ request.getRequestURL().toString(),
+ syndFeedType,
+ feed,
+ currentAccessLevel,
+ tag,
+ comments,
+ aggregateParam
+ );
- // If we have an entry on this feed, take the last entry's update timestamp and use it as
- // the published timestamp of the feed. The Rome library does not have a setUpdatedDate()
- // method and abuses the published date to write <updated> into the Atom <feed> element.
- if (lastFeedEntryDate != null) {
- syndFeed.setPublishedDate(lastFeedEntryDate);
- }
+ // If we have an entry on this feed, take the last entry's update timestamp and use it as
+ // the published timestamp of the feed. The Rome library does not have a setUpdatedDate()
+ // method and abuses the published date to write <updated> into the Atom <feed> element.
+ if (lastFeedEntryDate != null) {
+ syndFeed.setPublishedDate(lastFeedEntryDate);
+ }
- // Write feed to output
- response.setContentType(syndFeedType.contentType);
- response.setCharacterEncoding("UTF-8");
- SyndFeedOutput output = new SyndFeedOutput();
+ // Write feed to output
+ response.setContentType(syndFeedType.contentType);
+ response.setCharacterEncoding("UTF-8");
+ SyndFeedOutput output = new SyndFeedOutput();
+ try {
output.output(syndFeed, response.getWriter());
- response.getWriter().flush();
+ } catch (FeedException ex) {
+ throw new ServletException(ex);
+ }
+ response.getWriter().flush();
- log.debug("<<< commit, rendering complete");
+ log.debug("<<< feed rendering complete");
+ }
- if (startedTx) userTx.commit();
+ public Feed resolveFeed(String aggregateParam, String feedIdParam, String areaNameParam, String nodeNameParam) {
+ Feed feed;
+ // Find the feed, depending on variations of request parameters
+ if (aggregateParam != null && aggregateParam.length() > 0) {
+ feed = resolveFeedWithAggregateId(aggregateParam);
+ } else if (feedIdParam != null && feedIdParam.length() >0) {
+ feed = resolveFeedWithFeedId(feedIdParam);
+ } else if (areaNameParam != null && areaNameParam.length() > 0) {
+ feed = resolveFeedWithAreaNameAndNodeName(areaNameParam, nodeNameParam);
+ } else {
+ log.debug("no aggregate id, no feed id, no area name requested, getting wikiRoot feed");
+ WikiNodeFactory factory = (WikiNodeFactory)Component.getInstance(WikiNodeFactory.class);
+ feed = factory.loadWikiRoot().getFeed();
+ }
+ return feed;
+ }
- } catch (Exception ex) {
- if (startedTx && userTx != null) {
- // We started it, so we need to roll it back
- try {
- userTx.rollback();
- } catch (Exception rbEx) {
- log.error("could not roll back transaction: " + rbEx.getMessage());
- }
+ public Feed resolveFeedWithAggregateId(String aggregateId) {
+ Feed feed = null;
+ log.debug("trying to retrieve aggregated feed from cache: " + aggregateId);
+ FeedAggregateCache aggregateCache = (FeedAggregateCache)Component.getInstance(FeedAggregateCache.class);
+ List<FeedEntryDTO> result = aggregateCache.get(aggregateId);
+ if (result != null) {
+ feed = new Feed();
+ feed.setAuthor(Messages.instance().get("lacewiki.msg.AutomaticallyGeneratedFeed"));
+ feed.setTitle(Messages.instance().get("lacewiki.msg.AutomaticallyGeneratedFeed") + ": " + aggregateId);
+ feed.setPublishedDate(new Date());
+ // We are lying here, we don't really have an alternate representation link for this resource
+ feed.setLink( Preferences.instance().get(WikiPreferences.class).getBaseUrl() );
+ for (FeedEntryDTO feedEntryDTO : result) {
+ feed.getFeedEntries().add(feedEntryDTO.getFeedEntry());
}
- throw new ServletException(ex);
}
+ return feed;
+ }
- invalidateSessionIfPossible(request);
+ public Feed resolveFeedWithFeedId(String feedId) {
+ Feed feed = null;
+ try {
+ log.debug("trying to retrieve feed for id: " + feedId);
+ Long feedIdentifier = Long.valueOf(feedId);
+ FeedDAO feedDAO = (FeedDAO)Component.getInstance(FeedDAO.class);
+ feed = feedDAO.findFeed(feedIdentifier);
+ } catch (NumberFormatException ex) {
+ log.debug("feed identifier couldn't be converted to java.lang.Long");
+ }
+ return feed;
}
+ public Feed resolveFeedWithAreaNameAndNodeName(String areaName, String nodeName) {
+ Feed feed = null;
+ if (!areaName.matches("^[A-Z0-9]+.*")) return feed;
+ log.debug("trying to retrieve area: " + areaName);
+ WikiNodeDAO nodeDAO = (WikiNodeDAO)Component.getInstance(WikiNodeDAO.class);
+ WikiDirectory area = nodeDAO.findAreaUnrestricted(areaName);
+ if (area != null && (nodeName == null || !nodeName.matches("^[A-Z0-9]+.*")) && area.getFeed() != null) {
+ log.debug("using feed of area, no node requested: " + area);
+ feed = area.getFeed();
+ } else if (area != null && nodeName != null && nodeName.matches("^[A-Z0-9]+.*")) {
+ log.debug("trying to retrieve node: " + nodeName);
+ WikiDirectory nodeDir = nodeDAO.findWikiDirectoryInAreaUnrestricted(area.getAreaNumber(), nodeName);
+ if (nodeDir != null && nodeDir.getFeed() != null) {
+ log.debug("using feed of node: " + nodeDir);
+ feed = nodeDir.getFeed();
+ } else {
+ log.debug("node not found or node has no feed");
+ }
+ } else {
+ log.debug("area not found or area has no feed");
+ }
+ return feed;
+ }
+
public SyndFeed createSyndFeed(String baseURI, SyndFeedType syndFeedType, Feed feed, Integer currentAccessLevel) {
return createSyndFeed(baseURI, syndFeedType, feed, currentAccessLevel, null, Comments.include, null);
}
@@ -369,13 +353,4 @@
Hash hash = new Hash();
return hash.hash(date.toString());
}
-
- private void invalidateSessionIfPossible(HttpServletRequest request) {
- // If the user is not logged in, we might as well destroy the session immediately, saving some memory
- if (request.getSession().isNew() && !Identity.instance().isLoggedIn()) {
- log.debug("destroying session that was only created for reading the feed");
- Session.instance().invalidate();
- }
- }
-
}
Modified: trunk/examples/wiki/src/main/org/jboss/seam/wiki/core/ui/FileServlet.java
===================================================================
--- trunk/examples/wiki/src/main/org/jboss/seam/wiki/core/ui/FileServlet.java 2008-05-23 15:15:55 UTC (rev 8271)
+++ trunk/examples/wiki/src/main/org/jboss/seam/wiki/core/ui/FileServlet.java 2008-05-23 16:09:51 UTC (rev 8272)
@@ -1,7 +1,5 @@
package org.jboss.seam.wiki.core.ui;
-import org.jboss.seam.security.Identity;
-import org.jboss.seam.web.Session;
import org.jboss.seam.wiki.core.dao.WikiNodeDAO;
import org.jboss.seam.wiki.core.model.WikiUpload;
import org.jboss.seam.wiki.core.model.WikiUploadImage;
@@ -12,7 +10,6 @@
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
-import javax.transaction.UserTransaction;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
@@ -45,6 +42,7 @@
}
+ // TODO: All data access in this method runs with auto-commit mode, see http://jira.jboss.com/jira/browse/JBSEAM-957
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
@@ -63,32 +61,8 @@
response.sendError(HttpServletResponse.SC_NOT_FOUND, "File" + id);
}
- // TODO: Seam should use its transaction interceptor for java beans: http://jira.jboss.com/jira/browse/JBSEAM-957
- UserTransaction userTx = null;
- boolean startedTx = false;
- try {
-
- userTx = (UserTransaction)org.jboss.seam.Component.getInstance("org.jboss.seam.transaction.transaction");
- if (userTx.getStatus() != javax.transaction.Status.STATUS_ACTIVE) {
- startedTx = true;
- userTx.begin();
- }
-
- WikiNodeDAO wikiNodeDAO = (WikiNodeDAO)org.jboss.seam.Component.getInstance(WikiNodeDAO.class);
- file = wikiNodeDAO.findWikiUpload(fileId);
-
- if (startedTx) userTx.commit();
- } catch (Exception ex) {
- if (startedTx && userTx != null) {
- // We started it, so we need to roll it back
- try {
- userTx.rollback();
- } catch (Exception rbEx) {
- log.error("could not roll back transaction: " + rbEx.getMessage());
- }
- }
- throw new ServletException(ex);
- }
+ WikiNodeDAO wikiNodeDAO = (WikiNodeDAO)org.jboss.seam.Component.getInstance(WikiNodeDAO.class);
+ file = wikiNodeDAO.findWikiUpload(fileId);
}
String contentType = null;
@@ -137,15 +111,6 @@
response.getOutputStream().flush();
}
- invalidateSessionIfPossible(request);
}
- private void invalidateSessionIfPossible(HttpServletRequest request) {
- // If the user is not logged in, we might as well destroy the session immediately, saving some memory
- if (request.getSession().isNew() && !Identity.instance().isLoggedIn()) {
- log.debug("destroying session that was only created for reading the file");
- Session.instance().invalidate();
- }
- }
-
}
More information about the seam-commits
mailing list