001: /*
002: * This program is free software; you can redistribute it and/or modify
003: * it under the terms of the GNU General Public License as published by
004: * the Free Software Foundation; either version 2 of the License, or
005: * (at your option) any later version.
006: *
007: * This program is distributed in the hope that it will be useful,
008: * but WITHOUT ANY WARRANTY; without even the implied warranty of
009: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
010: * GNU Library General Public License for more details.
011: *
012: * You should have received a copy of the GNU General Public License
013: * along with this program; if not, write to the Free Software
014: * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
015: */
016: package web.layout;
017:
018: import java.io.IOException;
019: import java.io.Reader;
020: import java.util.ArrayList;
021: import java.util.Collections;
022: import java.util.Hashtable;
023: import java.util.List;
024:
025: import javax.servlet.http.HttpServletRequest;
026: import javax.servlet.http.HttpServletResponse;
027: import javax.servlet.jsp.JspException;
028: import javax.servlet.jsp.PageContext;
029: import javax.servlet.jsp.tagext.BodyTagSupport;
030:
031: import org.xml.sax.SAXException;
032:
033: import dlog4j.util.StringUtils;
034:
035: /**
036: * 用于处理页面排版文件中变量的替换
037: * @author liudong
038: */
039: public class LayoutTag extends BodyTagSupport {
040:
041: protected final static int BUFFER_SIZE = 512;
042: protected final static String ROOT = "{ROOT}";
043:
044: public int doStartTag() throws JspException {
045: return EVAL_BODY_BUFFERED;
046: }
047:
048: public int doEndTag() throws JspException {
049: Reader reader = getBodyContent().getReader();
050: char[] buf = new char[BUFFER_SIZE];
051: try {
052: HttpServletRequest req = (HttpServletRequest) pageContext
053: .getRequest();
054: HttpServletResponse res = (HttpServletResponse) pageContext
055: .getResponse();
056: StringBuffer content1 = new StringBuffer(BUFFER_SIZE);
057: do {
058: int rc = reader.read(buf);
059: if (rc > 0)
060: content1.append(buf, 0, rc);
061: if (rc < BUFFER_SIZE)
062: break;
063: } while (true);
064: String html = StringUtils.replaceIgnoreCase(content1
065: .toString(), ROOT, req.getContextPath());
066: List tokens = listTokens(html);
067: int curIdx = 0;
068: for (int i = 0; i < tokens.size(); i++) {
069: Token token = (Token) tokens.get(i);
070: pageContext.getOut().write(
071: html.substring(curIdx, token.begin));
072: try {
073: if (ROOT.equals(token.name)) {
074: pageContext.getOut()
075: .write(req.getContextPath());
076: } else {
077: String tokenPage = getTokenPage(token.name,
078: token.page);
079: pageContext.include(tokenPage);
080: }
081: } catch (Exception e0) {
082: pageContext.getServletContext()
083: .log(
084: "LayoutTag.doEndTag page="
085: + token.page, e0);
086: pageContext.setAttribute("excetion", e0,
087: PageContext.REQUEST_SCOPE);
088: if (!errorPage.startsWith("/"))
089: pageContext.include(baseDir + errorPage);
090: else
091: pageContext.include(errorPage);
092: }
093: curIdx = token.begin + token.name.length();
094: }
095: pageContext.getOut().write(html.substring(curIdx));
096: } catch (Exception e1) {
097: pageContext.getServletContext().log("LayoutTag.doEndTag",
098: e1);
099: }
100: return EVAL_PAGE;
101: }
102:
103: /**
104: * 根据参数来决定是否替换页面中的BODY部分
105: * @param token 变量名称
106: * @param page 变量对应的默认页面
107: * @return
108: */
109: protected String getTokenPage(String token, String page) {
110: String sPage;
111: if (mainPage == null || !"$BODY$".equals(token))
112: sPage = page;
113: else
114: sPage = (String) pageContext.findAttribute(mainPage);
115: return (sPage.startsWith("/")) ? sPage : (baseDir + sPage);
116: }
117:
118: /**
119: * 列出排版页面中存在的所有变量并进行位置的排续
120: * @param content
121: * @return
122: * @throws SAXException
123: * @throws IOException
124: */
125: protected synchronized List listTokens(String content)
126: throws Exception {
127: int hashcode = content.toString().hashCode();
128: Integer layout_hashcode = (Integer) ht_hashcodes.get(id);
129: final int layout_hc = (layout_hashcode != null) ? layout_hashcode
130: .intValue()
131: : -1;
132: final List last_tokens = (List) ht_tokens.get(id);
133: if (hashcode == layout_hc && last_tokens != null)
134: return last_tokens;
135: List tokens = new ArrayList();
136: LayoutConfig config = LayoutConfig.getConfig(pageContext
137: .getServletContext());
138: int pc = config.pageSize();
139: for (int i = 0; i < pc; i++) {
140: Page page = config.getPage(i);
141: int begin = content.indexOf(page.getName());
142: if (begin != -1) {
143: Token token = new Token();
144: token.begin = begin;
145: token.name = page.getName();
146: token.page = page.getUri();
147: tokens.add(token);
148: }
149: }
150: int begin = content.indexOf(ROOT);
151: if (begin != -1) {
152: Token token = new Token();
153: token.begin = begin;
154: token.name = ROOT;
155: tokens.add(token);
156: }
157: Collections.sort(tokens);//按位置进行排序
158: //缓冲信息
159: ht_hashcodes.put(id, new Integer(hashcode));
160: ht_tokens.put(id, tokens);
161: return tokens;
162: }
163:
164: private static Hashtable ht_tokens = new Hashtable();
165: private static Hashtable ht_hashcodes = new Hashtable();
166:
167: /**
168: * 用于变量替换保存临时参数
169: */
170: private class Token implements Comparable {
171: public int ident;
172: public String name;
173: public int begin;
174: public String page;
175:
176: public int compareTo(Object obj) {
177: return begin - ((Token) obj).begin;
178: }
179:
180: public int hashCode() {
181: return begin;
182: }
183: };
184:
185: protected String mainPage;
186: protected String baseDir = "/WEB-INF/jsp/";
187: protected String errorPage = "error/error.jsp";
188:
189: public String getMainPage() {
190: return mainPage;
191: }
192:
193: public void setMainPage(String mainPage) {
194: this .mainPage = mainPage;
195: }
196:
197: public String getBaseDir() {
198: return baseDir;
199: }
200:
201: public void setBaseDir(String baseDir) {
202: if (!baseDir.endsWith("/"))
203: baseDir += "/";
204: this .baseDir = baseDir;
205: }
206:
207: public String getErrorPage() {
208: return errorPage;
209: }
210:
211: public void setErrorPage(String errorPage) {
212: this.errorPage = errorPage;
213: }
214: }
|