You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cxf.apache.org by se...@apache.org on 2012/03/14 00:35:13 UTC

svn commit: r1300410 - in /cxf/branches/2.5.x-fixes: ./ common/common/src/main/java/org/apache/cxf/staxutils/ rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/

Author: sergeyb
Date: Tue Mar 13 23:35:13 2012
New Revision: 1300410

URL: http://svn.apache.org/viewvc?rev=1300410&view=rev
Log:
Merged revisions 1298832 via svnmerge from 
https://svn.apache.org/repos/asf/cxf/trunk

........
  r1298832 | sergeyb | 2012-03-09 14:04:08 +0000 (Fri, 09 Mar 2012) | 1 line
  
  [CXF-4172] Some refactoring plus working around the lack of streaming support in Jettison
........

Added:
    cxf/branches/2.5.x-fixes/common/common/src/main/java/org/apache/cxf/staxutils/DocumentDepthProperties.java   (with props)
Modified:
    cxf/branches/2.5.x-fixes/   (props changed)
    cxf/branches/2.5.x-fixes/common/common/src/main/java/org/apache/cxf/staxutils/DepthRestrictingStreamReader.java
    cxf/branches/2.5.x-fixes/common/common/src/main/java/org/apache/cxf/staxutils/StaxUtils.java
    cxf/branches/2.5.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/AbstractJAXBProvider.java
    cxf/branches/2.5.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/JSONProvider.java
    cxf/branches/2.5.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/JSONUtils.java

Propchange: cxf/branches/2.5.x-fixes/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Tue Mar 13 23:35:13 2012
@@ -1 +1 @@
-/cxf/trunk:1236902,1297296,1298470,1298601-1298624,1298830,1299635,1299682,1299707,1300342
+/cxf/trunk:1236902,1297296,1298470,1298601-1298624,1298830,1298832,1299635,1299682,1299707,1300342

Propchange: cxf/branches/2.5.x-fixes/
------------------------------------------------------------------------------
Binary property 'svnmerge-integrated' - no diff available.

Modified: cxf/branches/2.5.x-fixes/common/common/src/main/java/org/apache/cxf/staxutils/DepthRestrictingStreamReader.java
URL: http://svn.apache.org/viewvc/cxf/branches/2.5.x-fixes/common/common/src/main/java/org/apache/cxf/staxutils/DepthRestrictingStreamReader.java?rev=1300410&r1=1300409&r2=1300410&view=diff
==============================================================================
--- cxf/branches/2.5.x-fixes/common/common/src/main/java/org/apache/cxf/staxutils/DepthRestrictingStreamReader.java (original)
+++ cxf/branches/2.5.x-fixes/common/common/src/main/java/org/apache/cxf/staxutils/DepthRestrictingStreamReader.java Tue Mar 13 23:35:13 2012
@@ -23,11 +23,18 @@ import java.util.Stack;
 import javax.xml.stream.XMLStreamException;
 import javax.xml.stream.XMLStreamReader;
 
