001: /*
002: * Copyright (c) 1998-2008 Caucho Technology -- all rights reserved
003: *
004: * This file is part of Resin(R) Open Source
005: *
006: * Each copy or derived work must preserve the copyright notice and this
007: * notice unmodified.
008: *
009: * Resin Open Source is free software; you can redistribute it and/or modify
010: * it under the terms of the GNU General Public License version 2
011: * as published by the Free Software Foundation.
012: *
013: * Resin Open Source is distributed in the hope that it will be useful,
014: * but WITHOUT ANY WARRANTY; without even the implied warranty of
015: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
016: * of NON-INFRINGEMENT. See the GNU General Public License for more
017: * details.
018: *
019: * You should have received a copy of the GNU General Public License
020: * along with Resin Open Source; if not, write to the
021: *
022: * Free Software Foundation, Inc.
023: * 59 Temple Place, Suite 330
024: * Boston, MA 02111-1307 USA
025: *
026: * @author Scott Ferguson
027: */
028:
029: package javax.faces.webapp;
030:
031: import java.io.*;
032:
033: import java.util.*;
034:
035: import javax.faces.application.*;
036: import javax.faces.component.*;
037: import javax.faces.component.html.*;
038: import javax.faces.context.*;
039:
040: import javax.servlet.jsp.*;
041: import javax.servlet.jsp.tagext.*;
042: import javax.servlet.ServletRequest;
043:
044: public abstract class UIComponentClassicTagBase extends
045: UIComponentTagBase implements JspIdConsumer, BodyTag {
046: protected static final String UNIQUE_ID_PREFIX = "_id_";
047:
048: private String _id;
049: private String _jspId;
050:
051: protected PageContext pageContext;
052: protected BodyContent bodyContent;
053:
054: private FacesContext _facesContext;
055:
056: private UIComponentClassicTagBase _parentUIComponentTag;
057:
058: private Tag _parent;
059:
060: private UIComponent _component;
061: private boolean _created;
062:
063: protected UIComponentClassicTagBase() {
064: _facesContext = FacesContext.getCurrentInstance();
065: }
066:
067: protected String getFacetName() {
068: return null;
069: }
070:
071: public void setJspId(String id) {
072: _jspId = id;
073: }
074:
075: public String getJspId() {
076: return _jspId;
077: }
078:
079: public void setPageContext(PageContext pageContext) {
080: this .pageContext = pageContext;
081: }
082:
083: public Tag getParent() {
084: return _parent;
085: }
086:
087: public void setParent(Tag parent) {
088: _parent = parent;
089: }
090:
091: public void setBodyContent(BodyContent bodyContent) {
092: this .bodyContent = bodyContent;
093: }
094:
095: public BodyContent getBodyContent() {
096: return this .bodyContent;
097: }
098:
099: public JspWriter getPreviousOut() {
100: if (bodyContent != null)
101: return bodyContent.getEnclosingWriter();
102: else
103: return pageContext.getOut();
104: }
105:
106: public void setId(String id) {
107: if (id.startsWith(UNIQUE_ID_PREFIX))
108: throw new IllegalArgumentException("id may not begin with "
109: + UNIQUE_ID_PREFIX);
110:
111: _id = id;
112: }
113:
114: public String getId() {
115: return _id;
116: }
117:
118: protected abstract boolean hasBinding();
119:
120: public UIComponent getComponentInstance() {
121: return _component;
122: }
123:
124: public boolean getCreated() {
125: return _created;
126: }
127:
128: public int doStartTag() throws JspException {
129: PageContext pageContext = this .pageContext;
130:
131: this .bodyContent = null;
132: _created = false;
133: _component = null;
134:
135: _parentUIComponentTag = getParentUIComponentClassicTagBase(pageContext);
136:
137: ServletRequest request = pageContext.getRequest();
138:
139: Map tagMap = (Map) request.getAttribute("caucho.jsf.tag.map");
140:
141: if (tagMap == null) {
142: tagMap = new HashMap();
143: request.setAttribute("caucho.jsf.tag.map", tagMap);
144: }
145:
146: Integer iterCounter = (Integer) tagMap.get(_jspId);
147:
148: iterCounter = (iterCounter == null ? new Integer(0)
149: : new Integer(iterCounter.intValue() + 1));
150:
151: tagMap.put(_jspId, iterCounter);
152:
153: _component = findComponent(_facesContext);
154:
155: request.setAttribute("caucho.jsf.parent", this );
156:
157: return getDoStartValue();
158: }
159:
160: /**
161: * Returns the doStart value for the tag. Defaults to EVAL_BODY_BUFFERED.
162: */
163: protected int getDoStartValue() throws JspException {
164: return BodyTag.EVAL_BODY_BUFFERED;
165: }
166:
167: public void doInitBody() throws JspException {
168: }
169:
170: public int doAfterBody() throws JspException {
171: UIComponent verbatim = createVerbatimComponentFromBodyContent();
172:
173: if (verbatim != null) {
174: UIComponent component = getComponentInstance();
175:
176: if (component != null)
177: component.getChildren().add(verbatim);
178: }
179:
180: return getDoAfterBodyValue();
181: }
182:
183: protected int getDoAfterBodyValue() throws JspException {
184: return BodyTag.SKIP_PAGE;
185: }
186:
187: public int doEndTag() throws JspException {
188: pageContext.getRequest().setAttribute("caucho.jsf.parent",
189: _parentUIComponentTag);
190:
191: return getDoEndValue();
192: }
193:
194: protected int getDoEndValue() throws JspException {
195: return Tag.EVAL_PAGE;
196: }
197:
198: protected abstract UIComponent createComponent(
199: FacesContext context, String newId) throws JspException;
200:
201: protected abstract void setProperties(UIComponent component);
202:
203: protected UIComponent findComponent(FacesContext context)
204: throws JspException {
205: _created = false;
206:
207: if (_component != null)
208: return _component;
209:
210: UIComponentClassicTagBase parentTag = _parentUIComponentTag;
211:
212: if (parentTag == null) {
213: _component = context.getViewRoot();
214:
215: // XXX:
216: if (_component.getChildCount() == 0)
217: _created = true;
218:
219: return _component;
220: }
221:
222: UIComponent verbatim = parentTag
223: .createVerbatimComponentFromBodyContent();
224:
225: UIComponent parent = parentTag.getComponentInstance();
226:
227: String id = getId();
228: String facetName = null;
229:
230: if (id == null)
231: id = UIViewRoot.UNIQUE_ID_PREFIX + getJspId();
232:
233: Map tagMap = (Map) pageContext.getRequest().getAttribute(
234: "caucho.jsf.tag.map");
235:
236: Integer iterCounter = (Integer) tagMap.get(_jspId);
237:
238: if (iterCounter.intValue() > 0)
239: id = id + "_" + iterCounter.intValue();
240:
241: if (_parent instanceof FacetTag) {
242: facetName = ((FacetTag) _parent).getName();
243:
244: _component = parent.getFacet(facetName);
245:
246: if (_component != null)
247: return _component;
248: } else {
249: _component = parent.findComponent(id);
250:
251: if (_component != null) {
252: if (verbatim != null) {
253: addVerbatimBeforeComponent(parentTag, verbatim,
254: _component);
255: }
256:
257: return _component;
258: }
259:
260: if (verbatim != null) {
261: parent.getChildren().add(verbatim);
262: }
263: }
264:
265: String componentType = getComponentType();
266:
267: if (hasBinding()) {
268: // XXX: binding
269: }
270:
271: _component = createComponent(context, id);
272:
273: _created = true;
274:
275: _component.setId(id);
276:
277: setProperties(_component);
278:
279: if (facetName != null)
280: parent.getFacets().put(facetName, _component);
281: else
282: parent.getChildren().add(_component);
283:
284: return _component;
285: }
286:
287: protected int getIndexOfNextChildTag() {
288: throw new UnsupportedOperationException();
289: }
290:
291: protected void addChild(UIComponent child) {
292: getComponentInstance().getChildren().add(child);
293: }
294:
295: protected void addFacet(String name) {
296: throw new UnsupportedOperationException();
297: }
298:
299: protected UIComponent createVerbatimComponentFromBodyContent() {
300: BodyContent bodyContent = this .bodyContent;
301:
302: if (bodyContent == null)
303: return null;
304:
305: String text = bodyContent.getString();
306: bodyContent.clearBody();
307: boolean isWhitespace = true;
308:
309: for (int i = text.length() - 1; i >= 0; i--) {
310: char ch = text.charAt(i);
311:
312: if (!Character.isWhitespace(ch)) {
313: // check for comment
314: if (ch == '>' && text.indexOf("-->") + 2 == i) {
315: int head = text.indexOf("<!--");
316:
317: if (head >= 0) {
318: for (int j = 0; j < head; j++) {
319: if (!Character.isWhitespace(text.charAt(j))) {
320: isWhitespace = false;
321: break;
322: }
323: }
324:
325: if (isWhitespace)
326: return null;
327: }
328: }
329:
330: isWhitespace = false;
331: break;
332: }
333: }
334:
335: if (isWhitespace)
336: return null;
337:
338: UIOutput verbatim = createVerbatimComponent();
339:
340: verbatim.setValue(text);
341:
342: return verbatim;
343: }
344:
345: protected UIOutput createVerbatimComponent() {
346: Application app = _facesContext.getApplication();
347: UIOutput output = (UIOutput) app
348: .createComponent(HtmlOutputText.COMPONENT_TYPE);
349:
350: output.setId(_facesContext.getViewRoot().createUniqueId());
351: output.setTransient(true);
352: if (output instanceof HtmlOutputText)
353: ((HtmlOutputText) output).setEscape(false);
354:
355: return output;
356: }
357:
358: protected void addVerbatimBeforeComponent(
359: UIComponentClassicTagBase parentTag, UIComponent verbatim,
360: UIComponent component) {
361: UIComponent parent = parentTag.getComponentInstance();
362:
363: int size = parent.getChildCount();
364:
365: if (size > 0) {
366: List<UIComponent> children = parent.getChildren();
367:
368: for (int i = 0; i < size; i++) {
369: if (children.get(i) == component)
370: children.add(i, verbatim);
371: }
372: }
373: }
374:
375: protected void addVerbatimAfterComponent(
376: UIComponentClassicTagBase parentTag, UIComponent verbatim,
377: UIComponent component) {
378: UIComponent parent = parentTag.getComponentInstance();
379:
380: int size = parent.getChildCount();
381:
382: if (size > 0) {
383: List<UIComponent> children = parent.getChildren();
384:
385: for (int i = 0; i < size; i++) {
386: if (children.get(i) == component)
387: children.add(i + 1, verbatim);
388: }
389: }
390: }
391:
392: public List<String> getCreatedComponents() {
393: throw new UnsupportedOperationException();
394: }
395:
396: protected FacesContext getFacesContext() {
397: return _facesContext;
398: }
399:
400: @Deprecated
401: protected void setupResponseWriter() {
402: }
403:
404: @Deprecated
405: protected void encodeBegin() throws IOException {
406: UIComponent component = getComponentInstance();
407: FacesContext context = getFacesContext();
408:
409: if (component != null && context != null)
410: component.encodeBegin(context);
411: }
412:
413: @Deprecated
414: protected void encodeChildren() throws IOException {
415: UIComponent component = getComponentInstance();
416: FacesContext context = getFacesContext();
417:
418: if (component != null && context != null)
419: component.encodeChildren(context);
420: }
421:
422: @Deprecated
423: protected void encodeEnd() throws IOException {
424: UIComponent component = getComponentInstance();
425: FacesContext context = getFacesContext();
426:
427: if (component != null && context != null)
428: component.encodeEnd(context);
429: }
430:
431: public void release() {
432: }
433:
434: public static UIComponentClassicTagBase getParentUIComponentClassicTagBase(
435: PageContext pageContext) {
436: return (UIComponentClassicTagBase) pageContext.getRequest()
437: .getAttribute("caucho.jsf.parent");
438: }
439: }
|