You are viewing a plain text version of this content. The canonical link for it is here.
Posted to derby-commits@db.apache.org by ka...@apache.org on 2014/06/24 09:37:47 UTC

svn commit: r1605021 - in /db/derby/code/trunk/java: testing/org/apache/derbyTesting/functionTests/tests/lang/ testing/org/apache/derbyTesting/junit/ tools/org/apache/derby/impl/tools/planexporter/ tools/org/apache/derby/tools/

Author: kahatlen
Date: Tue Jun 24 07:37:46 2014
New Revision: 1605021

URL: http://svn.apache.org/r1605021
Log:
DERBY-6629: Restrict privileged operation in CreateXMLFile

Remove the privileged operation in the CreateXMLFile class. Instead, let
the caller do the privileged operation and pass in a Writer object that
CreateXMLFile can write the file to.

Make the tests invoke the plan exporter tool via its main class instead
of calling the internal API.

Modified:
    db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/XplainStatisticsTest.java
    db/derby/code/trunk/java/testing/org/apache/derbyTesting/junit/BaseTestCase.java
    db/derby/code/trunk/java/tools/org/apache/derby/impl/tools/planexporter/CreateXMLFile.java
    db/derby/code/trunk/java/tools/org/apache/derby/tools/PlanExporter.java

Modified: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/XplainStatisticsTest.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/XplainStatisticsTest.java?rev=1605021&r1=1605020&r2=1605021&view=diff
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/XplainStatisticsTest.java (original)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/XplainStatisticsTest.java Tue Jun 24 07:37:46 2014
@@ -21,9 +21,11 @@
 
 package org.apache.derbyTesting.functionTests.tests.lang;
 
+import java.io.ByteArrayOutputStream;
 import java.io.FileInputStream;
 import java.io.IOException;
 import java.io.InputStream;
+import java.io.PrintStream;
 import java.net.MalformedURLException;
 import java.security.AccessController;
 import java.security.PrivilegedActionException;
@@ -47,7 +49,7 @@ import junit.framework.Test;
 import junit.framework.TestSuite;
 
 import org.apache.derby.impl.tools.planexporter.AccessDatabase;
-import org.apache.derby.impl.tools.planexporter.CreateXMLFile;
+import org.apache.derby.tools.PlanExporter;
 import org.apache.derbyTesting.junit.BaseJDBCTestCase;
 import org.apache.derbyTesting.junit.CleanDatabaseTestSetup;
 import org.apache.derbyTesting.junit.JDBC;
@@ -536,9 +538,11 @@ public class XplainStatisticsTest extend
     /**
      * 
      * @param s
+     * @param exportPlan whether or not the PlanExporter tool should be used
+     *                   to export the plan of the recorded statements
      * @throws Exception
      */
-    private static void disableXplainStyle(Statement s)
+    private static void disableXplainStyle(Statement s, boolean exportPlan)
     throws Exception
     {
     	s.execute("call SYSCS_UTIL.SYSCS_SET_RUNTIMESTATISTICS(0)");
@@ -547,31 +551,22 @@ public class XplainStatisticsTest extend
     	 * Added by DERBY-4587 to test the generation of XML files
     	 * from PlanExporter tool.
     	 */
-    	String stmt_id="";
-    	ResultSet rs;
-    	AccessDatabase access;
+        if (exportPlan) {
+            String dbUrl = s.getConnection().getMetaData().getURL();
+
+            ResultSet rs = s.executeQuery(
+                    "select stmt_id from XPLTEST.sysxplain_statements");
+            while (rs.next()) {
+                String stmt_id = rs.getString(1);
+                String output = invokePlanExporterTool(
+                    dbUrl, "XPLTEST", stmt_id, "-xml",
+                    SupportFilesSetup.getReadWriteFileName(stmt_id + ".xml"));
+
+                // Expect the plan exporter tool to print nothing on success.
+                assertEquals("Unexpected output from PlanExporter", "", output);
+            }
+        }
 
-    	rs = s.executeQuery( 
-    			"select stmt_id from XPLTEST.sysxplain_statements"); 
-    	while (rs.next()) 
-    	{ 
-    		stmt_id = rs.getString(1); 
-    		access = 
-    			new AccessDatabase(s.getConnection(), "XPLTEST", stmt_id);
-    		if(access.initializeDataArray()){ 
-    			access.createXMLFragment();
-    			access.markTheDepth();
-
-    			CreateXMLFile xml_file = new CreateXMLFile(access); 
-    			xml_file.writeTheXMLFile(
-    					access.statement(),
-    					access.time(),
-    					access.getData(), 
-    					SupportFilesSetup.getReadWriteURL(stmt_id + ".xml")
-    					.getPath(),
-    					null);
-    		}
-    	} 
         s.execute("call syscs_util.syscs_set_xplain_schema('')");
     }
 
