Java tutorial
/** * Licensed under the GNU LESSER GENERAL PUBLIC LICENSE, version 2.1, dated February 1999. * * This program is free software; you can redistribute it and/or modify * it under the terms of the latest version of the GNU Lesser General * Public License as published by the Free Software Foundation; * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program (LICENSE.txt); if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ package org.jamwiki.servlets; import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.List; import java.util.Locale; import java.util.Properties; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; import org.apache.commons.lang.ClassUtils; import org.apache.commons.lang.LocaleUtils; import org.apache.commons.lang.StringUtils; import org.jamwiki.DataAccessException; import org.jamwiki.Environment; import org.jamwiki.WikiBase; import org.jamwiki.WikiException; import org.jamwiki.WikiMessage; import org.jamwiki.authentication.JAMWikiAuthenticationConstants; import org.jamwiki.authentication.RoleImpl; import org.jamwiki.authentication.WikiUserDetails; import org.jamwiki.model.Category; import org.jamwiki.model.Topic; import org.jamwiki.model.VirtualWiki; import org.jamwiki.model.Watchlist; import org.jamwiki.model.WikiUser; import org.jamwiki.parser.ParserException; import org.jamwiki.parser.ParserInput; import org.jamwiki.parser.ParserOutput; import org.jamwiki.parser.ParserUtil; import org.jamwiki.utils.LinkUtil; import org.jamwiki.utils.NamespaceHandler; import org.jamwiki.utils.Pagination; import org.jamwiki.utils.Utilities; import org.jamwiki.utils.WikiLink; import org.jamwiki.utils.WikiLogger; import org.jamwiki.utils.WikiUtil; import org.springframework.security.authentication.AuthenticationCredentialsNotFoundException; import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.web.servlet.ModelAndView; /** * Utility methods useful when processing JAMWiki servlet requests. */ public class ServletUtil { private static final WikiLogger logger = WikiLogger.getLogger(ServletUtil.class.getName()); /** The name of the JSP file used to render the servlet output for logins. */ protected static final String JSP_LOGIN = "login.jsp"; /** The name of the output parameter used to store page information. */ public static final String PARAMETER_PAGE_INFO = "pageInfo"; /** The name of the output parameter used to store topic information. */ public static final String PARAMETER_TOPIC_OBJECT = "topicObject"; /** * The name of the output parameter used to indicate that Spring should * redirect to another servlet. */ protected static final String SPRING_REDIRECT_PREFIX = "redirect:"; /** * */ private ServletUtil() { } /** * Retrieve the content of a topic from the cache, or if it is not yet in the * cache then add it to the cache. * * @param context * The servlet context for the topic being retrieved. May be * <code>null</code> if the <code>cook</code> parameter is set to * <code>false</code>. * @param locale * The locale for the topic being retrieved. May be <code>null</code> * if the <code>cook</code> parameter is set to <code>false</code>. * @param virtualWiki * The virtual wiki for the topic being retrieved. * @param topicName * The name of the topic being retrieved. * @param cook * A parameter indicating whether or not the content should be parsed * before it is added to the cache. Stylesheet content (CSS) is not * parsed, but most other content is parsed. * @return The parsed or unparsed (depending on the <code>cook</code> * parameter) topic content. */ protected static String cachedContent(String context, Locale locale, String virtualWiki, String topicName, boolean cook) { // return PageService.getHTMLContent(topicName); String content = null; // String key = WikiCache.key(virtualWiki, topicName); // Element cacheElement = WikiCache.retrieveFromCache( // WikiBase.CACHE_PARSED_TOPIC_CONTENT, key); // if (cacheElement != null) { // content = (String) cacheElement.getObjectValue(); // return (content == null) ? null : content; // } try { Topic topic = WikiBase.getDataHandler().lookupTopic(virtualWiki, topicName, false, null); if (topic == null) { return ""; } content = topic.getTopicContent(); if (cook) { ParserInput parserInput = new ParserInput(); parserInput.setContext(context); parserInput.setLocale(locale); parserInput.setVirtualWiki(virtualWiki); parserInput.setTopicName(topicName); content = ParserUtil.parse(parserInput, null, content); } // WikiCache.addToCache(WikiBase.CACHE_PARSED_TOPIC_CONTENT, key, // content); } catch (Exception e) { logger.warning("error getting cached page " + virtualWiki + " / " + topicName, e); return null; } return content; } /** * This is a utility method that will check topic content for spam, and return * <code>null</code> if no matching values are found, or if a spam pattern is * found then that pattern will be returned. It will also log information * about the offending spam and user to the logs. * * @param request * The current servlet request. * @param topicName * The name of the current topic being edited. * @param contents * The text for the current topic that the user is trying to add. * @return <code>null</code> if nothing in the topic content matches a current * spam pattern, or the text that matches a spam pattern if one is * found. */ // protected static String checkForSpam(HttpServletRequest request, // String topicName, String contents) throws DataAccessException { // String result = SpamFilter.containsSpam(contents); // if (StringUtils.isBlank(result)) { // return null; // } // String message = "SPAM found in topic " + topicName + " ("; // WikiUserDetails user = ServletUtil.currentUserDetails(); // if (!user.hasRole(RoleImpl.ROLE_ANONYMOUS)) { // message += user.getUsername() + " / "; // } // message += ServletUtil.getIpAddress(request) + "): " + result; // logger.info(message); // return result; // } /** * Retrieve the current <code>WikiUserDetails</code> from Spring Security * <code>SecurityContextHolder</code>. If the current user is not logged-in * then this method will return an empty <code>WikiUserDetails</code> object. * * @return The current logged-in <code>WikiUserDetails</code>, or an empty * <code>WikiUserDetails</code> if there is no user currently logged * in. This method will never return <code>null</code>. * @throws AuthenticationCredentialsNotFoundException * If authentication credentials are unavailable. */ public static WikiUserDetails currentUserDetails() throws AuthenticationCredentialsNotFoundException { Authentication auth = SecurityContextHolder.getContext().getAuthentication(); return WikiUserDetails.initWikiUserDetails(auth); } /** * Retrieve the current <code>WikiUser</code> using the * <code>WikiUserDetails</code> from Spring Security * <code>SecurityContextHolder</code>. If there is no current user (the user * is not logged in) then this method will return an empty WikiUser. The * method will never return <code>null</code>. * * @return The current logged-in <code>WikiUser</code>, or an empty WikiUser * if there is no user currently logged in. */ public static WikiUser currentWikiUser() throws AuthenticationCredentialsNotFoundException { WikiUserDetails userDetails = ServletUtil.currentUserDetails(); WikiUser user = new WikiUser(); String username = userDetails.getUsername(); if (username.equals(WikiUserDetails.ANONYMOUS_USER_USERNAME)) { return user; } if (!WikiUtil.isFirstUse() && !WikiUtil.isUpgrade()) { try { // FIXME - do not lookup the user every time this method is called, that // will kill performance user = WikiBase.getDataHandler().lookupWikiUser(username); } catch (DataAccessException e) { logger.severe("Failure while retrieving user from database with login: " + username, e); return user; } if (user == null) { // invalid user. someone has either spoofed a cookie or the user account // is no longer in // the database. logger.warning( "No user exists for principal found in security context authentication: " + username); SecurityContextHolder.clearContext(); throw new AuthenticationCredentialsNotFoundException("Invalid user credentials found - username " + username + " does not exist in this wiki installation"); } } return user; } /** * Retrieve the current logged-in user's watchlist from the session. If there * is no watchlist return an empty watchlist. * * @param request * The servlet request object. * @param virtualWiki * The virtual wiki for the watchlist being parsed. * @return The current logged-in user's watchlist, or an empty watchlist if * there is no watchlist in the session. * @throws WikiException * Thrown if any error occurs during processing. */ public static Watchlist currentWatchlist(HttpServletRequest request, String virtualWiki) throws WikiException { // try to get watchlist stored in session if (request.getSession(false) != null) { Watchlist watchlist = (Watchlist) request.getSession(false).getAttribute(WikiUtil.PARAMETER_WATCHLIST); if (watchlist != null) { return watchlist; } } // no watchlist in session, retrieve from database WikiUserDetails userDetails = ServletUtil.currentUserDetails(); Watchlist watchlist = new Watchlist(); if (userDetails.hasRole(RoleImpl.ROLE_ANONYMOUS)) { return watchlist; } WikiUser user = ServletUtil.currentWikiUser(); try { watchlist = WikiBase.getDataHandler().getWatchlist(virtualWiki, user.getUserId()); } catch (DataAccessException e) { throw new WikiException(new WikiMessage("error.unknown", e.getMessage()), e); } if (request.getSession(false) != null) { // add watchlist to session request.getSession(false).setAttribute(WikiUtil.PARAMETER_WATCHLIST, watchlist); } return watchlist; } /** * Duplicate the functionality of the request.getRemoteAddr() method, but for * IPv6 addresses strip off any local interface information (anything * following a "%"). * * @param request * the HTTP request object. * @return The IP address that the request originated from, or 0.0.0.0 if the * originating address cannot be determined. */ public static String getIpAddress(HttpServletRequest request) { if (request == null) { throw new IllegalArgumentException("Request object cannot be null"); } String ipAddress = request.getRemoteAddr(); int pos = ipAddress.indexOf('%'); if (pos != -1) { ipAddress = ipAddress.substring(0, pos); } if (!Utilities.isIpAddress(ipAddress)) { logger.info("Invalid IP address found in request: " + ipAddress); ipAddress = "0.0.0.0"; } return ipAddress; } /** * Initialize topic values for a Topic object. This method will check to see * if a topic with the specified name exists, and if it does exist then that * topic will be returned. Otherwise a new topic will be initialized, setting * initial parameters such as topic name, virtual wiki, and topic type. * * @param virtualWiki * The virtual wiki name for the topic being initialized. * @param topicName * The name of the topic being initialized. * @return A new topic object with basic fields initialized, or if a topic * with the given name already exists then the pre-existing topic is * returned. * @throws WikiException * Thrown if any error occurs while retrieving or initializing the * topic object. */ protected static Topic initializeTopic(String virtualWiki, String topicName) throws WikiException { // WikiUtil.validateTopicName(topicName); Topic topic = null; // try { topic = WikiBase.getDataHandler().lookupTopic(virtualWiki, topicName, false, null); // } catch (DataAccessException e) { // throw new WikiException(new WikiMessage("error.unknown", e.getMessage()), // e); // } if (topic != null) { return topic; } topic = new Topic(); topic.setName(topicName); // topic.setVirtualWiki(virtualWiki); WikiLink wikiLink = LinkUtil.parseWikiLink(topicName); String namespace = wikiLink.getNamespace(); topic.setTopicType(WikiUtil.findTopicTypeForNamespace(namespace)); return topic; } /** * Examine the request object, and see if the requested topic or page matches * a given value. * * @param request * The servlet request object. * @param value * The value to match against the current topic or page name. * @return <code>true</code> if the value matches the current topic or page * name, <code>false</code> otherwise. */ protected static boolean isTopic(HttpServletRequest request, String value) { String topic = WikiUtil.getTopicFromURI(request); if (StringUtils.isBlank(topic)) { return false; } if (value != null && topic.equals(value)) { return true; } return false; } /** * Utility method for adding categories associated with the current topic to * the ModelAndView object. This method adds a hashmap of category names and * sort keys to the session that can then be retrieved for display during * rendering. * * @param next * The current ModelAndView object used to return rendering * information. * @param virtualWiki * The virtual wiki name for the topic being rendered. * @param topicName * The name of the topic that is being rendered. * @throws WikiException * Thrown if any error occurs during processing. */ protected static void loadCategoryContent(ModelAndView next, String virtualWiki, String topicName) throws WikiException { String categoryName = topicName.substring( NamespaceHandler.NAMESPACE_CATEGORY.length() + NamespaceHandler.NAMESPACE_SEPARATOR.length()); next.addObject("categoryName", categoryName); List<Category> categoryTopics = null; try { categoryTopics = WikiBase.getDataHandler().lookupCategoryTopics(virtualWiki, topicName); } catch (DataAccessException e) { throw new WikiException(new WikiMessage("error.unknown", e.getMessage()), e); } List<Category> categoryImages = new ArrayList<Category>(); LinkedHashMap<String, String> subCategories = new LinkedHashMap<String, String>(); int i = 0; // loop through the results and split out images and sub-categories while (i < categoryTopics.size()) { Category category = categoryTopics.get(i); if (category.getTopicType() == Topic.TYPE_IMAGE) { categoryTopics.remove(i); categoryImages.add(category); continue; } if (category.getTopicType() == Topic.TYPE_CATEGORY) { categoryTopics.remove(i); String value = category.getChildTopicName().substring(NamespaceHandler.NAMESPACE_CATEGORY.length() + NamespaceHandler.NAMESPACE_SEPARATOR.length()); subCategories.put(category.getChildTopicName(), value); continue; } i++; } next.addObject("categoryTopics", categoryTopics); next.addObject("numCategoryTopics", categoryTopics.size()); next.addObject("categoryImages", categoryImages); next.addObject("numCategoryImages", categoryImages.size()); next.addObject("subCategories", subCategories); next.addObject("numSubCategories", subCategories.size()); } /** * Create a Pagination object and load all necessary values into the request * for processing by a JSP. * * @param request * The servlet request object. * @param next * A ModelAndView object corresponding to the page being constructed. * @return A Pagination object constructed from parameters found in the * request object. */ public static Pagination loadPagination(HttpServletRequest request, ModelAndView next) { if (next == null) { throw new IllegalArgumentException( "A non-null ModelAndView object must be specified when loading pagination values"); } Pagination pagination = WikiUtil.buildPagination(request); next.addObject("num", pagination.getNumResults()); next.addObject("offset", pagination.getOffset()); return pagination; } /** * Determine if a user has permission to edit a topic. * * @param virtualWiki * The virtual wiki name for the topic in question. * @param topicName * The name of the topic in question. * @param user * The current Wiki user, or <code>null</code> if there is no current * user. * @return <code>true</code> if the user is allowed to edit the topic, * <code>false</code> otherwise. * @throws WikiException * Thrown if any error occurs during processing. */ protected static boolean isEditable(String virtualWiki, String topicName, WikiUserDetails user) throws WikiException { if (user == null || !user.hasRole(RoleImpl.ROLE_EDIT_EXISTING)) { // user does not have appropriate permissions return false; } Topic topic = null; try { if (!user.hasRole(RoleImpl.ROLE_EDIT_NEW) && WikiBase.getDataHandler().lookupTopic(virtualWiki, topicName, false, null) == null) { // user does not have appropriate permissions return false; } topic = WikiBase.getDataHandler().lookupTopic(virtualWiki, topicName, false, null); } catch (Exception e) { throw new WikiException(new WikiMessage("error.unknown", e.getMessage()), e); } if (topic == null) { // new topic, edit away... return true; } if (topic.isAdminOnly() && !user.hasRole(RoleImpl.ROLE_ADMIN)) { return false; } if (topic.isReadOnly()) { return false; } return true; } /** * Determine if a user has permission to move a topic. * * @param virtualWiki * The virtual wiki name for the topic in question. * @param topicName * The name of the topic in question. * @param user * The current Wiki user, or <code>null</code> if there is no current * user. * @return <code>true</code> if the user is allowed to move the topic, * <code>false</code> otherwise. * @throws WikiException * Thrown if any error occurs during processing. */ protected static boolean isMoveable(String virtualWiki, String topicName, WikiUserDetails user) throws WikiException { if (user == null || !user.hasRole(RoleImpl.ROLE_MOVE)) { // no permission granted to move pages return false; } Topic topic = null; // try { topic = WikiBase.getDataHandler().lookupTopic(virtualWiki, topicName, false, null); // } catch (DataAccessException e) { // throw new WikiException(new WikiMessage("error.unknown", e.getMessage()), // e); // } if (topic == null) { // cannot move a topic that doesn't exist return false; } if (topic.isReadOnly()) { return false; } if (topic.isAdminOnly() && !user.hasRole(RoleImpl.ROLE_ADMIN)) { return false; } return true; } /** * Examine the request object, and see if the requested topic or page matches * a given value. * * @param request * The servlet request object. * @param value * The value to match against the current topic or page name. * @return <code>true</code> if the value matches the current topic or page * name, <code>false</code> otherwise. */ // protected static boolean isTopic(HttpServletRequest request, String value) // { // String topic = WikiUtil.getTopicFromURI(request); // if (StringUtils.isBlank(topic)) { // return false; // } // if (value != null && topic.equals(value)) { // return true; // } // return false; // } /** * Utility method for adding categories associated with the current topic to * the ModelAndView object. This method adds a hashmap of category names and * sort keys to the session that can then be retrieved for display during * rendering. * * @param next * The current ModelAndView object used to return rendering * information. * @param virtualWiki * The virtual wiki name for the topic being rendered. * @param topicName * The name of the topic that is being rendered. * @throws WikiException * Thrown if any error occurs during processing. */ // protected static void loadCategoryContent(ModelAndView next, // String virtualWiki, String topicName) throws WikiException { // String categoryName = topicName // .substring(NamespaceHandler.NAMESPACE_CATEGORY.length() // + NamespaceHandler.NAMESPACE_SEPARATOR.length()); // next.addObject("categoryName", categoryName); // List<Category> categoryTopics = null; // try { // categoryTopics = WikiBase.getDataHandler().lookupCategoryTopics( // virtualWiki, topicName); // } catch (DataAccessException e) { // throw new WikiException(new WikiMessage("error.unknown", e.getMessage()), // e); // } // List<Category> categoryImages = new ArrayList<Category>(); // LinkedHashMap<String, String> subCategories = new LinkedHashMap<String, // String>(); // int i = 0; // // loop through the results and split out images and sub-categories // while (i < categoryTopics.size()) { // Category category = categoryTopics.get(i); // if (category.getTopicType() == Topic.TYPE_IMAGE) { // categoryTopics.remove(i); // categoryImages.add(category); // continue; // } // if (category.getTopicType() == Topic.TYPE_CATEGORY) { // categoryTopics.remove(i); // String value = category.getChildTopicName().substring( // NamespaceHandler.NAMESPACE_CATEGORY.length() // + NamespaceHandler.NAMESPACE_SEPARATOR.length()); // subCategories.put(category.getChildTopicName(), value); // continue; // } // i++; // } // next.addObject("categoryTopics", categoryTopics); // next.addObject("numCategoryTopics", categoryTopics.size()); // next.addObject("categoryImages", categoryImages); // next.addObject("numCategoryImages", categoryImages.size()); // next.addObject("subCategories", subCategories); // next.addObject("numSubCategories", subCategories.size()); // } /** * Create a Pagination object and load all necessary values into the request * for processing by a JSP. * * @param request * The servlet request object. * @param next * A ModelAndView object corresponding to the page being constructed. * @return A Pagination object constructed from parameters found in the * request object. */ // public static Pagination loadPagination(HttpServletRequest request, // ModelAndView next) { // if (next == null) { // throw new IllegalArgumentException( // "A non-null ModelAndView object must be specified when loading pagination values"); // } // Pagination pagination = WikiUtil.buildPagination(request); // next.addObject("num", pagination.getNumResults()); // next.addObject("offset", pagination.getOffset()); // return pagination; // } /** * Utility method for parsing a multipart servlet request. This method returns * an iterator of FileItem objects that corresponds to the request. * * @param request * The servlet request containing the multipart request. * @param uploadDirectory * The directory into which files will be uploaded. * @param maxFileSize * The maximum allowed file size in bytes. * @return Returns an iterator of FileItem objects the corresponds to the * request. * @throws WikiException * Thrown if any problems occur while processing the request. */ // public static Iterator processMultipartRequest(HttpServletRequest request, // String uploadDirectory, long maxFileSize) throws WikiException { // // Create a factory for disk-based file items // DiskFileItemFactory factory = new DiskFileItemFactory(); // factory.setRepository(new File(uploadDirectory)); // ServletFileUpload upload = new ServletFileUpload(factory); // upload.setHeaderEncoding("UTF-8"); // upload.setSizeMax(maxFileSize); // try { // return upload.parseRequest(request).iterator(); // } catch (FileUploadException e) { // throw new WikiException(new WikiMessage("error.unknown", e.getMessage()), // e); // } // } /** * Modify the current ModelAndView object to create a Spring redirect * response, meaning that the view name becomes "redirect:" followed by the * redirection target. * * @param next * The current ModelAndView object, which will be reset by this * method. * @param virtualWiki * The virtual wiki name for the page being redirected to. * @param destination * The topic or page name that is the redirection target. An example * might be "Special:Login". * @throws WikiException * Thrown if any error occurs while processing. */ protected static void redirect(ModelAndView next, String virtualWiki, String destination) throws WikiException { String target = null; try { target = LinkUtil.buildTopicUrl(null, virtualWiki, destination, true); } catch (DataAccessException e) { throw new WikiException(new WikiMessage("error.unknown", e.getMessage()), e); } String view = ServletUtil.SPRING_REDIRECT_PREFIX + target; next.clear(); next.setViewName(view); } /** * Users can specify a default locale in their preferences, so determine if * the current user is logged-in and has chosen a locale. If not, use the * default locale from the request object. * * @param request * The request object for the HTTP request. * @return Either the user's default locale (for logged-in users) or the * locale specified in the request if no default locale is available. */ public static Locale retrieveUserLocale(HttpServletRequest request) { try { WikiUser user = ServletUtil.currentWikiUser(); if (user.getDefaultLocale() != null) { return LocaleUtils.toLocale(user.getDefaultLocale()); } } catch (AuthenticationCredentialsNotFoundException e) { // ignore } return request.getLocale(); } /** * Given a virtual wiki name, return a <code>VirtualWiki</code> object. If * there is no virtual wiki available with the given name then the default * virtual wiki is returned. * * @param virtualWikiName * The name of the virtual wiki that is being retrieved. * @return A <code>VirtualWiki</code> object. If there is no virtual wiki * available with the given name then the default virtual wiki is * returned. */ public static VirtualWiki retrieveVirtualWiki(String virtualWikiName) { VirtualWiki virtualWiki = null; if (virtualWikiName == null) { virtualWikiName = WikiBase.DEFAULT_VWIKI; } // FIXME - the check here for initialized properties is due to this // change being made late in a release cycle. Revisit in a future // release & clean this up. if (Environment.getBooleanValue(Environment.PROP_BASE_INITIALIZED)) { try { virtualWiki = WikiBase.getDataHandler().lookupVirtualWiki(virtualWikiName); } catch (DataAccessException e) { } } if (virtualWiki == null) { logger.severe("No virtual wiki found for " + virtualWikiName); virtualWiki = new VirtualWiki(WikiBase.DEFAULT_VWIKI, Environment.getValue(Environment.PROP_BASE_DEFAULT_TOPIC)); } return virtualWiki; } /** * Validate that vital system properties, such as database connection * settings, have been specified properly. * * @param props * The property object to validate against. * @return A list of WikiMessage objects containing any errors encountered, or * an empty list if no errors are encountered. */ protected static List<WikiMessage> validateSystemSettings(Properties props) { List<WikiMessage> errors = new ArrayList<WikiMessage>(); // test directory permissions & existence // WikiMessage baseDirError = WikiUtil.validateDirectory(props // .getProperty(Environment.PROP_BASE_FILE_DIR)); // if (baseDirError != null) { // errors.add(baseDirError); // } // WikiMessage fullDirError = WikiUtil.validateDirectory(props // .getProperty(Environment.PROP_FILE_DIR_FULL_PATH)); // if (fullDirError != null) { // errors.add(fullDirError); // } // String classesDir = null; // try { // classesDir = Utilities.getClassLoaderRoot().getPath(); // WikiMessage classesDirError = WikiUtil.validateDirectory(classesDir); // if (classesDirError != null) { // errors.add(classesDirError); // } // } catch (FileNotFoundException e) { // errors.add(new WikiMessage("error.directorywrite", classesDir, e // .getMessage())); // } // test database // String driver = props.getProperty(Environment.PROP_DB_DRIVER); // String url = props.getProperty(Environment.PROP_DB_URL); // String userName = props.getProperty(Environment.PROP_DB_USERNAME); // String password = Encryption.getEncryptedProperty( // Environment.PROP_DB_PASSWORD, props); // try { // DatabaseConnection.testDatabase(driver, url, userName, password, false); // } catch (ClassNotFoundException e) { // logger.severe("Invalid database settings", e); // errors.add(new WikiMessage("error.databaseconnection", e.getMessage())); // } catch (SQLException e) { // logger.severe("Invalid database settings", e); // errors.add(new WikiMessage("error.databaseconnection", e.getMessage())); // } // verify valid parser class String parserClass = props.getProperty(Environment.PROP_PARSER_CLASS); String abstractParserClass = "org.jamwiki.parser.AbstractParser"; boolean validParser = (parserClass != null && !parserClass.equals(abstractParserClass)); if (validParser) { try { Class parent = ClassUtils.getClass(parserClass); Class child = ClassUtils.getClass(abstractParserClass); if (!child.isAssignableFrom(parent)) { validParser = false; } } catch (ClassNotFoundException e) { validParser = false; } } if (!validParser) { errors.add(new WikiMessage("error.parserclass", parserClass)); } return errors; } /** * Utility method used when redirecting to a login page. * * @param request * The servlet request object. * @param pageInfo * The current WikiPageInfo object, which contains information needed * for rendering the final JSP page. * @param topic * The topic to be redirected to. Valid examples are "Special:Admin", * "StartingPoints", etc. * @param messageObject * A WikiMessage object to be displayed on the login page. * @return Returns a ModelAndView object corresponding to the login page * display. * @throws WikiException * Thrown if any error occurs during processing. */ protected static ModelAndView viewLogin(HttpServletRequest request, WikiPageInfo pageInfo, String topic, WikiMessage messageObject) throws WikiException { ModelAndView next = new ModelAndView("wiki"); pageInfo.reset(); String virtualWikiName = pageInfo.getVirtualWikiName(); String target = request .getParameter(JAMWikiAuthenticationConstants.SPRING_SECURITY_LOGIN_TARGET_URL_FIELD_NAME); if (StringUtils.isBlank(target)) { if (StringUtils.isBlank(topic)) { VirtualWiki virtualWiki = null; try { virtualWiki = WikiBase.getDataHandler().lookupVirtualWiki(virtualWikiName); } catch (DataAccessException e) { throw new WikiException(new WikiMessage("error.unknown", e.getMessage()), e); } topic = virtualWiki.getDefaultTopicName(); } target = "/" + virtualWikiName + "/" + topic; if (!StringUtils.isBlank(request.getQueryString())) { target += "?" + request.getQueryString(); } } next.addObject("springSecurityTargetUrlField", JAMWikiAuthenticationConstants.SPRING_SECURITY_LOGIN_TARGET_URL_FIELD_NAME); HttpSession session = request.getSession(false); if (request.getRequestURL().indexOf(request.getRequestURI()) != -1 && (session == null || session .getAttribute(JAMWikiAuthenticationConstants.SPRING_SECURITY_SAVED_REQUEST_SESSION_KEY) == null)) { // Only add a target URL if Spring Security has not saved a request in the // session. The request // URL vs URI check is needed due to the fact that the first time a user // is redirected by Spring // Security to the login page the saved request attribute is not yet // available in the session // due to weirdness and magic which I've thus far been unable to track // down, so comparing the URI // to the URL provides a way of determining if the user was redirected. // Anyone who can create // a check that reliably captures whether or not Spring Security has a // saved request should // feel free to modify the conditional above. next.addObject("springSecurityTargetUrl", target); } String springSecurityLoginUrl = "/" + virtualWikiName + JAMWikiAuthenticationConstants.SPRING_SECURITY_LOGIN_URL; next.addObject("springSecurityLoginUrl", springSecurityLoginUrl); next.addObject("springSecurityUsernameField", JAMWikiAuthenticationConstants.SPRING_SECURITY_LOGIN_USERNAME_FIELD_NAME); next.addObject("springSecurityPasswordField", JAMWikiAuthenticationConstants.SPRING_SECURITY_LOGIN_PASSWORD_FIELD_NAME); next.addObject("springSecurityRememberMeField", JAMWikiAuthenticationConstants.SPRING_SECURITY_LOGIN_REMEMBER_ME_FIELD_NAME); pageInfo.setPageTitle(new WikiMessage("login.title")); pageInfo.setContentJsp(JSP_LOGIN); pageInfo.setSpecial(true); if (messageObject != null) { next.addObject("messageObject", messageObject); } return next; } /** * Utility method used when viewing a topic. * * @param request * The current servlet request object. * @param next * The current Spring ModelAndView object. * @param pageInfo * The current WikiPageInfo object, which contains information needed * for rendering the final JSP page. * @param pageTitle * The title of the page being rendered. * @param topic * The Topic object for the topic being displayed. * @param sectionEdit * Set to <code>true</code> if edit links should be displayed for * each section of the topic. * @param allowRedirect * Setting this parameter to <code>true</code> will force the * redirection target to be displayed (rather than a redirect page) * if the topic is a redirect. * @throws WikiException * Thrown if any error occurs while retrieving or parsing the topic. */ protected static void viewTopic(HttpServletRequest request, ModelAndView next, WikiPageInfo pageInfo, WikiMessage pageTitle, Topic topic, boolean sectionEdit, boolean allowRedirect) throws WikiException { // FIXME - what should the default be for topics that don't exist? if (topic == null) { throw new WikiException(new WikiMessage("common.exception.notopic")); } // WikiUtil.validateTopicName(topic.getName()); // if (allowRedirect // && topic.getTopicType() == Topic.TYPE_REDIRECT // && (request.getParameter("redirect") == null || !request.getParameter( // "redirect").equalsIgnoreCase("no"))) { // Topic child = null; // try { // child = WikiUtil.findRedirectedTopic(topic, 0); // } catch (DataAccessException e) { // throw new WikiException( // new WikiMessage("error.unknown", e.getMessage()), e); // } // if (!child.getName().equals(topic.getName())) { // String redirectUrl = null; // try { // redirectUrl = LinkUtil.buildTopicUrl(request.getContextPath(), topic // .getVirtualWiki(), topic.getName(), true); // } catch (DataAccessException e) { // throw new WikiException(new WikiMessage("error.unknown", e // .getMessage()), e); // } // // FIXME - hard coding // redirectUrl += LinkUtil.appendQueryParam("", "redirect", "no"); // String redirectName = topic.getName(); // pageInfo.setRedirectInfo(redirectUrl, redirectName); // pageTitle = new WikiMessage("topic.title", child.getName()); // topic = child; // // update the page info's virtual wiki in case this redirect is to // // another virtual wiki // pageInfo.setVirtualWikiName(topic.getVirtualWiki()); // } // } String virtualWiki = topic.getVirtualWiki(); String topicName = topic.getName(); // WikiUserDetails userDetails = ServletUtil.currentUserDetails(); // if (sectionEdit // && !ServletUtil.isEditable(virtualWiki, topicName, userDetails)) { // sectionEdit = false; // } WikiUser user = ServletUtil.currentWikiUser(); ParserInput parserInput = new ParserInput(); parserInput.setContext(request.getContextPath()); parserInput.setLocale(request.getLocale()); parserInput.setWikiUser(user); parserInput.setTopicName(topicName); parserInput.setUserDisplay(ServletUtil.getIpAddress(request)); parserInput.setVirtualWiki(virtualWiki); parserInput.setAllowSectionEdit(sectionEdit); ParserOutput parserOutput = new ParserOutput(); String content = null; try { content = ParserUtil.parse(parserInput, parserOutput, topic.getTopicContent()); } catch (ParserException e) { throw new WikiException(new WikiMessage("error.unknown", e.getMessage()), e); } if (parserOutput.getCategories().size() > 0) { LinkedHashMap<String, String> categories = new LinkedHashMap<String, String>(); for (String key : parserOutput.getCategories().keySet()) { String value = key.substring(NamespaceHandler.NAMESPACE_CATEGORY.length() + NamespaceHandler.NAMESPACE_SEPARATOR.length()); categories.put(key, value); } next.addObject("categories", categories); } topic.setHtmlContent(content); if (topic.getTopicType() == Topic.TYPE_CATEGORY) { loadCategoryContent(next, virtualWiki, topic.getName()); } // if (topic.getTopicType() == Topic.TYPE_IMAGE // || topic.getTopicType() == Topic.TYPE_FILE) { // List<WikiFileVersion> fileVersions = null; // try { // fileVersions = WikiBase.getDataHandler().getAllWikiFileVersions( // virtualWiki, topicName, true); // } catch (DataAccessException e) { // throw new WikiException( // new WikiMessage("error.unknown", e.getMessage()), e); // } // WikiUser wikiUser; // for (WikiFileVersion fileVersion : fileVersions) { // // update version urls to include web root path // String url = FilenameUtils.normalize(Environment // .getValue(Environment.PROP_FILE_DIR_RELATIVE_PATH) // + "/" + fileVersion.getUrl()); // url = FilenameUtils.separatorsToUnix(url); // fileVersion.setUrl(url); // // make sure the authorDisplay field is equal to the login for // // non-anonymous uploads // if (fileVersion.getAuthorId() != null) { // try { // wikiUser = WikiBase.getDataHandler().lookupWikiUser( // fileVersion.getAuthorId()); // } catch (DataAccessException e) { // throw new WikiException(new WikiMessage("error.unknown", e // .getMessage()), e); // } // if (wikiUser != null) { // // wikiUser should never be null unless the data in the database is // // somehow corrupt // fileVersion.setAuthorDisplay(wikiUser.getUsername()); // } // } // } // next.addObject("fileVersions", fileVersions); // if (topic.getTopicType() == Topic.TYPE_IMAGE) { // next.addObject("topicImage", true); // } else { // next.addObject("topicFile", true); // } // } pageInfo.setSpecial(false); pageInfo.setTopicName(topicName); next.addObject(ServletUtil.PARAMETER_TOPIC_OBJECT, topic); if (pageTitle != null) { pageInfo.setPageTitle(pageTitle); } } }