KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > openharmonise > rm > publishing > WebPageEngine


1 /*
2  * The contents of this file are subject to the
3  * Mozilla Public License Version 1.1 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at http://www.mozilla.org/MPL/
6  *
7  * Software distributed under the License is distributed on an "AS IS"
8  * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
9  * See the License for the specific language governing rights and
10  * limitations under the License.
11  *
12  * The Initial Developer of the Original Code is Simulacra Media Ltd.
13  * Portions created by Simulacra Media Ltd are Copyright (C) Simulacra Media Ltd, 2004.
14  *
15  * All Rights Reserved.
16  *
17  * Contributor(s):
18  */
package org.openharmonise.rm.publishing;
19
20 import java.io.OutputStream JavaDoc;
21 import java.util.Vector JavaDoc;
22 import java.util.logging.*;
23
24 import org.openharmonise.commons.cache.CacheException;
25 import org.openharmonise.commons.dsi.AbstractDataStoreInterface;
26 import org.openharmonise.commons.xml.*;
27 import org.openharmonise.commons.xml.namespace.NamespaceClashException;
28 import org.openharmonise.rm.*;
29 import org.openharmonise.rm.commands.CommandProcessHandler;
30 import org.openharmonise.rm.config.*;
31 import org.openharmonise.rm.factory.*;
32 import org.openharmonise.rm.logging.*;
33 import org.openharmonise.rm.publishing.renderers.*;
34 import org.openharmonise.rm.resources.AbstractObject;
35 import org.openharmonise.rm.resources.publishing.*;
36 import org.openharmonise.rm.resources.xml.XMLResource;
37 import org.openharmonise.rm.security.authentication.InvalidUserException;
38 import org.openharmonise.rm.security.authorization.*;
39 import org.openharmonise.rm.sessions.*;
40 import org.w3c.dom.*;
41
42
43 /**
44  * This class provides the funtionality to process the publishing rules
45  * defined in a <code>WebPage</code> object's XML to produce XML containing the content
46  * to be presented.</p>
47  *
48  * @author Michael Bell
49  * @version $Revision: 1.2 $
50  *
51  */