@@ -601,6 +596,37 @@ public class XplainStatisticsTest extend
         rs.close();
     }
 
+    /**
+     * Invoke the PlanExporter tool.
+     *
+     * @param args the command line arguments to pass to the tool
+     * @return the output printed by the tool (typically an empty string
+     * on successful execution)
+     */
+    private static String invokePlanExporterTool(String... args) {
+        PrintStream out = System.out;
+        PrintStream err = System.err;
+
+        ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
+        PrintStream testOutput = new PrintStream(byteOut);
+
+        // Redirect System.out and System.err so that the output
+        // can be captured.
+        setSystemOut(testOutput);
+        setSystemErr(testOutput);
+
+        try {
+            PlanExporter.main(args);
+        } finally {
+            // Restore System.out and System.err.
+            setSystemOut(out);
+            setSystemErr(err);
+        }
+
+        testOutput.flush();
+        return byteOut.toString();
+    }
+
     // Can be used internally when diagnosing failed tests.
     //
     private void dumpResultSets(Statement s)
@@ -806,24 +832,29 @@ public class XplainStatisticsTest extend
     public void testPlanExporterIllegalFileAccess()
 	throws Exception
     {
-	AccessDatabase access = 
-    		new AccessDatabase(getConnection(), "NoSuchSchema", "nostmt"); 
-    	CreateXMLFile xml_file = new CreateXMLFile(access); 
-	try
-	{
-    		xml_file.writeTheXMLFile("nostmt", "notime", null,
-			"/illegal.xml", null);
-		fail("Expected exception for illegal file access");
-	}
-	catch (java.security.AccessControlException ace)
-	{
-		// Expected this exception to be thrown
-	}
-	catch (Exception e)
-	{
-		e.printStackTrace();
-		fail(e.getMessage());
-	}
+        // Make sure there is a statement with recorded statistics.
+        Statement s = createStatement();
+        enableXplainStyle(s);
+        JDBC.assertDrainResults(s.executeQuery("values 1"));
+        disableXplainStyle(s, true);
+
+        // Get the id of the statement.
+        ResultSet rs = s.executeQuery(
+                "select stmt_id from XPLTEST.sysxplain_statements");
+        assertTrue("no statements", rs.next());
+        String stmt_id = rs.getString("stmt_id");
+        JDBC.assertEmpty(rs);
+
+        // Try to write the plan to a file that the tool does not have
+        // permission to write to.
+        String output = invokePlanExporterTool(
+                getConnection().getMetaData().getURL(), "XPLTEST",
+                stmt_id, "-xml", "/illegal.xml");
+
+        // The plan exporter tool should fail with a permission error.
+        if (!output.contains("java.security.AccessControlException")) {
+            fail("Unexpected output from PlanExporter: " + output);
+        }
     }
 
     /**
@@ -868,21 +899,18 @@ public class XplainStatisticsTest extend
         rs.close();
 
         // Create the XML file. This used to result in a syntax error.
-        AccessDatabase access =
-                new AccessDatabase(getConnection(), schema, stmtId);
-        assertTrue(access.initializeDataArray());
-        access.createXMLFragment();
-        access.markTheDepth();
-        CreateXMLFile create = new CreateXMLFile(access);
-        create.writeTheXMLFile(
-                access.statement(),
-                access.time(),
-                access.getData(),
-                SupportFilesSetup.getReadWriteURL(stmtId + ".xml").getPath(),
-                null);
+        String output = invokePlanExporterTool(
+                getConnection().getMetaData().getURL(),
+                schema,
+                stmtId,
+                "-xml",
+                SupportFilesSetup.getReadWriteFileName(stmtId + ".xml"));
+
+        // Expect empty output on successful execution of the tool.
+        assertEquals("Unexpected output from PlanExporter", "", output);
 
         // If we have the required libraries for parsing XML files, verify
-        // that the output contains valid data.
+        // that the XML file contains valid data.
         if (XML.classpathMeetsXMLReqs()) {
             assertEquals(query, readStatement(stmtId));
         }
@@ -964,7 +992,7 @@ public class XplainStatisticsTest extend
             new String[][] {  {"Belize"}, {"Costa Rica"}, {"El Salvador"},
                 {"Guatemala"}, {"Honduras"}, {"Nicaragua"} } );
 
-        disableXplainStyle(s);
+        disableXplainStyle(s, true);
         
         // The statement should have been executed as a PROJECTION
         // wrapped around a TABLESCAN. The TABLESCAN should have had
@@ -1112,7 +1140,7 @@ public class XplainStatisticsTest extend
         	"SELECT country from countries "+
 	         "WHERE region = 'Central America'" ));
         clearXplainOnlyMode(s);
-        disableXplainStyle(s);
+        disableXplainStyle(s, true);
 
 	// dumpStatements(s);
         // dumpResultSets(s);
@@ -1146,7 +1174,7 @@ public class XplainStatisticsTest extend
             "select sql_text from syscs_diag.transaction_table " +
 	    "where status != 'IDLE'" ));
         clearXplainOnlyMode(s);
-        disableXplainStyle(s);
+        disableXplainStyle(s, true);
 
 	//dumpStatements(s);
         //dumpResultSets(s);
@@ -1181,7 +1209,7 @@ public class XplainStatisticsTest extend
         JDBC.assertEmpty(s.executeQuery(selectStatement));
 
         clearXplainOnlyMode(s);
-        disableXplainStyle(s);
+        disableXplainStyle(s, true);
 	//dumpStatements(s);
         //dumpResultSets(s);
 
@@ -1239,7 +1267,7 @@ public class XplainStatisticsTest extend
         enableXplainOnlyMode(s);
         JDBC.assertEmpty(ps.executeQuery());
         clearXplainOnlyMode(s);
-        disableXplainStyle(s);
+        disableXplainStyle(s, true);
 	//dumpStatements(s);
         //dumpResultSets(s);
 
@@ -1303,7 +1331,7 @@ public class XplainStatisticsTest extend
         enableXplainOnlyMode(s);
         JDBC.assertEmpty(ps.executeQuery());
         clearXplainOnlyMode(s);
-        disableXplainStyle(s);
+        disableXplainStyle(s, true);
 
         // Verify that statistics were collected.
         JDBC.assertDrainResults(
@@ -1333,7 +1361,7 @@ public class XplainStatisticsTest extend
                 {"Europe", "29"}, {"Middle East", "7"},
                 {"North Africa", "5"}, {"North America", "3"},
                 {"Pacific Islands", "3"}, {"South America", "11"} } );
-        disableXplainStyle(s);
+        disableXplainStyle(s, true);
 	//dumpStatements(s);
         //dumpResultSets(s);
 
@@ -1574,7 +1602,7 @@ public class XplainStatisticsTest extend
         JDBC.assertUnorderedResultSet(s.executeQuery(selectStatement),
             new String[][] {  {"AA1112"}, {"AA1114"}, {"AA1116"} } );
 
-        disableXplainStyle(s);
+        disableXplainStyle(s, true);
 
         // This query should have been executed as a PROJECTION whose child
         // is a ROWIDSCAN whose child is an INDEXSCAN. The INDEXSCAN should
@@ -1669,7 +1697,7 @@ public class XplainStatisticsTest extend
             "SELECT region from countries where country = 'Cameroon'";
         JDBC.assertSingleValueResultSet(s.executeQuery(selectStatement),
                 "Africa");
-        disableXplainStyle(s);
+        disableXplainStyle(s, true);
         JDBC.assertUnorderedResultSet(s.executeQuery(
                     "select op_identifier from xpltest.sysxplain_resultsets"),
             new String[][] {
@@ -1744,7 +1772,7 @@ public class XplainStatisticsTest extend
                 {"North Africa", "5"}, {"North America", "3"},
                 {"Pacific Islands", "3"}, {"South America", "11"} } );
 
-        disableXplainStyle(s);
+        disableXplainStyle(s, true);
 
         // This statement is executed as a PROJECTION with a child GROUPBY
         // with a child PROJECTION with a child TABLESCAN. The TABLESCAN
@@ -1843,7 +1871,7 @@ public class XplainStatisticsTest extend
         // Execute the statement and throw away the results. We just want
         // to look at the statistics.
         s.executeQuery(selectStatement).close();
-        disableXplainStyle(s);
+        disableXplainStyle(s, true);
 
         JDBC.assertSingleValueResultSet(s.executeQuery(
             "select count(*) from xpltest.sysxplain_sort_props"), "1");
@@ -1907,7 +1935,7 @@ public class XplainStatisticsTest extend
         String selectStatement = 
             "select count(distinct region) from countries";
         JDBC.assertSingleValueResultSet(s.executeQuery(selectStatement), "12");
-        disableXplainStyle(s);
+        disableXplainStyle(s, true);
 
         // The above statement results in the query execution:
         // PROJECTION(AGGREGATION(PROJECTION(TABLESCAN)))
@@ -1969,7 +1997,7 @@ public class XplainStatisticsTest extend
             "insert into AIRLINES values " +
             "('AA','Amazonian Airways',0.18,0.03,0.5,1.5,20,10,5)";
         int numRows = s.executeUpdate(insertStatement);
-        disableXplainStyle(s);
+        disableXplainStyle(s, true);
         assertEquals("Failed to insert into AIRLINES", 1, numRows);
         JDBC.assertUnorderedResultSet(s.executeQuery(
                     "select stmt_type, stmt_text " +
@@ -2062,7 +2090,7 @@ public class XplainStatisticsTest extend
         enableXplainStyle(s);
         numRows = s.executeUpdate(updateStatement);
         assertEquals("Failed to update AIRLINES", 1, numRows);
-        disableXplainStyle(s);
+        disableXplainStyle(s, true);
         JDBC.assertUnorderedResultSet(s.executeQuery(
                     "select stmt_type, stmt_text " +
                     " from xpltest.sysxplain_statements"),
@@ -2219,7 +2247,7 @@ public class XplainStatisticsTest extend
         enableXplainStyle(s);
         numRows = s.executeUpdate(deleteStatement);
         assertEquals("Failed to delete from AIRLINES", 1, numRows);
-        disableXplainStyle(s);
+        disableXplainStyle(s, true);
         JDBC.assertUnorderedResultSet(s.executeQuery(
                     "select stmt_type, stmt_text " +
                     " from xpltest.sysxplain_statements"),
@@ -2291,7 +2319,7 @@ public class XplainStatisticsTest extend
         String selectStatement = 
             "select region from countries order by country";
         s.executeQuery(selectStatement).close(); // Discard the results
-        disableXplainStyle(s);
+        disableXplainStyle(s, true);
 
         // The above statement results in the query execution:
         // PROJECTION(SORT(PROJECTION(TABLESCAN)))
@@ -2373,7 +2401,7 @@ public class XplainStatisticsTest extend
             " union " +
             "select country from countries where region = 'Africa'";
         s.executeQuery(selectStatement).close(); // Discard the results
-        disableXplainStyle(s);
+        disableXplainStyle(s, true);
 
         // The above statement results in the query execution:
         // SORT(UNION(PROJECTION(TABLESCAN),PROJECTION(TABLESCAN)))
@@ -2477,7 +2505,11 @@ public class XplainStatisticsTest extend
         String ddlStatement = 
             "create table t1 (a int, b char(10), c timestamp)";
         s.executeUpdate(ddlStatement);
-        disableXplainStyle(s);
+
+        // Don't run the PlanExporter tool on this statement. There is no
+        // result set graph recorded for DDL statements, so the PlanExporter
+        // tool will complain.
+        disableXplainStyle(s, false);
 
         JDBC.assertUnorderedResultSet(s.executeQuery(
                     "select stmt_type, stmt_text " +
@@ -2498,7 +2530,7 @@ public class XplainStatisticsTest extend
         String selectStatement = 
             "select max(country_iso_code) from countries";
         s.executeQuery(selectStatement).close();
-        disableXplainStyle(s);
+        disableXplainStyle(s, true);
 
         // The above query is executed as
         // PROJECTION(AGGREGATION(PROJECTION(LASTINDEXKEYSCAN)))
@@ -2613,7 +2645,7 @@ public class XplainStatisticsTest extend
                     {"ABQ",null},{"OKC",null},{"AKL",null},{"HNL",null},
                     {"AKL",null},{"NRT",null}
         });
-        disableXplainStyle(s);
+        disableXplainStyle(s, true);
 
         // We should get a Nested Loop Outer Join which  reads 10 rows
         // from the left (SEEN_ROWS), constructs 10 EMPTY_RIGHT_ROWS,
@@ -2708,7 +2740,7 @@ public class XplainStatisticsTest extend
         enableXplainStyle(s);
         for (int i = 0; i < searches.length; i++)
             s.executeQuery(searches[i]).close();
-        disableXplainStyle(s);
+        disableXplainStyle(s, true);
 
         ResultSet rs = s.executeQuery(
                 "select s.stmt_text, sp.start_position, sp.stop_position " +
@@ -2781,7 +2813,7 @@ public class XplainStatisticsTest extend
         String selectStatement = "select x from t";
         JDBC.assertUnorderedResultSet(s.executeQuery(selectStatement),
                 new String[][] { {"1"},{"2"},{"4"} });
-        disableXplainStyle(s);
+        disableXplainStyle(s, true);
         
         // There should be a CONSTRAINTSCAN result set with a SCAN PROPS
         // which indicates that we visited 1 deleted row while scanning
@@ -2854,7 +2886,7 @@ public class XplainStatisticsTest extend
         Statement s = createStatement();
         enableXplainStyle(s);
         JDBC.assertEmpty(s.executeQuery(sql));
-        disableXplainStyle(s);
+        disableXplainStyle(s, true);
 
         // Now, see if we find the query among the recorded statements.
         PreparedStatement ps = prepareStatement(
@@ -2905,7 +2937,7 @@ public class XplainStatisticsTest extend
 
         enableXplainStyle(s);
         JDBC.assertEmpty(s.executeQuery(queryText));
-        disableXplainStyle(s);
+        disableXplainStyle(s, true);
 
         ResultSet rs = s.executeQuery(
                 "SELECT STMT_ID, STMT_TEXT FROM XPLTEST.SYSXPLAIN_STATEMENTS");
@@ -2941,7 +2973,7 @@ public class XplainStatisticsTest extend
 
         enableXplainStyle(s);
         JDBC.assertEmpty(s.executeQuery(queryText));
-        disableXplainStyle(s);
+        disableXplainStyle(s, true);
 
         ResultSet rs = s.executeQuery(
         "SELECT STMT_ID, STMT_TEXT FROM XPLTEST.SYSXPLAIN_STATEMENTS");

Modified: db/derby/code/trunk/java/testing/org/apache/derbyTesting/junit/BaseTestCase.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/junit/BaseTestCase.java?rev=1605021&r1=1605020&r2=1605021&view=diff
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/junit/BaseTestCase.java (original)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/junit/BaseTestCase.java Tue Jun 24 07:37:46 2014
@@ -257,7 +257,7 @@ public abstract class BaseTestCase
      *
      * @param out the new stream
      */
