001: /*
002: * Created on Oct 19, 2004
003: */
004: package com.openedit.page;
005:
006: import java.io.IOException;
007: import java.util.ArrayList;
008: import java.util.HashMap;
009: import java.util.Iterator;
010: import java.util.List;
011: import java.util.Map;
012:
013: import org.apache.commons.logging.Log;
014: import org.apache.commons.logging.LogFactory;
015:
016: import com.openedit.OpenEditException;
017: import com.openedit.WebPageRequest;
018: import com.openedit.generators.Output;
019: import com.openedit.page.manage.PageManager;
020: import com.openedit.servlet.OpenEditEngine;
021: import com.openedit.util.PathUtilities;
022: import com.openedit.util.strainer.Filter;
023:
024: /**
025: * @author Matthew Avery, mavery@einnovation.com
026: */
027: public class PageStreamer {
028: private static final Log log = LogFactory
029: .getLog(PageStreamer.class);
030: protected OpenEditEngine fieldEngine;
031: protected Output fieldOutput;
032:
033: protected WebPageRequest fieldWebPageRequest;
034: protected Map fieldWebPageRequestedCount;
035: protected List fieldChildContentList;
036: protected int fieldMaxLoop = 50;
037: protected boolean fieldDebug = false;
038:
039: public PageStreamer() {
040: //log.debug("Created streamer");
041: }
042:
043: /**
044: * This is called only once
045: * We need to exec all the page actions ahead of time
046: * And check the read permissions ahead of time
047: * Then we can do the rendering
048: * @throws OpenEditException
049: */
050:
051: public void render() throws OpenEditException {
052: Page page = getWebPageRequest().getPage();
053: if (page.isHtml()) {
054: getChildContentList().add(
055: getWebPageRequest().getContentPage());
056: //allow someone to programatically override the top level inner layout
057:
058: String override = (String) getWebPageRequest()
059: .getPageValue(PageRequestKeys.INNERLAYOUTOVERRIDE);
060: if (override != null) {
061: if (!override.equals(Page.BLANK_LAYOUT)) {
062: Page il = getPage(override);
063: addInnerLayout(il);
064: }
065: } else {
066: addInnerLayout(getWebPageRequest().getContentPage());
067: }
068: //handle layout
069: String layout = getLayout();
070: if (layout != null) {
071: Page layoutPage = getPage(layout);
072: getChildContentList().add(0, layoutPage);
073: }
074: String debug = getWebPageRequest().getRequestParameter(
075: "oedebug");
076: if (debug != null) {
077: setDebug(Boolean.parseBoolean(debug));
078: }
079:
080: if (getChildContentList().size() > 1) {
081: String maxlevels = getWebPageRequest()
082: .getRequestParameter("oemaxlevel");
083: if (maxlevels == null) {
084: maxlevels = getWebPageRequest().getContentProperty(
085: "oemaxlevel");
086: }
087:
088: if (maxlevels != null) {
089: int cut = Integer.parseInt(maxlevels);
090: List toCut = getChildContentList();
091: if (cut < toCut.size()) {
092: toCut = toCut.subList(toCut.size() - cut, toCut
093: .size());
094: fieldChildContentList = toCut;
095: }
096: }
097: }
098: String cancel = getWebPageRequest().getPage()
099: .getPageSettings().getPropertyValueFixed(
100: "cancelinnerlayout");
101: if (cancel != null) {
102: List toCut = getChildContentList();
103: for (int i = 0; i < toCut.size(); i++) {
104: Page path = (Page) toCut.get(i);
105: if (path.getPath().equals(cancel)) {
106: toCut.remove(i);
107: break;
108: }
109: }
110: }
111: includeContent();
112: } else { //CSS files. Binary
113: WebPageRequest request = getWebPageRequest();
114: Page torender = getPageManager().getPage(page,
115: getWebPageRequest());
116: if (torender != page) //This could be a draft version
117: {
118: request = getWebPageRequest().copy(torender);
119: getEngine().executePageActions(request);
120: }
121: torender.generate(request, getOutput());
122: }
123: }
124:
125: protected void addInnerLayout(Page inContentPage)
126: throws OpenEditException {
127: if (inContentPage.hasInnerLayout()) {
128: String innerlayout = inContentPage.getInnerLayout();
129:
130: if (!inContentPage.getPath().equalsIgnoreCase(innerlayout)) {
131: Page il = getPage(innerlayout);
132: if (!getChildContentList().contains(il)) {
133: if (getChildContentList().size() < getMaxLoop()) {
134: getChildContentList().add(0, il);
135: addInnerLayout(il);
136: }
137: }
138: }
139: }
140: }
141:
142: protected void renderLayout() throws OpenEditException {
143: Page inLayout = getEngine().getPageManager().getPage(
144: getLayout(), getWebPageRequest().getUser() != null);
145: if (!inLayout.exists()) {
146: getWebPageRequest().putPageValue("missingLayoutPage",
147: inLayout.getPath());
148: inLayout = getPage("/layoutnotfound.html");
149: if (!inLayout.exists()) {
150: inLayout = getPage("/openedit/layoutnotfound.html");
151: }
152: }
153: include(inLayout);
154: }
155:
156: /**
157: * @deprecated use includeContent()
158: * @throws OpenEditException
159: */
160: public void streamContent() throws OpenEditException {
161: includeContent();
162: }
163:
164: /**
165: * @deprecated use includeContent()
166: * @throws OpenEditException
167: */
168: public void renderContent() throws OpenEditException {
169: includeContent();
170: }
171:
172: public void includeContent() throws OpenEditException {
173: //if I am being called from an inner layout make sure I am at the top first
174: if (getChildContentList().size() == 0) {
175: //throw new OpenEditException("Ran out of content on " + getWebPageRequest().getPath());
176: //stream(getPage());
177: return;
178: }
179: Page topChild = (Page) getChildContentList().get(0);
180:
181: getChildContentList().remove(0);
182: include(topChild, getWebPageRequest());
183: }
184:
185: public void include(Page inPage) throws OpenEditException {
186: include(inPage, getWebPageRequest());
187: }
188:
189: /**
190: * Allows a page to be streamed that uses this request as the parent request
191: */
192: public void include(Page inPage, WebPageRequest inContext)
193: throws OpenEditException {
194: int hitcount = incrementWebPageRequestedCount(inPage);
195: //This is used when viewing a layout page directly (i.e. /layout.html)
196: if (hitcount >= getMaxLoop()) {
197: //ok its an infinite loop
198: throw new OpenEditException("Page loop detected calling "
199: + inPage.getPath() + "more than " + getMaxLoop()
200: + " times.");
201: }
202: //This is trickly to understand. The contents actions have already been run. Now we either
203: //run the actions or if its the content page those actions have already been run
204:
205: Page torender = null;
206: WebPageRequest request = inContext;
207:
208: if (inPage == inContext.getContentPage()) {
209: torender = getPageManager().getPage(inPage, request);
210: if (torender != inPage) //This could be a draft version
211: {
212: request = inContext.copy(torender);
213: getEngine().executePageActions(request);
214: }
215: } else {
216: //these are the included pages ie. /sidebar.html that may have their own actions
217: request = inContext.copy(inPage);
218: // Ensure the FILE_PATH variable has the correct value for this streamed page.
219:
220: request.putPageValue(PageRequestKeys.FILE_PATH, inPage
221: .getDirectory()); //This is legacy from OE 4.0 can be deleted anytime
222: torender = getPageManager().getPage(inPage, request);
223: if (torender != inPage) //This could be a draft version
224: {
225: request = request.copy(torender);
226: }
227: if (!request.hasRedirected()) {
228: getEngine().executePageActions(request);
229: }
230: }
231: request.putPageValue("originalPage", inPage);
232: if (isDebug()) {
233: try {
234: getOutput()
235: .getWriter()
236: .write(
237: "<div style='border:1px dashed red;padding: 1px;'>");
238: getOutput().getWriter().write(
239: torender.getContentItem().getActualPath());
240: torender.generate(request, getOutput());
241: getOutput().getWriter().write("</div>");
242: } catch (IOException e) {
243: log.error(e);
244: }
245: } else {
246: torender.generate(request, getOutput());
247: }
248: }
249:
250: public void include(String inPath, WebPageRequest inReq)
251: throws OpenEditException {
252: String[] parts = inPath.split("[?]");
253: String fullPath = PathUtilities.resolveRelativePath(parts[0],
254: getWebPageRequest().getContentPage().getPath());
255: Page page = getEngine().getPageManager().getPage(fullPath,
256: getWebPageRequest().getUser() != null);
257:
258: if (parts.length > 1) {
259: String[] args = parts[1].split("&");
260: for (int i = 0; i < args.length; i++) {
261: String[] pairs = args[i].split("=");
262: if (pairs.length == 2) {
263: getWebPageRequest().setRequestParameter(pairs[0],
264: pairs[1]);
265: }
266: }
267: }
268: include(page, inReq);
269: }
270:
271: public void include(String inPath) throws OpenEditException {
272: include(inPath, getWebPageRequest());
273: }
274:
275: /**
276: * Use include
277: * @deprecated
278: */
279: public void stream(Page inPage) throws OpenEditException {
280: include(inPage);
281: }
282:
283: /**
284: * Use include
285: * @deprecated
286: */
287: public void stream(Page inPage, WebPageRequest inContext)
288: throws OpenEditException {
289: include(inPage, inContext);
290: }
291:
292: /**
293: * Use include
294: * @deprecated
295: */
296: public void stream(String inPath, WebPageRequest inReq)
297: throws OpenEditException {
298: include(inPath, inReq);
299: }
300:
301: /**
302: * Use include
303: * @deprecated
304: */
305: public void stream(String inPath) throws OpenEditException {
306: include(inPath);
307: }
308:
309: public Map getWebPageRequestedCount() {
310: if (fieldWebPageRequestedCount == null) {
311: fieldWebPageRequestedCount = new HashMap();
312: }
313: return fieldWebPageRequestedCount;
314: }
315:
316: protected int incrementWebPageRequestedCount(Page inPage) {
317: Integer count = (Integer) getWebPageRequestedCount()
318: .get(inPage);
319: int hitcount = 0;
320:
321: if (count != null) {
322: hitcount = count.intValue() + 1;
323: }
324:
325: getWebPageRequestedCount().put(inPage, new Integer(hitcount));
326: return hitcount;
327: }
328:
329: public boolean doesExist(String inPath) throws OpenEditException {
330: if (inPath == null) {
331: return false;
332: }
333: return loadRelativePath(inPath).exists();
334: }
335:
336: protected Page loadRelativePath(String inPath)
337: throws OpenEditException {
338: String fullPath = PathUtilities.buildRelative(inPath,
339: getWebPageRequest().getContentPage().getPath());
340: return getPage(fullPath);
341: }
342:
343: public Page getPage(String inPath) throws OpenEditException {
344: return getPageManager().getPage(inPath,
345: getWebPageRequest().getUser() != null);
346: }
347:
348: public PageManager getPageManager() {
349: return getEngine().getPageManager();
350: }
351:
352: public OpenEditEngine getEngine() {
353: return fieldEngine;
354: }
355:
356: public void setEngine(OpenEditEngine engine) {
357: fieldEngine = engine;
358: }
359:
360: public WebPageRequest getWebPageRequest() {
361: return fieldWebPageRequest;
362: }
363:
364: public void setWebPageRequest(WebPageRequest WebPageRequest) {
365: fieldWebPageRequest = WebPageRequest;
366: }
367:
368: public void forward(String path, WebPageRequest inReq)
369: throws OpenEditException {
370: //if this is the error page then we can get into an infinite loop
371: //WebPageRequest WebPageRequest = getWebPageRequest().copy();
372: //WebPageRequest.setPage( getPage( path ) );
373: //getEngine().render( WebPageRequest );
374: Page original = inReq.getPage();
375: Page page = getPage(path);
376: //remove layout overrides
377:
378: WebPageRequest req = getWebPageRequest();
379: req.removePageValue(PageRequestKeys.INNERLAYOUTOVERRIDE);
380: req.removePageValue(PageRequestKeys.LAYOUTOVERRIDE);
381: if (req.getContentPage().getPath().equals(
382: inReq.getPage().getPath())) //are we rendeing the content page?
383: {
384: req.putProtectedPageValue(PageRequestKeys.CONTENT, page);
385: }
386: req.putProtectedPageValue(PageRequestKeys.PAGE, page);
387: req.putPageValue("forwardpage", original);
388: getEngine().getModuleManager().executePathActions(page, req);
389: getEngine().getModuleManager().executePageActions(page, req);
390: inReq.setHasForwarded(true);
391: //Now it continues to render as normal but with alternative content.
392: //Does not support custom layouts
393: }
394:
395: public PageStreamer copy() {
396: PageStreamer streamer = new PageStreamer();
397: streamer.setEngine(getEngine());
398: streamer.fieldChildContentList = getChildContentList();
399: streamer.setWebPageRequest(getWebPageRequest());
400: streamer.setOutput(getOutput());
401: return streamer;
402: }
403:
404: protected String getLayout() {
405: String override = (String) getWebPageRequest().getPageValue(
406: "layoutoverride");
407: if (override != null) {
408: if (override.equals(Page.BLANK_LAYOUT)) {
409: return null;
410: }
411: return override;
412: }
413: Page page = getWebPageRequest().getPage();
414:
415: if (page.hasLayout()) {
416: String layout = page.getLayout();
417: layout = page.getPageSettings().replaceProperty(layout);
418: return layout;
419: }
420: return null;
421: }
422:
423: public List getChildContentList() {
424: if (fieldChildContentList == null) {
425: fieldChildContentList = new ArrayList();
426: }
427: return fieldChildContentList;
428: }
429:
430: public Output getOutput() {
431: return fieldOutput;
432: }
433:
434: public void setOutput(Output inOutput) {
435: fieldOutput = inOutput;
436: }
437:
438: public boolean canView(String inPath) throws OpenEditException {
439: Page linkpage = getPageManager().getPage(inPath,
440: getWebPageRequest().getUser() != null);
441: if (linkpage.exists()) {
442: Filter filter = linkpage.getViewFilter();
443: WebPageRequest req = getWebPageRequest().copy(linkpage);
444: boolean value = ((filter == null) || filter.passes(req));
445: return value;
446: }
447: return false;
448: }
449:
450: public boolean canEdit(String inPath) throws OpenEditException {
451: Page linkpage = getPageManager().getPage(inPath,
452: getWebPageRequest().getUser() != null);
453: Filter filter = linkpage.getEditFilter();
454: WebPageRequest req = getWebPageRequest().copy(linkpage);
455: boolean value = ((filter == null) || filter.passes(req));
456: return value;
457: }
458:
459: public int getMaxLoop() {
460: return fieldMaxLoop;
461: }
462:
463: public void setMaxLoop(int inMaxLoop) {
464: fieldMaxLoop = inMaxLoop;
465: }
466:
467: public boolean isDebug() {
468: return fieldDebug;
469: }
470:
471: public void setDebug(boolean inDebug) {
472: fieldDebug = inDebug;
473: }
474: }
|