001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: *
017: * $Header:$
018: */
019: package org.apache.beehive.netui.tags.tree;
020:
021: import org.apache.beehive.netui.util.internal.InternalStringBuilder;
022:
023: import org.apache.beehive.netui.pageflow.interceptor.InterceptorChain;
024: import org.apache.beehive.netui.pageflow.interceptor.InterceptorException;
025: import org.apache.beehive.netui.pageflow.interceptor.request.RequestInterceptor;
026: import org.apache.beehive.netui.pageflow.interceptor.request.RequestInterceptorContext;
027: import org.apache.beehive.netui.pageflow.requeststate.INameable;
028: import org.apache.beehive.netui.pageflow.requeststate.NameService;
029: import org.apache.beehive.netui.tags.rendering.AbstractRenderAppender;
030: import org.apache.beehive.netui.tags.rendering.StringBuilderRenderAppender;
031: import org.apache.beehive.netui.tags.TagConfig;
032: import org.apache.beehive.netui.util.logging.Logger;
033: import org.apache.beehive.netui.core.chain.Command;
034: import org.apache.beehive.netui.core.chain.Context;
035: import org.apache.beehive.netui.core.chain.web.WebChainContext;
036:
037: import javax.servlet.ServletContext;
038: import javax.servlet.ServletResponse;
039: import javax.servlet.http.HttpServletRequest;
040: import javax.servlet.http.HttpServletResponse;
041: import javax.servlet.jsp.JspException;
042: import java.io.IOException;
043: import java.io.Writer;
044:
045: public class TreeCRI extends RequestInterceptor implements Command {
046: private static final String TREE_COLLAPSE = "treeCollapse";
047: private static final String TREE_EXPAND = "treeExpand";
048:
049: private static final Logger logger = Logger
050: .getInstance(TreeCRI.class);
051:
052: // The elements we will create in the document
053: private static final String TREE_EXPAND_ELEM = "treeExpand";
054:
055: /**
056: * Implementation of the {@link Command} interface for using this class as part of a
057: * Chain of Responsibility.
058: *
059: * @param context the Chain's context object
060: * @return <code>true</code> if the request was handled by this command; <code>false</code> otherwise
061: * @throws Exception any exception that is throw during processing
062: */
063: public boolean execute(Context context) throws Exception {
064:
065: assert context != null;
066: assert context instanceof WebChainContext;
067: assert ((WebChainContext) context).getServletRequest() instanceof HttpServletRequest;
068: assert ((WebChainContext) context).getServletResponse() instanceof HttpServletResponse;
069:
070: WebChainContext webChainContext = (WebChainContext) context;
071: HttpServletRequest request = (HttpServletRequest) webChainContext
072: .getServletRequest();
073: HttpServletResponse response = (HttpServletResponse) webChainContext
074: .getServletResponse();
075:
076: String cmd = parseCommand(request.getRequestURI());
077: return render(request, response, webChainContext
078: .getServletContext(), cmd);
079: }
080:
081: /**
082: * Implementation of the {@link RequestInterceptor#preRequest(org.apache.beehive.netui.pageflow.interceptor.request.RequestInterceptorContext, org.apache.beehive.netui.pageflow.interceptor.InterceptorChain)}
083: * method for using this class as part of a request interceptor chain.
084: *
085: * @param ctxt the interceptor's context object
086: * @param chain the interceptor chain
087: * @throws InterceptorException any exception thrown during processing
088: */
089: public void preRequest(RequestInterceptorContext ctxt,
090: InterceptorChain chain) throws InterceptorException {
091: HttpServletRequest request = ctxt.getRequest();
092:
093: String cmd = parseCommand(request.getRequestURI());
094: render(request, ctxt.getResponse(), ctxt.getServletContext(),
095: cmd);
096:
097: chain.continueChain();
098: }
099:
100: /**
101: * Implementation of the {@link RequestInterceptor#postRequest(org.apache.beehive.netui.pageflow.interceptor.request.RequestInterceptorContext, org.apache.beehive.netui.pageflow.interceptor.InterceptorChain)}
102: * method for using this class as part of a request interceptor chain.
103: *
104: * @param context the interceptor's context object
105: * @param chain the interceptor chain
106: * @throws InterceptorException any exception thrown during processing
107: */
108: public void postRequest(RequestInterceptorContext context,
109: InterceptorChain chain) throws InterceptorException {
110: chain.continueChain();
111: }
112:
113: private String parseCommand(String cmd) {
114: // Create the command by striping off the context path and the extension
115: // catch any runtime errors here and return.
116: try {
117: int dot = cmd.lastIndexOf('.');
118: int slash = cmd.lastIndexOf('/');
119: if (dot != -1 && slash != -1 && slash < dot) {
120: cmd = cmd.substring(slash + 1, dot);
121: }
122: } catch (RuntimeException e) {
123: System.err
124: .println("Runtime Error creating XmlRequestServlet Command:"
125: + e.getClass().getName());
126: }
127:
128: return cmd;
129: }
130:
131: private boolean render(HttpServletRequest request,
132: HttpServletResponse response,
133: ServletContext servletContext, String cmd) {
134:
135: // check to see if we handle this command
136: if (TREE_COLLAPSE.equals(cmd)) {
137: handleExpandCollapse(false, request, response,
138: servletContext);
139: return true;
140: } else if (TREE_EXPAND.equals(cmd)) {
141: handleExpandCollapse(true, request, response,
142: servletContext);
143: return true;
144: }
145:
146: return false;
147: }
148:
149: private void handleExpandCollapse(boolean expand,
150: HttpServletRequest req, HttpServletResponse response,
151: ServletContext ctxt) {
152: // create an XML empty document, that isn't cached on the client
153: response.setContentType("text/xml");
154: response.setHeader("Pragma", "No-cache");
155: response.setHeader("Cache-Control", "no-cache");
156:
157: String tree = req.getParameter("tree");
158: String node = req.getParameter("node");
159: String expandSvr = req.getParameter("expandOnServer");
160: //System.err.println("TreeCommand:" + ((expand) ? "expand" : "collapse") +
161: // " Tree:" + tree + " Node:" + node + " expandSvr:" + expandSvr);
162:
163: NameService ns = NameService.instance(req.getSession());
164: assert (ns != null);
165:
166: // get the tree from the name service
167: INameable n = ns.get(tree);
168: if (n == null) {
169: logger.error("Tree '" + tree
170: + "' was not found in the NameService");
171: return;
172: }
173: if (!(n instanceof ITreeRootElement)) {
174: logger
175: .error("Named Tree was not an instance of a ITreeRootElement");
176: return;
177: }
178:
179: ITreeRootElement root = (ITreeRootElement) n;
180: TreeElement elem = ((TreeElement) root).findNode(node);
181: if (elem == null) {
182: System.err.println("Element '" + node
183: + "' not found in the tree");
184: return;
185: }
186: elem.onExpand(req, response);
187: elem.setExpanded(expand);
188:
189: if (expandSvr != null) {
190: InternalStringBuilder sb = new InternalStringBuilder(1024);
191: StringBuilderRenderAppender writer = new StringBuilderRenderAppender(
192: sb);
193: // Start the document
194: writeStartElement(writer, TREE_EXPAND_ELEM);
195:
196: // add a tree identifier
197: writeElement(writer, "node", node);
198: writeElement(writer, "treeId", tree);
199:
200: try {
201: TreeElement children[] = elem.getChildren();
202: AttributeRenderer extraAttrs = new AttributeRenderer();
203: int newLevel = elem.getLevel() + 1;
204: InternalStringBuilder nodeSB = new InternalStringBuilder();
205: StringBuilderRenderAppender childRendering = new StringBuilderRenderAppender(
206: nodeSB);
207: TreeElement tmp = elem;
208: InheritableState iState = null;
209: while (iState == null && tmp != null) {
210: iState = tmp.getInheritableState();
211: tmp = tmp.getParent();
212: }
213: if (iState == null) {
214: System.err
215: .println("Unable to find InheritableState");
216: iState = root.getInheritableState();
217: }
218:
219: TreeRenderState trs = root.getTreeRenderState();
220: String treeRendererClassName = TagConfig
221: .getTreeRendererClassName();
222: TreeRenderer tr = TreeRendererFactory
223: .getInstance(treeRendererClassName);
224: if (tr == null) {
225: tr = new TreeRenderer();
226: }
227: tr.init(trs, req, (HttpServletResponse) response, ctxt);
228: tr.setTreeRenderSupport(new ServletTreeRenderSupport(
229: writer, nodeSB));
230: for (int i = 0; i < children.length; i++) {
231: nodeSB.setLength(0);
232: tr.render(childRendering, children[i], newLevel,
233: extraAttrs, iState);
234: }
235: } catch (JspException se) {
236: //se.printStackTrace();
237: logger.error(
238: "Received a JSP excpetion Rendering the Tree",
239: se);
240: return;
241: } catch (RuntimeException re) {
242: //re.printStackTrace();
243: logger.error(
244: "Received a JSP excpetion Rendering the Tree",
245: re);
246: return;
247: }
248:
249: // add the tree text
250: writeEndElement(writer, TREE_EXPAND_ELEM);
251: write(response, sb.toString());
252: }
253: }
254:
255: public static void writeStartElement(AbstractRenderAppender writer,
256: String elementName) {
257: writer.append("<");
258: writer.append(elementName);
259: writer.append(">");
260:
261: }
262:
263: public static void writeEndElement(AbstractRenderAppender writer,
264: String elementName) {
265: writer.append("</");
266: writer.append(elementName);
267: writer.append(">");
268: }
269:
270: public static void writeElement(AbstractRenderAppender writer,
271: String elementName, String value) {
272: writeStartElement(writer, elementName);
273: writer.append(value);
274: writeEndElement(writer, elementName);
275:
276: }
277:
278: private void write(ServletResponse response, String string) {
279: try {
280: Writer writer = response.getWriter();
281: writer.write(string);
282: } catch (IOException e) {
283: }
284: }
285: }
|