-    protected void setSystemOut(final PrintStream out) {
+    protected static void setSystemOut(final PrintStream out) {
         AccessController.doPrivileged(new PrivilegedAction<Void>() {
             public Void run() {
                 System.setOut(out);
@@ -271,7 +271,7 @@ public abstract class BaseTestCase
      *
      * @param err the new stream
      */
-    protected void setSystemErr(final PrintStream err) {
+    protected static void setSystemErr(final PrintStream err) {
         AccessController.doPrivileged(new PrivilegedAction<Void>() {
             public Void run() {
                 System.setErr(err);

Modified: db/derby/code/trunk/java/tools/org/apache/derby/impl/tools/planexporter/CreateXMLFile.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/tools/org/apache/derby/impl/tools/planexporter/CreateXMLFile.java?rev=1605021&r1=1605020&r2=1605021&view=diff
==============================================================================
--- db/derby/code/trunk/java/tools/org/apache/derby/impl/tools/planexporter/CreateXMLFile.java (original)
+++ db/derby/code/trunk/java/tools/org/apache/derby/impl/tools/planexporter/CreateXMLFile.java Tue Jun 24 07:37:46 2014
@@ -21,14 +21,8 @@
 
 package org.apache.derby.impl.tools.planexporter;
 
-import java.io.BufferedWriter;
-import java.io.FileOutputStream;
 import java.io.IOException;
-import java.io.OutputStreamWriter;
 import java.io.Writer;
-import java.security.AccessController;
-import java.security.PrivilegedActionException;
-import java.security.PrivilegedExceptionAction;
 
 /**
  * This class is to create the final xml file, that will be used
@@ -46,15 +40,12 @@ public class CreateXMLFile {
     /**
      * @param stmt statement executed
      * @param time time which the statement was executed
-     * @param data large xml data string array
-     * @param file_name name of the file to be written
+     * @param out where to write the XML file
      * @param xsl_sheet_name name of the style sheet
-     * @throws PrivilegedActionException
      * @throws IOException
-     * @throws PrivilegedActionException
      */
     public void writeTheXMLFile(String stmt, String time,
-            TreeNode[] data, final String file_name, String xsl_sheet_name)
+                                Writer out, String xsl_sheet_name)
     throws IOException {
 
         String defaultXML = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
@@ -68,20 +59,6 @@ public class CreateXMLFile {
         String childTagStart = "<details>\n";
         String childTagEnd = "</details>\n";
 
-        FileOutputStream fos;
-        try {
-            fos = AccessController.doPrivileged(
-                    new PrivilegedExceptionAction<FileOutputStream>() {
-                        public FileOutputStream run() throws IOException {
-                            return new FileOutputStream(file_name);
-                        }
-                    });
-        } catch (PrivilegedActionException pae) {
-            throw (IOException) pae.getCause();
-        }
-
-        Writer out = new BufferedWriter(new OutputStreamWriter(fos, "UTF-8"));
-
         out.write(defaultXML);
 
         out.write(embedXSL);
@@ -106,6 +83,5 @@ public class CreateXMLFile {
         out.write(childTagEnd);
 
         out.write(parentTagEnd);
-        out.close();
     }
 }

Modified: db/derby/code/trunk/java/tools/org/apache/derby/tools/PlanExporter.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/tools/org/apache/derby/tools/PlanExporter.java?rev=1605021&r1=1605020&r2=1605021&view=diff
==============================================================================
--- db/derby/code/trunk/java/tools/org/apache/derby/tools/PlanExporter.java (original)
+++ db/derby/code/trunk/java/tools/org/apache/derby/tools/PlanExporter.java Tue Jun 24 07:37:46 2014
@@ -22,7 +22,13 @@
 package org.apache.derby.tools;
 
 import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStreamWriter;
+import java.io.Writer;
 import java.security.AccessController;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
 import org.apache.derby.impl.tools.planexporter.AccessDatabase;
 import org.apache.derby.impl.tools.planexporter.CreateHTMLFile;
 import org.apache.derby.impl.tools.planexporter.CreateXMLFile;
@@ -225,22 +231,34 @@ public class PlanExporter {
      * @param stmt statement executed
      * @param time time which the statement was executed
      * @param xsl name of the style sheet
-     * @throws Exception
+     * @throws IOException if an error occurs when writing the XML file
      */
     private static void generateXML(AccessDatabase access,
-            String arg, String stmt, String time, String xsl) throws Exception{
+            String arg, String stmt, String time, String xsl)
+            throws IOException {
         CreateXMLFile xmlFile = new CreateXMLFile(access);
 
-        if(arg.toUpperCase().endsWith(".XML")){
-            xmlFile.writeTheXMLFile(stmt, time,
-                    access.getData(),
-                    arg, xsl);
+        final String fileName = arg.toUpperCase().endsWith(".XML")
+                                ? arg : (arg + ".xml");
+
+        Writer out;
+        try {
+            out = AccessController.doPrivileged(
+                    new PrivilegedExceptionAction<Writer>() {
+                @Override
+                public Writer run() throws IOException {
+                    return new OutputStreamWriter(
+                            new FileOutputStream(fileName), "UTF-8");
+                }
+            });
+        } catch (PrivilegedActionException pae) {
+            throw (IOException) pae.getCause();
         }
-        else{
-            xmlFile.writeTheXMLFile(stmt, time,
-                    access.getData(),
-                    arg.concat(".xml"),
-                    xsl);
+
+        try {
+            xmlFile.writeTheXMLFile(stmt, time, out, xsl);
+        } finally {
+            out.close();
         }
     }