Java tutorial
/* * Copyright 2006-2011 the Seasar Foundation and the Others. * * Licensed 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. */ package org.seasar.s2click; import java.io.ByteArrayInputStream; import java.io.InputStream; import java.io.OutputStream; import java.io.UnsupportedEncodingException; import java.lang.reflect.Field; import java.util.Date; import java.util.Enumeration; import java.util.Iterator; import java.util.Map; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import net.arnx.jsonic.JSON; import ognl.Ognl; import ognl.OgnlException; import ognl.TypeConverter; import org.apache.click.Page; import org.apache.click.element.JsImport; import org.apache.click.element.JsScript; import org.apache.click.service.ConfigService; import org.apache.click.util.PropertyUtils; import org.apache.click.util.RequestTypeConverter; import org.apache.commons.io.IOUtils; import org.apache.commons.lang.StringUtils; import org.seasar.framework.container.SingletonS2Container; import org.seasar.framework.util.tiger.ReflectionUtil; import org.seasar.s2click.annotation.Layout; import org.seasar.s2click.annotation.Request; import org.seasar.s2click.control.AjaxLink; import org.seasar.s2click.exception.RequestConversionException; import org.seasar.s2click.exception.RequestRequiredException; import org.seasar.s2click.servlet.S2ClickServlet; import org.seasar.s2click.util.AjaxUtils; import org.seasar.s2click.util.S2ClickUtils; /** * * @author Naoki Takezoe * @since 0.4.0 */ public abstract class S2ClickPage extends Page { private static final long serialVersionUID = 1L; /** * ????????? * <p> * <code>renderResponse()</code>?????????? * ????????? * {@link S2ClickServlet}???????????? * ???? */ public static final String SKIP_RENDERING = S2ClickPage.class.getName() + "_skipRendering"; protected static TypeConverter typeConverter = new RequestTypeConverter(); @Override public void onInit() { super.onInit(); // ?? bindPageFields(); // @Ajax???????JavaScript? String ajaxJavaScript = AjaxUtils.createAjaxJavaScript(this); if (StringUtils.isNotEmpty(ajaxJavaScript)) { getHeadElements().add(new JsImport("/resources/prototype.js")); getHeadElements().add(new JsScript(ajaxJavaScript)); } } /** * OGNL?????? * @return OGNL?? */ protected static TypeConverter getTypeConverter() { return typeConverter; } /** * ??????? * * @param clazz ?<code>Class</code> * @param name ?? * @return ??????<code>null</code> */ private Field getRequestBindField(ConfigService configService, String name) { for (Field field : configService.getPageFieldArray(getClass())) { Request req = field.getAnnotation(Request.class); if (req != null) { if (StringUtils.isEmpty(req.name())) { if (field.getName().equals(name)) { return field; } } else { if (req.name().equals(name)) { return field; } } } } return null; } /** * {@link Request}?????? * * @throws RequestConversionException ?????? * @throws RequestRequiredException ?????????? */ @SuppressWarnings("rawtypes") protected void bindPageFields() throws RequestConversionException, RequestRequiredException { ConfigService configService = S2ClickUtils.getConfigService(); if (configService.getPageFields(getClass()).isEmpty()) { return; } Map ognlContext = null; boolean customConverter = !getTypeConverter().getClass().equals(RequestTypeConverter.class); HttpServletRequest request = getContext().getRequest(); for (Enumeration e = request.getParameterNames(); e.hasMoreElements();) { String name = e.nextElement().toString(); String value = request.getParameter(name); if (StringUtils.isNotEmpty(value)) { Field field = getRequestBindField(configService, name); if (field != null) { Class type = field.getType(); if (customConverter || (type.isPrimitive() || String.class.isAssignableFrom(type) || Number.class.isAssignableFrom(type) || Boolean.class.isAssignableFrom(type))) { if (ognlContext == null) { ognlContext = Ognl.createDefaultContext(this, null, getTypeConverter()); } try { PropertyUtils.setValueOgnl(this, field.getName(), value, ognlContext); } catch (OgnlException ex) { throw new RequestConversionException(ex); } // if (logger.isTraceEnabled()) { // logger.trace(" auto bound variable: " + name + "=" + value); // } } } } } // ?? for (Field field : configService.getPageFieldArray(getClass())) { Request ann = field.getAnnotation(Request.class); if (ann != null) { if (ann.required() == true) { Object value = ReflectionUtil.getValue(field, this); if (value == null || (value instanceof String && StringUtils.isEmpty((String) value))) { throw new RequestRequiredException(field.getName()); } } } } } /** * ??JSON???{@link AjaxLink}??????????? * * @param obj JSON????? */ protected void renderJSON(Object obj) { try { byte[] json = JSON.encode(obj).getBytes("UTF-8"); renderResponse(AjaxUtils.CONTENT_TYPE_JSON, new ByteArrayInputStream(json)); } catch (UnsupportedEncodingException ex) { // ??? } } /** * ??HTML???{@link AjaxLink}??????????? * * @param html ??HTML */ protected void renderHTML(String html) { try { renderResponse(AjaxUtils.CONTENT_TYPE_HTML, new ByteArrayInputStream(html.getBytes("UTF-8"))); } catch (UnsupportedEncodingException ex) { // ??? } } /** * ????????? * ??<code>application/octet-stream</code>???? * * @param fileName ?? * @param file ? */ protected void renderFile(String fileName, InputStream file) { renderFile(null, fileName, file); } /** * ????????? * * @param contentType null???<code>application/octet-stream</code>???? * @param fileName ?? * @param file ? */ protected void renderFile(String contentType, String fileName, InputStream file) { try { String contentDisposition = "attachment"; String userAgent = getContext().getRequest().getHeader("USER-AGENT"); if (userAgent.indexOf("MSIE") >= 0 && userAgent.indexOf("Opera") < 0) { fileName = new String(fileName.getBytes("Windows-31J"), "ISO8859_1"); } else { fileName = new String(fileName.getBytes("UTF-8"), "ISO8859_1"); } contentDisposition = contentDisposition + "; filename=\"" + fileName + "\""; getContext().getResponse().setHeader("Content-Disposition", contentDisposition); if (contentType == null) { renderResponse("application/octet-stream", file); } else { renderResponse(contentType, file); } } catch (UnsupportedEncodingException ex) { // ??? } } /** * ???? * * @param contentType * @param contents ?? */ protected void renderResponse(String contentType, InputStream contents) { HttpServletResponse res = getContext().getResponse(); // ???????? Map<String, Object> headers = getHeaders(); for (Iterator<Map.Entry<String, Object>> i = headers.entrySet().iterator(); i.hasNext();) { Map.Entry<String, Object> entry = i.next(); String name = entry.getKey().toString(); Object value = entry.getValue(); if (value instanceof String) { String strValue = (String) value; if (!strValue.equalsIgnoreCase("Content-Encoding")) { res.setHeader(name, strValue); } } else if (value instanceof Date) { long time = ((Date) value).getTime(); res.setDateHeader(name, time); } else { int intValue = ((Integer) value).intValue(); res.setIntHeader(name, intValue); } } OutputStream out = null; try { res.setContentLength(contents.available()); res.setContentType(contentType); out = res.getOutputStream(); IOUtils.copy(contents, out); res.flushBuffer(); } catch (Exception ex) { throw new RuntimeException(ex); } finally { IOUtils.closeQuietly(contents); IOUtils.closeQuietly(out); getContext().setRequestAttribute(SKIP_RENDERING, "true"); } } @Override public String getTemplate() { Layout layout = getClass().getAnnotation(Layout.class); if (layout == null) { return super.getTemplate(); } String path = layout.value(); if (StringUtils.isNotEmpty(path)) { return path; } S2ClickConfig config = SingletonS2Container.getComponent(S2ClickConfig.class); if (StringUtils.isNotEmpty(config.layoutTemplatePath)) { return config.layoutTemplatePath; } throw new RuntimeException("layoutTemplatePath is not configured."); } }