Repository: oozie
Updated Branches:
  refs/heads/master ef6d0af5e -> ba665da34


Fix parsing issue (satishsaley, asasvari)


Project: http://git-wip-us.apache.org/repos/asf/oozie/repo
Commit: http://git-wip-us.apache.org/repos/asf/oozie/commit/ba665da3
Tree: http://git-wip-us.apache.org/repos/asf/oozie/tree/ba665da3
Diff: http://git-wip-us.apache.org/repos/asf/oozie/diff/ba665da3

Branch: refs/heads/master
Commit: ba665da34c23b1fa86bf1570724147e6f8c85b1d
Parents: ef6d0af
Author: Attila Sasvari <asasv...@cloudera.com>
Authored: Sun Feb 4 11:51:41 2018 +0100
Committer: Attila Sasvari <asasv...@cloudera.com>
Committed: Sun Feb 4 21:39:34 2018 +0100

----------------------------------------------------------------------
 .../command/bundle/BundleSubmitXCommand.java    |   3 +-
 .../command/coord/CoordSubmitXCommand.java      |   3 +-
 .../oozie/service/ConfigurationService.java     |  24 +++--
 .../oozie/service/HadoopAccessorService.java    |   2 +-
 .../org/apache/oozie/service/SchemaService.java |  64 ++++++++++-
 .../org/apache/oozie/service/XLogService.java   |   4 +-
 .../apache/oozie/servlet/V2ValidateServlet.java |   6 +-
 .../org/apache/oozie/util/XConfiguration.java   | 106 ++++++++++++++-----
 .../java/org/apache/oozie/util/XmlUtils.java    |  65 +++++-------
 .../workflow/lite/LiteWorkflowAppParser.java    |  44 ++++----
 .../apache/oozie/service/TestSchemaService.java |   8 +-
 .../apache/oozie/util/TestXConfiguration.java   |  41 +++----
 .../org/apache/oozie/util/TestXmlUtils.java     |  16 ++-
 13 files changed, 246 insertions(+), 140 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/oozie/blob/ba665da3/core/src/main/java/org/apache/oozie/command/bundle/BundleSubmitXCommand.java
