/** * Copyright (c) 2003-2005, David A. Czarnecki * All rights reserved. * * Portions Copyright (c) 2003-2005 by Mark Lussier * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of the "David A. Czarnecki" and "blojsom" nor the names of * its contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * Products derived from this software may not be called "blojsom", * nor may "blojsom" appear in their name, without prior written permission of * David A. Czarnecki. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package org.blojsom.extension.atomapi; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.blojsom.BlojsomException; import org.blojsom.plugin.admin.event.AddBlogEntryEvent; import org.blojsom.plugin.admin.event.DeletedBlogEntryEvent; import org.blojsom.plugin.admin.event.UpdatedBlogEntryEvent; import org.blojsom.authorization.AuthorizationProvider; import org.blojsom.blog.*; import org.blojsom.fetcher.BlojsomFetcher; import org.blojsom.fetcher.BlojsomFetcherException; import org.blojsom.servlet.BlojsomBaseServlet; import org.blojsom.util.BlojsomConstants; import org.blojsom.util.BlojsomMetaDataConstants; import org.blojsom.util.BlojsomProperties; import org.blojsom.util.BlojsomUtils; import org.intabulas.sandler.AtomConstants; import org.intabulas.sandler.Sandler; import org.intabulas.sandler.SyndicationFactory; import org.intabulas.sandler.api.SearchResults; import org.intabulas.sandler.api.impl.SearchResultsImpl; import org.intabulas.sandler.authentication.AtomAuthentication; import org.intabulas.sandler.authentication.AuthenticationException; import org.intabulas.sandler.builders.XPPBuilder; import org.intabulas.sandler.elements.Entry; import org.intabulas.sandler.elements.Feed; import org.intabulas.sandler.elements.Link; import org.intabulas.sandler.elements.impl.LinkImpl; import org.intabulas.sandler.exceptions.MarshallException; import org.intabulas.sandler.serialization.SerializationException; import javax.servlet.ServletConfig; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.*; import java.util.*; /** * AtomAPIServlet *
* Implementation of J.C. Gregorio's Atom API. * * @author Mark Lussier * @version $Id: AtomAPIServlet.java,v 1.2.2.1 2005/07/21 04:30:22 johnan Exp $ * @since blojsom 2.0 */ public class AtomAPIServlet extends BlojsomBaseServlet implements BlojsomConstants, BlojsomMetaDataConstants, AtomAPIConstants { /** * Logger instance */ private Log _logger = LogFactory.getLog(AtomAPIServlet.class); private static final String ATOM_API_PERMISSION = "post_via_atom_api"; private AuthorizationProvider _authorizationProvider; private ServletConfig _servletConfig; /** * Default constructor */ public AtomAPIServlet() { } /** * Configure the authorization provider * * @throws ServletException If there is an error instantiating and/or initializing the authorization provider */ protected void configureAuthorization(ServletConfig servletConfig) throws ServletException { try { Class authorizationProviderClass = Class.forName(_blojsomConfiguration.getAuthorizationProvider()); _authorizationProvider = (AuthorizationProvider) authorizationProviderClass.newInstance(); _authorizationProvider.init(servletConfig, _blojsomConfiguration); } catch (ClassNotFoundException e) { _logger.error(e); throw new ServletException(e); } catch (InstantiationException e) { _logger.error(e); throw new ServletException(e); } catch (IllegalAccessException e) { _logger.error(e); throw new ServletException(e); } catch (BlojsomConfigurationException e) { _logger.error(e); throw new ServletException(e); } } /** * Initialize the blojsom AtomAPI servlet * * @param servletConfig Servlet configuration information * @throws ServletException If there is an error initializing the servlet */ public void init(ServletConfig servletConfig) throws ServletException { super.init(servletConfig); _servletConfig = servletConfig; configureBlojsom(servletConfig); configureAuthorization(servletConfig); _logger.info("AtomAPI initialized"); } /** * Configure the flavors for the blog which map flavor values like "html" and "rss" to * the proper template and content type * * @param servletConfig Servlet configuration information * @param blogUser {@link BlogUser} information * @since blojsom 2.22 */ protected void configureFlavorsForUser(ServletConfig servletConfig, BlogUser blogUser) throws ServletException { String flavorConfiguration = servletConfig.getInitParameter(BLOJSOM_FLAVOR_CONFIGURATION_IP); if (BlojsomUtils.checkNullOrBlank(flavorConfiguration)) { flavorConfiguration = DEFAULT_FLAVOR_CONFIGURATION_FILE; } Map flavors = new HashMap(); Map flavorToTemplateMap = new HashMap(); Map flavorToContentTypeMap = new HashMap(); String user = blogUser.getId(); Properties flavorProperties = new Properties(); InputStream is = servletConfig.getServletContext().getResourceAsStream(_baseConfigurationDirectory + user + '/' + flavorConfiguration); try { flavorProperties.load(is); is.close(); _logger.debug("Loaded flavor information for user: " + user); Iterator flavorIterator = flavorProperties.keySet().iterator(); while (flavorIterator.hasNext()) { String flavor = (String) flavorIterator.next(); String[] flavorMapping = BlojsomUtils.parseCommaList(flavorProperties.getProperty(flavor)); flavors.put(flavor, flavor); flavorToTemplateMap.put(flavor, flavorMapping[0]); flavorToContentTypeMap.put(flavor, flavorMapping[1]); } blogUser.setFlavors(flavors); blogUser.setFlavorToTemplate(flavorToTemplateMap); blogUser.setFlavorToContentType(flavorToContentTypeMap); } catch (IOException e) { _logger.error(e); throw new ServletException(e); } } /** * Loads a {@link BlogUser} object for a given user ID * * @param userID User ID * @return {@link BlogUser} configured for the given user ID ornull
if there is an error loading the user
*/
protected BlogUser loadBlogUser(String userID) {
BlogUser blogUser = new BlogUser();
blogUser.setId(userID);
try {
Properties userProperties = new BlojsomProperties();
InputStream is = _servletConfig.getServletContext().getResourceAsStream(_baseConfigurationDirectory + userID + '/' + BLOG_DEFAULT_PROPERTIES);
if (is == null) {
return null;
}
userProperties.load(is);
is.close();
Blog userBlog = null;
// If a global blog-home directory has been defined, use it for each user
if (!BlojsomUtils.checkNullOrBlank(_blojsomConfiguration.getGlobalBlogHome()) &&
!userProperties.containsKey(BLOG_HOME_IP)) {
String usersBlogHome = _blojsomConfiguration.getGlobalBlogHome() + userID + "/";
File blogHomeDirectory = new File(usersBlogHome);
if (!blogHomeDirectory.exists()) {
_logger.error("Unable to use blog-home directory for user: " + blogHomeDirectory.toString());
throw new BlojsomConfigurationException("Unable to use blog-home directory for user: " + blogHomeDirectory.toString());
}
userProperties.setProperty(BLOG_HOME_IP, usersBlogHome);
_logger.debug("Setting user blog-home directory: " + usersBlogHome);
}
userBlog = new Blog(userProperties);
blogUser.setBlog(userBlog);
configureFlavorsForUser(_servletConfig, blogUser);
_logger.debug("Configured blojsom user: " + blogUser.getId());
} catch (BlojsomConfigurationException e) {
_logger.error(e);
return null;
} catch (IOException e) {
_logger.error(e);
return null;
} catch (ServletException e) {
_logger.error(e);
return null;
}
return blogUser;
}
/**
* Is the request from an authorized poster to this blog?
*
* @param blogUser
* @param httpServletRequest Request
* @return a boolean indicating if the user was authorized or not
*/
private boolean isAuthorized(BlogUser blogUser, HttpServletRequest httpServletRequest) {
Blog blog = blogUser.getBlog();
try {
_authorizationProvider.loadAuthenticationCredentials(blogUser);
} catch (BlojsomException e) {
_logger.error(e);
return false;
}
boolean result = false;
if (httpServletRequest.getHeader(ATOMHEADER_WSSE_AUTHORIZATION) != null) {
AtomAuthentication auth = new AtomAuthentication(httpServletRequest.getHeader(ATOMHEADER_WSSE_AUTHORIZATION));
Map authMap = blog.getAuthorization();
if (authMap.containsKey(auth.getUsername())) {
try {
_authorizationProvider.checkPermission(blogUser, new HashMap(), auth.getUsername(), ATOM_API_PERMISSION);
result = auth.authenticate(BlojsomUtils.parseCommaList((String) authMap.get(auth.getUsername()))[0]);
} catch (AuthenticationException e) {
_logger.error(e.getMessage(), e);
} catch (BlojsomException e) {
_logger.error(e);
}
} else {
_logger.info("Unable to locate user [" + auth.getUsername() + "] in authorization table");
}
if (!result) {
_logger.info("Unable to authenticate user [" + auth.getUsername() + "]");
}
}
return result;
}
/**
* Send back failed authorization response
*
* @param httpServletResponse Response
* @param user BlogUser instance
*/
private void sendAuthenticationRequired(HttpServletResponse httpServletResponse, BlogUser user) {
httpServletResponse.setContentType(CONTENTTYPE_HTML);
// Send the NextNonce as part of a WWW-Authenticate header
httpServletResponse.setHeader(HEADER_WWWAUTHENTICATE, AUTHENTICATION_REALM);
httpServletResponse.setStatus(401);
}
/**
* Is this an AtomAPI search request?
*
* @param request Request
* @return true
if the request is a search request, false
otherwise
*/
private boolean isSearchRequest(HttpServletRequest request) {
Map paramMap = request.getParameterMap();
// Looks for the existence of specific params and also checks the QueryString for a name only param
return (paramMap.containsKey(KEY_ATOMALL) || paramMap.containsKey(KEY_ATOMLAST) || paramMap.containsKey("start-range")
|| (request.getQueryString().indexOf(KEY_ATOMALL) != -1));
}
/**
* Process the Search request
*
* @param request Request
* @param category Blog category
* @param blog Blog instance
* @param blogUser BlogUser instance
* @return the search result as a String
*/
private String processSearchRequest(HttpServletRequest request, String category, Blog blog, BlogUser blogUser) {
String result = null;
Map paramMap = request.getParameterMap();
int numPosts = -1;
// Did they specify how many entries?
if (paramMap.containsKey(KEY_ATOMLAST)) {
try {
numPosts = Integer.parseInt(((String[]) paramMap.get(KEY_ATOMLAST))[0]);
if (numPosts < -1 || numPosts == 0) {
numPosts = -1;
}
} catch (NumberFormatException e) {
numPosts = -1;
}
}
Map fetchMap = new HashMap();
BlogCategory blogCategory = _fetcher.newBlogCategory();
blogCategory.setCategory(category);
blogCategory.setCategoryURL(blog.getBlogURL() + category);
fetchMap.put(BlojsomFetcher.FETCHER_CATEGORY, blogCategory);
fetchMap.put(BlojsomFetcher.FETCHER_NUM_POSTS_INTEGER, new Integer(numPosts));
try {
BlogEntry[] entries = _fetcher.fetchEntries(fetchMap, blogUser);
if (entries != null && entries.length > 0) {
SearchResults searchResult = new SearchResultsImpl();
for (int x = 0; x < entries.length; x++) {
BlogEntry entry = entries[x];
Entry atomentry = AtomUtils.fromBlogEntrySearch(blog, blogUser, entry, request.getServletPath());
searchResult.addEntry(atomentry);
}
result = searchResult.toString();
}
} catch (BlojsomFetcherException e) {
_logger.error(e.getLocalizedMessage(), e);
}
return result;
}
/**
* Handle a Delete Entry message
*
* @param httpServletRequest Request
* @param httpServletResponse Response
* @throws ServletException If there is an error processing the request
* @throws IOException If there is an error during I/O
*/
protected void doDelete(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws ServletException, IOException {
httpServletRequest.setCharacterEncoding(UTF8);
Blog blog = null;
BlogUser blogUser = null;
String permalink = BlojsomUtils.getRequestValue(PERMALINK_PARAM, httpServletRequest);
String category = BlojsomUtils.getCategoryFromPath(httpServletRequest.getPathInfo());
category = BlojsomUtils.urlDecode(category);
String user = BlojsomUtils.getUserFromPath(httpServletRequest.getPathInfo());
_logger.info("AtomAPI Delete Called ================================================");
_logger.info(" Path: " + httpServletRequest.getPathInfo());
_logger.info(" User: " + user);
_logger.info(" Category: " + category);
_logger.info(" Permalink: " + permalink);
if (BlojsomUtils.checkNullOrBlank(user)) {
user = _blojsomConfiguration.getDefaultUser();
}
blogUser = loadBlogUser(user);
if (blogUser == null) {
_logger.error("Unable to configure user: " + user);
httpServletResponse.setStatus(404);
return;
}
blog = blogUser.getBlog();
if (isAuthorized(blogUser, httpServletRequest)) {
_logger.info("Fetching " + permalink);
Map fetchMap = new HashMap();
BlogCategory blogCategory = _fetcher.newBlogCategory();
blogCategory.setCategory(category);
blogCategory.setCategoryURL(blog.getBlogURL() + category);
fetchMap.put(BlojsomFetcher.FETCHER_CATEGORY, blogCategory);
fetchMap.put(BlojsomFetcher.FETCHER_PERMALINK, permalink);
try {
BlogEntry[] entries = _fetcher.fetchEntries(fetchMap, blogUser);
if (entries != null && entries.length > 0) {
BlogEntry entry = entries[0];
entry.delete(blogUser);
}
// Okay now we generate a new NextOnce value, just for saftey sake and shove in into the response
//String nonce = AtomUtils.generateNextNonce(blogUser);
//httpServletResponse.setHeader(ATOMHEADER_AUTHENTICATION_INFO, ATOM_TOKEN_NEXTNONCE + nonce + "\"");
httpServletResponse.setStatus(200);
// Send out a deleted blog entry event
_blojsomConfiguration.getEventBroadcaster().broadcastEvent(new DeletedBlogEntryEvent(this, new Date(), entries[0], blogUser));
} catch (BlojsomFetcherException e) {
_logger.error(e.getLocalizedMessage(), e);
httpServletResponse.setStatus(404);
} catch (BlojsomException e) {
_logger.error(e.getLocalizedMessage(), e);
httpServletResponse.setStatus(404);
}
} else {
sendAuthenticationRequired(httpServletResponse, blogUser);
}
}
/**
* Creates an AtomAPI Introspection response
*
* @param blog Blog Instance
* @param user BlogUser Instance
* @param servletPath URL path to Atom API servlet
* @return URL appropriate for introspection
*/
private String createIntrospectionResponse(Blog blog, BlogUser user, String servletPath) {
String atomuri = blog.getBlogBaseURL() + servletPath + "/" + user.getId() + "/";
String atomuri2 = blog.getBlogURL() + "?flavor=atom";
Feed feed = SyndicationFactory.newSyndicationFeed();
LinkImpl link = new LinkImpl();
link.setHref(atomuri);
link.setRelationship(AtomConstants.Rel.SERVICE_POST);
link.setType(AtomConstants.Type.ATOM_XML);
link.setTitle(blog.getBlogDescription());
feed.addLink(link);
LinkImpl link3 = new LinkImpl();
link3.setHref(atomuri);
link3.setRelationship(AtomConstants.Rel.SERVICE_EDIT);
link3.setType(AtomConstants.Type.ATOM_XML);
link3.setTitle(blog.getBlogDescription());
feed.addLink(link3);
LinkImpl link2 = new LinkImpl();
link2.setHref(atomuri2);
link2.setRelationship(AtomConstants.Rel.SERVICE_FEED);
link2.setType(AtomConstants.Type.ATOM_XML);
link2.setTitle(blog.getBlogDescription());
feed.addLink(link2);
String result = "";
try {
result = Sandler.marshallFeed(feed);
} catch (MarshallException e) {
_logger.error(e);
} catch (SerializationException e) {
_logger.error(e);
}
return result;
}
/**
* Process a Get Entry message
*
* @param httpServletRequest Request
* @param httpServletResponse Response
* @throws ServletException If there is an error processing the request
* @throws IOException If there is an error during I/O
*/
protected void doGet(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws ServletException, IOException {
httpServletRequest.setCharacterEncoding(UTF8);
Blog blog = null;
BlogUser blogUser = null;
String blogEntryExtension;
String permalink = BlojsomUtils.getRequestValue(PERMALINK_PARAM, httpServletRequest);
String category = BlojsomUtils.getCategoryFromPath(httpServletRequest.getPathInfo());
category = BlojsomUtils.urlDecode(category);
String user = BlojsomUtils.getUserFromPath(httpServletRequest.getPathInfo());
if (BlojsomUtils.checkNullOrBlank(user)) {
user = _blojsomConfiguration.getDefaultUser();
}
blogUser = loadBlogUser(user);
if (blogUser == null) {
_logger.error("Unable to configure user: " + user);
httpServletResponse.setStatus(404);
return;
}
blog = blogUser.getBlog();
// Check to see if we need to dynamically determine blog-base-url and blog-url?
BlojsomUtils.resolveDynamicBaseAndBlogURL(httpServletRequest, blog, user);
blogEntryExtension = blog.getBlogProperty(BLOG_ATOMAPI_ENTRY_EXTENSION_IP);
if (BlojsomUtils.checkNullOrBlank(blogEntryExtension)) {
blogEntryExtension = DEFAULT_BLOG_ATOMAPI_ENTRY_EXTENSION;
}
_logger.info("AtomAPI GET Called ==================================================");
_logger.info(" Path: " + httpServletRequest.getPathInfo());
_logger.info(" User: " + user);
_logger.info(" Category: " + category);
_logger.info(" Permalink: " + permalink);
_logger.info(" Query: " + httpServletRequest.getQueryString());
_logger.info(" Params Cnt: " + httpServletRequest.getParameterMap().size());
boolean hasParams = ((httpServletRequest.getParameterMap().size() > 0) || httpServletRequest.getQueryString() != null);
// NOTE: Assumes that the getPathInfo() returns only category data
String content = null;
if (isAuthorized(blogUser, httpServletRequest)) {
if (!hasParams) {
content = createIntrospectionResponse(blog, blogUser, httpServletRequest.getServletPath());
httpServletResponse.setContentType(CONTENTTYPE_ATOM);
} else if (isSearchRequest(httpServletRequest)) {
httpServletResponse.setContentType(CONTENTTYPE_XML);
if (isSearchRequest(httpServletRequest)) {
content = processSearchRequest(httpServletRequest, category, blog, blogUser);
}
} else {
_logger.info("Fetching " + permalink);
Map fetchMap = new HashMap();
BlogCategory blogCategory = _fetcher.newBlogCategory();
blogCategory.setCategory(category);
blogCategory.setCategoryURL(blog.getBlogURL() + category);
fetchMap.put(BlojsomFetcher.FETCHER_CATEGORY, blogCategory);
if (permalink != null) {
fetchMap.put(BlojsomFetcher.FETCHER_PERMALINK, permalink);
}
try {
BlogEntry[] entries = _fetcher.fetchEntries(fetchMap, blogUser);
if (entries != null && entries.length > 0) {
BlogEntry entry = entries[0];
Entry atomentry = AtomUtils.fromBlogEntry(blog, blogUser, entry, httpServletRequest.getServletPath());
String edituri = blog.getBlogBaseURL() + httpServletRequest.getServletPath() + "/" + blogUser.getId() + entry.getId();
LinkImpl link = new LinkImpl();
link.setHref(edituri);
link.setRelationship(AtomConstants.Rel.SERVICE_EDIT);
link.setType(AtomConstants.Type.ATOM_XML);
atomentry.addLink(link);
content = Sandler.marshallEntry(atomentry);
httpServletResponse.setContentType(CONTENTTYPE_ATOM);
}
} catch (MarshallException e) {
_logger.error(e);
httpServletResponse.setStatus(404);
} catch (SerializationException e) {
_logger.error(e);
httpServletResponse.setStatus(404);
} catch (BlojsomFetcherException e) {
_logger.error(e);
httpServletResponse.setStatus(404);
}
}
if (content != null) {
httpServletResponse.setStatus(200);
httpServletResponse.setContentLength(content.length());
OutputStreamWriter osw = new OutputStreamWriter(httpServletResponse.getOutputStream(), UTF8);
osw.write(content);
osw.flush();
} else {
httpServletResponse.setStatus(404);
}
} else {
sendAuthenticationRequired(httpServletResponse, blogUser);
}
}
/**
* Handle a Post Entry request
*
* @param httpServletRequest Request
* @param httpServletResponse Response
* @throws ServletException If there is an error processing the request
* @throws IOException If there is an error during I/O
*/
protected void doPost(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws ServletException, IOException {
httpServletRequest.setCharacterEncoding(UTF8);
// Check for SOAP request
if (httpServletRequest.getHeader(HEADER_SOAPACTION) != null) {
handleSOAPRequest(httpServletRequest, httpServletResponse);
return;
}
Blog blog = null;
BlogUser blogUser = null;
String blogEntryExtension = DEFAULT_BLOG_ATOMAPI_ENTRY_EXTENSION;
String permalink = BlojsomUtils.getRequestValue(PERMALINK_PARAM, httpServletRequest);
String category = BlojsomUtils.getCategoryFromPath(httpServletRequest.getPathInfo());
category = BlojsomUtils.urlDecode(category);
String user = BlojsomUtils.getUserFromPath(httpServletRequest.getPathInfo());
_logger.info("AtomAPI POST Called =================================================");
_logger.info(" Path: " + httpServletRequest.getPathInfo());
_logger.info(" User: " + user);
_logger.info(" Category: " + category);
_logger.info(" Permalink: " + permalink);
if (BlojsomUtils.checkNullOrBlank(user)) {
user = _blojsomConfiguration.getDefaultUser();
}
blogUser = loadBlogUser(user);
if (blogUser == null) {
_logger.error("Unable to configure user: " + user);
httpServletResponse.setStatus(404);
return;
}
blog = blogUser.getBlog();
// Check to see if we need to dynamically determine blog-base-url and blog-url?
BlojsomUtils.resolveDynamicBaseAndBlogURL(httpServletRequest, blog, user);
blogEntryExtension = blog.getBlogProperty(BLOG_ATOMAPI_ENTRY_EXTENSION_IP);
if (BlojsomUtils.checkNullOrBlank(blogEntryExtension)) {
blogEntryExtension = DEFAULT_BLOG_ATOMAPI_ENTRY_EXTENSION;
}
if (isAuthorized(blogUser, httpServletRequest)) {
// Quick verify that the category is valid
File blogCategory = getBlogCategoryDirectory(blog, category);
if (blogCategory.exists() && blogCategory.isDirectory()) {
try {
Entry atomEntry = Sandler.unmarshallEntry(httpServletRequest.getInputStream(), new XPPBuilder());
String filename = BlojsomUtils.getBlogEntryFilename(atomEntry.getTitle().getBody(), atomEntry.getContent(0).getBody());
String outputfile = blogCategory.getAbsolutePath() + File.separator + filename;
File sourceFile = new File(outputfile + blogEntryExtension);
int fileTag = 1;
while (sourceFile.exists()) {
sourceFile = new File(outputfile + "-" + fileTag + blogEntryExtension);
fileTag++;
}
BlogEntry entry = _fetcher.newBlogEntry();
Map attributeMap = new HashMap();
Map blogEntryMetaData = new HashMap();
attributeMap.put(SOURCE_ATTRIBUTE, sourceFile);
entry.setAttributes(attributeMap);
entry.setCategory(category);
entry.setDescription(atomEntry.getContent(0).getBody());
entry.setDate(atomEntry.getCreated());
entry.setTitle(atomEntry.getTitle().getBody());
if (atomEntry.getAuthor() != null) {
blogEntryMetaData.put(BLOG_ENTRY_METADATA_AUTHOR, atomEntry.getAuthor().getName());
} else {
blogEntryMetaData.put(BLOG_ENTRY_METADATA_AUTHOR, blog.getBlogOwner());
}
blogEntryMetaData.put(BLOG_ENTRY_METADATA_TIMESTAMP, new Long(new Date().getTime()).toString());
entry.setMetaData(blogEntryMetaData);
// Insert an escaped Link into the Blog Entry
entry.setLink(blog.getBlogURL() + BlojsomUtils.removeInitialSlash(entry.getId()));
entry.save(blogUser);
entry.load(blogUser);
// Send out an add blog entry event
_blojsomConfiguration.getEventBroadcaster().broadcastEvent(new AddBlogEntryEvent(this, new Date(), entry, blogUser));
httpServletResponse.setContentType(CONTENTTYPE_ATOM);
httpServletResponse.setStatus(201);
atomEntry = AtomUtils.fromBlogEntry(blog, blogUser, entry, httpServletRequest.getServletPath());
// Extract the service.edit link to send for the Location: header
Collection links = atomEntry.getLinks();
Iterator linksIterator = links.iterator();
while (linksIterator.hasNext()) {
Link link = (Link) linksIterator.next();
if (AtomConstants.Rel.SERVICE_EDIT.equals(link.getRelationship())) {
httpServletResponse.setHeader(HEADER_LOCATION, link.getEscapedHref());
break;
}
}
OutputStreamWriter osw = new OutputStreamWriter(httpServletResponse.getOutputStream(), UTF8);
osw.write(Sandler.marshallEntry(atomEntry, true));
osw.flush();
} catch (SerializationException e) {
_logger.error(e.getLocalizedMessage(), e);
httpServletResponse.setStatus(404);
} catch (MarshallException e) {
_logger.error(e.getLocalizedMessage(), e);
httpServletResponse.setStatus(404);
} catch (BlojsomException e) {
_logger.error(e);
httpServletResponse.setStatus(404);
}
}
} else {
sendAuthenticationRequired(httpServletResponse, blogUser);
}
}
/**
* Handle a Put Entry request
*
* @param httpServletRequest Request
* @param httpServletResponse Response
* @throws ServletException If there is an error processing the request
* @throws IOException If there is an error during I/O
*/
protected void doPut(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws ServletException, IOException {
httpServletRequest.setCharacterEncoding(UTF8);
Blog blog = null;
BlogUser blogUser = null;
String permalink = BlojsomUtils.getRequestValue(PERMALINK_PARAM, httpServletRequest);
String category = BlojsomUtils.getCategoryFromPath(httpServletRequest.getPathInfo());
category = BlojsomUtils.urlDecode(category);
String user = BlojsomUtils.getUserFromPath(httpServletRequest.getPathInfo());
_logger.info("AtomAPI PUT Called ==================================================");
_logger.info(" Path: " + httpServletRequest.getPathInfo());
_logger.info(" User: " + user);
_logger.info(" Category: " + category);
_logger.info(" Permalink: " + permalink);
if (BlojsomUtils.checkNullOrBlank(user)) {
user = _blojsomConfiguration.getDefaultUser();
}
blogUser = loadBlogUser(user);
if (blogUser == null) {
_logger.error("Unable to configure user: " + user);
httpServletResponse.setStatus(404);
return;
}
blog = blogUser.getBlog();
// Check to see if we need to dynamically determine blog-base-url and blog-url?
BlojsomUtils.resolveDynamicBaseAndBlogURL(httpServletRequest, blog, user);
if (isAuthorized(blogUser, httpServletRequest)) {
Map fetchMap = new HashMap();
BlogCategory blogCategory = _fetcher.newBlogCategory();
blogCategory.setCategory(category);
blogCategory.setCategoryURL(blog.getBlogURL() + category);
fetchMap.put(BlojsomFetcher.FETCHER_CATEGORY, blogCategory);
fetchMap.put(BlojsomFetcher.FETCHER_PERMALINK, permalink);
try {
BlogEntry[] entries = _fetcher.fetchEntries(fetchMap, blogUser);
if (entries != null && entries.length > 0) {
Entry atomEntry = Sandler.unmarshallEntry(httpServletRequest.getInputStream(), new XPPBuilder());
BlogEntry entry = entries[0];
Map blogEntryMetaData = entry.getMetaData();
entry.setCategory(category);
entry.setDescription(atomEntry.getContent(0).getBody());
entry.setTitle(atomEntry.getTitle().getBody());
if (atomEntry.getAuthor() != null) {
blogEntryMetaData.put(BLOG_ENTRY_METADATA_AUTHOR, atomEntry.getAuthor().getName());
}
entry.setMetaData(blogEntryMetaData);
entry.save(blogUser);
//String nonce = AtomUtils.generateNextNonce(blogUser);
//httpServletResponse.setHeader(x, ATOM_TOKEN_NEXTNONCE + nonce + "\"");
httpServletResponse.setStatus(204);
// Send out an updated blog entry event
_blojsomConfiguration.getEventBroadcaster().broadcastEvent(new UpdatedBlogEntryEvent(this, new Date(), entry, blogUser));
} else {
_logger.info("Unable to fetch " + permalink);
}
} catch (BlojsomFetcherException e) {
_logger.error(e);
httpServletResponse.setStatus(404);
} catch (BlojsomException e) {
_logger.error(e);
httpServletResponse.setStatus(404);
}
} else {
sendAuthenticationRequired(httpServletResponse, blogUser);
}
}
/**
* Handle a given SOAP request looking for the "SOAPAction" header to decide on which method to execute
*
* @param httpServletRequest Request
* @param httpServletResponse Response
*/
protected void handleSOAPRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) {
String soapAction = httpServletRequest.getHeader(HEADER_SOAPACTION);
if (SOAPACTION_PUT.equalsIgnoreCase(soapAction)) {
handleSOAPPut(httpServletRequest, httpServletResponse);
} else {
try {
httpServletResponse.sendError(404, "Unable to process SOAP request for unknown action: " + soapAction);
} catch (IOException e) {
_logger.error(e);
httpServletResponse.setStatus(404);
}
}
}
/**
* Retrieve an entry body (<entry>...</entry>) from arbitrary content
*
* @param content Content
* @return Entry body with entry tags included or null
if the entry body could not be found
*/
protected String retrieveEntryBody(String content) {
String entryStart = "null
value
* is returned.
*
* @param is {@link InputStream}
* @param length Length of input stream to read
* @return Content from input stream up to specified length
*/
protected String readContentFromInputStream(InputStream is, int length) {
char[] buffer = new char[0];
try {
InputStreamReader inputStreamReader = new InputStreamReader(is, UTF8);
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
buffer = new char[length];
bufferedReader.read(buffer, 0, length);
bufferedReader.close();
} catch (IOException e) {
_logger.error(e);
return null;
}
return new String(buffer);
}
/**
* Handle a SOAP PUT request
*
* @param httpServletRequest Request
* @param httpServletResponse Response
*/
protected void handleSOAPPut(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) {
Blog blog = null;
BlogUser blogUser = null;
String blogEntryExtension = DEFAULT_BLOG_ATOMAPI_ENTRY_EXTENSION;
String permalink = BlojsomUtils.getRequestValue(PERMALINK_PARAM, httpServletRequest);
String category = BlojsomUtils.getCategoryFromPath(httpServletRequest.getPathInfo());
category = BlojsomUtils.urlDecode(category);
String user = BlojsomUtils.getUserFromPath(httpServletRequest.getPathInfo());
_logger.info("AtomAPI SOAP PUT Called =================================================");
_logger.info(" Path: " + httpServletRequest.getPathInfo());
_logger.info(" User: " + user);
_logger.info(" Category: " + category);
_logger.info(" Permalink: " + permalink);
if (BlojsomUtils.checkNullOrBlank(user)) {
user = _blojsomConfiguration.getDefaultUser();
}
blogUser = loadBlogUser(user);
if (blogUser == null) {
_logger.error("Unable to configure user: " + user);
httpServletResponse.setStatus(404);
return;
}
blog = blogUser.getBlog();
// Check to see if we need to dynamically determine blog-base-url and blog-url?
BlojsomUtils.resolveDynamicBaseAndBlogURL(httpServletRequest, blog, user);
blogEntryExtension = blog.getBlogProperty(BLOG_ATOMAPI_ENTRY_EXTENSION_IP);
if (BlojsomUtils.checkNullOrBlank(blogEntryExtension)) {
blogEntryExtension = DEFAULT_BLOG_ATOMAPI_ENTRY_EXTENSION;
}
if (isAuthorized(blogUser, httpServletRequest)) {
try {
String content = readContentFromInputStream(httpServletRequest.getInputStream(), httpServletRequest.getContentLength());
if (content != null) {
String entryContent = retrieveEntryBody(content);
if (entryContent != null && entryContent.length() > 0) {
Map fetchMap = new HashMap();
BlogCategory blogCategory = _fetcher.newBlogCategory();
blogCategory.setCategory(category);
blogCategory.setCategoryURL(blog.getBlogURL() + category);
fetchMap.put(BlojsomFetcher.FETCHER_CATEGORY, blogCategory);
fetchMap.put(BlojsomFetcher.FETCHER_PERMALINK, permalink);
try {
BlogEntry[] entries = _fetcher.fetchEntries(fetchMap, blogUser);
if (entries != null && entries.length > 0) {
Entry atomEntry = Sandler.unmarshallEntry(entryContent, new XPPBuilder());
BlogEntry entry = entries[0];
Map blogEntryMetaData = entry.getMetaData();
entry.setCategory(category);
entry.setDescription(atomEntry.getContent(0).getBody());
entry.setTitle(atomEntry.getTitle().getBody());
if (atomEntry.getAuthor() != null) {
blogEntryMetaData.put(BLOG_ENTRY_METADATA_AUTHOR, atomEntry.getAuthor().getName());
}
entry.setMetaData(blogEntryMetaData);
// Insert an escaped Link into the Blog Entry
entry.setLink(blog.getBlogURL() + BlojsomUtils.removeInitialSlash(entry.getId()));
entry.save(blogUser);
entry.load(blogUser);
httpServletResponse.setContentType(CONTENTTYPE_ATOM);
httpServletResponse.setStatus(201);
// Send out an add blog entry event
_blojsomConfiguration.getEventBroadcaster().broadcastEvent(new AddBlogEntryEvent(this, new Date(), entry, blogUser));
atomEntry = AtomUtils.fromBlogEntry(blog, blogUser, entry, httpServletRequest.getServletPath());
// Extract the service.edit link to send for the Location: header
Collection links = atomEntry.getLinks();
Iterator linksIterator = links.iterator();
while (linksIterator.hasNext()) {
Link link = (Link) linksIterator.next();
if (AtomConstants.Rel.SERVICE_EDIT.equals(link.getRelationship())) {
httpServletResponse.setHeader(HEADER_LOCATION, link.getEscapedHref());
break;
}
}
OutputStreamWriter osw = new OutputStreamWriter(httpServletResponse.getOutputStream(), UTF8);
osw.write(Sandler.marshallEntry(atomEntry, true));
osw.flush();
} else {
_logger.info("Unable to fetch " + permalink);
}
} catch (BlojsomFetcherException e) {
_logger.error(e);
httpServletResponse.setStatus(404);
} catch (BlojsomException e) {
_logger.error(e);
httpServletResponse.setStatus(404);
} catch (SerializationException e) {
_logger.error(e);
httpServletResponse.setStatus(404);
} catch (MarshallException e) {
_logger.error(e);
httpServletResponse.setStatus(404);
}
} else {
httpServletResponse.setStatus(404);
}
} else {
httpServletResponse.setStatus(404);
}
} catch (IOException e) {
_logger.error(e);
httpServletResponse.setStatus(404);
}
} else {
sendAuthenticationRequired(httpServletResponse, blogUser);
}
}
/**
* Called when removing the servlet from the servlet container
*/
public void destroy() {
try {
_fetcher.destroy();
} catch (BlojsomFetcherException e) {
_logger.error(e);
}
}
/**
* Get the blog category. If the category exists, return the
* appropriate directory, otherwise return the "root" of this blog.
*
* @param categoryName Category name
* @return A directory into which a blog entry can be placed
* @since blojsom 1.9
*/
protected File getBlogCategoryDirectory(Blog blog, String categoryName) {
File blogCategory = new File(blog.getBlogHome() + BlojsomUtils.removeInitialSlash(categoryName));
if (blogCategory.exists() && blogCategory.isDirectory()) {
return blogCategory;
} else {
return new File(blog.getBlogHome() + "/");
}
}
}