001 /*
002 *
003 * $Revision: 15202 $ $Date: 2009-05-15 17:00:44 +0200 (Fri, 15 May 2009) $
004 *
005 * This file is part of *** M y C o R e ***
006 * See http://www.mycore.de/ for details.
007 *
008 * This program is free software; you can use it, redistribute it
009 * and / or modify it under the terms of the GNU General Public License
010 * (GPL) as published by the Free Software Foundation; either version 2
011 * of the License or (at your option) any later version.
012 *
013 * This program is distributed in the hope that it will be useful, but
014 * WITHOUT ANY WARRANTY; without even the implied warranty of
015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
016 * GNU General Public License for more details.
017 *
018 * You should have received a copy of the GNU General Public License
019 * along with this program, in a file called gpl.txt or license.txt.
020 * If not, write to the Free Software Foundation Inc.,
021 * 59 Temple Place - Suite 330, Boston, MA 02111-1307 USA
022 */
023
024 package org.mycore.frontend.wcms;
025
026 import java.io.BufferedReader;
027 import java.io.File;
028 import java.io.FileNotFoundException;
029 import java.io.FileReader;
030 import java.io.IOException;
031 import java.io.PrintWriter;
032 import java.io.StringWriter;
033 import java.util.Iterator;
034 import java.util.List;
035 import java.util.ListIterator;
036 import java.util.Vector;
037
038 import javax.servlet.http.HttpServletRequest;
039 import javax.servlet.http.HttpServletResponse;
040
041 import org.jdom.Comment;
042 import org.jdom.Document;
043 import org.jdom.Element;
044 import org.jdom.JDOMException;
045 import org.jdom.Namespace;
046 import org.jdom.Text;
047 import org.jdom.input.SAXBuilder;
048 import org.jdom.output.Format;
049 import org.jdom.output.XMLOutputter;
050 import org.mycore.common.MCRConfiguration;
051 import org.mycore.common.MCRSession;
052 import org.mycore.common.MCRSessionMgr;
053
054 /**
055 * Select action process for Web-Content-Management-System (WCMS).
056 */
057 public class MCRWCMSChooseServlet extends MCRWCMSServlet {
058
059 private static final long serialVersionUID = 1L;
060
061 private Namespace ns = Namespace.XML_NAMESPACE; // xml Namespace for the
062
063 // language attribute lang
064 private String currentLang = null; //
065
066 private String defaultLang = null; //
067
068 private String contentError = null;
069
070 private String href = null; // representing the href(dir) attribute of the
071
072 // selected element in the navigation.xml
073 // e.g. type="extern" --> href="http://www.db-thueringen.de" ||
074 // type="intern" --> href="/content/main/information/description.xml" ||
075 // dir != null --> href=dir(e.g. href="/main")
076 private String action = null; // selected action:{add, edit, delete}
077
078 private String mode = null; // if (action.equals(edit) mode = mode from
079
080 // selected element:{intern, extern}
081 // else mode=moda
082 private String moda = null; // mode dependent from selected action:{intern,
083
084 // extern}
085 private String label = null; // representing the label(name) of the
086
087 // selected
088
089 // link
090 private String label_currentLang = null; // representing the translated
091
092 // label(name) of the selected link
093 private String target = null; // target of the selected element: {_blank,
094
095 // _self}
096 private String template = null; // choosen Template
097
098 private String style = null; // style of the selected element: {bold, normal}
099
100 // have a valid dir attribute instead of a href
101 // attribute
102 private String addAtPosition = null; // position, where a link can be
103
104 // added:
105
106 // {predecessor, successor, child}
107 private String replaceMenu = null; // Representing a Parameter, allowing an
108
109 // navigation element to replace the
110 // previous navigation structure only
111 // with its subelements. Can be "true" or
112 // "false".
113 private String constrainPopUp = null; // menu must be open
114
115 char c; // representing the errorcodes {1,2,5,6,7,8,9,0}
116
117 char d; // representing the errorcodes {1,2,5,6,7,8,9,0}
118
119 char fs = File.separatorChar;
120
121 boolean validXHTML = true;
122
123 List contentList;
124
125 List defaultLangContentOutput;
126
127 List currentLangContentOutput;
128
129 /**
130 * Main program called by doGet and doPost.
131 */
132 protected void processRequest(HttpServletRequest request, HttpServletResponse response) throws IOException {
133
134 MCRSession mcrSession = MCRSessionMgr.getCurrentSession();
135 String userID = (String) mcrSession.get("userID");
136 String userClass = (String) mcrSession.get("userClass");
137 List rootNodes = (List) mcrSession.get("rootNodes");
138 addAtPosition = request.getParameter("addAtPosition");
139
140 if (request.getParameter("action") != null) {
141 action = request.getParameter("action");
142 } else {
143 action = "false";
144 }
145
146 File[] contentTemplates = new File(MCRConfiguration.instance().getString("MCR.templatePath") + "content/".replace('/', File.separatorChar)).listFiles();
147 File[] masterTemplates = new File(MCRConfiguration.instance().getString("MCR.templatePath") + "master/".replace('/', File.separatorChar)).listFiles();
148 template = request.getParameter("template");
149
150 File conTemp = new File(MCRConfiguration.instance().getString("MCR.templatePath") + "content/".replace('/', File.separatorChar));
151 Element templates = new Element("templates");
152 defaultLangContentOutput = null;
153 currentLangContentOutput = null;
154 contentError = null;
155
156 /* get languages */
157 if (mcrSession != null) {
158 defaultLang = MCRConfiguration.instance().getString("MCR.Metadata.DefaultLang", "en").toLowerCase();
159 currentLang = mcrSession.getCurrentLanguage().toLowerCase();
160 }
161
162 /*
163 * System.err.println("defaultLang"+defaultLang+"..."); System.err.println("currentLang"+currentLang+"...");
164 */
165
166 /**
167 * If action parameter contains a character '_' (e.g.: add_intern, add_extern) then split action in action (e.g.: add) and mode (e.g.: intern)
168 */
169 if ((action != null) && (action.indexOf('_') != -1)) {
170 moda = action.substring(action.indexOf('_') + 1);
171 action = action.substring(0, action.indexOf('_'));
172 }
173
174 if (action.equals("false")) {
175 contentError = "Error: Please select an action to be done.";
176 }
177
178 /**
179 * Split href parameter (e.g.: 1/content/top/index.xml) in character c and href for identifying the selected element in the navigation.xml and checking
180 * the selected action Transfered characters are: --- valid values ------------------------------------------------------------------------ '1' - if the
181 * selected element has a valid href attribute. '2' - if the selected element was a main element (e.g.: "Men? oberhalb", "Men? links" and "Zusatzmen?
182 * links unten") and has a valid dir attribute instead of a valid href attribute. --- invalid values
183 * ---------------------------------------------------------------------- '5' - if the selected element is a main navigation element like "Men? links"
184 * and addAtPosition is "predecessor" or "successor". '6' - if the selected element has an external target and action was add. This is to avoid the
185 * creation of a child under a parent with external target because it can not reached via navigation tree. '7' - if the selected element has child(s)
186 * and action was delete. Thus, an element with active childs can not be deleted. Deleting elements with active childs is only possible when deleting
187 * all childs first. '8' - if the selected element has childs but is not nested within a rootNode. This occurs only on restricted users trying to edit
188 * such an element. '9' - if a place holder was selected. '0' - if nothing was selected.
189 */
190 if (request.getParameter("href") != null) {
191 href = request.getParameter("href").substring(1);
192 c = d = request.getParameter("href").charAt(0);
193 } else {
194 c = d = '0';
195 }
196
197 if (c == '2') {
198 mcrSession.put("dir", href);
199 } else {
200 mcrSession.put("dir", "false");
201 }
202
203 /**
204 * Build jdom object dependence on the selected action and selected element.
205 */
206 Element rootOut = new Element("cms");
207 Document jdom = new Document(rootOut);
208
209 /**
210 * Try to build a jdom Object from the content of the navigation.xml.
211 */
212 try {
213 SAXBuilder builder = new SAXBuilder();
214 Document doc = builder.build(MCRConfiguration.instance().getString("MCR.navigationFile").replace('/', File.separatorChar));
215 Element root = doc.getRootElement();
216 validate(root);
217 } catch (JDOMException jdome) {
218 PrintWriter errorOut = response.getWriter();
219 errorOut.println(jdome.getMessage());
220 errorOut.close();
221 }
222
223 /**
224 * Try to build a jdom Object from the content (this has to be valid XHTML content) of the file to be edited. The path of this file is build from the
225 * webapp dir and the href parameter of the selected element found in the navigation.xml.
226 */
227 if ((action.equals("edit") && (c == '1')) || action.equals("add") || (action.equals("translate") && (c == '1'))) {
228 defaultLangContentOutput = new Vector();
229 currentLangContentOutput = new Vector();
230
231 try {
232 SAXBuilder sax = new SAXBuilder();
233 Document ed;
234
235 if (!action.equals("add") && mode.equals("intern")) {
236 ed = sax.build(getServletContext().getRealPath("") + fs + href);
237 } else {
238 // if (mode.equals("intern")) {
239 String edFiller = (MCRConfiguration.instance().getString("MCR.templatePath") + "content/").replace('/', File.separatorChar) + template;
240 ed = sax.build(edFiller);
241 System.out.println(edFiller);
242 // }
243 // else return;
244 }
245
246 Element begin = ed.getRootElement();
247 List contentElements = begin.getChildren("section");
248 Iterator contentElementsIterator = contentElements.iterator();
249
250 while (contentElementsIterator.hasNext()) {
251 Element content = (Element) contentElementsIterator.next();
252
253 if (content.getAttributeValue("lang", ns) != null) {
254 contentList = content.getContent();
255 validXHTML = true;
256
257 if (content.getAttributeValue("lang", ns).equals(defaultLang)) {
258 for (int i = (contentList.size() - 1); i >= 0; i--) {
259 Object o = contentList.get(i);
260
261 // String u = null;
262 if (o instanceof Element) {
263 ((Element) o).detach();
264 }
265
266 if (o instanceof Text) {
267 ((Text) o).detach();
268 }
269
270 if (o instanceof Comment) {
271 ((Comment) o).detach();
272 }
273
274 defaultLangContentOutput.add(o);
275 }
276 reverse(defaultLangContentOutput);
277 }
278
279 if (content.getAttributeValue("lang", ns).equals(currentLang) && action.equals("translate")) {
280 for (int i = (contentList.size() - 1); i >= 0; i--) {
281 Object o = contentList.get(i);
282 // String u = null;
283 if (o instanceof Element) {
284 ((Element) o).detach();
285 }
286 if (o instanceof Text) {
287 ((Text) o).detach();
288 }
289 if (o instanceof Comment) {
290 ((Comment) o).detach();
291 }
292 currentLangContentOutput.add(o);
293 }
294 reverse(currentLangContentOutput);
295 }
296 }
297 contentList.clear();
298 }
299 } catch (JDOMException je) {
300 try {
301 if (!mode.equals("extern")) {
302 // "Error: " + getServletContext().getRealPath("") + href.replace('/', File.separatorChar) + " is no valid XHTML file.";
303
304 File hrefFile = new File(getServletContext().getRealPath("") + href);
305 BufferedReader br = new BufferedReader(new FileReader(hrefFile));
306
307 validXHTML = false;
308
309 String str;
310 String stri = "";
311
312 while (true) {
313 if ((str = br.readLine()) != null) {
314 stri = stri.concat(str + '\n');
315 } else {
316 break;
317 }
318 }
319
320 br.close();
321
322 int begin = stri.indexOf("<section");
323 String wow = stri.substring(begin, stri.indexOf("</section>"));
324 String strin = stri.substring(begin + wow.indexOf('>') + 2, stri.indexOf("</section>"));
325 defaultLangContentOutput.add(strin);
326 }
327 } catch (FileNotFoundException fne) {
328 // System.out.println(fne);
329 }
330 }
331 }
332
333 /*
334 * catch (JDOMException je) { if (output != null) { output.clear(); output.add("File konnte nicht geparst werden."); } }
335 */
336 if (action.equals("edit") && (c == '2')) {
337 c = '8';
338 }
339
340 if (action.equals("delete") && (c == '2')) {
341 c = '7';
342 }
343
344 /**
345 * If character c consist an invalid value (5, 6, 7, 8, 9, 0) then print out the corresponding error and restart the WCMSChooseServlet (both things will
346 * be done by the belonging stylesheet). Output: <cms> <session>choose </session> <error>5|6|7|8|9|0 </error> <rootNode href="no"|"yes">rootNode
347 * </rootNode>{0,*} <templates><content> <template>$template </template>{0,*} </content> </templates> </cms>
348 */
349 if (((c != '1') && (c != '2')) || (contentError != null)) {
350 rootOut.addContent(new Element("session").setText("choose"));
351
352 if ((c != '1') && (c != '2')) {
353 rootOut.addContent(new Element("error").setText(String.valueOf(c)));
354 } else {
355 rootOut.addContent(new Element("contentError").setAttribute("msg", contentError).setText("yes"));
356 }
357
358 Iterator rootNodesIterator = rootNodes.iterator();
359
360 while (rootNodesIterator.hasNext()) {
361 Element rootNode = (Element) rootNodesIterator.next();
362 rootOut.addContent(new Element("rootNode").setAttribute("href", rootNode.getAttributeValue("href")).setText(rootNode.getTextTrim()));
363 }
364
365 Element contentTemp = new Element("content");
366
367 for (int i = 0; i < contentTemplates.length; i++) {
368 if (!contentTemplates[i].isDirectory()) {
369 contentTemp.addContent(new Element("template").setText(contentTemplates[i].getName()));
370 }
371 }
372
373 templates.addContent(contentTemp);
374 rootOut.addContent(templates);
375 }
376 /**
377 * Else output: <cms><session>action </session> <userName>uid </userName> <userClass>admin|editor|autor </userClass> <action
378 * mode="intern"|"extern">add|edit|delete </action> <addAtPosition>predecessor|successor|child </addAtPosition> <-- only at action add <href>href
379 * </href> <label>label </label> <target>_blank|_self </target> <style>normal|bold </style> <content>output </content> <-- only at action edit and add
380 * <images>$imagePath </images>{0,*} <documents>$documentPath </documents>{0,*} <templates><master><template>$template </template>{0,*} </master>
381 * <content><template>conTemp </template> </content> </templates> </cms>
382 */
383 else {
384 rootOut.addContent(new Element("session").setText("action"));
385 }
386
387 rootOut.addContent(new Element("userID").setText(userID));
388 rootOut.addContent(new Element("userClass").setText(userClass));
389
390 if (action.equals("add") && (mode != null)) {
391 mode = moda;
392 rootOut.addContent(new Element("action").setAttribute("mode", mode).setText(action));
393 rootOut.addContent(new Element("addAtPosition").setText(addAtPosition));
394 rootOut.addContent(new Element("replaceMenu").setText(replaceMenu));
395 }
396
397 if (action.equals("edit") && (mode != null)) {
398 rootOut.addContent(new Element("action").setAttribute("mode", mode).setText(action));
399
400 if (mode.equals("intern")) {
401 rootOut.addContent(new Element("replaceMenu").setText(replaceMenu));
402 }
403
404 rootOut.addContent(new Element("constrainPopUp").setText(constrainPopUp));
405 }
406
407 if (action.equals("delete") && (mode != null)) {
408 rootOut.addContent(new Element("action").setAttribute("mode", mode).setText(action));
409 }
410
411 if (action.equals("translate") && (mode != null)) {
412 rootOut.addContent(new Element("action").setAttribute("mode", mode).setText(action));
413 rootOut.addContent(new Element("label_currentLang").setText(label_currentLang));
414 }
415
416 rootOut.addContent(new Element("href").setText(href));
417 rootOut.addContent(new Element("label").setText(label));
418 rootOut.addContent(new Element("target").setText(target));
419 rootOut.addContent(new Element("style").setText(style));
420
421 if (defaultLangContentOutput != null) {
422 try {
423 if (validXHTML) {
424 /*
425 * String test = ""; Element elem = null; for ( int i=0; i <output.size(); i++ ) { elem = (Element)output.get(i); test += elem.getText(); }
426 * System.out.println(test);
427 */
428 StringWriter sw = new StringWriter();
429 XMLOutputter contentOut = new XMLOutputter(Format.getRawFormat().setTextMode(Format.TextMode.PRESERVE).setEncoding(OUTPUT_ENCODING));
430
431 // 1.Method: rootOut.addContent(new
432 // Element("content").setText(contentOut.output(defaultLangContentOutput,
433 // contentOut)));
434 contentOut.output(defaultLangContentOutput, sw);
435
436 // System.out.println("testoutput: "+sw.toString());
437 rootOut.addContent(new Element("content").setText(sw.toString()));
438 sw.flush();
439 sw.close();
440
441 if (action.equals("translate") && (currentLangContentOutput != null)) {
442 // rootOut.addContent(new
443 // Element("content_currentLang").setText(contentOut.outputString(currentLangContentOutput)));
444 contentOut.output(currentLangContentOutput, sw);
445
446 rootOut.addContent(new Element("content_currentLang").setText(sw.toString()));
447 sw.flush();
448 sw.close();
449 }
450 } else {
451 rootOut.addContent(new Element("content").setText((String) defaultLangContentOutput.get(0)));
452 rootOut.addContent(new Element("error").setText("invalidXHTML"));
453 }
454 } catch (Exception e) {
455 e.printStackTrace();
456 }
457 }
458
459 templates = getMultimediaConfig(rootOut);
460
461 Element master = new Element("master");
462
463 for (int i = 0; i < masterTemplates.length; i++) {
464 if (masterTemplates[i].isDirectory() && (masterTemplates[i].getName().compareToIgnoreCase("cvs") != 0)) {
465 master.addContent(new Element("template").setText(masterTemplates[i].getName()));
466 }
467 }
468
469 Element content = new Element("content");
470 content.addContent(new Element("template").setText(conTemp.toString()));
471 templates.addContent(master);
472 templates.addContent(content);
473 rootOut.addContent(templates);
474
475 /**
476 * and add some further attributes to the session object: --- allready existing --------------------------------- <session ... uid=uid
477 * userClass="admin"|"editor"|"autor" rootNodes=rootNodes ... --- new attributes ------------------------------------ ... href=href label=label
478 * action="add"|"edit"|"delete" mode="intern"|"extern" ... ... target="intern"|"extern" style="normal"|"bold" />
479 */
480 if (href != null) {
481 mcrSession.put("href", href);
482 }
483
484 if (label != null) {
485 mcrSession.put("label", label);
486 }
487
488 if (label_currentLang != null) {
489 mcrSession.put("label_currentLang", label_currentLang);
490 }
491
492 if (action != null) {
493 mcrSession.put("action", action);
494 }
495
496 if (mode != null) {
497 mcrSession.put("mode", mode);
498 }
499
500 if (target != null) {
501 mcrSession.put("target", target);
502 }
503
504 if (style != null) {
505 mcrSession.put("style", style);
506 }
507
508 if (defaultLang != null) {
509 mcrSession.put("defaultLang", defaultLang);
510 }
511
512 if (currentLang != null) {
513 mcrSession.put("currentLang", currentLang);
514 }
515
516 if (addAtPosition != null) {
517 mcrSession.put("addAtPosition", addAtPosition);
518 }
519
520 getLayoutService().doLayout(request, response, jdom);
521 }
522
523 /**
524 * Finds the selected element in the navigation.xml and assigns attribute values for the variables of the jdom object and setting character c respectively.
525 */
526 public void validate(Element element) {
527 List elements = element.getChildren();
528 Iterator elementIterator = elements.iterator();
529
530 while (elementIterator.hasNext()) {
531 Element child = (Element) elementIterator.next();
532
533 if (child.getAttribute("href") != null) {
534 if (child.getAttributeValue("href").equals(href)) {
535 if (action.equals("delete") && !child.getChildren("item").isEmpty()) {
536 c = '7';
537 }
538
539 else if (action.equals("add") && child.getAttributeValue("type").equals("extern") && addAtPosition.equals("child"))
540 c = '6';
541
542 else {
543 c = d;
544 }
545
546 if (child.getAttributeValue("type") != null) {
547 mode = child.getAttributeValue("type");
548 }
549
550 if ((getLabel(child, defaultLang) != null) && !getLabel(child, defaultLang).equals("")) {
551 label = getLabel(child, defaultLang);
552 }
553
554 if ((getLabel(child, currentLang) != null) && !getLabel(child, currentLang).equals("")) {
555 label_currentLang = getLabel(child, currentLang);
556 }
557
558 if (child.getAttributeValue("target") != null) {
559 target = child.getAttributeValue("target");
560 }
561
562 if (child.getAttributeValue("style") != null) {
563 style = child.getAttributeValue("style");
564 }
565
566 if (child.getAttributeValue("replaceMenu") != null) {
567 replaceMenu = child.getAttributeValue("replaceMenu");
568 }
569
570 if (child.getAttributeValue("constrainPopUp") != null) {
571 constrainPopUp = child.getAttributeValue("constrainPopUp");
572 } else {
573 replaceMenu = "false";
574 }
575
576 return;
577 }
578 }
579
580 if (child.getAttributeValue("dir") != null) {
581 if (child.getAttributeValue("dir").equals(href)) {
582 href = ((Element) child.getParent()).getAttributeValue("dir") + href;
583 mode = moda;
584
585 if (action.equals("delete") && !child.getChildren("item").isEmpty()) {
586 c = '7';
587 } else {
588 c = d;
589 }
590
591 if (action.equals("add") && !addAtPosition.equals("child")) {
592 c = '5';
593 }
594
595 return;
596 }
597 }
598
599 validate(child);
600 }
601 }
602
603 /**
604 * Finds the right label
605 */
606 public String getLabel(Element element, String language) {
607 List elements = element.getChildren("label");
608 Iterator elementIterator = elements.iterator();
609 String labelReturn = null;
610
611 while (elementIterator.hasNext()) {
612 Element child = (Element) elementIterator.next();
613
614 if (child.getAttribute("lang", ns) != null) {
615 if (child.getAttributeValue("lang", ns).equals(language)) {
616 if (child.getText() != null) {
617 labelReturn = child.getTextTrim();
618 }
619 }
620 }
621
622 getLabel(child, language);
623 }
624
625 return labelReturn;
626 }
627
628 public void reverse(List l) {
629 ListIterator fwd = l.listIterator();
630 ListIterator rev = l.listIterator(l.size());
631
632 for (int i = 0, n = l.size() / 2; i < n; i++) {
633 Object tmp = fwd.next();
634 fwd.set(rev.previous());
635 rev.set(tmp);
636 }
637 }
638 }