Search code examples
javaapache-fop

org.apache.fop.apps.FOPException: .fop (Access is denied) in Azure


I have recently added a fop pdf generator to an existing application. everything works fine locally but when I deploy to live on Azure I get the following errors:

org.apache.fop.apps.FOPException: .fop (Access is denied)
java.io.FileNotFoundException: .fop (Access is denied)

I'm puzzled as to why I'm getting a file access error when it would seem the exception is occurring when the fopfactory writes to a ByteOutputstream

The function where the catch occurs is

        public static void GeneratePDF(string foFile, HttpContext context) {
        StringBuilder sbDebug = new StringBuilder();

        sbDebug.AppendLine("Start");
        ByteArrayOutputStream os = new java.io.ByteArrayOutputStream();
        try
        {
            sbDebug.AppendLine("Got to 1");
            com.sun.org.apache.xerces.@internal.jaxp.SAXParserFactoryImpl s = new com.sun.org.apache.xerces.@internal.jaxp.SAXParserFactoryImpl();
            sbDebug.AppendLine("Got to 2");
            FopFactory fopFactory = FopFactory.newInstance(new java.io.File(System.Web.Hosting.HostingEnvironment.MapPath("~/App_Data/Test.xconf")));
            sbDebug.AppendLine("Got to 3 - file ").AppendLine(System.Web.Hosting.HostingEnvironment.MapPath("~/App_Data/Test.xconf"));
            Fop fop = fopFactory.newFop("application/pdf", os);

            sbDebug.AppendLine("Got to 4");
            javax.xml.transform.TransformerFactory factory = javax.xml.transform.TransformerFactory.newInstance();
            javax.xml.transform.Transformer transformer = factory.newTransformer();
            javax.xml.transform.Source src = new javax.xml.transform.stream.StreamSource(new java.io.StringReader(foFile));
            javax.xml.transform.Result res = new javax.xml.transform.sax.SAXResult(fop.getDefaultHandler());
            sbDebug.AppendLine("Got to 5");
            transformer.transform(src, res);

            context.Response.ContentType = "application/pdf";
            context.Response.BinaryWrite(os.toByteArray());
            //context.Response.BinaryWrite(System.Text.Encoding.UTF8.GetBytes(os.ToString()));
        }

        catch (Exception ex) {
            throw new Exception(sbDebug.AppendLine(ex.ToString()).ToString());
        }

        finally {
            os.close();
        }
    }

You can see I've added some debug lines as I had to resort to old fashioned debugging to see what was happening. The output from this is:

Catch Error: System.Exception: Start
Got to 1
Got to 2
Got to 3 - file 
D:\home\site\wwwroot\App_Data\Test.xconf
org.apache.fop.apps.FOPException: .fop (Access is denied)
java.io.FileNotFoundException: .fop (Access is denied)

So I can see the exception is occurring at this line:

Fop fop = fopFactory.newFop("application/pdf", os);

I'm expecting everything to be happening in memory apart from the read of the xconf file which is where it should be.

Update 21/02/2017 I've now verified that the xconf file exists in the correct place using

string curFile = System.Web.Hosting.HostingEnvironment.MapPath("~/App_Data/Test.xconf");
            if (System.IO.File.Exists(curFile)) //Used System.IO prefix as without it compiler complains of ambiguity with java.io
            {
                sbDebug.AppendLine("Got to 3a - file found");
            }
            else
            {
                sbDebug.AppendLine("Got to 3a - file NOT found");
            }

And also that it can be read using

BufferedReader br = new BufferedReader(new FileReader(curFile));
            sbDebug.AppendLine("Got to 3b");

            String sJIObrOut = br.readLine();
            sbDebug.AppendLine("Got to 3c");
            while ((sJIObrOut = br.readLine()) != null) 
            {
                sbDebug.Append("3d: ").AppendLine(sJIObrOut);
            }

This suggest that fopfactory is trying to access a different file but I can't figure out what.

Any help gratefully received.

UPDATE 2 22/3/17 I had no success with Azure Cloud services so decided to build a local web app to just convert the xslfo doc to a pdf and run it as a web service. This works perfectly locally so published the service on a server we use for other clients. This doesn't work and I get exactly the same error as my original post. That means it's not an Azure problem - does any one have any other ideas?


Solution

  • Very many thanks to @mondjunge for pointing me in the right direction. I now have a solution which works outside of Azure for now - In due course I'm hoping this will be something I can apply to Azure directly, and I will add to this post accordingly

    It seems as if the cache writing is what is causing the problem (permissions).

    The workaround/fix I have implemented is to add the following line into the xconf file (I put it just before the /fop closing tag but don't think it matters as long as it's a direct child node of fop)

    <use-cache>false</use-cache>
    

    Hope this saves someone else days of hassle and stress

    Update 7/4/17

    Out of interest I tried adding this line to the pure azure hosted version and it no longer gave me the permissions error instead it gave me an error about GDI which is probably along the lines of what @PeterPan suggested originally. Since I have a working version of the fop application hosted elsewhere I'm going to leave it at that.