001    /*
002     * 
003     * $Revision: 15272 $ $Date: 2009-05-26 12:37:41 +0200 (Tue, 26 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.servlets;
025    
026    import java.io.File;
027    import java.io.FileOutputStream;
028    import java.io.IOException;
029    import java.io.InputStream;
030    import java.io.PrintWriter;
031    import java.io.StringWriter;
032    import java.net.URL;
033    import java.util.ArrayList;
034    import java.util.List;
035    
036    import javax.servlet.http.HttpSession;
037    
038    import org.apache.log4j.Level;
039    import org.apache.log4j.Logger;
040    import org.jdom.Document;
041    import org.jdom.Element;
042    import org.mycore.common.MCRConfiguration;
043    import org.mycore.common.MCRConfigurationException;
044    import org.mycore.common.MCRException;
045    import org.mycore.common.MCRSession;
046    import org.mycore.common.MCRSessionMgr;
047    import org.mycore.common.MCRUtils;
048    import org.mycore.datamodel.metadata.MCRObjectID;
049    import org.mycore.datamodel.metadata.validator.MCREditorOutValidator;
050    import org.mycore.frontend.editor.MCREditorSubmission;
051    import org.mycore.frontend.editor.MCRRequestParameters;
052    import org.mycore.frontend.workflow.MCRSimpleWorkflowManager;
053    
054    /**
055     * This class is the superclass of servlets which checks the MCREditorServlet
056     * output XML and store the XML in a file or if an error was occured start the
057     * editor again.
058     * 
059     * @author Jens Kupferschmidt
060     * @author Thomas Scheffler (yagee)
061     * @version $Revision: 15272 $ $Date: 2009-05-26 12:37:41 +0200 (Tue, 26 May 2009) $
062     */
063    abstract public class MCRCheckDataBase extends MCRCheckBase {
064        private static final long serialVersionUID = 8744330302159842747L;
065    
066        private static Logger LOGGER = Logger.getLogger(MCRCheckDataBase.class);
067    
068        /**
069          * This method overrides doGetPost of MCRServlet. <br />
070          */
071        public void doGetPost(MCRServletJob job) throws Exception {
072            // read the XML data
073            MCREditorSubmission sub = (MCREditorSubmission) (job.getRequest().getAttribute("MCREditorSubmission"));
074            org.jdom.Document indoc = sub.getXML();
075    
076            // read the parameter
077            MCRRequestParameters parms;
078    
079            if (sub == null) {
080                parms = new MCRRequestParameters(job.getRequest());
081            } else {
082                parms = sub.getParameters();
083            }
084    
085            String oldmcrid = parms.getParameter("mcrid");
086            String oldtype = parms.getParameter("type");
087            String oldstep = parms.getParameter("step");
088            LOGGER.debug("XSL.target.param.0 = " + oldmcrid);
089            LOGGER.debug("XSL.target.param.1 = " + oldtype);
090            LOGGER.debug("XSL.target.param.2 = " + oldstep);
091    
092            // get the MCRSession object for the current thread from the session
093            // manager.
094            MCRSession mcrSession = MCRSessionMgr.getCurrentSession();
095            String lang = mcrSession.getCurrentLanguage();
096            LOGGER.info("LANG = " + lang);
097    
098            // prepare the MCRObjectID's for the Metadata
099            String mmcrid = "";
100            boolean hasid = false;
101    
102            try {
103                mmcrid = indoc.getRootElement().getAttributeValue("ID");
104    
105                if (mmcrid == null) {
106                    mmcrid = oldmcrid;
107                } else {
108                    hasid = true;
109                }
110            } catch (Exception e) {
111                mmcrid = oldmcrid;
112            }
113    
114            MCRObjectID ID = new MCRObjectID(mmcrid);
115    
116            if (!ID.getTypeId().equals(oldtype)) {
117                ID = new MCRObjectID(oldmcrid);
118                hasid = false;
119            }
120    
121            if (!hasid) {
122                indoc.getRootElement().setAttribute("ID", ID.getId());
123            }
124    
125            // check access
126            if (!checkAccess(ID)) {
127                job.getResponse().sendRedirect(getBaseURL() + usererrorpage);
128                return;
129            }
130    
131            // Save the incoming to a file
132            byte[] outxml = MCRUtils.getByteArray(indoc);
133            File savedir = MCRSimpleWorkflowManager.instance().getDirectoryPath(ID.getBase());
134            File fullname = new File(savedir, ID.getId() + ".xml");
135            storeMetadata(outxml, job, ID, fullname.getAbsolutePath());
136    
137            // create a metadata object and prepare it
138            org.jdom.Document outdoc = prepareMetadata((org.jdom.Document) indoc.clone(), ID, job, lang);
139            if (outdoc == null)
140                return;
141            outxml = MCRUtils.getByteArray(outdoc);
142    
143            // Save the prepared metadata object
144            boolean okay = storeMetadata(outxml, job, ID, fullname.getAbsolutePath());
145    
146            // call the getNextURL and sendMail methods
147            String url = getNextURL(ID, okay);
148            sendMail(ID);
149            if (!job.getResponse().isCommitted())
150                job.getResponse().sendRedirect(job.getResponse().encodeRedirectURL(getBaseURL() + url));
151        }
152    
153        /**
154         * The method stores the data in a working directory dependenced of the
155         * type.
156         * 
157         * @param outxml
158         *            the prepared JDOM object
159         * @param job
160         *            the MCRServletJob
161         * @param ID
162         *            MCRObjectID of the MCRObject/MCRDerivate
163         * @param fullname
164         *            the file name where the JDOM was stored.
165         */
166        public final boolean storeMetadata(byte[] outxml, MCRServletJob job, MCRObjectID ID, String fullname) throws Exception {
167            if (outxml == null) {
168                return false;
169            }
170    
171            // Save the prepared MCRObject/MCRDerivate to a file
172            FileOutputStream out = new FileOutputStream(fullname);
173            try {
174                out.write(outxml);
175                out.flush();
176            } catch (IOException ex) {
177                LOGGER.error(ex.getMessage());
178                LOGGER.error("Exception while store to file " + fullname);
179                errorHandlerIO(job);
180    
181                return false;
182            } finally {
183                out.close();
184            }
185    
186            LOGGER.info("Object " + ID.getId() + " stored under " + fullname + ".");
187            return true;
188        }
189    
190        /**
191         * The method read the incoming JDOM tree in a MCRObject and prepare this by
192         * the following rules. After them it return a JDOM as result of
193         * MCRObject.createXML(). <br/>
194         * <li>remove all target of MCRMetaClassification they have not a categid
195         * attribute.</li>
196         * <br/>
197         * <li>remove all target of MCRMetaLangText they have an empty text</li>
198         * <br/>
199         * 
200         * @param jdom_in
201         *            the JDOM tree from the editor
202         * @param ID
203         *            the MCRObjectID of the MCRObject
204         * @param job
205         *            the MCRServletJob data
206         * @param lang
207         *            the current language
208         * @throws IOException 
209         */
210        protected org.jdom.Document prepareMetadata(org.jdom.Document jdom_in, MCRObjectID ID, MCRServletJob job, String lang)
211                throws IOException {
212            MCREditorOutValidator ev = null;
213            try {
214                ev = new MCREditorOutValidator(jdom_in, ID);
215                Document jdom_out = ev.generateValidMyCoReObject();
216                if (LOGGER.getEffectiveLevel().isGreaterOrEqual(Level.INFO))
217                    for (String logMsg : ev.getErrorLog()) {
218                        LOGGER.info(logMsg);
219                    }
220                return jdom_out;
221            } catch (Exception e) {
222                List<String> errorLog = ev != null ? ev.getErrorLog() : new ArrayList<String>();
223                StringWriter sw = new StringWriter();
224                PrintWriter pw = new PrintWriter(sw);
225                e.printStackTrace(pw);
226                errorLog.add(sw.toString());
227                pw.close();
228                errorHandlerValid(job, errorLog, ID, lang);
229                return null;
230            }
231        }
232    
233        /**
234         * A method to handle valid errors.
235         * @throws IOException 
236         */
237        private final void errorHandlerValid(MCRServletJob job, List<String> logtext, MCRObjectID ID, String lang) throws IOException {
238            // handle HttpSession
239            String sessionID = "";
240            HttpSession session = job.getRequest().getSession(false);
241            if (session != null) {
242                String jSessionID = MCRConfiguration.instance().getString("MCR.Session.Param", ";jsessionid=");
243                sessionID = jSessionID + session.getId();
244            }
245    
246            // write to the log file
247            for (int i = 0; i < logtext.size(); i++) {
248                LOGGER.error(logtext.get(i));
249            }
250    
251            // prepare editor with error messages
252            String pagedir = MCRConfiguration.instance().getString("MCR.SWF.PageDir", "");
253            String myfile = pagedir + MCRConfiguration.instance().getString("MCR.SWF.PageErrorFormular", "editor_error_formular.xml");
254            org.jdom.Document jdom = null;
255    
256            try {
257                //TODO: Access File directly
258                InputStream in = new URL(getBaseURL() + myfile + sessionID + "?XSL.Style=xml").openStream();
259    
260                if (in == null) {
261                    throw new MCRConfigurationException("Can't read editor file " + myfile);
262                }
263    
264                jdom = new org.jdom.input.SAXBuilder().build(in);
265    
266                Element root = jdom.getRootElement();
267                @SuppressWarnings("unchecked")
268                List<Element> sectionlist = root.getChildren("section");
269    
270                for (int i = 0; i < sectionlist.size(); i++) {
271                    Element section = sectionlist.get(i);
272    
273                    final String sectLang = section.getAttributeValue("lang", org.jdom.Namespace.XML_NAMESPACE);
274                    if (!sectLang.equals(lang) && !sectLang.equals("all")) {
275                        continue;
276                    }
277    
278                    Element p = new Element("p");
279                    section.addContent(0, p);
280    
281                    Element center = new Element("center");
282    
283                    // the error message
284                    Element table = new Element("table");
285                    table.setAttribute("width", "80%");
286    
287                    for (String logMsg : logtext) {
288                        Element tr = new Element("tr");
289                        Element td = new Element("td");
290                        Element el = new Element("pre");
291                        el.setAttribute("style", "color:red;");
292                        el.addContent(logMsg);
293                        td.addContent(el);
294                        tr.addContent(td);
295                        table.addContent(tr);
296                    }
297    
298                    center.addContent(table);
299                    section.addContent(1, center);
300                    p = new Element("p");
301                    section.addContent(2, p);
302                    break;
303                }
304            } catch (org.jdom.JDOMException e) {
305                throw new MCRException("Can't read editor file " + myfile + " or it has a parse error.", e);
306            }
307    
308            // restart editor
309            getLayoutService().doLayout(job.getRequest(), job.getResponse(), jdom);
310        }
311    
312    }