+/**
+ * XMLStreamReader implementation which can be used to enforce a number of
+ * depth-restricting policies. The following properties are currently supported:
+ * - total number of elements in the document
+ * - the maximum depth of the given element; the root element will be checked by default
+ * - the maximum number of immediate child nodes for individual elements
+ * 
+ * More sophisticated policies can be supported in the future.      
+ */
 public class DepthRestrictingStreamReader extends DepthXMLStreamReader {
-    private int elementCountThreshold = -1;
-    private int innerElementLevelThreshold = -1;
-    private int innerElementCountThreshold = -1;
     
+    private DocumentDepthProperties props;
     private int totalElementCount;
     private Stack<Integer> stack = new Stack<Integer>();
     
@@ -36,25 +43,33 @@ public class DepthRestrictingStreamReade
                                         int innerElementLevelThreshold,
                                         int innerElementCountThreshold) {
         super(reader);
-        this.elementCountThreshold = elementCountThreshold;
-        this.innerElementLevelThreshold = innerElementLevelThreshold;
-        this.innerElementCountThreshold = innerElementCountThreshold;
+        this.props = new DocumentDepthProperties(elementCountThreshold, 
+                                            innerElementLevelThreshold,
+                                            innerElementCountThreshold);
+    }
+    
+    public DepthRestrictingStreamReader(XMLStreamReader reader,
+                                        DocumentDepthProperties props) {
+        super(reader);
+        this.props = props;
     }
     
     @Override
     public int next() throws XMLStreamException {
         int next = super.next();
         if (next == START_ELEMENT) {
-            if (innerElementLevelThreshold != -1 && getDepth() >= innerElementLevelThreshold) {
+            if (props.getInnerElementLevelThreshold() != -1 
+                && getDepth() >= props.getInnerElementLevelThreshold()) {
                 throw new DepthExceededStaxException();
             }
-            if (elementCountThreshold != -1 && ++totalElementCount >= elementCountThreshold) {
+            if (props.getElementCountThreshold() != -1 
+                && ++totalElementCount >= props.getElementCountThreshold()) {
                 throw new DepthExceededStaxException();
             }
-            if (innerElementCountThreshold != -1) {
+            if (props.getInnerElementCountThreshold() != -1) {
                 if (!stack.empty()) {
                     int currentCount = stack.pop();
-                    if (++currentCount >= innerElementCountThreshold) {
+                    if (++currentCount >= props.getInnerElementCountThreshold()) {
                         throw new DepthExceededStaxException();
                     } else {
                         stack.push(currentCount);
@@ -63,11 +78,9 @@ public class DepthRestrictingStreamReade
                 stack.push(0);
             }
             
-        } else if (next == END_ELEMENT && innerElementCountThreshold != -1) {
+        } else if (next == END_ELEMENT && props.getInnerElementCountThreshold() != -1) {
             stack.pop();
         }
         return next;
     }
-
-    
 }

Added: cxf/branches/2.5.x-fixes/common/common/src/main/java/org/apache/cxf/staxutils/DocumentDepthProperties.java
URL: http://svn.apache.org/viewvc/cxf/branches/2.5.x-fixes/common/common/src/main/java/org/apache/cxf/staxutils/DocumentDepthProperties.java?rev=1300410&view=auto
==============================================================================
--- cxf/branches/2.5.x-fixes/common/common/src/main/java/org/apache/cxf/staxutils/DocumentDepthProperties.java (added)
+++ cxf/branches/2.5.x-fixes/common/common/src/main/java/org/apache/cxf/staxutils/DocumentDepthProperties.java Tue Mar 13 23:35:13 2012
@@ -0,0 +1,59 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.cxf.staxutils;
+
+public class DocumentDepthProperties {
+    private int elementCountThreshold = -1;
+    private int innerElementLevelThreshold = -1;
+    private int innerElementCountThreshold = -1;
+    public DocumentDepthProperties() {
+        
+    }
+    public DocumentDepthProperties(int elementCountThreshold,
+                                   int innerElementLevelThreshold,
+                                   int innerElementCountThreshold) {
+        this.elementCountThreshold = elementCountThreshold;
+        this.innerElementLevelThreshold = innerElementLevelThreshold;
+        this.innerElementCountThreshold = innerElementCountThreshold;    
+    }
+    
+    public boolean isEffective() {
+        return elementCountThreshold != -1 || innerElementLevelThreshold != -1
+            || innerElementCountThreshold != -1;
+    }
+    
+    public void setElementCountThreshold(int elementCountThreshold) {
+        this.elementCountThreshold = elementCountThreshold;
+    }
+    public int getElementCountThreshold() {
+        return elementCountThreshold;
+    }
+    public void setInnerElementLevelThreshold(int innerElementLevelThreshold) {
+        this.innerElementLevelThreshold = innerElementLevelThreshold;
+    }
+    public int getInnerElementLevelThreshold() {
+        return innerElementLevelThreshold;
+    }
+    public void setInnerElementCountThreshold(int innerElementCountThreshold) {
+        this.innerElementCountThreshold = innerElementCountThreshold;
+    }
+    public int getInnerElementCountThreshold() {
+        return innerElementCountThreshold;
+    }
+}

Propchange: cxf/branches/2.5.x-fixes/common/common/src/main/java/org/apache/cxf/staxutils/DocumentDepthProperties.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cxf/branches/2.5.x-fixes/common/common/src/main/java/org/apache/cxf/staxutils/DocumentDepthProperties.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Modified: cxf/branches/2.5.x-fixes/common/common/src/main/java/org/apache/cxf/staxutils/StaxUtils.java
URL: http://svn.apache.org/viewvc/cxf/branches/2.5.x-fixes/common/common/src/main/java/org/apache/cxf/staxutils/StaxUtils.java?rev=1300410&r1=1300409&r2=1300410&view=diff
==============================================================================
--- cxf/branches/2.5.x-fixes/common/common/src/main/java/org/apache/cxf/staxutils/StaxUtils.java (original)
+++ cxf/branches/2.5.x-fixes/common/common/src/main/java/org/apache/cxf/staxutils/StaxUtils.java Tue Mar 13 23:35:13 2012
@@ -82,6 +82,7 @@ import org.apache.cxf.helpers.DOMUtils;
 import org.apache.cxf.helpers.XMLUtils;
 
 public final class StaxUtils {
+    public static final String TOTAL_ELEMENT_COUNT = "org.apache.cxf.staxutils.totalElementCountThreshold";
     public static final String INNER_ELEMENT_COUNT = "org.apache.cxf.staxutils.innerElementCountThreshold";
     public static final String INNER_ELEMENT_LEVEL = "org.apache.cxf.staxutils.innerElementLevelThreshold";
     
@@ -530,7 +531,10 @@ public final class StaxUtils {
                 }
                 break;
             case XMLStreamConstants.CHARACTERS:
-                writer.writeCharacters(reader.getText());
+                String s = reader.getText();
+                if (s != null) {
+                    writer.writeCharacters(s);
+                }
                 break;
             case XMLStreamConstants.COMMENT:
                 writer.writeComment(reader.getText());

Modified: cxf/branches/2.5.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/AbstractJAXBProvider.java
URL: http://svn.apache.org/viewvc/cxf/branches/2.5.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/AbstractJAXBProvider.java?rev=1300410&r1=1300409&r2=1300410&view=diff
==============================================================================
--- cxf/branches/2.5.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/AbstractJAXBProvider.java (original)
+++ cxf/branches/2.5.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/AbstractJAXBProvider.java Tue Mar 13 23:35:13 2012
@@ -74,6 +74,7 @@ import org.apache.cxf.message.Message;
 import org.apache.cxf.phase.PhaseInterceptorChain;
 import org.apache.cxf.staxutils.DepthRestrictingStreamReader;
 import org.apache.cxf.staxutils.DepthXMLStreamReader;
+import org.apache.cxf.staxutils.DocumentDepthProperties;
 import org.apache.cxf.staxutils.StaxUtils;
 import org.apache.cxf.staxutils.transform.TransformUtils;
 
@@ -118,6 +119,7 @@ public abstract class AbstractJAXBProvid
     private boolean validateOutput;
     private boolean validateBeforeWrite;
     private ValidationEventHandler eventHandler;
+    private DocumentDepthProperties depthProperties;
     
     public void setValidationHandler(ValidationEventHandler handler) {
         eventHandler = handler;
@@ -577,8 +579,6 @@ public abstract class AbstractJAXBProvid
         this.inDropElements = dropElementsSet;
     }
     
-    
-    
     public void setAttributesToElements(boolean value) {
         this.attributesToElements = value;
     }
@@ -610,23 +610,39 @@ public abstract class AbstractJAXBProvid
     }
     
     protected XMLStreamReader createDepthReaderIfNeeded(XMLStreamReader reader, InputStream is) {
+        DocumentDepthProperties props = getDepthProperties();
+        if (props != null && props.isEffective()) {
+            reader = TransformUtils.createNewReaderIfNeeded(reader, is);
+            return new DepthRestrictingStreamReader(reader, props);
+        }
+        return reader;
+    }
+    
+    protected DocumentDepthProperties getDepthProperties() {
+        if (depthProperties != null) {
+            return depthProperties;
+        }
         if (getContext() != null) {
-            String elementCountStr = (String)getContext().getContextualProperty(
+            String totalElementCountStr = (String)getContext().getContextualProperty(
+                StaxUtils.TOTAL_ELEMENT_COUNT);
+            String innerElementCountStr = (String)getContext().getContextualProperty(
                 StaxUtils.INNER_ELEMENT_COUNT);
             String elementLevelStr = (String)getContext().getContextualProperty(
                 StaxUtils.INNER_ELEMENT_LEVEL);
-            if (elementCountStr != null || elementLevelStr != null) {
+            if (totalElementCountStr != null || innerElementCountStr != null || elementLevelStr != null) {
                 try {
+                    int totalElementCount = totalElementCountStr != null 
+                        ? Integer.valueOf(totalElementCountStr) : -1;
                     int elementLevel = elementLevelStr != null ? Integer.valueOf(elementLevelStr) : -1;
-                    int elementCount = elementCountStr != null ? Integer.valueOf(elementCountStr) : -1;
-                    reader = TransformUtils.createNewReaderIfNeeded(reader, is);
-                    reader = new DepthRestrictingStreamReader(reader, -1, elementLevel, elementCount);
+                    int innerElementCount = innerElementCountStr != null 
+                        ? Integer.valueOf(innerElementCountStr) : -1;
+                    return new DocumentDepthProperties(totalElementCount, elementLevel, innerElementCount);
                 } catch (Exception ex) {
                     throw new WebApplicationException(ex);
                 }
             }
         }
-        return reader;
+        return null;
     }
     
     public void setValidateBeforeWrite(boolean validateBeforeWrite) {
@@ -637,6 +653,10 @@ public abstract class AbstractJAXBProvid
         this.validateOutput = validateOutput;
     }
 
+    public void setDepthProperties(DocumentDepthProperties depthProperties) {
+        this.depthProperties = depthProperties;
+    }
+
     @XmlRootElement
     protected static class CollectionWrapper {
         

Modified: cxf/branches/2.5.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/JSONProvider.java
URL: http://svn.apache.org/viewvc/cxf/branches/2.5.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/JSONProvider.java?rev=1300410&r1=1300409&r2=1300410&view=diff
==============================================================================
--- cxf/branches/2.5.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/JSONProvider.java (original)
+++ cxf/branches/2.5.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/JSONProvider.java Tue Mar 13 23:35:13 2012
@@ -258,10 +258,9 @@ public class JSONProvider extends Abstra
         if (BADGER_FISH_CONVENTION.equals(convention)) {
             reader = JSONUtils.createBadgerFishReader(is);
         } else {
-            reader = JSONUtils.createStreamReader(is, readXsiType, namespaceMap);
+            reader = JSONUtils.createStreamReader(is, readXsiType, namespaceMap, getDepthProperties());
         }
         reader = createTransformReaderIfNeeded(reader, is);
-        reader = createDepthReaderIfNeeded(reader, is);
         
         return reader;
     }

Modified: cxf/branches/2.5.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/JSONUtils.java
URL: http://svn.apache.org/viewvc/cxf/branches/2.5.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/JSONUtils.java?rev=1300410&r1=1300409&r2=1300410&view=diff
==============================================================================
--- cxf/branches/2.5.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/JSONUtils.java (original)
+++ cxf/branches/2.5.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/JSONUtils.java Tue Mar 13 23:35:13 2012
@@ -40,14 +40,21 @@ import javax.xml.stream.XMLStreamWriter;
 import org.apache.cxf.common.WSDLConstants;
 import org.apache.cxf.common.util.StringUtils;
 import org.apache.cxf.staxutils.DelegatingXMLStreamWriter;
+import org.apache.cxf.staxutils.DepthExceededStaxException;
 import org.apache.cxf.staxutils.DepthXMLStreamReader;
+import org.apache.cxf.staxutils.DocumentDepthProperties;
 import org.apache.cxf.staxutils.transform.IgnoreNamespacesWriter;
+import org.codehaus.jettison.AbstractXMLInputFactory;
 import org.codehaus.jettison.AbstractXMLStreamWriter;
 import org.codehaus.jettison.badgerfish.BadgerFishXMLInputFactory;
 import org.codehaus.jettison.badgerfish.BadgerFishXMLOutputFactory;
+import org.codehaus.jettison.json.JSONException;
+import org.codehaus.jettison.json.JSONObject;
+import org.codehaus.jettison.json.JSONTokener;
 import org.codehaus.jettison.mapped.Configuration;
 import org.codehaus.jettison.mapped.MappedNamespaceConvention;
 import org.codehaus.jettison.mapped.MappedXMLInputFactory;
+import org.codehaus.jettison.mapped.MappedXMLStreamReader;
 import org.codehaus.jettison.mapped.MappedXMLStreamWriter;
 import org.codehaus.jettison.mapped.TypeConverter;
 
@@ -134,13 +141,57 @@ public final class JSONUtils {
     
     public static XMLStreamReader createStreamReader(InputStream is, boolean readXsiType,
         ConcurrentHashMap<String, String> namespaceMap) throws Exception {
+        return createStreamReader(is, readXsiType, namespaceMap, null);
+    }
+    
+    public static XMLStreamReader createStreamReader(InputStream is, boolean readXsiType,
+        ConcurrentHashMap<String, String> namespaceMap, 
+        DocumentDepthProperties depthProps) throws Exception {
         if (readXsiType) {
             namespaceMap.putIfAbsent(XSI_URI, XSI_PREFIX);
         }
-        MappedXMLInputFactory factory = new MappedXMLInputFactory(namespaceMap);
+        XMLInputFactory factory = depthProps != null 
+            ? new JettisonMappedReaderFactory(namespaceMap, depthProps) 
+            : new MappedXMLInputFactory(namespaceMap);
         return new JettisonReader(namespaceMap, factory.createXMLStreamReader(is));
     }
     
+    private static class JettisonMappedReaderFactory extends AbstractXMLInputFactory {
+        private MappedNamespaceConvention convention;
+        private DocumentDepthProperties depthProps;
+        public JettisonMappedReaderFactory(Map<?, ?> nstojns, DocumentDepthProperties depthProps) {
+            convention = new MappedNamespaceConvention(new Configuration(nstojns));
+            this.depthProps = depthProps;
+        }
+        @Override
+        public XMLStreamReader createXMLStreamReader(JSONTokener tokener) throws XMLStreamException {
+            try {
+                JSONObject root = new JettisonJSONObject(tokener, depthProps);
+                return new MappedXMLStreamReader(root, convention);
+            } catch (JSONException e) {
+                throw new XMLStreamException(e);
+            }
+        }    
+    }
+    
+    private static class JettisonJSONObject extends JSONObject {
+        private static final long serialVersionUID = 9016458891093343731L;
+        private int threshold;
+        public JettisonJSONObject(JSONTokener tokener, DocumentDepthProperties depthProps) 
+            throws JSONException {
+            super(tokener);
+            this.threshold = depthProps.getElementCountThreshold() != -1 
+                ? depthProps.getElementCountThreshold() : depthProps.getInnerElementCountThreshold();
+        }
+        @Override
+        public JSONObject put(String key, Object value) throws JSONException {
+            if (threshold != -1 && super.length() >= threshold) {
+                throw new DepthExceededStaxException();
+            }
+            return super.put(key, value);    
+        }
+    }
+    
     private static class JettisonReader extends DepthXMLStreamReader {
         private Map<String, String> namespaceMap;
         public JettisonReader(Map<String, String> nsMap,