Java tutorial
/* * This software is distributed under the terms of the FSF * Gnu Lesser General Public License (see lgpl.txt). * * This program is distributed WITHOUT ANY WARRANTY. See the * GNU General Public License for more details. */ package com.scooterframework.web.controller; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.servlet.RequestDispatcher; import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.fileupload.FileItem; import org.apache.commons.fileupload.servlet.ServletFileUpload; import com.scooterframework.admin.ApplicationConfig; import com.scooterframework.admin.Constants; import com.scooterframework.admin.EnvConfig; import com.scooterframework.admin.FilterManager; import com.scooterframework.admin.FilterManagerFactory; import com.scooterframework.common.logging.LogUtil; import com.scooterframework.common.util.Converters; import com.scooterframework.common.util.CurrentThreadCache; import com.scooterframework.common.util.CurrentThreadCacheClient; import com.scooterframework.common.util.DateUtil; import com.scooterframework.common.util.Message; import com.scooterframework.common.util.Util; import com.scooterframework.common.validation.ValidationResults; import com.scooterframework.orm.activerecord.ActiveRecord; import com.scooterframework.orm.misc.JdbcPageListSource; import com.scooterframework.orm.misc.Paginator; /** * <p> * ActionControl class serves as a helper class for all controller classes. * </p> * * @author (Fei) John Chen */ public class ActionControl { private static LogUtil log = LogUtil.getLogger(ActionControl.class.getName()); /** * Returns controller name which handles the request. The controller name * is linked to key * {@link com.scooterframework.admin.Constants#CONTROLLER}. */ public static String getController() { return CurrentThreadCacheClient.controller(); } /** * Returns action name which handles the request. The action name * is linked to key * {@link com.scooterframework.admin.Constants#ACTION}. */ public static String getAction() { return CurrentThreadCacheClient.action(); } /** * Returns model name. * * <p> * Model name must be set in current thread cache before this method is * called. * </p> * * @return model name */ public static String getModel() { String model = CurrentThreadCacheClient.model(); if (model == null) throw new IllegalArgumentException("Model name (Constants.MODEL: key.model) must be set first."); return model; } /** * Returns resource name which is linked to key * {@link com.scooterframework.admin.Constants#RESOURCE}. */ public static String getResource() { return CurrentThreadCacheClient.resource(); } /** * <p> * Returns request extension which is linked to key * {@link com.scooterframework.admin.Constants#FORMAT}.</p> * * </p> * This is obtained from the request path. For example, if the request * path is <tt>/blog/posts/1.xml</tt>, then the format is <tt>xml</tt>, * which means the client wants the response be sent * in <tt>xml</tt> format.</p> * * <p> * The value of <tt>format()</tt> is what is used as a default format * for response.</p> */ public static String format() { return CurrentThreadCacheClient.format(); } /** * Returns URI path to a view template of the current controller's action. * <pre> * Examples: * viewPath("show") : /WEB-INF/views/posts/show.jsp * viewPath("index"): /WEB-INF/views/posts/index.jsp * </pre> * @param action action name * @return path to a view file */ public static String viewPath(String action) { return viewPath(getController(), action); } /** * Returns URI path to a view template of a controller's action. * <pre> * Examples: * viewPath("posts", "show") : /WEB-INF/views/posts/show.jsp * viewPath("posts", "index"): /WEB-INF/views/posts/index.jsp * </pre> * * @param controller controller name * @param action action name * @return path to a view file */ public static String viewPath(String controller, String action) { return EnvConfig.getViewURI(controller, action); } /** * Returns model class name related to the underlying controller class name * based on naming convention. * * @return string model class name */ public static String getModelClassName(Class<?> controllerClass) { return EnvConfig.getInstance().getModelClassNameFromControllerClassName(controllerClass.getName()); } /** * Returns a paginator for the underlying model. * * <p> * Paging control options are constructed based on URL parameters. * Therefore in URL, there must be parameters like <tt>limit</tt>, * <tt>offset</tt>, <tt>npage</tt>, etc.</p> * * <p> * For a complete list of paging options, see description of * {@link com.scooterframework.orm.misc.Paginator} class.</p> * * @param modelClass the model class * @return Paginator instance */ public static Paginator jdbcPaginator(Class<? extends ActiveRecord> modelClass) { return jdbcPaginator(modelClass, (Map<String, String>) null, (Map<String, String>) null); } /** * Returns a paginator for the underlying model. * * <p> * For a complete list of paging options, see description of * {@link com.scooterframework.orm.misc.Paginator} class.</p> * * @param modelClass the model class * @param pagingOptions paging control options string * @return Paginator instance */ public static Paginator jdbcPaginator(Class<? extends ActiveRecord> modelClass, String pagingOptions) { return jdbcPaginator(modelClass, Converters.convertStringToMap(pagingOptions), (Map<String, String>) null); } /** * Returns a paginator for the underlying model. * * <p> * For a complete list of paging options, see description of * {@link com.scooterframework.orm.misc.Paginator} class.</p> * * <p> * For a complete list of SQL options, see description of <tt>options</tt> * in {@link com.scooterframework.orm.activerecord.ActiveRecord} * class.</p> * * @param modelClass the model class * @param pagingOptions paging control options string * @param sqlOptions SQL options string * @return Paginator instance */ public static Paginator jdbcPaginator(Class<? extends ActiveRecord> modelClass, String pagingOptions, String sqlOptions) { return jdbcPaginator(modelClass, Converters.convertStringToMap(pagingOptions), Converters.convertSqlOptionStringToMap(sqlOptions)); } /** * Returns a paginator for the underlying model. * * <p> * For a complete list of paging options, see description of * {@link com.scooterframework.orm.misc.Paginator} class.</p> * * <p> * For a complete list of SQL options, see description of <tt>options</tt> * in {@link com.scooterframework.orm.activerecord.ActiveRecord} * class.</p> * * @param modelClass the model class * @param pagingOptions paging control options string * @param sqlOptions SQL options Map * @return Paginator instance */ public static Paginator jdbcPaginator(Class<? extends ActiveRecord> modelClass, String pagingOptions, Map<String, String> sqlOptions) { return jdbcPaginator(modelClass, Converters.convertStringToMap(pagingOptions), sqlOptions); } /** * Returns a paginator for the underlying model. * * <p> * For a complete list of paging options, see description of * {@link com.scooterframework.orm.misc.Paginator} class.</p> * * @param modelClass the model class * @param pagingOptions paging control options Map * @return Paginator instance */ public static Paginator jdbcPaginator(Class<? extends ActiveRecord> modelClass, Map<String, ?> pagingOptions) { return jdbcPaginator(modelClass, Converters.convertMapToMapSS(pagingOptions), (Map<String, String>) null); } /** * Returns a paginator for the underlying model. * * <p> * For a complete list of paging options, see description of * {@link com.scooterframework.orm.misc.Paginator} class.</p> * * <p> * For a complete list of SQL options, see description of <tt>options</tt> * in {@link com.scooterframework.orm.activerecord.ActiveRecord} * class.</p> * * @param modelClass the model class * @param pagingOptions paging control options Map * @param sqlOptions SQL options string * @return Paginator instance */ public static Paginator jdbcPaginator(Class<? extends ActiveRecord> modelClass, Map<String, String> pagingOptions, String sqlOptions) { return jdbcPaginator(modelClass, pagingOptions, Converters.convertSqlOptionStringToMap(sqlOptions)); } /** * Returns a paginator for the underlying model. * * <p> * For a complete list of paging options, see description of * {@link com.scooterframework.orm.misc.Paginator} class.</p> * * <p> * For a complete list of SQL options, see description of <tt>options</tt> * in {@link com.scooterframework.orm.activerecord.ActiveRecord} * class.</p> * * @param modelClass the model class * @param pagingOptions paging control options Map * @param sqlOptions SQL options Map * @return Paginator instance */ public static Paginator jdbcPaginator(Class<? extends ActiveRecord> modelClass, Map<String, String> pagingOptions, Map<String, String> sqlOptions) { Map<String, String> pagingOptionsMerged = Converters.convertMapToMapSS(ACH.getAC().getParameterDataAsMap()); if (pagingOptions != null) { pagingOptionsMerged.putAll(pagingOptions); } return new Paginator(new JdbcPageListSource(modelClass, sqlOptions), pagingOptionsMerged); } /** * Returns all request parameters as a map. This includes data in both * parameter scope and request scope. * * @return a map of all request parameters */ public static Map<String, Object> params() { return ACH.getAC().getAllRequestDataAsMap(); } /** * Returns all request parameters as a map for those keys that have a * prefix. * * @param keyPrefix * @return a map of request parameters */ public static Map<String, Object> paramsWithPrefix(String keyPrefix) { return ACH.getAC().getAllRequestDataAsMap(keyPrefix); } /** * Returns a value corresponding to a key in request parameters or request * attributes. * * @param key name of a key in the request parameters * @return a value corresponding to a key in the request parameters */ public static String params(String key) { Object o = ACH.getAC().getFromAllRequestData(key); return Util.getSafeString(o); } /** * Alias of method <tt>params(String key)</tt>. * * Returns a value corresponding to a key in request parameters or request * attributes. * * @param key name of a key in the request parameters * @return a value corresponding to a key in the request parameters */ public static String p(String key) { return params(key); } /** * Returns a string array corresponding to a key in request parameters or * request attributes. * * @param key name of a key in the request parameters * @return a string array corresponding to a key in the request parameters */ public static String[] pArray(String key) { Object o = ACH.getAC().getFromAllRequestData(key); if (o == null) return new String[0]; String[] valueAry = null; if (o instanceof Object[]) { valueAry = (String[]) o; } else { valueAry = new String[1]; valueAry[0] = (String) o; } return valueAry; } /** * Returns a date instance corresponding to a key in request parameters or * request attributes. * * @param key name of a key in the request parameters * @return a date instance corresponding to a key in the request parameters */ public static Date pDate(String key) { return DateUtil.parseDate(p(key)); } /** * Returns a date instance corresponding to a key in request parameters or * request attributes. * * @param key name of a key in the request parameters * @param pattern the pattern describing the date and time format * @return a date instance corresponding to a key in the request parameters */ public static Date pDate(String key, String pattern) { return DateUtil.parseDate(p(key), pattern); } /** * Returns true or false corresponding to a key in request parameters or * request attributes. * * Only string of "true"--regardless of case--would return <tt>true</tt>. * * @param key name of a key in the request parameters * @return true or false corresponding to a key in the request parameters */ public static Boolean pBoolean(String key) { return Boolean.valueOf(p(key)); } /** * Checks if this is an AJAX request. * * @return true if this is an AJAX request. */ public static boolean isAjaxRequest() { return (params(Constants.AJAX_REQUEST) != null) ? true : false; } /** * Checks if this is a file-upload request or multipart request. * * @return true if this is a file-upload request or multipart request. */ public static boolean isFileUploadRequest() { return ServletFileUpload.isMultipartContent(ACH.getWAC().getHttpServletRequest()); } /** * Alias of method <tt>getUploadedFile(String key)</tt>. * * Returns an upload file which is an instance of <tt>UploadFile</tt>. * * @return an instance of <tt>UploadFile</tt> * @throws Exception */ public static UploadFile paramsFile(String key) throws Exception { return getUploadFile(key); } /** * Alias of method <tt>getUploadFiles()</tt>. * * Returns a list of upload files. * * @return a list of <tt>UploadFile</tt> instances * @throws Exception */ public static List<UploadFile> paramsFiles() throws Exception { return getUploadFiles(); } /** * Alias of method <tt>getUploadFilesMap()</tt>. * * Returns a map of upload files. In each key/value pair, the key is the * field name in the HTTP form, and the value is a <tt>UploadFile</tt> instance. * * @return a map of field/upload file (UploadFile) pairs * @throws Exception */ public static Map<String, UploadFile> paramsFilesMap() throws Exception { return getUploadFilesMap(); } /** * Alias of method <tt>paramsFile(String key)</tt>. * * Returns an upload file which is an instance of <tt>UploadFile</tt>. * * @return an instance of <tt>UploadFile</tt> * @throws Exception */ public static UploadFile pFile(String key) throws Exception { return paramsFile(key); } /** * Alias of method <tt>paramsFiles()</tt>. * Returns a list of upload files. * * @return a list of <tt>UploadFile</tt> instances * @throws Exception */ public static List<UploadFile> pFiles() throws Exception { return paramsFiles(); } /** * Alias of method <tt>paramsFilesMap()</tt>. * * Returns a map of upload files. In each key/value pair, the key is the * field name in the HTTP form, and the value is a <tt>UploadFile</tt> instance. * * @return a map of field/upload file (UploadFile) pairs * @throws Exception */ public static Map<String, UploadFile> pFilesMap() throws Exception { return paramsFilesMap(); } /** * Returns a value corresponding to a key in the request parameters. The * case of the key string is ignored. * * @param key name of a key in the request parameters * @return a value corresponding to a key in the request parameters */ public static String paramsIgnoreCase(String key) { Object o = ACH.getAC().getFromParameterDataIgnoreCase(key); return Util.getSafeString(o); } /** * Returns field values of a route. * * @return field values of a route. */ public static Map<String, String> routeFieldValues() { return CurrentThreadCacheClient.fieldValues(); } /** * Returns value of a field for route. * * @param field the field * @return value of a field for route. */ public static String routeFieldValue(String field) { return routeFieldValues().get(field); } public static Object getFromThreadData(String key) { return ActionContext.getFromThreadData(key); } public static Object getFromParameterData(String key) { return ACH.getAC().getFromParameterData(key); } public static Object getFromRequestData(String key) { return ACH.getAC().getFromRequestData(key); } public static Object getFromSessionData(String key) { return ACH.getAC().getFromSessionData(key); } public static Object getFromContextData(String key) { return ACH.getAC().getFromContextData(key); } public static Object getFromGlobalData(String key) { return ActionContext.getFromGlobalData(key); } public static void storeToThread(String key, Object obj) { ActionContext.storeToThread(key, obj); } public static void storeToRequest(String key, Object obj) { ACH.getAC().storeToRequest(key, obj); } public static void storeToSession(String key, Object obj) { ACH.getAC().storeToSession(key, obj); } public static void storeToContext(String key, Object obj) { ACH.getAC().storeToContext(key, obj); } public static void storeToGlobal(String key, Object obj) { ActionContext.storeToGlobal(key, obj); } public static void removeFromThreadData(String key) { ActionContext.removeFromThreadData(key); } public static void removeFromRequestData(String key) { ACH.getAC().removeFromRequestData(key); } public static void removeFromSessionData(String key) { ACH.getAC().removeFromSessionData(key); } public static void removeFromContextData(String key) { ACH.getAC().removeFromContextData(key); } public static void removeFromGlobalData(String key) { ActionContext.removeFromGlobalData(key); } public static void remove(String key) { ACH.getAC().remove(key); } public static void removeAllSessionData() { ACH.getAC().removeAllSessionData(); } /** * Binds data to view attribute for view rendering. * * @param key a string representing a place holder on view * @param data the data value to be filled in the view */ public static void setViewData(String key, Object data) { storeToRequest(key, data); } /** * Returns the current HTTP Servlet request instance. */ public static HttpServletRequest getHttpServletRequest() { return ACH.getWAC().getHttpServletRequest(); } /** * Returns the current HTTP Servlet response instance. */ public static HttpServletResponse getHttpServletResponse() { return ACH.getWAC().getHttpServletResponse(); } /** * Returns the HTTP ServletContext instance. */ public static ServletContext getServletContext() { return ACH.getWAC().getHttpServletRequest().getSession().getServletContext(); } /** * Returns content type of HTTP request. */ public static String getHttpRequestContentType() { return ACH.getWAC().getHttpServletRequest().getContentType(); } /** * Records a flash message of a specific <tt>type</tt>. The message can be * either a sentence or a message key in a messages.properties file. * * @param type flash message type * @param message the message or message key */ public static void flash(String type, String message) { Flash.flash(type, message); } /** * Records a flash message of a specific <tt>type</tt>. The message can be * either a sentence or a message key in a messages.properties file. * * @param type flash message type * @param message the message or message key * @param value a value that can be used in the message */ public static void flash(String type, String message, Object value) { Flash.flash(type, message, value); } /** * Records a flash message of a specific <tt>type</tt>. The message can be * either a sentence or a message key in a messages.properties file. * * @param type flash message type * @param message the message or message key * @param value0 a value that can be used in the message * @param value1 a value that can be used in the message */ public static void flash(String type, String message, Object value0, Object value1) { Flash.flash(type, message, value0, value1); } /** * Records a flash message of a specific <tt>type</tt>. The message can be * either a sentence or a message key in a messages.properties file. * * @param type flash message type * @param message the message or message key * @param value0 a value that can be used in the message * @param value1 a value that can be used in the message * @param value2 a value that can be used in the message */ public static void flash(String type, String message, Object value0, Object value1, Object value2) { Flash.flash(type, message, value0, value1, value2); } /** * Records a flash message of a specific <tt>type</tt>. The <tt>message</tt> * is of type {@link com.scooterframework.common.util.Message} or its subclass. * * @param type flash message type * @param message a {@link com.scooterframework.common.util.Message} object */ public static void flash(String type, Message message) { Flash.flash(type, message); } /** * Records a flash message of <tt>error</tt> type. The message can be * either a sentence or a message key in a messages.properties file. * * @param message the message or message key */ public static void flashError(String message) { Flash.error(message); } /** * Records a flash message of <tt>error</tt> type. The message can be * either a sentence or a message key in a messages.properties file. * * @param message the message or message key * @param value a value that can be used in the message */ public static void flashError(String message, Object value) { Flash.error(message, value); } /** * Records a flash message of <tt>error</tt> type. The message can be * either a sentence or a message key in a messages.properties file. * * @param message the message or message key * @param value0 a value that can be used in the message * @param value1 a value that can be used in the message */ public static void flashError(String message, Object value0, Object value1) { Flash.error(message, value0, value1); } /** * Records a flash message of <tt>error</tt> type. The message can be * either a sentence or a message key in a messages.properties file. * * @param message the message or message key * @param value0 a value that can be used in the message * @param value1 a value that can be used in the message * @param value2 a value that can be used in the message */ public static void flashError(String message, Object value0, Object value1, Object value2) { Flash.error(message, value0, value1, value2); } /** * Records a flash message of <tt>error</tt> type. The <tt>message</tt> * is of type {@link com.scooterframework.common.util.Message} or its subclass. * * @param message a {@link com.scooterframework.common.util.Message} object */ public static void flashError(Message message) { Flash.error(message); } /** * Records a flash message of <tt>notice</tt> type. The message can be * either a sentence or a message key in a messages.properties file. * * @param message the message or message key */ public static void flashNotice(String message) { Flash.notice(message); } /** * Records a flash message of <tt>notice</tt> type. The message can be * either a sentence or a message key in a messages.properties file. * * @param message the message or message key * @param value a value that can be used in the message */ public static void flashNotice(String message, Object value) { Flash.notice(message, value); } /** * Records a flash message of <tt>notice</tt> type. The message can be * either a sentence or a message key in a messages.properties file. * * @param message the message or message key * @param value0 a value that can be used in the message * @param value1 a value that can be used in the message */ public static void flashNotice(String message, Object value0, Object value1) { Flash.notice(message, value0, value1); } /** * Records a flash message of <tt>notice</tt> type. The message can be * either a sentence or a message key in a messages.properties file. * * @param message the message or message key * @param value0 a value that can be used in the message * @param value1 a value that can be used in the message * @param value2 a value that can be used in the message */ public static void flashNotice(String message, Object value0, Object value1, Object value2) { Flash.notice(message, value0, value1, value2); } /** * Records a flash message of <tt>notice</tt> type. The <tt>message</tt> * is of type {@link com.scooterframework.common.util.Message} or its subclass. * * @param message a {@link com.scooterframework.common.util.Message} object */ public static void flashNotice(Message message) { Flash.notice(message); } /** * Returns an instance of Validators. * * <p> * Subclass must override this method if a different validator is used. * </p> * * @return Validators object */ public static ActionValidators validators() { ActionValidators validators = (ActionValidators) CurrentThreadCache.get(KEY_Validators); if (validators == null) { validators = new ActionValidators(); CurrentThreadCache.set(KEY_Validators, validators); } return validators; } private static final String KEY_Validators = "key.Validators"; private static final String KEY_ValidationResults = "key.ValidationResults"; /** * Returns controller validation results. */ public static ValidationResults currentValidationResults() { ValidationResults vr = (ValidationResults) CurrentThreadCache.get(KEY_ValidationResults); if (vr == null) { vr = new ValidationResults(); CurrentThreadCache.set(KEY_ValidationResults, vr); } return vr; } /** * Cleans up cached ValidationResults. */ public static void cleanupValidationResults() { CurrentThreadCache.set(KEY_ValidationResults, null); } /** * Checks if validation failed. * * @return true if validation is failed, false otherwise. */ public static boolean validationFailed() { return currentValidationResults().failed(); } /** * Returns an error-tagged content string for error output. * * @param content the error content * @return a error-tagged content string */ public static String error(String content) { return ActionResult.error(content); } /** * Returns a html-tagged content string for html output. * * @param content the html content * @return a html-tagged content string */ public static String html(String content) { return ActionResult.html(content); } /** * Returns a text-tagged content string for plain-text output. * * @param content the text content * @return a text-tagged content string */ public static String text(String content) { return ActionResult.text(content); } /** * Returns a xml-tagged content string for xml output. * * @param content the xml content * @return a xml-tagged content string */ public static String xml(String content) { return ActionResult.xml(content); } /** * Returns a forward-tagged URI string with a query string. The query string is * formed by listing all primary key and value pairs of the record instance. * * @param uri an URI string * @param record an ActiveRecord instance * @return a formatted forward-tagged URI string */ public static String forwardTo(String uri, ActiveRecord record) { return ActionResult.forwardTo(uri, record); } /** * Returns a forward-tagged URI string with a query string. * * @param uri an URI string * @param nameValuePairs a map of name and value pairs as HTTP query string * @return a formatted forward-tagged URI string */ public static String forwardTo(String uri, Map<String, Object> nameValuePairs) { return ActionResult.forwardTo(uri, nameValuePairs); } /** * Returns a forward-tagged URI string with a query string. * * @param uri an URI string * @param nameValuePairs a string of name and value pairs as HTTP query string * @return a formatted forward-tagged URI string */ public static String forwardTo(String uri, String nameValuePairs) { return ActionResult.forwardTo(uri, nameValuePairs); } /** * Returns a forward-tagged URI string. * * @param uri an URI string * @return a formatted forward-tagged URI string */ public static String forwardTo(String uri) { return ActionResult.forwardTo(uri); } /** * Returns a redirect-tagged URI string with a query string. The query string is * formed by listing all primary key and value pairs of the record instance. * * @param uri an URI string * @param record an ActiveRecord instance * @return a formatted redirect-tagged URI string */ public static String redirectTo(String uri, ActiveRecord record) { return ActionResult.redirectTo(uri, record); } /** * Returns a redirect-tagged URI string with a query string. * * @param uri an URI string * @param nameValuePairs a map of name and value pairs as HTTP query string * @return a formatted redirect-tagged URI string */ public static String redirectTo(String uri, Map<String, Object> nameValuePairs) { return ActionResult.redirectTo(uri, nameValuePairs); } /** * Returns a redirect-tagged URI string with a query string. * * @param uri an URI string * @param nameValuePairs a string of name and value pairs as HTTP query string * @return a formatted redirect-tagged URI string */ public static String redirectTo(String uri, String nameValuePairs) { return ActionResult.redirectTo(uri, nameValuePairs); } /** * Returns a redirect-tagged URI string. * * @param uri an URI string * @return a formatted redirect-tagged URI string */ public static String redirectTo(String uri) { return ActionResult.redirectTo(uri); } /** * Returns root path to the application. */ public static String applicationPath() { return ApplicationConfig.getInstance().getApplicationPath(); } /** * Returns a list of upload files. Each item in the list is an instance * of <tt>java.io.File</tt> instance. * * @param fileRepository * @return a list of upload files (File) * @throws Exception */ public static List<File> getUploadFilesAsFiles(String fileRepository) throws Exception { List<File> files = new ArrayList<File>(); List<FileItem> items = prepareFileItems(); for (FileItem item : items) { if (!item.isFormField() && !"".equals(item.getName())) { File f = new File(fileRepository + File.separator + item.getName()); files.add(f); } } return files; } /** * Returns a list of upload files. Each item in the list is an instance * of <tt>UploadFile</tt> instance. * * @return a list of upload files (UploadFile) * @throws Exception */ public static List<UploadFile> getUploadFiles() throws Exception { List<UploadFile> files = new ArrayList<UploadFile>(); List<FileItem> items = prepareFileItems(); for (FileItem item : items) { if (!item.isFormField() && !"".equals(item.getName())) { files.add(new UploadFile(item)); } } return files; } /** * Returns a map of upload files. In each key/value pair, the key is the * field name in the HTTP form, and the value is a <tt>UploadFile</tt> instance. * * @return a map of field/upload file (UploadFile) pairs * @throws Exception */ public static Map<String, UploadFile> getUploadFilesMap() throws Exception { Map<String, UploadFile> files = new HashMap<String, UploadFile>(); List<FileItem> items = prepareFileItems(); for (FileItem item : items) { if (!item.isFormField() && !"".equals(item.getName())) { files.put(item.getFieldName(), new UploadFile(item)); } } return files; } /** * Returns an upload file which is an instance of <tt>UploadFile</tt>. * * @return an instance of <tt>UploadFile</tt> * @throws Exception */ public static UploadFile getUploadFile(String key) throws Exception { return (UploadFile) getUploadFilesMap().get(key); } @SuppressWarnings("unchecked") private static List<FileItem> prepareFileItems() throws Exception { List<FileItem> files = (List<FileItem>) CurrentThreadCache.get(Constants.FILE_UPLOAD_REQUEST_FILES); return files; } /** * Renders content. The format of the response is derived from request * extension. The default format is <tt>html</tt> which is defined by * {@link com.scooterframework.admin.Constants#DEFAULT_RESPONSE_FORMAT}. * * @param content The content to be sent. * @return a token of render */ public static String render(Object content) { return render(content, format()); } /** * Renders content associated with a specific request format. * * The default format is <tt>html</tt> which is defined by * {@link com.scooterframework.admin.Constants#DEFAULT_RESPONSE_FORMAT}. * * @param content The content to be sent. * @param format The request format. * @return a token of render */ public static String render(Object content, String format) { if (content == null) { log.warn("No rendering for a null content with format " + format); getHttpServletRequest().setAttribute(Constants.REQUEST_RENDERED, "true"); return null; } if (format == null) { format = Constants.DEFAULT_RESPONSE_FORMAT; } ContentHandler handler = ContentHandlerFactory.getContentHandler(format); if (handler != null) { try { handler.handle(getHttpServletRequest(), getHttpServletResponse(), content, format); getHttpServletRequest().setAttribute(Constants.REQUEST_RENDERED, "true"); } catch (Exception ex) { String error = "Error in render() for format \"" + format + "\", because " + ex.getMessage(); throw new RuntimeException(error); } } else { throw new IllegalArgumentException("There is no handler found for format \"" + format + "\". You may create your own as a plugin by " + "extending the Plugin class and " + "implementing the ContentHandler interface."); } return ActionResult.TAG_RENDER; } /** * Publishes a file for display. * * @param file The file to be published. */ public static void publishFile(File file) { publishFile(file, file.getName(), false); } /** * Publishes a file for display. * * @param file The file to be published. * @param mimeType The content MIME type. */ public static void publishFile(File file, String mimeType) { publishFile(file, file.getName(), mimeType, false); } /** * Publishes a file. Its MIME type is detected from the file extension. * * <p> * The file extension detection rule is as follows: * 1. If the <tt>file</tt> input has an extension, use it. Otherwise, * 2. If the <tt>displayableName</tt> input has an extension, use it. * * @param file The file to be published. * @param displayableName The display name of the file in the download dialog. * @param forDownload indicates whether this is for file download or display. */ public static void publishFile(File file, String displayableName, boolean forDownload) { String extension = null; String fn = file.getName(); if (fn != null && !"".equals(fn) && fn.indexOf('.') != -1) { extension = fn.substring(fn.lastIndexOf('.') + 1); } else if (displayableName != null && displayableName.indexOf('.') != -1) { extension = displayableName.substring(displayableName.lastIndexOf('.') + 1); } String mimeType = ""; if (extension != null && !"".equals(extension)) { mimeType = EnvConfig.getInstance().getMimeType(extension); } publishFile(file, displayableName, mimeType, forDownload); } /** * Publishes a file. If the <tt>mimeType</tt> is empty, it is default to * <tt>application/octet-stream</tt>. * * @param file The file to be published. * @param displayableName The display name of the file in the download dialog. * @param mimeType The content MIME type. * @param forDownload indicates whether this is for file download or display. */ public static void publishFile(File file, String displayableName, String mimeType, boolean forDownload) { try { ContentHandlerHelper.publish(ACH.getWAC().getHttpServletResponse(), file, displayableName, mimeType, forDownload); ACH.getWAC().getHttpServletRequest().setAttribute(Constants.REQUEST_RENDERED, "true"); } catch (Exception ex) { String error = "Error in publishFile() for file \"" + file + "\", because " + ex.getMessage(); throw new RuntimeException(error); } } /** * Checks whether a file is a text file. * * @param file the file to check * @return true if it is a text file. */ public static boolean isTextFile(File file) { return EnvConfig.getInstance().isTextFile(file); } /** * Returns the file extension. * * @param file the file to check * @return file extension or null */ public static String getFileExtension(File file) { String fName = file.getName(); int lastDot = fName.lastIndexOf('.'); return (lastDot != -1) ? (fName.substring(lastDot + 1)) : null; } /** * Returns all view data as a map. This includes data in both * parameter scope and request scope. * * @return a map of all view data */ public static Map<String, Object> getViewDataMap() { return params(); } /** * Renders a view template file with all properties in the container. * * The file extension of the view template is used to look up related * template engine. If the <tt>view</tt> does not have an extension * specified, the default extension is defined by <tt>view.extension</tt> * property in the <tt>environment.properties</tt> file. * * <p>Examples: </p> * <pre> * //render view file show.jsp * renderView("show"); * * //render view .../WEB-INF/views/products/show.jsp * renderView("products/show"); * * //render view file /home/foo/templates/show.st with StringTemplate engine * renderView("/home/foo/templates/show.st"); * * //render view file show.jsp and return result in text format * renderView("show", "text"); * </pre> * * @param view The render template file * @return rendered content */ public static String renderView(String view) { return renderView(view, getViewDataMap()); } /** * Renders a view template file with all properties in the container. * * The file extension of the view template is used to look up related * template engine. If the <tt>view</tt> does not have an extension * specified, the default extension is defined by <tt>view.extension</tt> * property in the <tt>environment.properties</tt> file. * * <p>Examples: </p> * <pre> * //render view file show.jsp * renderView("show"); * * //render view .../WEB-INF/views/products/show.jsp * renderView("products/show"); * * //render view file /home/foo/templates/show.st with StringTemplate engine * renderView("/home/foo/templates/show.st"); * * //render view file show.jsp and return result in text format * renderView("show", "text"); * </pre> * * <p>The response <tt>format</tt> does not apply to <tt>jsp</tt> views.</p> * * @param view The render template file * @param format the response format * @return rendered content */ public static String renderView(String view, String format) { return renderView(view, format, getViewDataMap()); } /** * Renders a view template file with view data in <tt>viewDataMap</tt>. * * The file extension of the view template is used to look up related * template engine. If the <tt>view</tt> does not have an extension * specified, the default extension is defined by <tt>view.extension</tt> * property in the <tt>environment.properties</tt> file. * * @param view the render template file * @param viewDataMap data (name/value pairs) to be passed to the view * @return rendered content */ public static String renderView(String view, Map<String, Object> viewDataMap) { return renderView(view, format(), viewDataMap); } /** * Renders a view template file with view data in <tt>viewDataMap</tt>. * * The file extension of the view template is used to look up related * template engine. If the <tt>view</tt> does not have an extension * specified, the default extension is defined by <tt>view.extension</tt> * property in the <tt>environment.properties</tt> file. * * <p>Examples:</p> * <pre> * //return a view coded in String Template as html * return renderView("paged_list.st", "html", map); * * //return a view coded in FreeMarker Template as text * return renderView("paged_list.ftl", "text", map); * </pre> * * @param view the render template file * @param format response format of the render template file * @param viewDataMap data (name/value pairs) to be passed to the view * @return rendered content */ public static String renderView(String view, String format, Map<String, Object> viewDataMap) { if (view == null) throw new IllegalArgumentException("View can not be null for rendering."); if (format == null) { format = Constants.DEFAULT_RESPONSE_FORMAT; } String viewPath = view; String viewExtension = ""; String viewFile = ""; int lastDot = view.lastIndexOf('.'); if (lastDot != -1) { viewExtension = view.substring(lastDot + 1); } else { viewExtension = EnvConfig.getInstance().getViewExtension(); viewPath = (viewExtension.startsWith(".")) ? (view + viewExtension) : (view + '.' + viewExtension); } int lastSlash = viewPath.lastIndexOf('/'); if (lastSlash == -1 && File.separatorChar != '/') { lastSlash = viewPath.lastIndexOf(File.separatorChar); } if (lastSlash != -1) { File p = new File(viewPath); if (!p.exists()) { viewPath = viewPath("", viewPath); viewFile = applicationPath() + viewPath; } } else { viewPath = viewPath(viewPath); viewFile = applicationPath() + viewPath; } //handle view try { HttpServletRequest request = getHttpServletRequest(); HttpServletResponse response = getHttpServletResponse(); if (viewExtension.equalsIgnoreCase("jsp") || viewExtension.equalsIgnoreCase(".jsp")) { doForward(viewPath, request, response); } else { TemplateHandler handler = TemplateHandlerFactory.getTemplateHandler(viewExtension); if (handler == null) throw new IllegalArgumentException("There is no " + "template handler found for view template " + "of type \"" + viewExtension + "\"."); String result = handler.handle(new File(viewFile), viewDataMap); render(result, format); } request.setAttribute(Constants.REQUEST_RENDERED, "true"); } catch (Exception ex) { String errorMessage = "Failed to render view \"" + viewFile + "\" because " + ex.getMessage(); log.error(errorMessage, ex); throw new NoTemplateHandlerException(errorMessage, viewExtension); } return null; } /** * <p>Do a forward to specified URI using a <tt>RequestDispatcher</tt>. * This method is used by all methods needing to do a forward.</p> * * @param uri Context-relative URI to forward to * @param request HTTP servlet request * @param response HTTP servlet response * @throws java.io.IOException * @throws javax.servlet.ServletException */ public static void doForward(String uri, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { log.debug("doForward: " + uri); if (uri == null) return; if (uri != null && !uri.startsWith("/")) uri = "/" + uri; RequestDispatcher rd = request.getSession().getServletContext().getRequestDispatcher(uri); if (rd == null) { uri = "/WEB-INF/views/404.jsp"; log.error("Unable to locate \"" + uri + "\", forward to " + uri); rd = getServletContext().getRequestDispatcher(uri); } rd.forward(request, response); } /** * Returns the FilterManager for a class type. */ public static FilterManager filterManagerFor(Class<?> clazz) { return FilterManagerFactory.getInstance().getFilterManager(clazz); } /** * Adds color to a string. */ public static String color(String s, String color) { return String.format("<font color=\"%s\">%s</font>", color, s); } }