52 public class WebPageEngine {
53
54     protected AbstractDataStoreInterface m_dsi = null;
55
56     protected Session m_Session = null;
57
58     protected static XMLPrettyPrint m_xprinter = new XMLPrettyPrint();
59     
60     /**
61      * Logger for this class
62      */

63     private static final Logger m_logger = Logger.getLogger(WebPageEngine.class.getName());
64
65     /**
66      * Basic constructor
67      *
68      */

69     public WebPageEngine() {
70     }
71
72     /**
73      * Constructs an object with an interface to the DB
74      *
75      * @param con
76      * @throws PublishException
77      */

78     public WebPageEngine(AbstractDataStoreInterface con)
79         throws PublishException {
80         m_dsi = con;
81
82         try {
83             m_Session =
84                 new Session(
85                     m_dsi,
86                     Integer.parseInt(
87                         ConfigSettings.getProperty(
88                             Session.DEFAULT_TIMEOUT_PNAME)));
89             WebPageEngineCache.getInstance(this.m_dsi).addToCache(
90                 m_Session.getSessionId(),
91                 this);
92         } catch (NumberFormatException JavaDoc e) {
93             throw new PublishException("Number formatting error", e);
94         } catch (SessionException e) {
95             throw new PublishException("Error creating session", e);
96         } catch (ConfigException e) {
97             throw new PublishException("Error getting config data", e);
98         } catch (CacheException e) {
99             throw new PublishException("Error getting object from cache", e);
100         }
101     }
102
103     /**
104      * Constructs an object with an interface to the DB for the session associated
105      * to the given session id.
106      *
107      * @param con
108      * @param sSessionId
109      * @throws PublishException
110      */

111     public WebPageEngine(AbstractDataStoreInterface con, String JavaDoc sSessionId)
112         throws PublishException {
113         m_dsi = con;
114         
115         if(m_logger.isLoggable(Level.FINE)) {
116             m_logger.logp(Level.FINE, this.getClass().getName(), "WebPageEngine", "Constructing webpage engine for session " + sSessionId);
117         }
118
119         try {
120             m_Session = new Session(m_dsi, sSessionId);
121         } catch (SessionException e) {
122             throw new PublishException("Error creating session", e);
123         }
124     }
125
126     /**
127      * Returns the <code>Session</code> associated with this object
128      *
129      */

130     public Session getSession() {
131         return m_Session;
132     }
133
134     /**
135      * Processes the given <code>WebPage</code> in the context of the given <code>State</code>
136      * and returns the resultant <code>HarmoniseOutput</code>. The method gets the XML associated
137      * with the <code>WebPage</code> and parses it to find the instructions on what
138      * content to include in the resultant <code>HarmoniseOutput</code>, the <code>State</code>
139      * gives a context to the process.
140      *
141      * @param page
142      * @param state
143      * @return
144      * @throws PublishException
145      */

146     public HarmoniseOutput createXML(WebPage page, State state)
147         throws PublishException {
148         XMLDocument xml = null;
149         HarmoniseOutput xout = null;
150         
151         if(m_logger.isLoggable(Level.FINE)) {
152             m_logger.logp(Level.FINE, this.getClass().getName(), "createXML", "Generating XML for webpage " + page.getId());
153         }
154         
155         try {
156             m_Session.processState(state, page.getTimeout());
157
158             if (AuthorizationValidator.isVisible(m_Session.getUser(), page)
159                 == false) {
160                 if(m_logger.isLoggable(Level.INFO)) {
161                     m_logger.logp(Level.INFO, this.getClass().getName(), "createXML", "User id " + m_Session.getUser().getId() + " not allowed to view page " + page.getId());
162                 }
163                 throw new InvalidUserException("User does not have permission to view page");
164             }
165             xml = page.getXML().getXIncludeResolvedDocument();
166
167         } catch (SessionException e) {
168             throw new PublishException("Error processing state", e);
169         } catch (DataAccessException e) {
170             throw new PublishException("Data access error", e);
171         } catch (AuthorizationException e) {
172             throw new PublishException("Error validating user", e);
173         } catch (InvalidUserException e) {
174             throw new PublishException("Invalid User", e);
175         }
176         try {
177             xout = processXML(xml.getDocumentElement(), state);
178         } catch (PublishException e) {
179             m_logger.log(Level.SEVERE, "Template XML form for page id"
180                     + page.getId()
181                     + " was invalid,"
182                     + " unable to build any XML", e);
183             throw new RuntimeException JavaDoc(
184                 "Template XML form for page id"
185                     + page.getId()
186                     + " was invalid,"
187                     + " unable to build any XML");
188         }
189         return xout;
190     }
191
192     /**
193      * Processes the given <code>Element</code> in the context of the given <code>State</code>
194      * and returns the resultant <code>HarmoniseOutput</code>. The method
195      * parses the XML to find the instructions on what content to include in the
196      * resultant <code>HarmoniseOutput</code>. The <code>State</code>
197      * gives a context to the process.
198      *
199      * @param page
200      * @param state
201      * @return
202      * @throws PublishException
203      */

204     public HarmoniseOutput createXML(Element topEl, State state)
205         throws PublishException {
206         XMLDocument xdoc = null;
207         try {
208             XMLResource xml = new XMLResource();
209             m_xprinter.setNamespaceAware(true);
210             xml.setContent(m_xprinter.printNode(topEl));
211             xdoc = xml.getXIncludeResolvedDocument();
212         } catch (PopulateException e) {
213             throw new PublishException("Error populating xml resource", e);
214         } catch (NamespaceClashException e) {
215             throw new PublishException("Namespace error", e);
216         } catch (DataAccessException e) {
217             throw new PublishException("Data access error", e);
218         }
219
220         return processXML(xdoc.getDocumentElement(), state);
221     }
222
223     /**
224      * Processes the given <code>Element</code> in the context of the given <code>State</code>
225      * and returns the resultant <code>HarmoniseOutput</code>. The method parses the XML
226      * to find the instructions on what content to include in the resultant
227      * <code>HarmoniseOutput</code>. The <code>State</code> gives a context to the process.
228      *
229      * @param topEl
230      * @param state
231      * @return
232      * @throws PublishException
233      */

234     private HarmoniseOutput processXML(Element topEl, State state)
235         throws PublishException {
236         Element pageState;
237         HarmoniseOutput xOutput = new HarmoniseOutput(m_dsi);
238
239         Element tempPublishEl;
240         Element root;
241         root = xOutput.createElement(WebPage.TAG_HARMONISE);
242         xOutput.appendChild(root);
243
244         tempPublishEl = null;
245
246         pageState = xOutput.createElement(State.TAG_STATE);
247         root.appendChild(pageState);
248
249         pageState.appendChild(m_Session.publish(xOutput));
250
251         copyStateChildren((Node) pageState, state, xOutput);
252
253         NodeList children = topEl.getChildNodes();
254
255         for (int i = 0; i < children.getLength(); i++) {
256             if (children.item(i).getNodeType() != Node.ELEMENT_NODE) {
257                 continue;
258             }
259
260             Element next = (Element) children.item(i);
261             String JavaDoc sTagName = next.getTagName();
262
263             Vector JavaDoc ignore_tags = new Vector JavaDoc();
264
265             ignore_tags.add(WebPage.TAG_PAGETITLE);
266
267             try {
268                 if (sTagName.equals(WebPage.TAG_NAVIGATION)) {
269                     tempPublishEl = navigation(next, state, xOutput);
270                 } else if (sTagName.equals(Template.TAG_TEMPLATE)) {
271                     tempPublishEl = publishTemplate(next, state, xOutput);
272                 } else if (
273                     sTagName.equals(CommandProcessHandler.TAG_WORKFLOW)) {
274                     CommandProcessHandler cmdHandler =
275                         new CommandProcessHandler(m_dsi);
276
277                     tempPublishEl = cmdHandler.publish(next, xOutput, state);
278                 } else if (ignore_tags.contains(sTagName)) {
279                     tempPublishEl = (Element) xOutput.copyNode(next);
280                 } else {
281                     try {
282                         Publishable pubObj =
283                             HarmoniseObjectFactory.instantiatePublishableObject(
284                                 this.m_dsi,
285                                 next,
286                                 state);
287
288                         tempPublishEl = pubObj.publish(next, xOutput, state);
289                     } catch (HarmoniseFactoryException e) {
290                         tempPublishEl = (Element) xOutput.copyNode(next);
291                         root.appendChild(e.publish(xOutput));
292                         m_logger.log(Level.WARNING, e.getLocalizedMessage(), e);
293                     }
294                 }
295             } catch (PublishException e) {
296                 tempPublishEl = e.publish(xOutput);
297             }
298
299             if (tempPublishEl != null) {
300                 root.appendChild(tempPublishEl);
301             }
302
303         }
304
305         if (((Node) root).getChildNodes().getLength() == 0) {
306             throw new PublishException("Unable to publish Harmonise Page.");
307         }
308
309         return xOutput;
310     }
311
312     /* (non-Javadoc)
313      * @see java.lang.Object#toString()
314      */

315     public String JavaDoc toString() {
316         StringBuffer JavaDoc strbuf = new StringBuffer JavaDoc();
317
318         
319         strbuf.append("WepPageEngine Session details:").append(
320                 m_Session.toString());
321         
322
323         return strbuf.toString();
324     }
325
326     /**
327      * Renders page to <code>OutputStream</code> using the page's default renderer
328      *
329      * @param page
330      * @param state
331      * @param out
332      * @throws PublishException
333      * @throws RenderException
334      */

335     public void render(WebPage page, State state, OutputStream JavaDoc out)
336         throws PublishException, RenderException {
337         
338         if(m_logger.isLoggable(Level.FINE)) {
339             m_logger.logp(Level.FINE, this.getClass().getName(), "render", "Rendering page " + page.getId());
340         }
341         
342         XMLDocument xdoc = createXML(page, state);
343
344         try {
345             PageRenderer renderer =
346                 PageRendererFactory.getRenderer(page.getXSL().getOutputType());
347
348             renderer.render(xdoc, page.getXSL().getTemplates(), out);
349             logPublish(page, state);
350         } catch (DataAccessException e) {
351             throw new PublishException("Error occured accessing page data", e);
352         }
353     }
354
355     /**
356      * Renders page to <code>OutputStream</code> using the given renderer.
357      *
358      * @param page
359      * @param state
360      * @param renderer
361      * @param out
362      * @throws PublishException
363      * @throws RenderException
364      */

365     public void render(
366         WebPage page,
367         State state,
368         PageRenderer renderer,
369         OutputStream JavaDoc out)
370         throws PublishException, RenderException {
371         XMLDocument xdoc = createXML(page, state);
372
373         try {
374             renderer.render(xdoc, page.getXSL().getTemplates(), out);
375
376             logPublish(page, state);
377
378         } catch (DataAccessException e) {
379             throw new PublishException("Error occured accessing page data", e);
380         }
381     }
382
383     /*----------------------------------------------------------------------------
384     Protected Functions
385     -----------------------------------------------------------------------------*/

386
387     /**
388      * Logs the publishing of the given web page.
389      *
390      * @param page
391      * @param state
392      * @throws PublishException
393      */

394     protected void logPublish(WebPage page, State state)
395         throws PublishException {
396
397         try {
398             PublishLogEvent event = new PublishLogEvent();
399
400             event.setEventObject(page);
401             event.setState(state);
402
403             EventLogController.getInstance().logEvent(event);
404         } catch (PopulateException e) {
405             throw new PublishException("Error setting state of event", e);
406         } catch (LogException e) {
407             throw new PublishException("Error logging event", e);
408         }
409
410     }
411
412     /**
413      * Processes a 'Navigation' element, returning a new 'Navigation' element with
414      * the appropriate content.
415      *
416      * @param nav
417      * @param state
418      * @param output
419      * @return
420      * @throws PublishException
421      */

422     protected Element navigation(Element nav, State state, HarmoniseOutput output)
423         throws PublishException {
424         Element tempEl = null;
425
426         Element newNav = output.createElement(WebPage.TAG_NAVIGATION);
427
428         Element childNav = null;
429
430         NamedNodeMap navAttributes = nav.getAttributes();
431         Node navName = navAttributes.getNamedItem("name");
432
433         newNav.setAttribute("name", navName.getNodeValue());
434
435         Node navDescription = navAttributes.getNamedItem("description");
436
437         if (navDescription != null) {
438             newNav.setAttribute("description", navDescription.getNodeValue());
439         }
440
441         NodeList children = nav.getChildNodes();
442
443         for (int i = 0; i < children.getLength(); i++) {
444             if (children.item(i).getNodeType() != Node.ELEMENT_NODE) {
445                 continue;
446             }
447
448             Element next = (Element) children.item(i);
449
450             if (next.getTagName().equals(Template.TAG_TEMPLATE)) {
451
452                 tempEl = publishTemplate(next, state, output);
453
454                 if (tempEl != null) {
455                     newNav.appendChild(tempEl);
456                 }
457
458             } else if (next.getTagName().equals(WebPage.TAG_NAVIGATION)) {
459                 childNav = null;
460                 childNav = navigation(next, state, output);
461
462                 if (childNav != null) {
463                     newNav.appendChild(childNav);
464                 }
465             } else if (next.getTagName().equals(WebPage.TAG_ANCILLARY_TEXT)) {
466                 newNav.appendChild(output.copyNode(next));
467             } else if (next.getTagName().equals(AbstractObject.TAG_LINK)) {
468                 newNav.appendChild(output.copyNode(next));
469             } else {
470
471                 try {
472                     Publishable pubObj =
473                         HarmoniseObjectFactory.instantiatePublishableObject(
474                             this.m_dsi,
475                             next,
476                             state);
477
478                     newNav.appendChild(pubObj.publish(next, output, state));
479                 } catch (HarmoniseFactoryException e) {
480                     throw new PublishException(
481                         "Error instantiating object from factory",
482                         e);
483                 } catch (PublishException e) {
484                     newNav.appendChild(e.publish(output));
485                 }
486
487             }
488         }
489
490         return newNav;
491     }
492
493     /**
494      * Processes a 'Template' element, returning an element which is the result of the
495      * publishing the corresponding <code>Template</code> object.
496      *
497      * @param templateEl
498      * @param state
499      * @param output
500      * @return
501      * @throws PublishException
502      */

503     protected Element publishTemplate(
504         Element templateEl,
505         State state,
506         HarmoniseOutput output)
507         throws PublishException {
508         if (templateEl.getTagName().equalsIgnoreCase(Template.TAG_TEMPLATE)
509             == false) {
510             throw new InvalidXMLElementException("Template tag needed");
511         }
512
513         Element returnEl = null;
514         Template templ = null;
515         try {
516             templ = (Template) HarmoniseObjectFactory.instantiateHarmoniseObject(m_dsi, Template.class.getName(), Integer.parseInt(
517                 templateEl.getAttribute(AbstractObject.ATTRIB_ID)));
518         } catch (NumberFormatException JavaDoc e) {
519             throw new PublishException(e);
520         } catch (HarmoniseFactoryException e) {
521             throw new PublishException(e);
522         }
523         Element templRoot = null;
524         try {
525             templRoot = templ.getTemplateRootElement();
526         } catch (DataAccessException e) {
527             throw new PublishException(
528                 "Error occured getting template root",
529                 e);
530         }
531         NodeList templChildren = templateEl.getChildNodes();
532
533         int nPageId = -2;
534         NodeList pageNodes = templateEl.getElementsByTagName(WebPage.TAG_PAGE);
535
536         if (pageNodes.getLength() > 0) {
537             nPageId =
538                 Integer.parseInt(
539                     ((Element) pageNodes.item(0)).getAttribute(
540                         AbstractObject.ATTRIB_ID));
541         }
542
543         for (int i = 0; i < templChildren.getLength(); i++) {
544             if (templChildren.item(i).getNodeType() == Node.ELEMENT_NODE) {
545                 Element child = (Element) templChildren.item(i);
546
547                 if (templRoot
548                     .getTagName()
549                     .equalsIgnoreCase(child.getTagName())) {
550
551                     Publishable pubObj = null;
552                     try {
553                         pubObj =
554                             HarmoniseObjectFactory.instantiatePublishableObject(
555                                 this.m_dsi,
556                                 child,
557                                 state);
558                     } catch (HarmoniseFactoryException e) {
559                         throw new PublishException(
560                             "Error occured getting object from factory",
561                             e);
562                     }
563
564                     if (pubObj != null) {
565                         returnEl =
566                             templ.publishObjectToElement(pubObj, output, state);
567
568                         String JavaDoc sStateId =
569                             child.getAttribute(State.ATTRIB_STATE_ID);
570
571                         if ((sStateId != null) && (sStateId.length() > 0)) {
572                             returnEl.setAttribute(
573                                 State.ATTRIB_STATE_ID,
574                                 sStateId);
575                         }
576
577                         output.addPageIdToLinkNode(
578                             state.getLoggedInUser(),
579                             returnEl,
580                             nPageId);
581                     }
582
583                 }
584             }
585         }
586
587         return returnEl;
588     }
589
590     /**
591      * Copies the children of the given <code>State</code>, ignoring any Session tags,
592      * to the <code>Node</code> appendTo.
593      *
594      * @param appendTo
595      * @param state
596      * @param output
597      */

598     protected void copyStateChildren(
599         Node appendTo,
600         State state,
601         HarmoniseOutput output) {
602         Node stateRoot = state.getDocumentElement();
603         NodeList stateElements = stateRoot.getChildNodes();
604
605         for (int i = 0; i < stateElements.getLength(); i++) {
606
607             if ((stateElements.item(i).getNodeType() == Node.ELEMENT_NODE)
608                 && (((Element) stateElements.item(i))
609                     .getTagName()
610                     .equals(Session.TAG_SESSION))) {
611                 continue;
612             }
613
614             appendTo.appendChild(output.copyNode(stateElements.item(i)));
615         }
616     }
617
618     /**
619      * Assign the session id associated with this object to the
620      * given <code>State</code>.
621      *
622      * @param state the state to be assigned the session id
623      */

624     public void assignSessionId(State state) {
625         String JavaDoc sSessionId = m_Session.getSessionId();
626         
627         state.setSessionId(sSessionId);
628     }
629
630 }
Popular Tags