Java tutorial
/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. 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. For additional information regarding * copyright in this work, please see the NOTICE file in the top level * directory of this distribution. */ package org.apache.roller.planet.ui.rendering; import java.io.IOException; import java.util.HashSet; import java.util.Set; import javax.servlet.RequestDispatcher; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.roller.planet.business.PlanetFactory; import org.apache.roller.planet.business.PlanetManager; import org.apache.roller.planet.config.PlanetConfig; import org.apache.roller.planet.pojos.Planet; import org.apache.roller.planet.pojos.PlanetGroup; /** * Multi-planet request mapper. * * This request mapper is used to map all planet specific urls of the form * /<planet handle>/* to the appropriate servlet for handling the actual * request. */ public class MultiPlanetRequestMapper implements RequestMapper { private static Log log = LogFactory.getLog(MultiPlanetRequestMapper.class); private static final String PAGE_SERVLET = "/planet-ui/rendering/page"; private static final String FEED_SERVLET = "/planet-ui/rendering/feed"; private static final String OPML_SERVLET = "/planet-ui/rendering/opml"; // url patterns that are not allowed to be considered planet handles Set restricted = null; public MultiPlanetRequestMapper() { this.restricted = new HashSet(); // build roller restricted list String restrictList = PlanetConfig.getProperty("rendering.multiPlanetMapper.rollerProtectedUrls"); if (restrictList != null && restrictList.trim().length() > 0) { String[] restrict = restrictList.split(","); for (int i = 0; i < restrict.length; i++) { this.restricted.add(restrict[i]); } } // add user restricted list restrictList = PlanetConfig.getProperty("rendering.multiPlanetMapper.userProtectedUrls"); if (restrictList != null && restrictList.trim().length() > 0) { String[] restrict = restrictList.split(","); for (int i = 0; i < restrict.length; i++) { this.restricted.add(restrict[i]); } } } public boolean handleRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // kinda silly, but we need to keep track of whether or not the url had // a trailing slash so that we can act accordingly boolean trailingSlash = false; String planetHandle = null; String planetContext = null; String groupHandle = null; String groupContext = null; String extraRequestData = null; log.debug("evaluating [" + request.getRequestURI() + "]"); // figure out potential planet handle String uri = request.getRequestURI(); String pathInfo = null; if (uri != null && uri.trim().length() > 1) { if (request.getContextPath() != null) uri = uri.substring(request.getContextPath().length()); // strip off the leading slash uri = uri.substring(1); // strip off trailing slash if needed if (uri.endsWith("/")) { uri = uri.substring(0, uri.length() - 1); trailingSlash = true; } if (uri.indexOf("/") != -1) { planetHandle = uri.substring(0, uri.indexOf("/")); pathInfo = uri.substring(uri.indexOf("/") + 1); } else { planetHandle = uri; } } log.debug("potential planet handle = " + planetHandle); // check if it's a valid planet handle if (restricted.contains(planetHandle) || !this.isPlanet(planetHandle)) { log.debug("SKIPPED " + planetHandle); return false; } log.debug("PLANET_URL " + request.getServletPath()); // parse the rest of the url if (pathInfo != null) { // parse the next portion of the url // we expect <context>/<groupHandle>/<groupContext>/<extra>/<info> String[] urlPath = pathInfo.split("/", 4); planetContext = urlPath[0]; if (urlPath.length == 2) { groupHandle = urlPath[1]; } else if (urlPath.length == 3) { groupHandle = urlPath[1]; groupContext = urlPath[2]; } else if (urlPath.length == 4) { groupHandle = urlPath[1]; groupContext = urlPath[2]; extraRequestData = urlPath[3]; } } // special handling for trailing slash issue // we need this because by http standards the urls /foo and /foo/ are // supposed to be considered different, so we must enforce that if ((planetContext == null && !trailingSlash) || (groupHandle != null && groupContext == null && !trailingSlash)) { // this means someone referred to a planet or group index page // with the shortest form of url /<planet> or /<planet>/group/<group> // and we need to add a slash to the url and redirect String redirectUrl = request.getRequestURI() + "/"; if (request.getQueryString() != null) { redirectUrl += "?" + request.getQueryString(); } response.sendRedirect(redirectUrl); return true; } else if (groupContext != null && trailingSlash) { // this means that someone has accessed a url and included a // trailing slash, like /<planet>/group/<group>/feed/atom/ which is // not supported, so we need to offer up a 404 Not Found response.sendError(HttpServletResponse.SC_NOT_FOUND); return true; } // calculate forward url String forwardUrl = calculateForwardUrl(request, planetHandle, planetContext, groupHandle, groupContext, extraRequestData); // if we don't have a forward url then the request was invalid somehow if (forwardUrl == null) { return false; } // dispatch to forward url log.debug("forwarding to " + forwardUrl); RequestDispatcher dispatch = request.getRequestDispatcher(forwardUrl); dispatch.forward(request, response); // we dealt with this request ourselves, so return "true" return true; } /** * Convenience method for caculating the servlet forward url given a set * of information to make the decision with. * * handle is always assumed valid, all other params may be null. */ private String calculateForwardUrl(HttpServletRequest request, String planetHandle, String planetContext, String groupHandle, String groupContext, String data) { log.debug(planetHandle + "," + planetContext + "," + groupHandle + "," + groupContext + "," + data); StringBuffer forwardUrl = new StringBuffer(); // no context means planet homepage if (planetContext == null) { forwardUrl.append(PAGE_SERVLET); forwardUrl.append("/").append(planetHandle); // requests for a specific planet group } else if (planetContext.equals("group") && groupHandle != null) { // no group context means group homepage if (groupContext == null) { forwardUrl.append(PAGE_SERVLET); forwardUrl.append("/").append(planetHandle); forwardUrl.append("/").append(groupHandle); // request for planet group feed } else if ("feed".equals(groupContext)) { forwardUrl.append(FEED_SERVLET); forwardUrl.append("/").append(planetHandle); forwardUrl.append("/").append(groupHandle); if (data != null) { forwardUrl.append("/").append(data); } // request for planet group opml descriptor } else if ("opml".equals(groupContext)) { forwardUrl.append(OPML_SERVLET); forwardUrl.append("/").append(planetHandle); forwardUrl.append("/").append(groupHandle); if (data != null) { forwardUrl.append("/").append(data); } // unsupported planet group url } else { return null; } // unsupported planet url } else { return null; } log.debug("FORWARD_URL " + forwardUrl.toString()); return forwardUrl.toString(); } /** * convenience method which determines if the given string is a valid * planet handle. */ private boolean isPlanet(String planetHandle) { log.debug("checking planet handle " + planetHandle); boolean isPlanet = false; try { PlanetManager mgr = PlanetFactory.getPlanet().getPlanetManager(); Planet planet = mgr.getPlanet(planetHandle); if (planet != null) { isPlanet = true; } } catch (Exception ex) { // doesn't really matter to us why it's not a valid planet } return isPlanet; } }