You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cxf.apache.org by re...@apache.org on 2018/05/10 21:59:22 UTC

[cxf] branch master updated: [CXF-7716] Reduce StringBuilders and other performance changes. (#407)

This is an automated email from the ASF dual-hosted git repository.

reta pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/cxf.git


The following commit(s) were added to refs/heads/master by this push:
     new 7b39380  [CXF-7716] Reduce StringBuilders and other performance changes. (#407)
7b39380 is described below

commit 7b39380bb9b654f891741c56c69530095ab5c543
Author: Adam Anderson <31...@users.noreply.github.com>
AuthorDate: Thu May 10 16:59:18 2018 -0500

    [CXF-7716] Reduce StringBuilders and other performance changes. (#407)
---
 .../lifecycle/PerRequestResourceProvider.java      | 10 ++-
 .../org/apache/cxf/jaxrs/model/URITemplate.java    | 32 ++++++++--
 .../apache/cxf/jaxrs/provider/ProviderFactory.java | 13 +---
 .../cxf/jaxrs/utils/AccumulatingIntersector.java   | 74 ++++++++++++++++++++++
 .../java/org/apache/cxf/jaxrs/utils/HttpUtils.java | 41 +++++++-----
 .../org/apache/cxf/jaxrs/utils/JAXRSUtils.java     | 72 +++++++++------------
 .../cxf/jaxrs/utils/MimeTypesIntersector.java      | 26 ++++++++
 .../jaxrs/utils/NonAccumulatingIntersector.java    | 36 +++++++++++
 .../org/apache/cxf/jaxrs/utils/ResourceUtils.java  | 17 ++++-
 9 files changed, 247 insertions(+), 74 deletions(-)

diff --git a/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/lifecycle/PerRequestResourceProvider.java b/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/lifecycle/PerRequestResourceProvider.java
index 1bc98bd..61881fb 100644
--- a/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/lifecycle/PerRequestResourceProvider.java
+++ b/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/lifecycle/PerRequestResourceProvider.java
@@ -19,9 +19,11 @@
 
 package org.apache.cxf.jaxrs.lifecycle;
 
+import java.lang.annotation.Annotation;
 import java.lang.reflect.Constructor;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
+import java.lang.reflect.Type;
 import java.util.Collections;
 import java.util.Map;
 
@@ -45,6 +47,9 @@ public class PerRequestResourceProvider implements ResourceProvider {
     private Constructor<?> c;
     private Method postConstructMethod;
     private Method preDestroyMethod;
+    private final Class<?>[] params;
+    private final Annotation[][] anns;
+    private final Type[] genericTypes;
 
     public PerRequestResourceProvider(Class<?> clazz) {
         c = ResourceUtils.findResourceConstructor(clazz, true);
@@ -52,6 +57,9 @@ public class PerRequestResourceProvider implements ResourceProvider {
             throw new RuntimeException("Resource class " + clazz
                                        + " has no valid constructor");
         }
+        params = c.getParameterTypes();
+        anns = c.getParameterAnnotations();
+        genericTypes = c.getGenericParameterTypes();
         postConstructMethod = ResourceUtils.findPostConstructMethod(clazz);
         preDestroyMethod = ResourceUtils.findPreDestroyMethod(clazz);
     }
@@ -75,7 +83,7 @@ public class PerRequestResourceProvider implements ResourceProvider {
             (ProviderInfo<?>)m.getExchange().getEndpoint().get(Application.class.getName());
         Map<Class<?>, Object> mapValues = CastUtils.cast(application == null ? null
             : Collections.singletonMap(Application.class, application.getProvider()));
-        Object[] values = ResourceUtils.createConstructorArguments(c, m, true, mapValues);
+        Object[] values = ResourceUtils.createConstructorArguments(c, m, true, mapValues, params, anns, genericTypes);
         try {
             Object instance = values.length > 0 ? c.newInstance(values) : c.newInstance(new Object[]{});
             InjectionUtils.invokeLifeCycleMethod(instance, postConstructMethod);
diff --git a/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/model/URITemplate.java b/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/model/URITemplate.java
index 29777a8..b5059f3 100644
--- a/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/model/URITemplate.java
+++ b/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/model/URITemplate.java
@@ -130,10 +130,34 @@ public final class URITemplate {
 
     private static String escapeCharacters(String expression) {
 
-        StringBuilder sb = new StringBuilder();
-        for (int i = 0; i < expression.length(); i++) {
-            char ch = expression.charAt(i);
-            sb.append(isReservedCharacter(ch) ? "\\" + ch : ch);
+        int length = expression.length();
+        int i = 0;
+        char ch = ' ';
+        for (; i < length; ++i) {
+            ch = expression.charAt(i);
+            if (isReservedCharacter(ch)) {
+                break;
+            }
+        }
+
+        if (i == length) {
+            return expression;
+        }
+
+        // Allows for up to 8 escaped characters before we start creating more
+        // StringBuilders. 8 is an arbitrary limit, but it seems to be
+        // sufficient in most cases.
+        StringBuilder sb = new StringBuilder(length + 8);
+        sb.append(expression, 0, i);
+        sb.append('\\');
+        sb.append(ch);
+        ++i;
+        for (; i < length; ++i) {
+            ch = expression.charAt(i);
+            if (isReservedCharacter(ch)) {
+                sb.append('\\');
+            }
+            sb.append(ch);
         }
         return sb.toString();
     }
diff --git a/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/ProviderFactory.java b/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/ProviderFactory.java
index e62d339..03b6a5e 100644
--- a/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/ProviderFactory.java
+++ b/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/ProviderFactory.java
@@ -222,7 +222,7 @@ public abstract class ProviderFactory {
                         if (argCls != null && argCls.isAssignableFrom(contextCls)) {
                             List<MediaType> mTypes = JAXRSUtils.getProduceTypes(
                                  cr.getProvider().getClass().getAnnotation(Produces.class));
-                            if (JAXRSUtils.intersectMimeTypes(mTypes, type).size() > 0) {
+                            if (JAXRSUtils.doMimeTypesIntersect(mTypes, type)) {
                                 injectContextValues(cr, m);
                                 candidates.add((ContextResolver<T>)cr.getProvider());
                             }
@@ -728,10 +728,7 @@ public abstract class ProviderFactory {
         MessageBodyReader<?> ep = pi.getProvider();
         List<MediaType> supportedMediaTypes = JAXRSUtils.getProviderConsumeTypes(ep);
 
-        List<MediaType> availableMimeTypes =
-            JAXRSUtils.intersectMimeTypes(Collections.singletonList(mediaType), supportedMediaTypes, false);
-
-        return availableMimeTypes.size() != 0;
+        return JAXRSUtils.doMimeTypesIntersect(Collections.singletonList(mediaType), supportedMediaTypes);
     }
 
     private boolean isReadable(ProviderInfo<MessageBodyReader<?>> pi,
@@ -752,11 +749,7 @@ public abstract class ProviderFactory {
         MessageBodyWriter<?> ep = pi.getProvider();
         List<MediaType> supportedMediaTypes = JAXRSUtils.getProviderProduceTypes(ep);
 
-        List<MediaType> availableMimeTypes =
-            JAXRSUtils.intersectMimeTypes(Collections.singletonList(mediaType),
-                                          supportedMediaTypes, false);
-
-        return availableMimeTypes.size() != 0;
+        return JAXRSUtils.doMimeTypesIntersect(Collections.singletonList(mediaType), supportedMediaTypes);
     }
 
     private boolean isWriteable(ProviderInfo<MessageBodyWriter<?>> pi,
diff --git a/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/AccumulatingIntersector.java b/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/AccumulatingIntersector.java
new file mode 100644
index 0000000..3d2537f
--- /dev/null
+++ b/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/AccumulatingIntersector.java
@@ -0,0 +1,74 @@
+/**
+ * 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.jaxrs.utils;
+
+import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
+import java.util.Map;
+import java.util.Set;
+
+import javax.ws.rs.core.MediaType;
+
+public class AccumulatingIntersector implements MimeTypesIntersector {
+    private static final String MEDIA_TYPE_DISTANCE_PARAM = "d";
+    private final Set<MediaType> supportedMimeTypeList = new LinkedHashSet<MediaType>();
+    private final boolean addRequiredParamsIfPossible;
+    private final boolean addDistanceParameter;
+
+    AccumulatingIntersector(boolean addRequiredParamsIfPossible, boolean addDistanceParameter) {
+        this.addRequiredParamsIfPossible = addRequiredParamsIfPossible;
+        this.addDistanceParameter = addDistanceParameter;
+    }
+
+    @Override
+    public boolean intersect(MediaType requiredType, MediaType userType) {
+        boolean requiredTypeWildcard = requiredType.getType().equals(MediaType.MEDIA_TYPE_WILDCARD);
+        boolean requiredSubTypeWildcard = requiredType.getSubtype().contains(MediaType.MEDIA_TYPE_WILDCARD);
+
+        String type = requiredTypeWildcard ? userType.getType() : requiredType.getType();
+        String subtype = requiredSubTypeWildcard ? userType.getSubtype() : requiredType.getSubtype();
+
+        Map<String, String> parameters = userType.getParameters();
+        if (addRequiredParamsIfPossible) {
+            parameters = new LinkedHashMap<String, String>(parameters);
+            for (Map.Entry<String, String> entry : requiredType.getParameters().entrySet()) {
+                if (!parameters.containsKey(entry.getKey())) {
+                    parameters.put(entry.getKey(), entry.getValue());
+                }
+            }
+        }
+        if (addDistanceParameter) {
+            int distance = 0;
+            if (requiredTypeWildcard) {
+                distance++;
+            }
+            if (requiredSubTypeWildcard) {
+                distance++;
+            }
+            parameters.put(MEDIA_TYPE_DISTANCE_PARAM, Integer.toString(distance));
+        }
+        getSupportedMimeTypeList().add(new MediaType(type, subtype, parameters));
+        return true;
+    }
+
+    public Set<MediaType> getSupportedMimeTypeList() {
+        return supportedMimeTypeList;
+    }
+}
diff --git a/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/HttpUtils.java b/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/HttpUtils.java
index 41286c3..53a2143 100644
--- a/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/HttpUtils.java
+++ b/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/HttpUtils.java
@@ -117,24 +117,29 @@ public final class HttpUtils {
 
     private static String componentEncode(String reservedChars, String value) {
 
-        StringBuilder buffer = new StringBuilder();
-        StringBuilder bufferToEncode = new StringBuilder();
-
-        for (int i = 0; i < value.length(); i++) {
+        StringBuilder buffer = null;
+        int length = value.length();
+        int startingIndex = 0;
+        for (int i = 0; i < length; i++) {
             char currentChar = value.charAt(i);
             if (reservedChars.indexOf(currentChar) != -1) {
-                if (bufferToEncode.length() > 0) {
-                    buffer.append(urlEncode(bufferToEncode.toString()));
-                    bufferToEncode.setLength(0);
+                if (buffer == null) {
+                    buffer = new StringBuilder(length + 8);
+                }
+                // If it is going to be an empty string nothing to encode.
+                if (i != startingIndex) {
+                    buffer.append(urlEncode(value.substring(startingIndex, i)));
                 }
                 buffer.append(currentChar);
-            } else {
-                bufferToEncode.append(currentChar);
+                startingIndex = i + 1;
             }
         }
 
-        if (bufferToEncode.length() > 0) {
-            buffer.append(urlEncode(bufferToEncode.toString()));
+        if (buffer == null) {
+            return urlEncode(value);
+        }
+        if (startingIndex < length) {
+            buffer.append(urlEncode(value.substring(startingIndex, length)));
         }
 
         return buffer.toString();
@@ -186,15 +191,21 @@ public final class HttpUtils {
             return encoded;
         }
         Matcher m = ENCODE_PATTERN.matcher(encoded);
-        StringBuilder sb = new StringBuilder();
+
+        if (!m.find()) {
+            return query ? HttpUtils.queryEncode(encoded) : HttpUtils.pathEncode(encoded);
+        }
+
+        int length = encoded.length();
+        StringBuilder sb = new StringBuilder(length + 8);
         int i = 0;
-        while (m.find()) {
+        do {
             String before = encoded.substring(i, m.start());
             sb.append(query ? HttpUtils.queryEncode(before) : HttpUtils.pathEncode(before));
             sb.append(m.group());
             i = m.end();
-        }
-        String tail = encoded.substring(i, encoded.length());
+        } while (m.find());
+        String tail = encoded.substring(i, length);
         sb.append(query ? HttpUtils.queryEncode(tail) : HttpUtils.pathEncode(tail));
         return sb.toString();
     }
diff --git a/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/JAXRSUtils.java b/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/JAXRSUtils.java
index 3094a3e..252f4cd 100644
--- a/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/JAXRSUtils.java
+++ b/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/JAXRSUtils.java
@@ -35,7 +35,6 @@ import java.util.Collections;
 import java.util.Comparator;
 import java.util.HashSet;
 import java.util.LinkedHashMap;
-import java.util.LinkedHashSet;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
@@ -1400,21 +1399,21 @@ public final class JAXRSUtils {
     public static boolean matchConsumeTypes(MediaType requestContentType,
                                             OperationResourceInfo ori) {
 
-        return !intersectMimeTypes(ori.getConsumeTypes(), requestContentType).isEmpty();
+        return doMimeTypesIntersect(ori.getConsumeTypes(), requestContentType);
     }
 
     public static boolean matchProduceTypes(MediaType acceptContentType,
                                               OperationResourceInfo ori) {
 
-        return !intersectMimeTypes(ori.getProduceTypes(), acceptContentType).isEmpty();
+        return doMimeTypesIntersect(ori.getProduceTypes(), acceptContentType);
     }
 
     public static boolean matchMimeTypes(MediaType requestContentType,
                                          MediaType acceptContentType,
                                          OperationResourceInfo ori) {
 
-        return intersectMimeTypes(ori.getConsumeTypes(), requestContentType).size() != 0
-            && intersectMimeTypes(ori.getProduceTypes(), acceptContentType).size() != 0;
+        return doMimeTypesIntersect(ori.getConsumeTypes(), requestContentType)
+                && doMimeTypesIntersect(ori.getProduceTypes(), acceptContentType);
     }
 
     public static List<MediaType> parseMediaTypes(String types) {
@@ -1439,6 +1438,16 @@ public final class JAXRSUtils {
         return acceptValues;
     }
 
+    public static boolean doMimeTypesIntersect(List<MediaType> mimeTypesA, MediaType mimeTypeB) {
+        return doMimeTypesIntersect(mimeTypesA, Collections.singletonList(mimeTypeB));
+    }
+
+    public static boolean doMimeTypesIntersect(List<MediaType> requiredMediaTypes, List<MediaType> userMediaTypes) {
+        final NonAccumulatingIntersector intersector = new NonAccumulatingIntersector();
+        intersectMimeTypes(requiredMediaTypes, userMediaTypes, intersector);
+        return intersector.doIntersect();
+    }
+
     /**
      * intersect two mime types
      *
@@ -1451,11 +1460,19 @@ public final class JAXRSUtils {
                                                      boolean addRequiredParamsIfPossible) {
         return intersectMimeTypes(requiredMediaTypes, userMediaTypes, addRequiredParamsIfPossible, false);
     }
+
     public static List<MediaType> intersectMimeTypes(List<MediaType> requiredMediaTypes,
                                                      List<MediaType> userMediaTypes,
                                                      boolean addRequiredParamsIfPossible,
                                                      boolean addDistanceParameter) {
-        Set<MediaType> supportedMimeTypeList = new LinkedHashSet<MediaType>();
+        final AccumulatingIntersector intersector = new AccumulatingIntersector(addRequiredParamsIfPossible,
+                addDistanceParameter);
+        intersectMimeTypes(requiredMediaTypes, userMediaTypes, intersector);
+        return new ArrayList<>(intersector.getSupportedMimeTypeList());
+    }
+
+    private static void intersectMimeTypes(List<MediaType> requiredMediaTypes, List<MediaType> userMediaTypes,
+            MimeTypesIntersector intersector) {
 
         for (MediaType requiredType : requiredMediaTypes) {
             for (MediaType userType : userMediaTypes) {
@@ -1464,12 +1481,10 @@ public final class JAXRSUtils {
                     boolean parametersMatched = true;
                     for (Map.Entry<String, String> entry : userType.getParameters().entrySet()) {
                         String value = requiredType.getParameters().get(entry.getKey());
-                        if (value != null && entry.getValue() != null
-                            && !(stripDoubleQuotesIfNeeded(value).equals(
-                                    stripDoubleQuotesIfNeeded(entry.getValue())))) {
-                            
-                            if (HTTP_CHARSET_PARAM.equals(entry.getKey())
-                                && value.equalsIgnoreCase(entry.getValue())) {
+                        if (value != null && entry.getValue() != null && !(stripDoubleQuotesIfNeeded(value)
+                                .equals(stripDoubleQuotesIfNeeded(entry.getValue())))) {
+
+                            if (HTTP_CHARSET_PARAM.equals(entry.getKey()) && value.equalsIgnoreCase(entry.getValue())) {
                                 continue;
                             }
                             parametersMatched = false;
@@ -1479,40 +1494,15 @@ public final class JAXRSUtils {
                     if (!parametersMatched) {
                         continue;
                     }
-                    boolean requiredTypeWildcard = requiredType.getType().equals(MediaType.MEDIA_TYPE_WILDCARD);
-                    boolean requiredSubTypeWildcard = requiredType.getSubtype().contains(MediaType.MEDIA_TYPE_WILDCARD);
-
-                    String type = requiredTypeWildcard ? userType.getType() : requiredType.getType();
-                    String subtype = requiredSubTypeWildcard ? userType.getSubtype() : requiredType.getSubtype();
-
-                    Map<String, String> parameters = userType.getParameters();
-                    if (addRequiredParamsIfPossible) {
-                        parameters = new LinkedHashMap<String, String>(parameters);
-                        for (Map.Entry<String, String> entry : requiredType.getParameters().entrySet()) {
-                            if (!parameters.containsKey(entry.getKey())) {
-                                parameters.put(entry.getKey(), entry.getValue());
-                            }
-                        }
-                    }
-                    if (addDistanceParameter) {
-                        int distance = 0;
-                        if (requiredTypeWildcard) {
-                            distance++;
-                        }
-                        if (requiredSubTypeWildcard) {
-                            distance++;
-                        }
-                        parameters.put(MEDIA_TYPE_DISTANCE_PARAM, Integer.toString(distance));
+
+                    if (!intersector.intersect(requiredType, userType)) {
+                        return;
                     }
-                    supportedMimeTypeList.add(new MediaType(type, subtype, parameters));
                 }
             }
         }
-
-        return new ArrayList<>(supportedMimeTypeList);
-
     }
-    
+
     private static String stripDoubleQuotesIfNeeded(String value) {
         if (value != null && value.startsWith("\"") 
             && value.endsWith("\"") && value.length() > 1) {
diff --git a/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/MimeTypesIntersector.java b/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/MimeTypesIntersector.java
new file mode 100644
index 0000000..3dd3e47
--- /dev/null
+++ b/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/MimeTypesIntersector.java
@@ -0,0 +1,26 @@
+/**
+ * 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.jaxrs.utils;
+
+import javax.ws.rs.core.MediaType;
+
+public interface MimeTypesIntersector {
+    boolean intersect(MediaType requiredType, MediaType userType);
+}
diff --git a/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/NonAccumulatingIntersector.java b/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/NonAccumulatingIntersector.java
new file mode 100644
index 0000000..7f6661e
--- /dev/null
+++ b/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/NonAccumulatingIntersector.java
@@ -0,0 +1,36 @@
+/**
+ * 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.jaxrs.utils;
+
+import javax.ws.rs.core.MediaType;
+
+public class NonAccumulatingIntersector implements MimeTypesIntersector {
+    private boolean doIntersect;
+
+    @Override
+    public boolean intersect(MediaType requiredType, MediaType userType) {
+        doIntersect = true;
+        return false;
+    }
+
+    public boolean doIntersect() {
+        return doIntersect;
+    }
+}
diff --git a/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/ResourceUtils.java b/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/ResourceUtils.java
index 39d9769..1b32e85 100644
--- a/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/ResourceUtils.java
+++ b/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/ResourceUtils.java
@@ -816,12 +816,23 @@ public final class ResourceUtils {
                                                       Message m,
                                                       boolean perRequest,
                                                       Map<Class<?>, Object> contextValues) {
-        if (m == null) {
-            m = new MessageImpl();
-        }
         Class<?>[] params = c.getParameterTypes();
         Annotation[][] anns = c.getParameterAnnotations();
         Type[] genericTypes = c.getGenericParameterTypes();
+        return createConstructorArguments(c, m, perRequest, contextValues, params, anns, genericTypes);
+    }
+
+    public static Object[] createConstructorArguments(Constructor<?> c,
+                                                      Message m,
+                                                      boolean perRequest,
+                                                      Map<Class<?>,
+                                                      Object> contextValues,
+                                                      Class<?>[] params,
+                                                      Annotation[][] anns,
+                                                      Type[] genericTypes) {
+        if (m == null) {
+            m = new MessageImpl();
+        }
         @SuppressWarnings("unchecked")
         MultivaluedMap<String, String> templateValues =
             (MultivaluedMap<String, String>)m.get(URITemplate.TEMPLATE_PARAMETERS);

-- 
To stop receiving notification emails like this one, please contact
reta@apache.org.