----------------------------------------------------------------------
diff --git 
a/core/src/main/java/org/apache/oozie/command/bundle/BundleSubmitXCommand.java 
b/core/src/main/java/org/apache/oozie/command/bundle/BundleSubmitXCommand.java
index 3a17234..dff2223 100644
--- 
a/core/src/main/java/org/apache/oozie/command/bundle/BundleSubmitXCommand.java
+++ 
b/core/src/main/java/org/apache/oozie/command/bundle/BundleSubmitXCommand.java
@@ -348,9 +348,8 @@ public class BundleSubmitXCommand extends 
SubmitTransitionXCommand {
      * @throws BundleJobException thrown if failed to validate xml
      */
     private void validateXml(String xmlContent) throws BundleJobException {
-        javax.xml.validation.Schema schema = 
Services.get().get(SchemaService.class).getSchema(SchemaName.BUNDLE);
-        Validator validator = schema.newValidator();
         try {
+            Validator validator = 
Services.get().get(SchemaService.class).getValidator(SchemaName.BUNDLE);
             validator.validate(new StreamSource(new StringReader(xmlContent)));
         }
         catch (SAXException ex) {

http://git-wip-us.apache.org/repos/asf/oozie/blob/ba665da3/core/src/main/java/org/apache/oozie/command/coord/CoordSubmitXCommand.java
----------------------------------------------------------------------
diff --git 
a/core/src/main/java/org/apache/oozie/command/coord/CoordSubmitXCommand.java 
b/core/src/main/java/org/apache/oozie/command/coord/CoordSubmitXCommand.java
index fecf006..42bdc99 100644
--- a/core/src/main/java/org/apache/oozie/command/coord/CoordSubmitXCommand.java
+++ b/core/src/main/java/org/apache/oozie/command/coord/CoordSubmitXCommand.java
@@ -507,9 +507,8 @@ public class CoordSubmitXCommand extends 
SubmitTransitionXCommand {
      * @throws CoordinatorJobException thrown if unable to validate 
coordinator xml
      */
     private void validateXml(String xmlContent) throws CoordinatorJobException 
{
-        javax.xml.validation.Schema schema = 
Services.get().get(SchemaService.class).getSchema(SchemaName.COORDINATOR);
-        Validator validator = schema.newValidator();
         try {
+            Validator validator = 
Services.get().get(SchemaService.class).getValidator(SchemaName.COORDINATOR);
             validator.validate(new StreamSource(new StringReader(xmlContent)));
         }
         catch (SAXException ex) {

http://git-wip-us.apache.org/repos/asf/oozie/blob/ba665da3/core/src/main/java/org/apache/oozie/service/ConfigurationService.java
----------------------------------------------------------------------
diff --git 
a/core/src/main/java/org/apache/oozie/service/ConfigurationService.java 
b/core/src/main/java/org/apache/oozie/service/ConfigurationService.java
index 15076de..618d5e6 100644
--- a/core/src/main/java/org/apache/oozie/service/ConfigurationService.java
+++ b/core/src/main/java/org/apache/oozie/service/ConfigurationService.java
@@ -19,13 +19,15 @@
 package org.apache.oozie.service;
 
 import com.google.common.base.Strings;
+import com.google.common.annotations.VisibleForTesting;
 import org.apache.hadoop.conf.Configuration;
+import org.apache.oozie.ErrorCode;
 import org.apache.oozie.util.ConfigUtils;
 import org.apache.oozie.util.Instrumentable;
 import org.apache.oozie.util.Instrumentation;
-import org.apache.oozie.util.XLog;
 import org.apache.oozie.util.XConfiguration;
-import org.apache.oozie.ErrorCode;
+import org.apache.oozie.util.XLog;
+import org.apache.oozie.util.ZKUtils;
 
 import java.io.File;
 import java.io.FileInputStream;
@@ -34,15 +36,11 @@ import java.io.InputStream;
 import java.io.StringWriter;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
+import java.util.Arrays;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Map;
 import java.util.Set;
-import java.util.Arrays;
-
-import org.apache.oozie.util.ZKUtils;
-
-import com.google.common.annotations.VisibleForTesting;
 
 import javax.xml.parsers.DocumentBuilderFactory;
 
@@ -122,6 +120,13 @@ public class ConfigurationService implements Service, 
Instrumentable {
         // These properties should be masked when displayed because they 
contain sensitive info (e.g. password)
         MASK_PROPS.add(JPAService.CONF_PASSWORD);
         MASK_PROPS.add("oozie.authentication.signature.secret");
+
+        try {
+            Method method = 
Configuration.class.getDeclaredMethod("setRestrictSystemPropertiesDefault", 
boolean
+                    .class);
+            method.invoke(null, true);
+        } catch( NoSuchMethodException | InvocationTargetException | 
IllegalAccessException ignore) {
+        }
     }
 
     public static final String DEFAULT_CONFIG_FILE = "oozie-default.xml";
@@ -303,6 +308,7 @@ public class ConfigurationService implements Service, 
Instrumentable {
     private XConfiguration loadConfig(InputStream inputStream, boolean 
defaultConfig) throws IOException, ServiceException {
         XConfiguration configuration;
         configuration = new XConfiguration(inputStream);
+        configuration.setRestrictSystemProperties(false);
         for(Map.Entry<String,String> entry: configuration) {
             if (defaultConfig) {
                 defaultConfigs.put(entry.getKey(), entry.getValue());
@@ -322,6 +328,10 @@ public class ConfigurationService implements Service, 
Instrumentable {
                     setValue(entry.getKey(), entry.getValue());
                 }
             }
+            if(conf instanceof XConfiguration) {
+                
this.setRestrictParser(((XConfiguration)conf).getRestrictParser());
+                
this.setRestrictSystemProperties(((XConfiguration)conf).getRestrictSystemProperties());
+            }
         }
 
         @Override

http://git-wip-us.apache.org/repos/asf/oozie/blob/ba665da3/core/src/main/java/org/apache/oozie/service/HadoopAccessorService.java
----------------------------------------------------------------------
diff --git 
a/core/src/main/java/org/apache/oozie/service/HadoopAccessorService.java 
b/core/src/main/java/org/apache/oozie/service/HadoopAccessorService.java
index 73300a6..05cdc55 100644
--- a/core/src/main/java/org/apache/oozie/service/HadoopAccessorService.java
+++ b/core/src/main/java/org/apache/oozie/service/HadoopAccessorService.java
@@ -266,7 +266,7 @@ public class HadoopAccessorService implements Service {
             File f = new File(dir, file);
             if (f.exists()) {
                 InputStream is = new FileInputStream(f);
-                Configuration conf = new XConfiguration(is);
+                Configuration conf = new XConfiguration(is, false);
                 is.close();
                 XConfiguration.copy(conf, hadoopConf);
             }

http://git-wip-us.apache.org/repos/asf/oozie/blob/ba665da3/core/src/main/java/org/apache/oozie/service/SchemaService.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/oozie/service/SchemaService.java 
b/core/src/main/java/org/apache/oozie/service/SchemaService.java
index 9d2a521..14d1eeb 100644
--- a/core/src/main/java/org/apache/oozie/service/SchemaService.java
+++ b/core/src/main/java/org/apache/oozie/service/SchemaService.java
@@ -28,11 +28,18 @@ import javax.xml.XMLConstants;
 import javax.xml.transform.stream.StreamSource;
 import javax.xml.validation.Schema;
 import javax.xml.validation.SchemaFactory;
+import javax.xml.validation.Validator;
 
 import org.apache.oozie.ErrorCode;
 import org.apache.oozie.util.IOUtils;
 import org.apache.oozie.util.schema.ResourceResolver;
+import org.apache.xerces.xni.XMLResourceIdentifier;
+import org.apache.xerces.xni.XNIException;
+import org.apache.xerces.xni.parser.XMLEntityResolver;
+import org.apache.xerces.xni.parser.XMLInputSource;
 import org.xml.sax.SAXException;
+import org.xml.sax.SAXNotRecognizedException;
+import org.xml.sax.SAXNotSupportedException;
 
 
 /**
@@ -75,6 +82,10 @@ public class SchemaService implements Service {
 
     private Schema slaSchema;
 
+    private SchemaFactory schemaFactory;
+
+    private static NoXMLEntityResolver xmlEntityResolver;
+
     private Schema loadSchema(String baseSchemas, String extSchema) throws 
SAXException, IOException {
         Set<String> schemaNames = new HashSet<String>();
         String[] schemas = ConfigurationService.getStrings(baseSchemas);
@@ -101,9 +112,8 @@ public class SchemaService implements Service {
             s.setSystemId(schemaName);
             sources.add(s);
         }
-        SchemaFactory factory = 
SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
-        factory.setResourceResolver(new ResourceResolver());
-        return factory.newSchema(sources.toArray(new 
StreamSource[sources.size()]));
+        schemaFactory.setResourceResolver(new ResourceResolver());
+        return schemaFactory.newSchema(sources.toArray(new 
StreamSource[sources.size()]));
     }
 
     /**
@@ -115,10 +125,12 @@ public class SchemaService implements Service {
     @Override
     public void init(Services services) throws ServiceException {
         try {
+            schemaFactory = createSchemaFactory();
             wfSchema = loadSchema(WF_CONF_SCHEMAS, WF_CONF_EXT_SCHEMAS);
             coordSchema = loadSchema(COORD_CONF_SCHEMAS, 
COORD_CONF_EXT_SCHEMAS);
             bundleSchema = loadSchema(BUNDLE_CONF_SCHEMAS, 
BUNDLE_CONF_EXT_SCHEMAS);
             slaSchema = loadSchema(SLA_CONF_SCHEMAS, SLA_CONF_EXT_SCHEMAS);
+            xmlEntityResolver = new NoXMLEntityResolver();
         }
         catch (SAXException ex) {
             throw new ServiceException(ErrorCode.E0130, ex.getMessage(), ex);
@@ -129,6 +141,19 @@ public class SchemaService implements Service {
     }
 
     /**
+     * Creates schema factory
+     * @return
+     * @throws SAXNotRecognizedException
+     * @throws SAXNotSupportedException
+     */
+    private SchemaFactory createSchemaFactory() throws 
SAXNotRecognizedException, SAXNotSupportedException {
+        SchemaFactory factory = 
SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
+        
factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl";, 
true);
+        factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING,true);
+        return factory;
+    }
+
+    /**
      * Return the public interface of the service.
      *
      * @return {@link SchemaService}.
@@ -188,4 +213,37 @@ public class SchemaService implements Service {
             return id;
         }
     }
+
+    /**
+     * Returns validator for schema
+     * @param schemaName
+     * @return
+     * @throws SAXException
+     */
+    public Validator getValidator(SchemaName schemaName) throws SAXException {
+        return getValidator(getSchema(schemaName));
+    }
+
+    /**
+     * Returns validator for schema
+     * @param schema
+     * @return
+     * @throws SAXException
+     */
+    public static Validator getValidator(Schema schema) throws SAXException {
+        Validator validator = schema.newValidator();
+        
validator.setFeature("http://apache.org/xml/features/disallow-doctype-decl";, 
true);
+        
validator.setFeature("http://xml.org/sax/features/external-general-entities";, 
false);
+        
validator.setFeature("http://xml.org/sax/features/external-parameter-entities";, 
false);
+        
validator.setProperty("http://apache.org/xml/properties/internal/entity-resolver";,
 xmlEntityResolver);
+        return validator;
+    }
+
+    private static class NoXMLEntityResolver implements XMLEntityResolver {
+        @Override
+        public XMLInputSource resolveEntity(XMLResourceIdentifier 
xmlResourceIdentifier) throws XNIException, IOException {
+            throw new IOException("DOCTYPE is disallowed when the feature 
http://apache.org/xml/features/disallow-doctype-decl "
+                    + "set to true.");
+        }
+    }
 }

http://git-wip-us.apache.org/repos/asf/oozie/blob/ba665da3/core/src/main/java/org/apache/oozie/service/XLogService.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/oozie/service/XLogService.java 
b/core/src/main/java/org/apache/oozie/service/XLogService.java
index 0b43722..1ac82f5 100644
--- a/core/src/main/java/org/apache/oozie/service/XLogService.java
+++ b/core/src/main/java/org/apache/oozie/service/XLogService.java
@@ -144,6 +144,7 @@ public class XLogService implements Service, Instrumentable 
{
         String oozieHome = Services.getOozieHome();
         String oozieLogs = System.getProperty(OOZIE_LOG_DIR, oozieHome + 
"/logs");
         System.setProperty(OOZIE_LOG_DIR, oozieLogs);
+
         try {
             LogManager.resetConfiguration();
             log4jFileName = System.getProperty(LOG4J_FILE, 
DEFAULT_LOG4J_PROPERTIES);
@@ -211,7 +212,8 @@ public class XLogService implements Service, Instrumentable 
{
         Properties props = new Properties();
         props.load(is);
 
-        Configuration conf = new XConfiguration();
+        XConfiguration conf = new XConfiguration();
+        conf.setRestrictSystemProperties(false);
         for (Map.Entry entry : props.entrySet()) {
             conf.set((String) entry.getKey(), (String) entry.getValue());
         }

http://git-wip-us.apache.org/repos/asf/oozie/blob/ba665da3/core/src/main/java/org/apache/oozie/servlet/V2ValidateServlet.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/oozie/servlet/V2ValidateServlet.java 
b/core/src/main/java/org/apache/oozie/servlet/V2ValidateServlet.java
index 7bf8fb3..b86fa6a 100644
--- a/core/src/main/java/org/apache/oozie/servlet/V2ValidateServlet.java
+++ b/core/src/main/java/org/apache/oozie/servlet/V2ValidateServlet.java
@@ -137,8 +137,8 @@ public class V2ValidateServlet extends JsonRestServlet {
     }
 
     private void validateSchema(Schema schema, Reader src) throws 
SAXException, IOException, OozieCLIException{
-            Validator validator = schema.newValidator();
-            validator.validate(new StreamSource(src));
+        Validator validator = SchemaService.getValidator(schema);
+        validator.validate(new StreamSource(src));
     }
 
     private JSONObject createJSON(String content) {
@@ -147,4 +147,4 @@ public class V2ValidateServlet extends JsonRestServlet {
         return jsonObject;
     }
 
-}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/oozie/blob/ba665da3/core/src/main/java/org/apache/oozie/util/XConfiguration.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/oozie/util/XConfiguration.java 
b/core/src/main/java/org/apache/oozie/util/XConfiguration.java
index bd62cb1..e3591db 100644
--- a/core/src/main/java/org/apache/oozie/util/XConfiguration.java
+++ b/core/src/main/java/org/apache/oozie/util/XConfiguration.java
@@ -50,6 +50,8 @@ public class XConfiguration extends Configuration {
 
     public static final String CONFIGURATION_SUBSTITUTE_DEPTH = 
"oozie.configuration.substitute.depth";
 
+    private boolean restrictSystemProperties = true;
+    private boolean restrictParser = true;
     /**
      * Create an empty configuration. <p> Default values are not loaded.
      */
@@ -62,25 +64,49 @@ public class XConfiguration extends Configuration {
      * Create a configuration from an InputStream. <p> Code canibalized from 
<code>Configuration.loadResource()</code>.
      *
      * @param is inputstream to read the configuration from.
+     * @param restrictParser whether to restrict the parser
      * @throws IOException thrown if the configuration could not be read.
      */
-    public XConfiguration(InputStream is) throws IOException {
+    public XConfiguration(InputStream is, boolean restrictParser) throws 
IOException {
         this();
+        this.restrictParser = restrictParser;
         parse(is);
     }
 
     /**
+     * Create a configuration from an InputStream. <p> Code canibalized from 
<code>Configuration.loadResource()</code>.
+     *
+     * @param is inputstream to read the configuration from.
+     * @throws IOException thrown if the configuration could not be read.
+     */
+    public XConfiguration(InputStream is) throws IOException {
+        this(is, true);
+    }
+
+    /**
      * Create a configuration from an Reader. <p> Code canibalized from 
<code>Configuration.loadResource()</code>.
      *
      * @param reader reader to read the configuration from.
+     * @param restrictParser whether to restrict the parser
      * @throws IOException thrown if the configuration could not be read.
      */
-    public XConfiguration(Reader reader) throws IOException {
+    public XConfiguration(Reader reader, boolean restrictParser) throws 
IOException {
         this();
+        this.restrictParser = restrictParser;
         parse(reader);
     }
 
     /**
+     * Create a configuration from an Reader. <p> Code canibalized from 
<code>Configuration.loadResource()</code>.
+     *
+     * @param reader reader to read the configuration from.
+     * @throws IOException thrown if the configuration could not be read.
+     */
+    public XConfiguration(Reader reader) throws IOException {
+        this(reader, true);
+    }
+
+    /**
      * Create an configuration from a Properties instance.
      *
      * @param props Properties instance to get all properties from.
@@ -90,7 +116,6 @@ public class XConfiguration extends Configuration {
         for (Map.Entry entry : props.entrySet()) {
             set((String) entry.getKey(), (String) entry.getValue());
         }
-
     }
 
     /**
@@ -123,7 +148,7 @@ public class XConfiguration extends Configuration {
      */
     @Override
     public String get(String name) {
-      return substituteVars(getRaw(name));
+        return substituteVars(getRaw(name));
     }
 
     /**
@@ -173,8 +198,9 @@ public class XConfiguration extends Configuration {
             var = var.substring(2, var.length() - 1); // remove ${ .. }
 
             String val = getRaw(var);
-            if (val == null) {
-                val = System.getProperty(var);
+
+            if (val == null && !this.restrictSystemProperties) {
+                val =  System.getProperty(var);
             }
 
             if (val == null) {
@@ -253,16 +279,7 @@ public class XConfiguration extends Configuration {
     // Canibalized from Hadoop <code>Configuration.loadResource()</code>.
     private void parse(InputStream is) throws IOException {
         try {
-            DocumentBuilderFactory docBuilderFactory = 
DocumentBuilderFactory.newInstance();
-            // support for includes in the xml file
-            docBuilderFactory.setNamespaceAware(true);
-            docBuilderFactory.setXIncludeAware(true);
-            // ignore all comments inside the xml file
-            docBuilderFactory.setIgnoringComments(true);
-            docBuilderFactory.setExpandEntityReferences(false);
-            
docBuilderFactory.setFeature("http://apache.org/xml/features/disallow-doctype-decl";,
 true);
-            DocumentBuilder builder = docBuilderFactory.newDocumentBuilder();
-            Document doc = builder.parse(is);
+            Document doc = getDocumentBuilder().parse(is);
             parseDocument(doc);
 
         }
@@ -277,16 +294,7 @@ public class XConfiguration extends Configuration {
     // Canibalized from Hadoop <code>Configuration.loadResource()</code>.
     private void parse(Reader reader) throws IOException {
         try {
-            DocumentBuilderFactory docBuilderFactory = 
DocumentBuilderFactory.newInstance();
-            // support for includes in the xml file
-            docBuilderFactory.setNamespaceAware(true);
-            docBuilderFactory.setXIncludeAware(true);
-            // ignore all comments inside the xml file
-            docBuilderFactory.setIgnoringComments(true);
-            docBuilderFactory.setExpandEntityReferences(false);
-            
docBuilderFactory.setFeature("http://apache.org/xml/features/disallow-doctype-decl";,
 true);
-            DocumentBuilder builder = docBuilderFactory.newDocumentBuilder();
-            Document doc = builder.parse(new InputSource(reader));
+            Document doc = getDocumentBuilder().parse(new InputSource(reader));
             parseDocument(doc);
         }
         catch (SAXException e) {
@@ -306,7 +314,7 @@ public class XConfiguration extends Configuration {
         processNodes(root);
     }
 
-    // Canibalized from Hadoop <code>Configuration.loadResource()</code>.
+    // Cannibalized from Hadoop <code>Configuration.loadResource()</code>.
     private void processNodes(Element root) throws IOException {
         try {
             NodeList props = root.getChildNodes();
@@ -392,4 +400,48 @@ public class XConfiguration extends Configuration {
         }
         return values;
     }
+
+    private DocumentBuilder getDocumentBuilder() throws 
ParserConfigurationException {
+        DocumentBuilderFactory docBuilderFactory = 
DocumentBuilderFactory.newInstance();
+        docBuilderFactory.setNamespaceAware(true);
+        
docBuilderFactory.setFeature("http://apache.org/xml/features/disallow-doctype-decl",true);
+        docBuilderFactory.setXIncludeAware(true);
+        if(this.restrictParser) {
+            docBuilderFactory.setXIncludeAware(false);
+            //Redundant with disallow-doctype, but just in case
+            
docBuilderFactory.setFeature("http://xml.org/sax/features/external-general-entities";,
 false);
+            
docBuilderFactory.setFeature("http://xml.org/sax/features/external-parameter-entities";,
 false);
+            
docBuilderFactory.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd";,
 false);
+        }
+        docBuilderFactory.setExpandEntityReferences(false);
+        // ignore all comments inside the xml file
+        docBuilderFactory.setIgnoringComments(true);
+        return docBuilderFactory.newDocumentBuilder();
+    }
+
+    /**
+     * Restrict the parser
+     * @param restrictParser
+     */
+    public void setRestrictParser(boolean restrictParser) {
+     this.restrictParser = restrictParser;
+    }
+
+    public boolean getRestrictParser() {
+        return restrictParser;
+    }
+    /**
+     * Restrict reading property from System.getProperty()
+     * @param restrictSystemProperties
+     */
+    public void setRestrictSystemProperties(boolean restrictSystemProperties) {
+        this.restrictSystemProperties = restrictSystemProperties;
+    }
+
+    public boolean getRestrictSystemProperties() {
+        return restrictSystemProperties;
+    }
+
+
+
 }

http://git-wip-us.apache.org/repos/asf/oozie/blob/ba665da3/core/src/main/java/org/apache/oozie/util/XmlUtils.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/oozie/util/XmlUtils.java 
b/core/src/main/java/org/apache/oozie/util/XmlUtils.java
index 6875eec..9db46b3 100644
--- a/core/src/main/java/org/apache/oozie/util/XmlUtils.java
+++ b/core/src/main/java/org/apache/oozie/util/XmlUtils.java
@@ -32,7 +32,9 @@ import java.util.Map;
 import java.util.Properties;
 
 import javax.xml.XMLConstants;
+import javax.xml.parsers.DocumentBuilder;
 import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
 import javax.xml.transform.Result;
 import javax.xml.transform.Source;
 import javax.xml.transform.Transformer;
@@ -56,8 +58,6 @@ import org.jdom.Namespace;
 import org.jdom.input.SAXBuilder;
 import org.jdom.output.Format;
 import org.jdom.output.XMLOutputter;
-import org.xml.sax.EntityResolver;
-import org.xml.sax.InputSource;
 import org.xml.sax.SAXException;
 
 /**
@@ -65,23 +65,12 @@ import org.xml.sax.SAXException;
  */
 public class XmlUtils {
 
-    private static class NoExternalEntityEntityResolver implements 
EntityResolver {
-
-        @Override
-        public InputSource resolveEntity(String publicId, String systemId) 
throws SAXException, IOException {
-            return new InputSource(new ByteArrayInputStream(new byte[0]));
-        }
-
-    }
-
     private static SAXBuilder createSAXBuilder() {
         SAXBuilder saxBuilder = new SAXBuilder();
-
-        //THIS IS NOT WORKING
-        
//saxBuilder.setFeature("http://xml.org/sax/features/external-general-entities";,
 false);
-
-        //INSTEAD WE ARE JUST SETTING AN EntityResolver that does not resolve 
entities
-        saxBuilder.setEntityResolver(new NoExternalEntityEntityResolver());
+        
saxBuilder.setFeature("http://apache.org/xml/features/disallow-doctype-decl",true);
+        
saxBuilder.setFeature("http://xml.org/sax/features/external-general-entities";, 
false);
+        
saxBuilder.setFeature("http://xml.org/sax/features/external-parameter-entities";,
 false);
+        
saxBuilder.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd";,
 false);
         return saxBuilder;
     }
 
@@ -281,28 +270,10 @@ public class XmlUtils {
      * @throws IOException in case of IO error
      */
     public static void validateXml(Schema schema, String xml) throws 
SAXException, IOException {
-
-        Validator validator = schema.newValidator();
+        Validator validator = SchemaService.getValidator(schema);
         validator.validate(new StreamSource(new 
ByteArrayInputStream(xml.getBytes())));
     }
 
-    /**
-     * Create schema object for the given xsd
-     *
-     * @param is inputstream to schema.
-     * @return the schema object.
-     */
-    public static Schema createSchema(InputStream is) {
-        SchemaFactory factory = 
SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
-        StreamSource src = new StreamSource(is);
-        try {
-            return factory.newSchema(src);
-        }
-        catch (SAXException e) {
-            throw new RuntimeException(e.getMessage(), e);
-        }
-    }
-
     public static void validateData(String xmlData, SchemaName xsdFile) throws 
SAXException, IOException {
         if (xmlData == null || xmlData.length() == 0) {
             return;
@@ -320,7 +291,7 @@ public class XmlUtils {
      */
     public static String writePropToString(Properties props) throws 
IOException {
         try {
-            org.w3c.dom.Document doc = 
DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
+            org.w3c.dom.Document doc = getDocumentBuilder().newDocument();
             org.w3c.dom.Element conf = doc.createElement("configuration");
             doc.appendChild(conf);
             conf.appendChild(doc.createTextNode("\n"));
@@ -364,6 +335,26 @@ public class XmlUtils {
     }
 
     /**
+     * Returns a DocumentBuilder
+     * @return DocumentBuilder
+     * @throws ParserConfigurationException
+     */
+    private static DocumentBuilder getDocumentBuilder() throws 
ParserConfigurationException {
+        DocumentBuilderFactory docBuilderFactory = 
DocumentBuilderFactory.newInstance();
+        docBuilderFactory.setNamespaceAware(true);
+        docBuilderFactory.setXIncludeAware(false);
+        docBuilderFactory.setExpandEntityReferences(false);
+        
docBuilderFactory.setFeature("http://apache.org/xml/features/disallow-doctype-decl",true);
+        //Redundant with disallow-doctype, but just in case
+        
docBuilderFactory.setFeature("http://xml.org/sax/features/external-general-entities";,
 false);
+        
docBuilderFactory.setFeature("http://xml.org/sax/features/external-parameter-entities";,
 false);
+        
docBuilderFactory.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd";,
 false);
+        // ignore all comments inside the xml file
+        docBuilderFactory.setIgnoringComments(true);
+        return docBuilderFactory.newDocumentBuilder();
+    }
+
+    /**
      * Escape characters for text appearing as XML data, between tags.
      * <p>
      * The following characters are replaced with corresponding character 
entities :

http://git-wip-us.apache.org/repos/asf/oozie/blob/ba665da3/core/src/main/java/org/apache/oozie/workflow/lite/LiteWorkflowAppParser.java
----------------------------------------------------------------------
diff --git 
a/core/src/main/java/org/apache/oozie/workflow/lite/LiteWorkflowAppParser.java 
b/core/src/main/java/org/apache/oozie/workflow/lite/LiteWorkflowAppParser.java
index aa0e06b..c236daf 100644
--- 
a/core/src/main/java/org/apache/oozie/workflow/lite/LiteWorkflowAppParser.java
+++ 
b/core/src/main/java/org/apache/oozie/workflow/lite/LiteWorkflowAppParser.java
@@ -18,27 +18,6 @@
 
 package org.apache.oozie.workflow.lite;
 
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.DataInput;
-import java.io.DataInputStream;
-import java.io.DataOutput;
-import java.io.DataOutputStream;
-import java.io.IOException;
-import java.io.Reader;
-import java.io.StringReader;
-import java.io.StringWriter;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.zip.Deflater;
-import java.util.zip.DeflaterOutputStream;
-import java.util.zip.Inflater;
-import java.util.zip.InflaterInputStream;
-
-import javax.xml.transform.stream.StreamSource;
-import javax.xml.validation.Schema;
-import javax.xml.validation.Validator;
-
 import org.apache.commons.codec.binary.Base64;
 import org.apache.commons.lang.StringUtils;
 import org.apache.hadoop.conf.Configuration;
@@ -49,6 +28,7 @@ import org.apache.oozie.action.hadoop.FsActionExecutor;
 import org.apache.oozie.action.oozie.SubWorkflowActionExecutor;
 import org.apache.oozie.service.ActionService;
 import org.apache.oozie.service.ConfigurationService;
+import org.apache.oozie.service.SchemaService;
 import org.apache.oozie.service.Services;
 import org.apache.oozie.util.ELUtils;
 import org.apache.oozie.util.IOUtils;
@@ -63,6 +43,26 @@ import org.jdom.JDOMException;
 import org.jdom.Namespace;
 import org.xml.sax.SAXException;
 
+import javax.xml.transform.stream.StreamSource;
+import javax.xml.validation.Schema;
+import javax.xml.validation.Validator;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.DataInput;
+import java.io.DataInputStream;
+import java.io.DataOutput;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.io.Reader;
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.zip.Deflater;
+import java.util.zip.DeflaterOutputStream;
+import java.util.zip.Inflater;
+import java.util.zip.InflaterInputStream;
+
 /**
  * Class to parse and validate workflow xml
  */
@@ -166,7 +166,7 @@ public class LiteWorkflowAppParser {
             String strDef = writer.toString();
 
             if (schema != null) {
-                Validator validator = schema.newValidator();
+                Validator validator = SchemaService.getValidator(schema);
                 validator.validate(new StreamSource(new StringReader(strDef)));
             }
 

http://git-wip-us.apache.org/repos/asf/oozie/blob/ba665da3/core/src/test/java/org/apache/oozie/service/TestSchemaService.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/oozie/service/TestSchemaService.java 
b/core/src/test/java/org/apache/oozie/service/TestSchemaService.java
index d0a3fdf..3ae6f6f 100644
--- a/core/src/test/java/org/apache/oozie/service/TestSchemaService.java
+++ b/core/src/test/java/org/apache/oozie/service/TestSchemaService.java
@@ -319,9 +319,9 @@ public class TestSchemaService extends XTestCase {
         super.setUp();
         new Services().init();
         wss = Services.get().get(SchemaService.class);
-        workflowValidator = wss.getSchema(SchemaName.WORKFLOW).newValidator();
-        coordinatorValidator = 
wss.getSchema(SchemaName.COORDINATOR).newValidator();
-        bundleValidator = wss.getSchema(SchemaName.BUNDLE).newValidator();
+        workflowValidator = wss.getValidator(SchemaName.WORKFLOW);
+        coordinatorValidator = wss.getValidator(SchemaName.COORDINATOR);
+        bundleValidator = wss.getValidator(SchemaName.BUNDLE);
     }
 
     @Override
@@ -355,7 +355,7 @@ public class TestSchemaService extends XTestCase {
         setSystemProperty(SchemaService.WF_CONF_EXT_SCHEMAS, 
"wf-ext-schema.xsd");
         new Services().init();
         SchemaService wss = Services.get().get(SchemaService.class);
-        Validator validator = 
wss.getSchema(SchemaName.WORKFLOW).newValidator();
+        Validator validator = wss.getValidator(SchemaName.WORKFLOW);
         validator.validate(new StreamSource(new StringReader(APP2)));
     }
 

http://git-wip-us.apache.org/repos/asf/oozie/blob/ba665da3/core/src/test/java/org/apache/oozie/util/TestXConfiguration.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/oozie/util/TestXConfiguration.java 
b/core/src/test/java/org/apache/oozie/util/TestXConfiguration.java
index bd8e077..7a9d780 100644
--- a/core/src/test/java/org/apache/oozie/util/TestXConfiguration.java
+++ b/core/src/test/java/org/apache/oozie/util/TestXConfiguration.java
@@ -56,32 +56,24 @@ public class TestXConfiguration extends XTestCase {
         String parentXml = "parentXml";
         prepareXmlWithInclude(parentXml);
         try {
-            XConfiguration conf = new XConfiguration(new FileInputStream(new 
File(getTestCaseDir(), parentXml)));
-            assertEquals("DEFAULT", conf.get("oozie.dummy"));
-            // verify the properties from include file
-            assertEquals("bar", conf.get("foo"));
-            assertEquals("def", conf.get("abc"));
-        } catch (IOException e) {
-            e.printStackTrace();
-            fail("XInclude failed");
+            new XConfiguration(new FileInputStream(new File(getTestCaseDir(), 
parentXml)));
+            fail("XInclude should not be allowed");
+        }
+        catch (IOException e) {
+            assertEquals("bad conf file: element not <property>", 
e.getMessage());
         }
-
     }
 
     public void testAddXIncludeFromReader() throws IOException {
         String parentXml = "parentXml";
         prepareXmlWithInclude(parentXml);
         try {
-            XConfiguration conf = new XConfiguration(new FileReader(new 
File(getTestCaseDir(), parentXml)));
-            assertEquals("DEFAULT", conf.get("oozie.dummy"));
-            // verify the properties from include file
-            assertEquals("bar", conf.get("foo"));
-            assertEquals("def", conf.get("abc"));
-        }  catch (IOException e) {
-            e.printStackTrace();
-            fail("XInclude failed");
+            new XConfiguration(new FileReader(new File(getTestCaseDir(), 
parentXml)));
+            fail("XInclude should not be allowed");
+        }
+        catch (IOException e) {
+            assertEquals("bad conf file: element not <property>", 
e.getMessage());
         }
-
     }
 
     // Copy the parent xml to testCaseDir and add the include element
@@ -184,6 +176,7 @@ public class TestXConfiguration extends XTestCase {
 
     public void testResolve() {
         XConfiguration conf = new XConfiguration();
+        conf.setRestrictSystemProperties(false);
         conf.set("a", "A");
         conf.set("b", "${a}");
         assertEquals("A", conf.getRaw("a"));
@@ -205,14 +198,9 @@ public class TestXConfiguration extends XTestCase {
         assertEquals("${aa}", conf.getRaw("c"));
         assertEquals("A", conf.get("a"));
         assertEquals("A", conf.get("b"));
-        assertEquals("foo", conf.get("c"));
         assertEquals("${aaa}", conf.get("d"));
-
         conf.set("un","${user.name}");
-        assertEquals(System.getProperty("user.name"), conf.get("un"));
-        setSystemProperty("user.name", "foo");
-        assertEquals("foo", conf.get("un"));
-
+        assertEquals("${user.name}", conf.get("un"));
     }
 
     public void testSubstituteVar() throws ServiceException {
@@ -235,7 +223,8 @@ public class TestXConfiguration extends XTestCase {
         try {
             conf.get(String.valueOf("key" + (depth)));
             fail("Fail to apply substitution depth");
-        } catch (IllegalStateException e) {
+        }
+        catch (IllegalStateException e) {
             assertTrue(e.getMessage().contains("Variable substitution depth 
too large: " + depth));
         }
 
@@ -264,4 +253,4 @@ public class TestXConfiguration extends XTestCase {
 
         services.destroy();
     }
-}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/oozie/blob/ba665da3/core/src/test/java/org/apache/oozie/util/TestXmlUtils.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/oozie/util/TestXmlUtils.java 
b/core/src/test/java/org/apache/oozie/util/TestXmlUtils.java
index ac0b5ed..133789c 100644
--- a/core/src/test/java/org/apache/oozie/util/TestXmlUtils.java
+++ b/core/src/test/java/org/apache/oozie/util/TestXmlUtils.java
@@ -18,10 +18,10 @@
 
 package org.apache.oozie.util;
 
-import org.jdom.Element;
 import org.junit.Test;
-
-import static junit.framework.Assert.assertEquals;
+import org.jdom.input.JDOMParseException;
+import static junit.framework.Assert.assertTrue;
+import static junit.framework.Assert.fail;
 
 public class TestXmlUtils {
 
@@ -30,8 +30,14 @@ public class TestXmlUtils {
 
     @Test
     public void testExternalEntity() throws Exception {
-        Element e = XmlUtils.parseXml(EXTERNAL_ENTITY_XML);
-        assertEquals(0, e.getText().length());
+        try {
+            XmlUtils.parseXml(EXTERNAL_ENTITY_XML);
+            fail("DOCTYPE should not be allowed");
+        } catch (JDOMParseException e) {
+            assertTrue("Exception has different message.", e.getMessage().
+                    contains("DOCTYPE is disallowed when the feature 
\"http://apache.";
+                            + "org/xml/features/disallow-doctype-decl\" set to 
true"));
+        }
     }
 
     @Test

Reply via email to