Java tutorial
/* * Copyright 2000-2011 Enonic AS * http://www.enonic.com/license */ package com.enonic.vertical.userservices; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.rmi.RemoteException; import java.text.DateFormat; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Enumeration; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import org.apache.commons.fileupload.DiskFileUpload; import org.apache.commons.fileupload.FileItem; import org.apache.commons.fileupload.FileUpload; import org.apache.commons.fileupload.FileUploadBase; import org.apache.commons.fileupload.FileUploadException; import org.apache.commons.lang.StringUtils; import org.springframework.web.servlet.ModelAndView; import com.octo.captcha.service.CaptchaServiceException; import com.enonic.esl.containers.ExtendedMap; import com.enonic.esl.containers.MultiValueMap; import com.enonic.esl.util.ArrayUtil; import com.enonic.esl.util.RegexpUtil; import com.enonic.vertical.adminweb.VerticalAdminLogger; import com.enonic.vertical.engine.VerticalCreateException; import com.enonic.vertical.engine.VerticalEngineException; import com.enonic.vertical.engine.VerticalRemoveException; import com.enonic.vertical.engine.VerticalSecurityException; import com.enonic.vertical.engine.VerticalUpdateException; import com.enonic.vertical.presentation.AbstractPresentationController; import com.enonic.cms.framework.util.UrlPathDecoder; import com.enonic.cms.core.internal.service.CmsCoreServicesSpringManagedBeansBridge; import com.enonic.cms.core.service.UserServicesService; import com.enonic.cms.business.captcha.CaptchaService; import com.enonic.cms.business.core.security.UserStoreParser; import com.enonic.cms.domain.Attribute; import com.enonic.cms.domain.SiteKey; import com.enonic.cms.domain.SitePath; import com.enonic.cms.domain.content.ContentAccessException; import com.enonic.cms.domain.content.category.CategoryAccessException; import com.enonic.cms.domain.portal.VerticalSession; import com.enonic.cms.domain.portal.httpservices.UserServicesException; public class AbstractUserServicesHandlerController extends AbstractPresentationController { // fatal errors public final static int ERR_OPERATION_BACKEND = 504; public final static int ERR_OPERATION_HANDLER = 505; public final static int ERR_SECURITY_EXCEPTION = 506; // general errors public final static int ERR_PARAMETERS_MISSING = 400; public final static int ERR_PARAMETERS_INVALID = 401; public final static int ERR_EMAIL_SEND_FAILED = 402; public final static int ERR_INVALID_CAPTCHA = 405; protected static DateFormat dateFormatFrom = new SimpleDateFormat("dd.MM.yyyy"); protected static DateFormat isoDateFormatNoTime = new SimpleDateFormat("yyyy-MM-dd"); private static final FileUploadBase fileUpload; protected CaptchaService captchaService; private UserServicesRedirectUrlResolver userServicesRedirectUrlResolver; private UserServicesAccessManager userServicesAccessManager; static { fileUpload = new DiskFileUpload(); fileUpload.setHeaderEncoding("UTF-8"); } protected UserStoreParser userStoreParser; public void setUserStoreParser(UserStoreParser userStoreParser) { this.userStoreParser = userStoreParser; } public void setUserServicesRedirectHelper(UserServicesRedirectUrlResolver value) { this.userServicesRedirectUrlResolver = value; } public void setCaptchaService(CaptchaService service) { captchaService = service; } protected void handlerCreate(HttpServletRequest request, HttpServletResponse response, HttpSession session, ExtendedMap formItems, UserServicesService userServices, SiteKey siteKey) throws VerticalUserServicesException, VerticalCreateException, VerticalSecurityException, RemoteException { String message = "OperationWrapper CREATE not implemented."; VerticalUserServicesLogger.error(this.getClass(), 0, message, null); } protected void handlerRemove(HttpServletRequest request, HttpServletResponse response, HttpSession session, ExtendedMap formItems, UserServicesService userServices, SiteKey siteKey) throws VerticalUserServicesException, VerticalRemoveException, VerticalSecurityException, RemoteException { String message = "OperationWrapper REMOVE not implemented."; VerticalUserServicesLogger.error(this.getClass(), 0, message, null); } protected void handlerCustom(HttpServletRequest request, HttpServletResponse response, HttpSession session, ExtendedMap formItems, UserServicesService userServices, SiteKey siteKey, String operation) throws VerticalUserServicesException, VerticalEngineException, IOException, ClassNotFoundException, IllegalAccessException, InstantiationException, ParseException { String message = "Custom operation not implemented: %0"; if (operation != null) { operation = operation.toUpperCase(); } VerticalUserServicesLogger.error(this.getClass(), 0, message, operation, null); } protected void handlerUpdate(HttpServletRequest request, HttpServletResponse response, HttpSession session, ExtendedMap formItems, UserServicesService userServices, SiteKey siteKey) throws VerticalUserServicesException, VerticalUpdateException, VerticalSecurityException, RemoteException { String message = "OperationWrapper UPDATE not implemented."; VerticalUserServicesLogger.error(this.getClass(), 0, message, null); } protected UserServicesService lookupUserServices() { return CmsCoreServicesSpringManagedBeansBridge.getUserServicesService(); } public boolean isArrayFormItem(Map formItems, String string) { if (!formItems.containsKey(string)) { return false; } return formItems.get(string).getClass() == String[].class; } private ExtendedMap parseSimpleRequest(HttpServletRequest request) { ExtendedMap formItems = new ExtendedMap(true); Enumeration paramNames = request.getParameterNames(); while (paramNames.hasMoreElements()) { String key = paramNames.nextElement().toString(); String[] values = request.getParameterValues(key); if (values != null) { if (values.length == 1 && values[0] != null) { String value = values[0]; if ("true".equals(value)) { formItems.putBoolean(key, true); } else if ("false".equals(value)) { formItems.putBoolean(key, false); } else { formItems.putString(key, value); } } else if (values.length > 1) { formItems.put(key, values); } } else { formItems.put(key, ""); } } return formItems; } private ExtendedMap parseMultiPartRequest(HttpServletRequest request) { ExtendedMap formItems = new ExtendedMap(true); try { List paramList = fileUpload.parseRequest(request); for (Iterator iter = paramList.iterator(); iter.hasNext();) { FileItem fileItem = (FileItem) iter.next(); String name = fileItem.getFieldName(); if (fileItem.isFormField()) { String value = fileItem.getString("UTF-8"); if (formItems.containsKey(name)) { ArrayList<Object> values = new ArrayList<Object>(); Object obj = formItems.get(name); if (obj instanceof Object[]) { String[] objArray = (String[]) obj; for (int i = 0; i < objArray.length; i++) { values.add(objArray[i]); } } else { values.add(obj); } values.add(value); formItems.put(name, values.toArray(new String[values.size()])); } else { formItems.put(name, value); } } else { if (fileItem.getSize() > 0) { if (formItems.containsKey(name)) { ArrayList<Object> values = new ArrayList<Object>(); Object obj = formItems.get(name); if (obj instanceof FileItem[]) { FileItem[] objArray = (FileItem[]) obj; for (int i = 0; i < objArray.length; i++) { values.add(objArray[i]); } } else { values.add(obj); } values.add(fileItem); formItems.put(name, values.toArray(new FileItem[values.size()])); } else { formItems.put(name, fileItem); } } } } } catch (FileUploadException fue) { String message = "Error occured with file upload: %t"; VerticalAdminLogger.error(this.getClass(), 0, message, fue); } catch (UnsupportedEncodingException uee) { String message = "Character encoding not supported: %t"; VerticalAdminLogger.error(this.getClass(), 0, message, uee); } // Add parameters from url Map paramMap = request.getParameterMap(); for (Iterator iter = paramMap.entrySet().iterator(); iter.hasNext();) { Map.Entry entry = (Map.Entry) iter.next(); String key = (String) entry.getKey(); if (entry.getValue() instanceof String[]) { String[] values = (String[]) entry.getValue(); for (int i = 0; i < values.length; i++) { formItems.put(key, values[i]); } } else { formItems.put(key, entry.getValue()); } } return formItems; } protected ExtendedMap parseForm(HttpServletRequest request) { if (FileUpload.isMultipartContent(request)) { return parseMultiPartRequest(request); } else { return parseSimpleRequest(request); } } /** * Process incoming HTTP requests. */ public ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response, SitePath sitePath) throws ServletException, IOException { HttpSession session = request.getSession(true); ExtendedMap formItems = parseForm(request); UserServicesService userServices = lookupUserServices(); SiteKey siteKey = sitePath.getSiteKey(); SitePath originalSitePath = (SitePath) request.getAttribute(Attribute.ORIGINAL_SITEPATH); String handler = UserServicesParameterResolver.resolveHandlerFromSitePath(originalSitePath); String operation = UserServicesParameterResolver.resolveOperationFromSitePath(originalSitePath); if (!userServicesAccessManager.isOperationAllowed(siteKey, handler, operation)) { String message = "Access to http service '" + handler + "." + operation + "' on site " + siteKey + " is not allowed by configuration. Check the settings in site-" + siteKey + ".properties"; VerticalUserServicesLogger.warn(this.getClass(), 0, message, null); String httpErrorMsg = "Access denied to http service '" + handler + "." + operation + "' on site " + siteKey; response.sendError(HttpServletResponse.SC_FORBIDDEN, httpErrorMsg); return null; } try { if (!(this instanceof FormHandlerController)) { // Note: The FormHandlerController is doing its own validation. Boolean captchaOk = captchaService.validateCaptcha(formItems, request, handler, operation); if ((captchaOk != null) && (!captchaOk)) { VerticalSession vsession = (VerticalSession) session .getAttribute(VerticalSession.VERTICAL_SESSION_OBJECT); if (vsession == null) { vsession = new VerticalSession(); session.setAttribute(VerticalSession.VERTICAL_SESSION_OBJECT, vsession); } vsession.setAttribute("error_" + handler + "_" + operation, captchaService.buildErrorXMLForSessionContext(formItems).getAsDOMDocument()); redirectToErrorPage(request, response, formItems, ERR_INVALID_CAPTCHA, null); return null; } } if ("create".equals(operation)) { handlerCreate(request, response, session, formItems, userServices, siteKey); } else if ("update".equals(operation)) { handlerUpdate(request, response, session, formItems, userServices, siteKey); } else if ("remove".equals(operation)) { handlerRemove(request, response, session, formItems, userServices, siteKey); } else { handlerCustom(request, response, session, formItems, userServices, siteKey, operation); } } catch (CaptchaServiceException e) { String message = "Failed during captcha validation: %t"; VerticalUserServicesLogger.error(this.getClass(), 0, message, e); redirectToErrorPage(request, response, formItems, ERR_OPERATION_BACKEND, null); } catch (VerticalUserServicesException vuse) { String message = "Failed to handle request: %t"; VerticalUserServicesLogger.error(this.getClass(), 0, message, vuse); redirectToErrorPage(request, response, formItems, ERR_OPERATION_HANDLER, null); } catch (VerticalUpdateException vue) { String message = "Failed to handle update request: %t"; VerticalUserServicesLogger.warn(this.getClass(), 0, message, vue); redirectToErrorPage(request, response, formItems, ERR_OPERATION_BACKEND, null); } catch (VerticalRemoveException vre) { String message = "Failed to handle remove request: %t"; VerticalUserServicesLogger.warn(this.getClass(), 0, message, vre); redirectToErrorPage(request, response, formItems, ERR_OPERATION_BACKEND, null); } catch (VerticalSecurityException vse) { String message = "No rights to handle request: %t"; VerticalUserServicesLogger.warn(this.getClass(), 0, message, vse); redirectToErrorPage(request, response, formItems, ERR_SECURITY_EXCEPTION, null); } catch (ContentAccessException vse) { String message = "No rights to handle request: %t"; VerticalUserServicesLogger.warn(this.getClass(), 0, message, vse); redirectToErrorPage(request, response, formItems, ERR_SECURITY_EXCEPTION, null); } catch (CategoryAccessException vse) { String message = "No rights to handle request: %t"; VerticalUserServicesLogger.warn(this.getClass(), 0, message, vse); redirectToErrorPage(request, response, formItems, ERR_SECURITY_EXCEPTION, null); } catch (VerticalEngineException vee) { String message = "Failed to handle engine request: %t"; VerticalUserServicesLogger.warn(this.getClass(), 0, message, vee); redirectToErrorPage(request, response, formItems, ERR_OPERATION_BACKEND, null); } catch (UserServicesException use) { throw use; } catch (Exception e) { String message = "Failed to handle request: %t"; VerticalUserServicesLogger.error(this.getClass(), 0, message, e); redirectToErrorPage(request, response, formItems, ERR_OPERATION_BACKEND, null); } return null; } protected void redirectToPage(HttpServletRequest request, HttpServletResponse response, ExtendedMap formItems) { redirectToPage(request, response, formItems, null); } protected void redirectToPage(HttpServletRequest request, HttpServletResponse response, ExtendedMap formItems, MultiValueMap queryParams) { String redirect = formItems.getString("_redirect", null); String url = userServicesRedirectUrlResolver.resolveRedirectUrlToPage(request, redirect, queryParams); if (isAbsoluteUrl(url)) { siteRedirectHelper.sendRedirectWithAbsoluteURL(response, url); } else { String decodedUrl = UrlPathDecoder.decode(url); siteRedirectHelper.sendRedirectWithPath(request, response, decodedUrl); } } private boolean isAbsoluteUrl(String url) { return url.matches("^[a-z]{3,6}://.+"); } protected void redirectToErrorPage(HttpServletRequest request, HttpServletResponse response, ExtendedMap formItems, int code, MultiValueMap queryParams) { redirectToErrorPage(request, response, formItems, new int[] { code }, queryParams); } protected void redirectToErrorPage(HttpServletRequest request, HttpServletResponse response, ExtendedMap formItems, int[] codes, MultiValueMap queryParams) { String url = userServicesRedirectUrlResolver.resolveRedirectUrlToErrorPage(request, formItems, codes, queryParams); siteRedirectHelper.sendRedirect(request, response, url); } protected static String createMissingParametersMessage(String operation, List<String> missingParameters) { StringBuffer message = new StringBuffer(); message.append(operation).append(" : Missing ").append(missingParameters.size()).append(" parameters: "); boolean isFirst = true; for (String missingParameter : missingParameters) { if (isFirst) { isFirst = false; } else { message.append(", "); } message.append(missingParameter); } return message.toString(); } protected static List<String> findMissingRequiredParameters(String[] requiredParameters, ExtendedMap formItems, boolean allowEmpty) { List<String> missingParameters = new ArrayList<String>(); for (String requiredParameter : requiredParameters) { if (!formItems.containsKey(requiredParameter)) { missingParameters.add(requiredParameter); continue; } String submittedValue = formItems.getString(requiredParameter); if (StringUtils.isEmpty(submittedValue) && !allowEmpty) { missingParameters.add(requiredParameter); } } return missingParameters; } public void setUserServicesAccessManager(UserServicesAccessManager userServicesAccessManager) { this.userServicesAccessManager = userServicesAccessManager; } protected static class Util { protected static String replaceKeys(ExtendedMap formItems, String inText, String[] excludeKeys) { String outText = inText; for (Object o : formItems.keySet()) { String key = (String) o; Pattern p = Pattern.compile(".*%" + key + "%.*", Pattern.DOTALL); Matcher m = p.matcher(outText); if ((excludeKeys == null || !ArrayUtil.arrayContains(key, excludeKeys)) && m.matches() && formItems.containsKey(key)) { String regexp = "%" + key + "%"; outText = RegexpUtil.substituteAll(regexp, formItems.getString(key, ""), outText); } } return outText; } protected static String removeTokens(String inText) { return inText.replaceAll("%[^%]+%", ""); } } }