Skip to content

Commit

Permalink
Merge branch 'BezrukovM-jpylyzer-plugin'
Browse files Browse the repository at this point in the history
  • Loading branch information
carlwilson committed May 29, 2016
2 parents 2da039e + 2c43ea0 commit c9d586c
Show file tree
Hide file tree
Showing 4 changed files with 350 additions and 1 deletion.
15 changes: 15 additions & 0 deletions jpylyzer-plugin/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>verapdf-library-samples</artifactId>
<groupId>org.verapdf</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

<artifactId>jpylyzer-plugin</artifactId>


</project>
134 changes: 134 additions & 0 deletions jpylyzer-plugin/src/main/java/org/verapdf/JpylyzerConfig.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
/**
*
*/
package org.verapdf;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import java.io.*;

/**
* @author Maksim Bezrukov
*/
@XmlRootElement(namespace = "http://www.verapdf.org/JpylyzerConfig", name = "jpylyzerConfig")
final class JpylyzerConfig {

@XmlElement
private final String cliPath;
@XmlElement
private final String outFolder;
@XmlElement
private final boolean isVerbose;

private JpylyzerConfig() {
this("", "", false);
}

private JpylyzerConfig(String outFolder, String cliPath, boolean isVerbose) {
this.cliPath = cliPath;
this.outFolder = outFolder;
this.isVerbose = isVerbose;
}

public String getOutFolder() {
return outFolder;
}

public boolean isVerbose() {
return isVerbose;
}

public String getCliPath() {
return cliPath;
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;

JpylyzerConfig config = (JpylyzerConfig) o;

if (isVerbose != config.isVerbose) return false;
if (cliPath != null ? !cliPath.equals(config.cliPath) : config.cliPath != null) return false;
return outFolder != null ? outFolder.equals(config.outFolder) : config.outFolder == null;

}

@Override
public int hashCode() {
int result = cliPath != null ? cliPath.hashCode() : 0;
result = 31 * result + (outFolder != null ? outFolder.hashCode() : 0);
result = 31 * result + (isVerbose ? 1 : 0);
return result;
}

static JpylyzerConfig defaultInstance() {
return new JpylyzerConfig(null, null, false);
}

static JpylyzerConfig fromValues(final String cliPath, final String outFolder, final boolean isVerbose) {
return new JpylyzerConfig(cliPath, outFolder, isVerbose);
}

static String toXml(final JpylyzerConfig toConvert, Boolean prettyXml)
throws JAXBException, IOException {
String retVal = "";
try (StringWriter writer = new StringWriter()) {
toXml(toConvert, writer, prettyXml);
retVal = writer.toString();
return retVal;
}
}

static JpylyzerConfig fromXml(final String toConvert)
throws JAXBException {
try (StringReader reader = new StringReader(toConvert)) {
return fromXml(reader);
}
}

static void toXml(final JpylyzerConfig toConvert,
final OutputStream stream, Boolean prettyXml) throws JAXBException {
Marshaller varMarshaller = getMarshaller(prettyXml);
varMarshaller.marshal(toConvert, stream);
}

static JpylyzerConfig fromXml(final InputStream toConvert)
throws JAXBException {
Unmarshaller stringUnmarshaller = getUnmarshaller();
return (JpylyzerConfig) stringUnmarshaller.unmarshal(toConvert);
}

static void toXml(final JpylyzerConfig toConvert, final Writer writer,
Boolean prettyXml) throws JAXBException {
Marshaller varMarshaller = getMarshaller(prettyXml);
varMarshaller.marshal(toConvert, writer);
}

static JpylyzerConfig fromXml(final Reader toConvert)
throws JAXBException {
Unmarshaller stringUnmarshaller = getUnmarshaller();
return (JpylyzerConfig) stringUnmarshaller.unmarshal(toConvert);
}

private static Unmarshaller getUnmarshaller() throws JAXBException {
JAXBContext context = JAXBContext
.newInstance(JpylyzerConfig.class);
Unmarshaller unmarshaller = context.createUnmarshaller();
return unmarshaller;
}

private static Marshaller getMarshaller(Boolean setPretty)
throws JAXBException {
JAXBContext context = JAXBContext
.newInstance(JpylyzerConfig.class);
Marshaller marshaller = context.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, setPretty);
return marshaller;
}
}
199 changes: 199 additions & 0 deletions jpylyzer-plugin/src/main/java/org/verapdf/JpylyzerExtractor.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,199 @@
package org.verapdf;

import org.verapdf.core.FeatureParsingException;
import org.verapdf.features.AbstractImageFeaturesExtractor;
import org.verapdf.features.ImageFeaturesData;
import org.verapdf.features.tools.FeatureTreeNode;
import org.w3c.dom.Document;
import org.xml.sax.SAXException;

import javax.xml.bind.JAXBException;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;
import java.io.*;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.file.*;
import java.util.ArrayList;
import java.util.List;

