View Javadoc
1   /*
2    * This file is part of ***  M y C o R e  ***
3    * See http://www.mycore.de/ for details.
4    *
5    * MyCoRe is free software: you can redistribute it and/or modify
6    * it under the terms of the GNU General Public License as published by
7    * the Free Software Foundation, either version 3 of the License, or
8    * (at your option) any later version.
9    *
10   * MyCoRe is distributed in the hope that it will be useful,
11   * but WITHOUT ANY WARRANTY; without even the implied warranty of
12   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13   * GNU General Public License for more details.
14   *
15   * You should have received a copy of the GNU General Public License
16   * along with MyCoRe.  If not, see <http://www.gnu.org/licenses/>.
17   */
18  
19  package org.mycore.frontend.xeditor;
20  
21  import java.io.IOException;
22  import java.util.Collections;
23  import java.util.HashMap;
24  import java.util.Iterator;
25  import java.util.Map;
26  import java.util.Map.Entry;
27  import java.util.regex.Matcher;
28  import java.util.regex.Pattern;
29  
30  import javax.xml.transform.TransformerException;
31  
32  import org.apache.logging.log4j.LogManager;
33  import org.apache.logging.log4j.Logger;
34  import org.jdom2.Document;
35  import org.jdom2.Element;
36  import org.jdom2.JDOMException;
37  import org.jdom2.Namespace;
38  import org.jdom2.Verifier;
39  import org.mycore.common.MCRConstants;
40  import org.mycore.common.config.MCRConfiguration;
41  import org.mycore.common.content.MCRSourceContent;
42  import org.mycore.common.xsl.MCRParameterCollector;
43  import org.mycore.frontend.xeditor.tracker.MCRBreakpoint;
44  import org.mycore.frontend.xeditor.tracker.MCRChangeTracker;
45  import org.mycore.frontend.xeditor.validation.MCRXEditorValidator;
46  import org.xml.sax.SAXException;
47  
48  /**
49   * @author Frank L\u00FCtzenkirchen
50   */
51  public class MCREditorSession {
52  
53      private static final Logger LOGGER = LogManager.getLogger(MCREditorSession.class);
54  
55      private static final Pattern PATTERN_URI = Pattern.compile("\\{\\$([^\\}]+)\\}");
56  
57      private String id;
58  
59      private String url;
60  
61      private Map<String, String[]> requestParameters = new HashMap<>();
62  
63      private Map<String, Object> variables;
64  
65      private String cancelURL;
66  
67      private Document editedXML;
68  
69      private MCRChangeTrackerChangeTracker.html#MCRChangeTracker">MCRChangeTracker tracker = new MCRChangeTracker();
70  
71      private MCREditorSubmissionon.html#MCREditorSubmission">MCREditorSubmission submission = new MCREditorSubmission(this);
72  
73      private MCRXEditorValidatorditorValidator.html#MCRXEditorValidator">MCRXEditorValidator validator = new MCRXEditorValidator(this);
74  
75      private MCRXMLCleanereaner.html#MCRXMLCleaner">MCRXMLCleaner cleaner = new MCRXMLCleaner();
76  
77      private MCRXEditorPostProcessor postProcessor = getDefaultPostProcessorImplementation();
78  
79      private static MCRPostProcessorXSL getDefaultPostProcessorImplementation() {
80          return MCRConfiguration.instance().getInstanceOf("MCR.XEditor.PostProcessor.Default");
81      }
82  
83      public MCREditorSession(Map<String, String[]> requestParameters, MCRParameterCollector collector) {
84          this.requestParameters.putAll(requestParameters); // make a copy, the original may be re-used by servlet container
85          this.variables = new HashMap<>(collector.getParameterMap());
86          removeIllegalVariables();
87      }
88  
89      public MCREditorSession() {
90          this(Collections.emptyMap(), new MCRParameterCollector());
91      }
92  
93      public Map<String, Object> getVariables() {
94          return variables;
95      }
96  
97      private void removeIllegalVariables() {
98          for (Iterator<Entry<String, Object>> entries = variables.entrySet().iterator(); entries.hasNext();) {
99              String name = entries.next().getKey();
100             String result = Verifier.checkXMLName(name);
101             if (result != null) {
102                 LOGGER.warn("Illegally named transformation parameter, removing {}", name);
103                 entries.remove();
104             }
105         }
106     }
107 
108     public void setID(String id) {
109         this.id = id;
110     }
111 
112     public String getID() {
113         return id;
114     }
115 
116     public String getCombinedSessionStepID() {
117         return id + "-" + tracker.getChangeCounter();
118     }
119 
120     public void setPageURL(String pageURL) {
121         if (url == null) {
122             this.url = pageURL.contains("?") ? pageURL.substring(0, pageURL.indexOf("?")) : pageURL;
123             LOGGER.debug("Editor page URL set to {}", this.url);
124         }
125     }
126 
127     public String getPageURL() {
128         return this.url;
129     }
130 
131     public String getRedirectURL(String anchor) {
132         return url + "?" + MCREditorSessionStore.XEDITOR_SESSION_PARAM + "=" + id
133             + (anchor != null ? "#" + anchor : "");
134     }
135 
136     public Map<String, String[]> getRequestParameters() {
137         return requestParameters;
138     }
139 
140     public String getCancelURL() {
141         return cancelURL;
142     }
143 
144     public void setCancelURL(String cancelURL) {
145         if (this.cancelURL != null)
146             return;
147 
148         cancelURL = replaceParameters(cancelURL);
149         if (!cancelURL.contains("{")) {
150             LOGGER.debug("{} set cancel URL to {}", id, cancelURL);
151             this.cancelURL = cancelURL;
152         }
153     }
154 
155     public String replaceParameters(String uri) {
156         Matcher m = PATTERN_URI.matcher(uri);
157         StringBuffer sb = new StringBuffer();
158         while (m.find()) {
159             String token = m.group(1);
160             Object value = variables.get(token);
161             m.appendReplacement(sb, value == null ? m.group().replace("$", "\\$") : value.toString());
162         }
163         m.appendTail(sb);
164         return sb.toString();
165     }
166 
167     public Document getEditedXML() {
168         return editedXML;
169     }
170 
171     public void setEditedXML(Document editedXML) throws JDOMException {
172         this.editedXML = editedXML;
173         addNamespacesFrom(editedXML.getRootElement());
174     }
175 
176     private void addNamespacesFrom(Element element) {
177         MCRConstants.registerNamespace(element.getNamespace());
178         for (Namespace ns : element.getAdditionalNamespaces()) {
179             MCRConstants.registerNamespace(ns);
180         }
181         for (Element child : element.getChildren())
182             addNamespacesFrom(child);
183     }
184 
185     public void setEditedXML(String uri) throws JDOMException, IOException, SAXException, TransformerException {
186         if ((editedXML != null) || (uri = replaceParameters(uri)).contains("{"))
187             return;
188 
189         LOGGER.info("Reading edited XML from {}", uri);
190         Document xml = MCRSourceContent.getInstance(uri).asXML();
191         setEditedXML(xml);
192         setBreakpoint("Reading XML from " + uri);
193     }
194 
195     public MCRBinding getRootBinding() throws JDOMException {
196         MCRBindingnding.html#MCRBinding">MCRBinding binding = new MCRBinding(editedXML, tracker);
197         binding.setVariables(variables);
198         return binding;
199     }
200 
201     public void setBreakpoint(String msg) {
202         if (editedXML != null)
203             tracker.track(MCRBreakpoint.setBreakpoint(editedXML.getRootElement(), msg));
204     }
205 
206     public MCRChangeTracker getChangeTracker() {
207         return tracker;
208     }
209 
210     public MCREditorSubmission getSubmission() {
211         return submission;
212     }
213 
214     public MCRXEditorValidator getValidator() {
215         return validator;
216     }
217 
218     public MCRXMLCleaner getXMLCleaner() {
219         return cleaner;
220     }
221 
222     public MCRXEditorPostProcessor getPostProcessor() {
223         return postProcessor;
224     }
225 
226     protected void setPostProcessor(MCRXEditorPostProcessor postProcessor) {
227         this.postProcessor = postProcessor;
228     }
229 }