1 /*
   2  * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 package sax;
  25 
  26 import static jaxp.library.JAXPTestUtilities.runWithAllPerm;
  27 
  28 import java.io.StringReader;
  29 
  30 import javax.xml.parsers.SAXParser;
  31 import javax.xml.parsers.SAXParserFactory;
  32 
  33 import org.testng.Assert;
  34 import org.testng.annotations.Listeners;
  35 import org.testng.annotations.Test;
  36 import org.xml.sax.InputSource;
  37 import org.xml.sax.helpers.DefaultHandler;
  38 
  39 /*
  40  * @test
  41  * @bug 8173390 8176168
  42  * @library /javax/xml/jaxp/libs /javax/xml/jaxp/unittest
  43  * @run testng/othervm -Djdk.xml.resetSymbolTable=false sax.SymbolTableResetTest
  44  * @run testng/othervm -Djdk.xml.resetSymbolTable=true sax.SymbolTableResetTest
  45  * @run testng/othervm -Djdk.xml.resetSymbolTable=false -DrunSecMngr=true sax.SymbolTableResetTest
  46  * @run testng/othervm -Djdk.xml.resetSymbolTable=true -DrunSecMngr=true sax.SymbolTableResetTest
  47  * @summary Test that SAXParser reallocates symbol table during
  48  *          subsequent parse operations
  49  */
  50 @Listeners({jaxp.library.BasePolicy.class})
  51 public class SymbolTableResetTest {
  52 
  53     /*
  54      * Test verifies the following use cases when the parser feature is not set:
  55      *  a) Reset symbol table is requested via the system property
  56      *  b) Reset symbol table is not requested via the system property
  57      *     and therefore the default value should be used - reset
  58      *     operation should not occur.
  59      */
  60     @Test
  61     public void testNoFeatureSet() throws Exception {
  62         parseAndCheckReset(false, false);
  63     }
  64 
  65 
  66     /*
  67      * Test that when symbol table reset is requested through parser
  68      * feature it is not affected by the system property value
  69      */
  70     @Test
  71     public void testResetEnabled() throws Exception {
  72         parseAndCheckReset(true, true);
  73     }
  74 
  75     /*
  76      * Test that when symbol table reset is disabled through parser
  77      * feature it is not affected by the system property value
  78      */
  79     @Test
  80     public void testResetDisabled() throws Exception {
  81         parseAndCheckReset(true, false);
  82     }
  83 
  84     /*
  85      * Test mimics the SAXParser usage in SAAJ-RI that reuses the
  86      * parsers from the internal pool. To avoid memory leaks, symbol
  87      * table associated with the parser should be reallocated during each
  88      * parse() operation.
  89      */
  90     private void parseAndCheckReset(boolean setFeature, boolean value) throws Exception {
  91         // Expected result based on system property and feature
  92         boolean resetExpected = setFeature && value;
  93         // Indicates if system property is set
  94         boolean spSet = runWithAllPerm(() -> System.getProperty(RESET_FEATURE)) != null;
  95         // Dummy xml input for parser
  96         String input = "<dummy>Test</dummy>";
  97 
  98         // Check if system property is set only when feature setting is not requested
  99         // and estimate if reset of symbol table is expected
 100         if (!setFeature && spSet) {
 101             resetExpected = runWithAllPerm(() -> Boolean.getBoolean(RESET_FEATURE));
 102         }
 103 
 104         // Create SAXParser and set feature if it is requested
 105         SAXParserFactory spf = SAXParserFactory.newInstance();
 106         if (setFeature) {
 107             spf.setFeature(RESET_FEATURE, value);
 108         }
 109         SAXParser p = spf.newSAXParser();
 110 
 111         // First parse iteration
 112         p.parse(new InputSource(new StringReader(input)), new DefaultHandler());
 113         // Get first symbol table reference
 114         Object symTable1 = p.getProperty(SYMBOL_TABLE_PROPERTY);
 115 
 116         // reset parser
 117         p.reset();
 118 
 119         // Second parse iteration
 120         p.parse(new InputSource(new StringReader(input)), new DefaultHandler());
 121         // Get second symbol table reference
 122         Object symTable2 = p.getProperty(SYMBOL_TABLE_PROPERTY);
 123 
 124         // Check symbol table references after two subsequent parse operations
 125         if (resetExpected) {
 126             Assert.assertNotSame(symTable1, symTable2, "Symbol table references");
 127         } else {
 128             Assert.assertSame(symTable1, symTable2, "Symbol table references");
 129         }
 130     }
 131 
 132     // Reset symbol table feature
 133     private static final String RESET_FEATURE = "jdk.xml.resetSymbolTable";
 134 
 135     // Symbol table property
 136     private static final String SYMBOL_TABLE_PROPERTY = "http://apache.org/xml/properties/internal/symbol-table";
 137 }