/**
* @author Maksim Bezrukov
*/
public class JpylyzerExtractor extends AbstractImageFeaturesExtractor {

@Override
public List<FeatureTreeNode> getImageFeatures(ImageFeaturesData imageFeaturesData) {
boolean doesContainsJPXFilter = false;
for (ImageFeaturesData.Filter filter : imageFeaturesData.getFilters()) {
if ("JPXDecode".equals(filter.getName())) {
doesContainsJPXFilter = true;
break;
}
}
if (!doesContainsJPXFilter) {
return null;
}
List<FeatureTreeNode> result = new ArrayList<>();
try {
try {
JpylyzerConfig config = getConfig(result);
File temp = generateTempFile(imageFeaturesData.getStream(), "jpx");
exec(result, config, temp);
} catch (IOException | InterruptedException | URISyntaxException e) {
FeatureTreeNode node = FeatureTreeNode.createRootNode("error");
node.setValue("Error in execution. Error message: " + e.getMessage());
result.add(node);
}
} catch (FeatureParsingException e) {
throw new IllegalStateException(e);
}
return result;
}

private File generateTempFile(byte[] stream, String name) throws IOException {
File fold = getTempFolder();
File temp = File.createTempFile(name == null ? "" : name, "", fold);
temp.deleteOnExit();
FileOutputStream out = new FileOutputStream(temp);
out.write(stream);
out.close();
return temp;
}

private void exec(List<FeatureTreeNode> nodes, JpylyzerConfig config, File temp) throws InterruptedException, FeatureParsingException, IOException, URISyntaxException {
String scriptPath = getScriptPath(config);
if (scriptPath == null) {
FeatureTreeNode error = FeatureTreeNode.createRootNode("error");
error.setValue("Can not obtain jpylyzer script or binary");
nodes.add(error);
return;
}
String[] args;
if (config.isVerbose()) {
args = new String[3];
args[0] = scriptPath;
args[1] = "--verbose";
args[2] = temp.getCanonicalPath();
} else {
args = new String[2];
args[0] = scriptPath;
args[1] = temp.getCanonicalPath();
}
Runtime rt = Runtime.getRuntime();
Process pr = rt.exec(args);
File out = getOutFile(config, nodes);
FileOutputStream outStream = new FileOutputStream(out);
byte[] buffer = new byte[1024];
int bytesRead;
while ((bytesRead = pr.getInputStream().read(buffer)) != -1) {
outStream.write(buffer, 0, bytesRead);
}
pr.waitFor();
outStream.close();
FeatureTreeNode node = FeatureTreeNode.createRootNode("resultPath");
node.setValue(out.getCanonicalPath());
nodes.add(node);

try {
String isValidJP2Value = getXMLNodeValue("//jpylyzer/isValidJP2", out);
FeatureTreeNode validationNode = FeatureTreeNode.createRootNode("isValidJP2");
validationNode.setValue(isValidJP2Value);
nodes.add(validationNode);
} catch (ParserConfigurationException | SAXException | XPathExpressionException e) {
FeatureTreeNode error = FeatureTreeNode.createRootNode("error");
error.setValue("Error in obtaining validation result. Error message: " + e.getMessage());
nodes.add(error);
}
}

private static String getXMLNodeValue(String xPath, File xml) throws ParserConfigurationException, IOException, SAXException, XPathExpressionException {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document document = builder.parse(xml);
XPathExpression xp = XPathFactory.newInstance().newXPath().compile(xPath);
return xp.evaluate(document);
}

private static File getOutFile(JpylyzerConfig config, List<FeatureTreeNode> nodes) throws FeatureParsingException, IOException {
if (config.getOutFolder() == null) {
File tempFolder = getTempFolder();
return getOutFileInFolder(tempFolder);
} else {
File outFolder = new File(config.getOutFolder());
if (outFolder.isDirectory()) {
return getOutFileInFolder(outFolder);
} else {
FeatureTreeNode node = FeatureTreeNode.createRootNode("error");
node.setValue("Config file contains out folder path but it doesn't link a directory.");
nodes.add(node);
File tempFolder = getTempFolder();
return getOutFileInFolder(tempFolder);
}
}
}

private static File getTempFolder() {
File tempDir = new File(System.getProperty("java.io.tmpdir"));
File tempFolder = new File(tempDir, "veraPDFJpylyzerPluginTemp");
if (!tempFolder.exists()) {
tempFolder.mkdir();
}
tempFolder.deleteOnExit();
return tempFolder;
}

private static File getOutFileInFolder(File folder) throws IOException {
File out = File.createTempFile("veraPDF_Jpylyzer_Plugin_out", ".xml", folder);
out.deleteOnExit();
return out;
}

private JpylyzerConfig getConfig(List<FeatureTreeNode> nodes) throws FeatureParsingException {
JpylyzerConfig config = JpylyzerConfig.defaultInstance();
File conf = getConfigFile();
if (conf.isFile() && conf.canRead()) {
try {
config = JpylyzerConfig.fromXml(new FileInputStream(conf));
} catch (JAXBException | FileNotFoundException e) {
FeatureTreeNode node = FeatureTreeNode.createRootNode("error");
node.setValue("Config file contains wrong syntax. Error message: " + e.getMessage());
nodes.add(node);
}
}
return config;
}

private File getConfigFile() {
return new File(getFolderPath().toFile(), "config.xml");
}

@Override
public String getID() {
return "3ee4e6b3-af6b-4510-8b95-1af29fc81629";
}

@Override
public String getDescription() {
return "Extracts features of the Image using Jpylyzer";
}

private String getScriptPath(JpylyzerConfig config) {
String cliPath = config.getCliPath();
if (cliPath == null) {
cliPath = getFolderPath().toString() + "/jpylyzer-master/jpylyzer/jpylyzer.py";
}

File cli = new File(cliPath);
if (!(cli.exists() && cli.isFile())) {
return null;
}
return cliPath;
}
}


3 changes: 2 additions & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
<module>imageSample-plugin</module>
<module>metsMetadata-plugin</module>
<module>mediaconch</module>
<module>jpylyzer-plugin</module>
</modules>

<repositories>
Expand All @@ -46,7 +47,7 @@
<dependency>
<groupId>org.verapdf</groupId>
<artifactId>core</artifactId>
<version>[0.13.0,0.14.0)</version>
<version>[0.15.0,0.16.0)</version>
</dependency>
</dependencies>

Expand Down

0 comments on commit c9d586c

Please sign in to comment.