Coverage Summary for Class: XMLEditor (org.kitodo.production.editor)
Class |
Class, %
|
Method, %
|
Line, %
|
XMLEditor |
100%
(1/1)
|
80%
(8/10)
|
49,2%
(31/63)
|
/*
* (c) Kitodo. Key to digital objects e. V. <contact@kitodo.org>
*
* This file is part of the Kitodo project.
*
* It is licensed under GNU General Public License version 3 or later.
*
* For the full copyright and license information, please read the
* GPL3-License.txt file that was distributed with this source code.
*/
package org.kitodo.production.editor;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.Serializable;
import java.io.StringReader;
import java.nio.file.Files;
import java.util.Objects;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import javax.annotation.PostConstruct;
import javax.faces.application.FacesMessage;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.view.ViewScoped;
import javax.inject.Named;
import javax.xml.XMLConstants;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.kitodo.config.enums.KitodoConfigFile;
import org.w3c.dom.Document;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
@Named("XMLEditor")
@ViewScoped
public class XMLEditor implements Serializable {
private static final Logger logger = LogManager.getLogger(XMLEditor.class);
private KitodoConfigFile configurationFile;
private String currentConfigurationFile = "";
private String xmlConfigurationString = "";
private static DocumentBuilder documentBuilder = null;
/**
* Constructor.
*/
public XMLEditor() {
try {
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
documentBuilderFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
documentBuilder = documentBuilderFactory.newDocumentBuilder();
} catch (ParserConfigurationException e) {
logger.error("ERROR: unable to instantiate document builder: {}", e.getMessage());
}
}
/**
* Load first configuration file when bean is created.
*/
@PostConstruct
public void loadInitialConfiguration() {
loadProjectConfiguration();
}
/**
* Get the XML configuration string.
*
* @return the XML configuration string
*/
public String getXMLConfiguration() {
return this.xmlConfigurationString;
}
/**
* Set the XML configuration string.
*
* @param configuration
* the XML configuration string
*/
public void setXMLConfiguration(String configuration) {
this.xmlConfigurationString = configuration;
}
/**
* Get name of configuration file currently loaded into frontend editor.
*
* @return configuration file name
*/
public String getCurrentConfigurationFile() {
return currentConfigurationFile;
}
/**
* Load the content of the XML configuration file with the given name
* 'configurationFile'.
*
* @param configurationFile
* name of the configuration to be loaded
*/
public void loadXMLConfiguration(String configurationFile) {
try {
currentConfigurationFile = configurationFile;
this.configurationFile = KitodoConfigFile.getByName(configurationFile);
try (Stream<String> lines = Files.lines(this.configurationFile.getFile().toPath())) {
this.xmlConfigurationString = lines.collect(Collectors.joining("\n"));
}
} catch (IOException e) {
String errorMessage = "ERROR: Unable to load configuration file '" + configurationFile + "'.";
logger.error("{} {}", errorMessage, e.getMessage());
this.xmlConfigurationString = errorMessage;
}
}
/**
* Save the String 'xmlConfigurationString' to the XML file denoted by
* 'configurationFile'.
*/
public void saveXMLConfiguration() {
logger.info("Saving configuration to file {}", currentConfigurationFile);
try {
Document document = documentBuilder.parse(new InputSource(new StringReader(this.xmlConfigurationString)));
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
DOMSource domSource = new DOMSource(document);
try (FileOutputStream outputStream = new FileOutputStream(configurationFile.getFile(), false);
PrintWriter printWriter = new PrintWriter(outputStream)) {
StreamResult streamResult = new StreamResult(printWriter);
transformer.transform(domSource, streamResult);
} catch (TransformerException e) {
logger.error("ERROR: transformation failed: {}", e.getMessage());
}
} catch (TransformerConfigurationException e) {
logger.error("ERROR: transformer configuration exception: {}", e.getMessage());
} catch (FileNotFoundException e) {
logger.error("ERROR: file not found: " + e.getMessage());
} catch (IOException e) {
logger.error("ERROR: could not save XML configuration: {}", e.getMessage());
} catch (SAXException e) {
logger.error("ERROR: error parsing given XML string: {}", e.getMessage());
}
}
/**
* Check and return whether the given String 'xmlCode' contains well formed XML
* code or not.
*
* @param facesContext
* the current FacesContext
* @param uiComponent
* the component containing the String that is being validated
* @param xmlCode
* XML code that will be validated
* @return whether 'xmlCode' is well formed or not
*/
public boolean validateXMLConfiguration(FacesContext facesContext, UIComponent uiComponent, String xmlCode) {
if (!Objects.equals(documentBuilder, null)) {
InputSource inputSource = new InputSource(new StringReader(xmlCode));
try {
documentBuilder.parse(inputSource);
return true;
} catch (SAXParseException e) {
// parse method throwing an SAXParseException means given xml code is not well
// formed!
String errorString = "Error while parsing XML: line = " + e.getLineNumber() + ", column = "
+ e.getColumnNumber() + ": " + e.getMessage();
FacesMessage errorMessage = new FacesMessage(FacesMessage.SEVERITY_ERROR, "XML parsing error",
errorString);
facesContext.addMessage(uiComponent.getClientId(), errorMessage);
logger.error(errorString);
return false;
} catch (SAXException | IOException e) {
logger.error("{}: {}", e.getClass().getSimpleName(), e.getMessage());
return false;
}
} else {
logger.error("ERROR: document builder is null!");
return false;
}
}
/**
* Load the project XML configuration file and display its content in the
* editor.
*/
public void loadProjectConfiguration() {
loadXMLConfiguration(KitodoConfigFile.PROJECT_CONFIGURATION.getName());
}
}