| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| * |
| */ |
| package org.apache.lenya.cms.editors.forms; |
| |
| import java.io.ByteArrayInputStream; |
| import java.io.IOException; |
| import java.io.StringReader; |
| import java.io.StringWriter; |
| import java.util.ArrayList; |
| import java.util.HashSet; |
| import java.util.List; |
| import java.util.Set; |
| |
| import javax.xml.parsers.ParserConfigurationException; |
| import javax.xml.transform.stream.StreamSource; |
| |
| import org.apache.commons.io.IOUtils; |
| import org.apache.lenya.cms.cocoon.source.SourceUtil; |
| import org.apache.lenya.cms.linking.LinkConverter; |
| import org.apache.lenya.cms.publication.ResourceType; |
| import org.apache.lenya.cms.usecase.DocumentUsecase; |
| import org.apache.lenya.cms.usecase.UsecaseException; |
| import org.apache.lenya.cms.workflow.WorkflowUtil; |
| import org.apache.lenya.cms.workflow.usecases.UsecaseWorkflowHelper; |
| import org.apache.lenya.util.ServletHelper; |
| import org.apache.lenya.xml.DocumentHelper; |
| import org.apache.lenya.xml.Schema; |
| import org.apache.lenya.xml.ValidationUtil; |
| import org.w3c.dom.Document; |
| import org.xml.sax.ErrorHandler; |
| import org.xml.sax.SAXException; |
| import org.xml.sax.SAXParseException; |
| |
| /** |
| * One form editor. |
| * |
| * @version $Id$ |
| */ |
| public class OneFormEditor extends DocumentUsecase implements ErrorHandler { |
| |
| protected static final String PARAM_VALIDATION_ERRORS = "validationErrors"; |
| protected static final String PARAM_CONTENT = "content"; |
| protected static final String DEFAULT_ENCODING = "utf-8"; |
| |
| /** |
| * @see org.apache.lenya.cms.usecase.AbstractUsecase#getNodesToLock() |
| */ |
| protected org.apache.lenya.cms.publication.Node[] getNodesToLock() throws UsecaseException { |
| org.apache.lenya.cms.publication.Document doc = getSourceDocument(); |
| Set nodes = new HashSet(); |
| if (doc != null) { |
| nodes.add(doc); |
| } |
| return (org.apache.lenya.cms.publication.Node[]) nodes |
| .toArray(new org.apache.lenya.cms.publication.Node[nodes.size()]); |
| } |
| |
| protected void prepareView() throws Exception { |
| super.prepareView(); |
| |
| StringWriter writer = new StringWriter(); |
| IOUtils.copy(getSourceDocument().getInputStream(), writer, DEFAULT_ENCODING); |
| String xmlString = writer.toString(); |
| setParameter(PARAM_CONTENT, xmlString); |
| validate(xmlString, DEFAULT_ENCODING); |
| } |
| |
| /** |
| * @see org.apache.lenya.cms.usecase.AbstractUsecase#doCheckPreconditions() |
| */ |
| protected void doCheckPreconditions() throws Exception { |
| super.doCheckPreconditions(); |
| if (!hasErrors()) { |
| UsecaseWorkflowHelper.checkWorkflow(this, getEvent(), getSourceDocument(), getLogger()); |
| if (!ServletHelper.isUploadEnabled()) { |
| addErrorMessage("upload-disabled"); |
| } |
| } |
| setParameter("executable", Boolean.valueOf(!hasErrors())); |
| } |
| |
| /** |
| * @see org.apache.lenya.cms.usecase.AbstractUsecase#doExecute() |
| */ |
| protected void doExecute() throws Exception { |
| super.doExecute(); |
| saveDocument(getXml(getContent(), getRequestEncoding())); |
| } |
| |
| protected String getRequestEncoding() { |
| return getRequest().getCharacterEncoding(); |
| } |
| |
| protected String getContent() { |
| return getParameterAsString(PARAM_CONTENT); |
| } |
| |
| public void advance() throws UsecaseException { |
| clearErrorMessages(); |
| try { |
| String content = getContent(); |
| String encoding = getRequestEncoding(); |
| Document xml = getXml(content, encoding); |
| if (xml != null) { |
| validate(content, encoding); |
| } |
| if (!hasErrors()) { |
| IOUtils.copy(new StringReader(content), getSourceDocument().getOutputStream()); |
| deleteParameter(PARAM_CONTENT); |
| } |
| } catch (Exception e) { |
| throw new UsecaseException(e); |
| } |
| } |
| |
| protected void doCheckExecutionConditions() throws Exception { |
| super.doCheckExecutionConditions(); |
| if (hasErrors()) { |
| return; |
| } |
| String encoding = getRequestEncoding(); |
| Document xml = getXml(getContent(), encoding); |
| if (xml != null) { |
| validate(getContent(), encoding); |
| } |
| } |
| |
| protected void validate(String xmlString, String encoding) throws Exception { |
| ResourceType resourceType = getSourceDocument().getResourceType(); |
| Schema schema = resourceType.getSchema(); |
| if (schema == null) { |
| getLogger().info( |
| "No schema declared for resource type [" + resourceType.getName() |
| + "], skipping validation."); |
| } else { |
| deleteParameter(PARAM_VALIDATION_ERRORS); |
| byte bytes[] = xmlString.getBytes(encoding); |
| ByteArrayInputStream stream = new ByteArrayInputStream(bytes); |
| StreamSource source = new StreamSource(stream); |
| ValidationUtil.validate(source, schema, this); |
| if (!getValidationErrors().isEmpty()) { |
| addErrorMessage("editors.validationFailed"); |
| } |
| } |
| } |
| |
| protected Document getXml(String xmlString, String encoding) |
| throws ParserConfigurationException, IOException { |
| try { |
| return DocumentHelper.readDocument(xmlString, encoding); |
| } catch (SAXException e) { |
| addErrorMessage("error-document-form", new String[] { e.getMessage() }); |
| return null; |
| } |
| } |
| |
| /** |
| * Save the content to the document source. After saving, the XML is validated. If validation |
| * errors occur, the usecase transaction is rolled back, so the changes are not persistent. If |
| * the validation succeeded, the workflow event is invoked. |
| * |
| * @param content The content to save. |
| * @throws Exception if an error occurs. |
| */ |
| protected void saveDocument(Document content) throws Exception { |
| saveXMLFile(content, getSourceDocument()); |
| WorkflowUtil.invoke(getSourceDocument(), getEvent()); |
| } |
| |
| /** |
| * Save the XML file |
| * |
| * @param content The content |
| * @param document The source |
| */ |
| protected void saveXMLFile(Document content, org.apache.lenya.cms.publication.Document document) { |
| try { |
| SourceUtil.writeDOM(content, document.getOutputStream()); |
| LinkConverter converter = new LinkConverter(getLogger()); |
| //florent : cause changes in linkconverter |
| //converter.convertUrlsToUuids(getSourceDocument(), false); |
| converter.convertUrlsToUuids(getPublication(),getSourceDocument(), false); |
| } catch (Exception e) { |
| addErrorMessage(e.getMessage()); |
| } |
| } |
| |
| protected String getEvent() { |
| return "edit"; |
| } |
| |
| public static class ValidationError { |
| |
| protected static final int SEVERITY_WARNING = 0; |
| protected static final int SEVERITY_ERROR = 1; |
| protected static final int SEVERITY_FATAL = 2; |
| |
| private int severity; |
| |
| public int getLine() { |
| return this.line; |
| } |
| |
| public int getColumn() { |
| return this.column; |
| } |
| |
| public String getMessage() { |
| return this.message; |
| } |
| |
| private int line; |
| private int column; |
| private String message; |
| |
| public ValidationError(int severity, SAXParseException e) { |
| this.message = e.getMessage(); |
| this.line = e.getLineNumber(); |
| this.column = e.getColumnNumber(); |
| this.severity = severity; |
| } |
| |
| } |
| |
| protected List getValidationErrors() { |
| List errors = (List) getParameter(PARAM_VALIDATION_ERRORS); |
| if (errors == null) { |
| errors = new ArrayList(); |
| setParameter(PARAM_VALIDATION_ERRORS, errors); |
| } |
| return errors; |
| } |
| |
| public void error(SAXParseException e) throws SAXException { |
| getValidationErrors().add(new ValidationError(ValidationError.SEVERITY_ERROR, e)); |
| } |
| |
| public void fatalError(SAXParseException e) throws SAXException { |
| getValidationErrors().add(new ValidationError(ValidationError.SEVERITY_FATAL, e)); |
| } |
| |
| public void warning(SAXParseException e) throws SAXException { |
| getValidationErrors().add(new ValidationError(ValidationError.SEVERITY_WARNING, e)); |
| } |
| |
| } |