I am trying to write an embedded custom fop xml to pdf java application using a custom image redirect within fop
I have the following in an old xslt file
<fo:block text-indent="1mm" padding-before="20mm">
<xsl:variable name="barcode" select="concat('/prescriptions/', id, '/barcode.html')"/>
<fo:external-graphic>
<xsl:attribute name="src">
<xsl:value-of select="$barcode" />
</xsl:attribute>
</fo:external-graphic>
</fo:block>
I have written a customResourceResolver
package embedding;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.apache.xmlgraphics.io.Resource;
import org.apache.xmlgraphics.io.ResourceResolver;
import java.io.BufferedInputStream;
import java.net.URI;
import java.net.URISyntaxException;
public class CustomResourceResolver implements ResourceResolver {
String base;
String session;
String cookie;
String user_id;
String authorization;
static final Logger logger = Logger.getLogger("fop-log");
public String get_base(){
return base;
}
public CustomResourceResolver(String _base, String _session, String _cookie, String _user_id, String _authorization){
super();
base = _base;
session = _session;
cookie = _cookie;
user_id = _user_id;
authorization = _authorization;
}
@Override
public Resource getResource(URI uri) throws IOException {
HttpURLConnection urlConnection = null;
try {
String href = uri.getRawPath();
if (!href.startsWith("/") && !base.endsWith("/")) {
base = base + "/";
}
String new_uri;
if (href.startsWith("http://") || href.startsWith("https://")) {
new_uri = href;
} else {
new_uri = base + href;
}
uri = new URI(new_uri);
logger.log(Level.INFO, "loading: ({0})", new_uri);
URL url = uri.toURL();
urlConnection = (HttpURLConnection) url.openConnection();
if(session!= null){
urlConnection.setRequestProperty("Cookie", cookie + "=" + session);
}
if(authorization != null){
urlConnection.setRequestProperty("Fop-authorization", authorization );
}
if(user_id != null){
urlConnection.setRequestProperty("Fop-user",user_id );
}
InputStream in = new BufferedInputStream(urlConnection.getInputStream());
return new Resource(in);
} catch (MalformedURLException e) {
logger.log(Level.SEVERE, null, e);
return null;
} catch (IOException | URISyntaxException ioe) {
logger.log(Level.SEVERE, null, ioe);
return null;
} finally {
if (urlConnection != null) {
urlConnection.disconnect();
}
}
}
@Override
public OutputStream getOutputStream(URI uri) throws IOException {
URL url = uri.toURL();
return url.openConnection().getOutputStream();
}
}
And this gets called by
CustomResourceResolver resolver = new CustomResourceResolver(base, session, cookie, user_id, authorization);
FopFactoryBuilder builder = new FopFactoryBuilder(new File(".").toURI(), (ResourceResolver)resolver);
final FopFactory fopFactory = builder.build();
FOUserAgent foUserAgent = fopFactory.newFOUserAgent();
OutputStream out = new java.io.FileOutputStream(pdffile);
out = new java.io.BufferedOutputStream(out);
try {
Fop fop = fopFactory.newFop(MimeConstants.MIME_PDF, foUserAgent, out);
TransformerFactory factory = TransformerFactory.newInstance();
URIResolver uiResolver = new CustomUriResolver(base, session, cookie, user_id, authorization);
factory.setURIResolver(uiResolver);
Transformer transformer = factory.newTransformer(new StreamSource(xsltfile));
// Set the value of a <param> in the stylesheet
transformer.setParameter("versionParam", "2.0");
// Setup input for XSLT transformation
Source src = new StreamSource(xmlfile);
// Resulting SAX events (the generated FO) must be piped through to FOP
Result res = new SAXResult(fop.getDefaultHandler());
// Start XSLT transformation and FOP processing
transformer.transform(src, res);
} finally {
out.close();
}
java is packaged inside a single FopXml2Pdf.jar and is called from the command line like
java -jar FopXml2Pdf.jar file.xml file.xsl file.config
but when I run the code I get
Sep 19, 2023 6:52:36 AM embedding.CustomResourceResolver getResource
INFO: loading: (http://localhost:3000/prescriptions/420/barcode.html)
Sep 19, 2023 6:52:36 AM org.apache.xmlgraphics.image.loader.impl.AbstractImageSessionContext createImageSource
SEVERE: Unable to create ImageInputStream for InputStream from system identifier 'file:/media/sf_Clintel/careright/./' (stream is closed)
Sep 19, 2023 6:52:36 AM org.apache.fop.events.LoggingEventListener processEvent
SEVERE: Image not found. URI: /prescriptions/420/barcode.html. (No context info available)
I can see that the redirection is loading the correct url getting the correct data but
new File(".").toURI() is resolving to file:/media/sf_Clintel/careright/./
What should I set this to so that it saves the data from Resource getResource?
The issue has been solved. packaging of Batik-all-1.14.jar into a single fat Jar using ANT was causing this exception. changing the packaging to use MVN has fixed the problem
<?xml version="1.0"?>
<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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.clintel.java_fop</groupId>
<artifactId>java_fop</artifactId>
<version>develop</version>
<name>java_fop</name>
<url>http://maven.apache.org</url>
<packaging>jar</packaging>
<repositories>
<repository>
<id>Sonatype-public</id>
<name>SnakeYAML repository</name>
<url>https://oss.sonatype.org/content/groups/public/</url>
</repository>
</repositories>
<dependencies>
<!-- https://mvnrepository.com/artifact/commons-logging/commons-logging -->
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.0.4</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.github.jtidy/jtidy -->
<dependency>
<groupId>com.github.jtidy</groupId>
<artifactId>jtidy</artifactId>
<version>1.0.3</version>
</dependency>
<!-- https://mvnrepository.com/artifact/xalan/serializer -->
<dependency>
<groupId>xalan</groupId>
<artifactId>serializer</artifactId>
<version>2.7.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/xalan/xalan -->
<dependency>
<groupId>xalan</groupId>
<artifactId>xalan</artifactId>
<version>2.7.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/xerces/xercesImpl -->
<dependency>
<groupId>xerces</groupId>
<artifactId>xercesImpl</artifactId>
<version>2.12.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.xmlgraphics/xmlgraphics-commons -->
<dependency>
<groupId>org.apache.xmlgraphics</groupId>
<artifactId>xmlgraphics-commons</artifactId>
<version>2.6</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.xmlgraphics/batik-all -->
<dependency>
<groupId>org.apache.xmlgraphics</groupId>
<artifactId>batik-all</artifactId>
<version>1.14</version>
<type>pom</type>
</dependency>
<!-- https://mvnrepository.com/artifact/xml-apis/xml-apis -->
<dependency>
<groupId>xml-apis</groupId>
<artifactId>xml-apis</artifactId>
<version>1.4.01</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.xmlgraphics</groupId>
<artifactId>fop</artifactId>
<version>2.6</version>
</dependency>
<dependency>
<groupId>com.github.jnr</groupId>
<artifactId>jnr-posix</artifactId>
<version>3.0.15</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.11.0</version>
<configuration>
<compilerVersion>1.8</compilerVersion>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<shadedArtifactAttached>true</shadedArtifactAttached>
<transformers>
<transformer implementation=
"org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>embedding.FopXml2Pdf</mainClass>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>