You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@syncope.apache.org by il...@apache.org on 2018/03/20 16:37:59 UTC

syncope git commit: Temporary adding CXF's ResourceUtils

Repository: syncope
Updated Branches:
  refs/heads/master cb4291181 -> 3fa2a5aaa


Temporary adding CXF's ResourceUtils


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

Branch: refs/heads/master
Commit: 3fa2a5aaa7428a90611eb80006033cb1f6a5aca8
Parents: cb42911
Author: Francesco Chicchiriccò <il...@apache.org>
Authored: Tue Mar 20 17:37:51 2018 +0100
Committer: Francesco Chicchiriccò <il...@apache.org>
Committed: Tue Mar 20 17:37:51 2018 +0100

----------------------------------------------------------------------
 .../apache/cxf/jaxrs/utils/ResourceUtils.java   | 1014 ++++++++++++++++++
 1 file changed, 1014 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/syncope/blob/3fa2a5aa/core/rest-cxf/src/main/java/org/apache/cxf/jaxrs/utils/ResourceUtils.java
----------------------------------------------------------------------
diff --git a/core/rest-cxf/src/main/java/org/apache/cxf/jaxrs/utils/ResourceUtils.java b/core/rest-cxf/src/main/java/org/apache/cxf/jaxrs/utils/ResourceUtils.java
new file mode 100644
index 0000000..e93b112
--- /dev/null
+++ b/core/rest-cxf/src/main/java/org/apache/cxf/jaxrs/utils/ResourceUtils.java
@@ -0,0 +1,1014 @@
+/*
+ * 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.io.File;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.lang.reflect.Type;
+import java.lang.reflect.TypeVariable;
+import java.net.URL;
+import java.nio.charset.StandardCharsets;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.ResourceBundle;
+import java.util.Set;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.annotation.PostConstruct;
+import javax.annotation.PreDestroy;
+import javax.ws.rs.ApplicationPath;
+import javax.ws.rs.BeanParam;
+import javax.ws.rs.CookieParam;
+import javax.ws.rs.Encoded;
+import javax.ws.rs.FormParam;
+import javax.ws.rs.HeaderParam;
+import javax.ws.rs.MatrixParam;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.container.AsyncResponse;
+import javax.ws.rs.container.Suspended;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.ext.MessageBodyWriter;
+import javax.ws.rs.ext.Provider;
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBElement;
+import javax.xml.bind.JAXBException;
+import javax.xml.namespace.QName;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+import org.apache.cxf.Bus;
+import org.apache.cxf.BusFactory;
+import org.apache.cxf.common.classloader.ClassLoaderUtils;
+import org.apache.cxf.common.i18n.BundleUtils;
+import org.apache.cxf.common.jaxb.JAXBUtils;
+import org.apache.cxf.common.logging.LogUtils;
+import org.apache.cxf.common.util.StringUtils;
+import org.apache.cxf.feature.Feature;
+import org.apache.cxf.helpers.CastUtils;
+import org.apache.cxf.helpers.DOMUtils;
+import org.apache.cxf.jaxrs.JAXRSServerFactoryBean;
+import org.apache.cxf.jaxrs.ext.DefaultMethod;
+import org.apache.cxf.jaxrs.ext.xml.ElementClass;
+import org.apache.cxf.jaxrs.ext.xml.XMLName;
+import org.apache.cxf.jaxrs.lifecycle.PerRequestResourceProvider;
+import org.apache.cxf.jaxrs.lifecycle.ResourceProvider;
+import org.apache.cxf.jaxrs.lifecycle.SingletonResourceProvider;
+import org.apache.cxf.jaxrs.model.ClassResourceInfo;
+import org.apache.cxf.jaxrs.model.MethodDispatcher;
+import org.apache.cxf.jaxrs.model.OperationResourceInfo;
+import org.apache.cxf.jaxrs.model.Parameter;
+import org.apache.cxf.jaxrs.model.ParameterType;
+import org.apache.cxf.jaxrs.model.ResourceTypes;
+import org.apache.cxf.jaxrs.model.URITemplate;
+import org.apache.cxf.jaxrs.model.UserOperation;
+import org.apache.cxf.jaxrs.model.UserResource;
+import org.apache.cxf.jaxrs.provider.JAXBElementProvider;
+import org.apache.cxf.message.Message;
+import org.apache.cxf.message.MessageImpl;
+import org.apache.cxf.resource.ResourceManager;
+import org.apache.cxf.staxutils.StaxUtils;
+
+public final class ResourceUtils {
+
+    //CHECKSTYLE:OFF
+    private static final Logger LOG = LogUtils.getL7dLogger(ResourceUtils.class);
+    private static final ResourceBundle BUNDLE = BundleUtils.getBundle(ResourceUtils.class);
+    private static final String CLASSPATH_PREFIX = "classpath:";
+    private static final String NOT_RESOURCE_METHOD_MESSAGE_ID = "NOT_RESOURCE_METHOD";
+    private static final String NOT_SUSPENDED_ASYNC_MESSAGE_ID = "NOT_SUSPENDED_ASYNC_METHOD";
+    private static final String NO_VOID_RETURN_ASYNC_MESSAGE_ID = "NO_VOID_RETURN_ASYNC_METHOD";
+    private static final Set<String> SERVER_PROVIDER_CLASS_NAMES;
+    static {
+        SERVER_PROVIDER_CLASS_NAMES = new HashSet<>();
+        SERVER_PROVIDER_CLASS_NAMES.add("javax.ws.rs.ext.MessageBodyWriter");
+        SERVER_PROVIDER_CLASS_NAMES.add("javax.ws.rs.ext.MessageBodyReader");
+        SERVER_PROVIDER_CLASS_NAMES.add("javax.ws.rs.ext.ExceptionMapper");
+        SERVER_PROVIDER_CLASS_NAMES.add("javax.ws.rs.ext.ContextResolver");
+        SERVER_PROVIDER_CLASS_NAMES.add("javax.ws.rs.ext.ReaderInterceptor");
+        SERVER_PROVIDER_CLASS_NAMES.add("javax.ws.rs.ext.WriterInterceptor");
+        SERVER_PROVIDER_CLASS_NAMES.add("javax.ws.rs.ext.ParamConverterProvider");
+        SERVER_PROVIDER_CLASS_NAMES.add("javax.ws.rs.container.ContainerRequestFilter");
+        SERVER_PROVIDER_CLASS_NAMES.add("javax.ws.rs.container.ContainerResponseFilter");
+        SERVER_PROVIDER_CLASS_NAMES.add("javax.ws.rs.container.DynamicFeature");
+        SERVER_PROVIDER_CLASS_NAMES.add("javax.ws.rs.core.Feature");
+        SERVER_PROVIDER_CLASS_NAMES.add("org.apache.cxf.jaxrs.ext.ContextProvider");
+
+    }
+
+    private ResourceUtils() {
+    }
+
+    private static Method[] getDeclaredMethods(final Class<?> c) {
+        return AccessController.doPrivileged(new PrivilegedAction<Method[]>() {
+            @Override
+            public Method[] run() {
+                return c.getDeclaredMethods();
+            }
+        });
+    }
+    public static Method findPostConstructMethod(Class<?> c) {
+        return findPostConstructMethod(c, null);
+    }
+    public static Method findPostConstructMethod(Class<?> c, String name) {
+        if (Object.class == c || null == c) {
+            return null;
+        }
+        for (Method m : getDeclaredMethods(c)) {
+            if (name != null) {
+                if (m.getName().equals(name)) {
+                    return m;
+                }
+            } else if (m.getAnnotation(PostConstruct.class) != null) {
+                return m;
+            }
+        }
+        Method m = findPostConstructMethod(c.getSuperclass(), name);
+        if (m != null) {
+            return m;
+        }
+        for (Class<?> i : c.getInterfaces()) {
+            m = findPostConstructMethod(i, name);
+            if (m != null) {
+                return m;
+            }
+        }
+        return null;
+    }
+
+    public static Method findPreDestroyMethod(Class<?> c) {
+        return findPreDestroyMethod(c, null);
+    }
+
+    public static Method findPreDestroyMethod(Class<?> c, String name) {
+        if (Object.class == c || null == c) {
+            return null;
+        }
+        for (Method m : getDeclaredMethods(c)) {
+            if (name != null) {
+                if (m.getName().equals(name)) {
+                    return m;
+                }
+            } else if (m.getAnnotation(PreDestroy.class) != null) {
+                return m;
+            }
+        }
+        Method m = findPreDestroyMethod(c.getSuperclass(), name);
+        if (m != null) {
+            return m;
+        }
+        for (Class<?> i : c.getInterfaces()) {
+            m = findPreDestroyMethod(i, name);
+            if (m != null) {
+                return m;
+            }
+        }
+        return null;
+    }
+
+    public static ClassResourceInfo createClassResourceInfo(
+        Map<String, UserResource> resources, UserResource model,
+        Class<?> defaultClass,
+        boolean isRoot, boolean enableStatic,
+        Bus bus) {
+        final boolean isDefaultClass = defaultClass != null;
+        Class<?> sClass = !isDefaultClass  ? loadClass(model.getName()) : defaultClass;
+        return createServiceClassResourceInfo(resources, model, sClass, isRoot, enableStatic, bus);
+    }
+
+    public static ClassResourceInfo createServiceClassResourceInfo(
+        Map<String, UserResource> resources, UserResource model,
+        Class<?> sClass, boolean isRoot, boolean enableStatic, Bus bus) {
+        if (model == null) {
+            throw new RuntimeException("Resource class " + sClass.getName() + " has no model info");
+        }
+        ClassResourceInfo cri =
+            new ClassResourceInfo(sClass, sClass, isRoot, enableStatic, true,
+                                  model.getConsumes(), model.getProduces(), bus);
+        URITemplate t = URITemplate.createTemplate(model.getPath());
+        cri.setURITemplate(t);
+
+        MethodDispatcher md = new MethodDispatcher();
+        Map<String, UserOperation> ops = model.getOperationsAsMap();
+
+        Method defaultMethod = null;
+        Map<String, Method> methodNames = new HashMap<>();
+        for (Method m : cri.getServiceClass().getMethods()) {
+            if (m.getAnnotation(DefaultMethod.class) != null) {
+                // if needed we can also support multiple default methods
+                defaultMethod = m;
+            }
+            methodNames.put(m.getName(), m);
+        }
+
+        for (Map.Entry<String, UserOperation> entry : ops.entrySet()) {
+            UserOperation op = entry.getValue();
+            Method actualMethod = methodNames.get(op.getName());
+            if (actualMethod == null) {
+                actualMethod = defaultMethod;
+            }
+            if (actualMethod == null) {
+                continue;
+            }
+            OperationResourceInfo ori =
+                new OperationResourceInfo(actualMethod, cri, URITemplate.createTemplate(op.getPath()),
+                                          op.getVerb(), op.getConsumes(), op.getProduces(),
+                                          op.getParameters(),
+                                          op.isOneway());
+            String rClassName = actualMethod.getReturnType().getName();
+            if (op.getVerb() == null) {
+                if (resources.containsKey(rClassName)) {
+                    ClassResourceInfo subCri = rClassName.equals(model.getName()) ? cri
+                        : createServiceClassResourceInfo(resources, resources.get(rClassName),
+                                                         actualMethod.getReturnType(), false, enableStatic, bus);
+                    if (subCri != null) {
+                        cri.addSubClassResourceInfo(subCri);
+                        md.bind(ori, actualMethod);
+                    }
+                }
+            } else {
+                md.bind(ori, actualMethod);
+            }
+        }
+
+        cri.setMethodDispatcher(md);
+        return checkMethodDispatcher(cri) ? cri : null;
+
+    }
+
+    public static ClassResourceInfo createClassResourceInfo(final Class<?> rClass,
+                                                            final Class<?> sClass,
+                                                            boolean root,
+                                                            boolean enableStatic) {
+        return createClassResourceInfo(rClass, sClass, root, enableStatic, BusFactory.getThreadDefaultBus());
+
+    }
+
+    public static ClassResourceInfo createClassResourceInfo(final Class<?> rClass,
+                                                            final Class<?> sClass,
+                                                            boolean root,
+                                                            boolean enableStatic,
+                                                            Bus bus) {
+        return createClassResourceInfo(rClass, sClass, null, root, enableStatic, bus);
+    }
+
+    public static ClassResourceInfo createClassResourceInfo(final Class<?> rClass,
+                                                            final Class<?> sClass,
+                                                            ClassResourceInfo parent,
+                                                            boolean root,
+                                                            boolean enableStatic,
+                                                            Bus bus) {
+        ClassResourceInfo cri = new ClassResourceInfo(rClass, sClass, root, enableStatic, bus);
+        cri.setParent(parent);
+
+        if (root) {
+            URITemplate t = URITemplate.createTemplate(cri.getPath());
+            cri.setURITemplate(t);
+        }
+
+        evaluateResourceClass(cri, enableStatic);
+        return checkMethodDispatcher(cri) ? cri : null;
+    }
+
+    private static void evaluateResourceClass(ClassResourceInfo cri, boolean enableStatic) {
+        MethodDispatcher md = new MethodDispatcher();
+        Class<?> serviceClass = cri.getServiceClass();
+
+        for (Method m : serviceClass.getMethods()) {
+
+            Method annotatedMethod = AnnotationUtils.getAnnotatedMethod(serviceClass, m);
+
+            String httpMethod = AnnotationUtils.getHttpMethodValue(annotatedMethod);
+            Path path = AnnotationUtils.getMethodAnnotation(annotatedMethod, Path.class);
+
+            if (httpMethod != null || path != null) {
+                if (!checkAsyncResponse(annotatedMethod)) {
+                    continue;
+                }
+
+                md.bind(createOperationInfo(m, annotatedMethod, cri, path, httpMethod), m);
+                if (httpMethod == null) {
+                    // subresource locator
+                    Class<?> subClass = m.getReturnType();
+                    if (subClass == Class.class) {
+                        subClass = InjectionUtils.getActualType(m.getGenericReturnType());
+                    }
+                    if (enableStatic) {
+                        ClassResourceInfo subCri = cri.findResource(subClass, subClass);
+                        if (subCri == null) {
+                            ClassResourceInfo ancestor = getAncestorWithSameServiceClass(cri, subClass);
+                            subCri = ancestor != null ? ancestor
+                                     : createClassResourceInfo(subClass, subClass, cri, false, enableStatic,
+                                                               cri.getBus());
+                        }
+
+                        if (subCri != null) {
+                            cri.addSubClassResourceInfo(subCri);
+                        }
+                    }
+                }
+            } else {
+                reportInvalidResourceMethod(m, NOT_RESOURCE_METHOD_MESSAGE_ID, Level.FINE);
+            }
+        }
+        cri.setMethodDispatcher(md);
+    }
+
+    private static void reportInvalidResourceMethod(Method m, String messageId, Level logLevel) {
+        if (LOG.isLoggable(logLevel)) {
+            LOG.log(logLevel, new org.apache.cxf.common.i18n.Message(messageId,
+                                                             BUNDLE,
+                                                             m.getDeclaringClass().getName(),
+                                                             m.getName()).toString());
+        }
+    }
+
+    private static boolean checkAsyncResponse(Method m) {
+        Class<?>[] types = m.getParameterTypes();
+        for (int i = 0; i < types.length; i++) {
+            if (types[i] == AsyncResponse.class) {
+                if (AnnotationUtils.getAnnotation(m.getParameterAnnotations()[i], Suspended.class) == null) {
+                    reportInvalidResourceMethod(m, NOT_SUSPENDED_ASYNC_MESSAGE_ID, Level.FINE);
+                    return false;
+                }
+                if (m.getReturnType() == Void.TYPE || m.getReturnType() == Void.class) {
+                    return true;
+                }
+                reportInvalidResourceMethod(m, NO_VOID_RETURN_ASYNC_MESSAGE_ID, Level.WARNING);
+                return false;
+            }
+        }
+        return true;
+    }
+
+    private static ClassResourceInfo getAncestorWithSameServiceClass(ClassResourceInfo parent, Class<?> subClass) {
+        if (parent == null) {
+            return null;
+        }
+        if (parent.getServiceClass() == subClass) {
+            return parent;
+        }
+        return getAncestorWithSameServiceClass(parent.getParent(), subClass);
+    }
+
+    public static Constructor<?> findResourceConstructor(Class<?> resourceClass, boolean perRequest) {
+        List<Constructor<?>> cs = new LinkedList<Constructor<?>>();
+        for (Constructor<?> c : resourceClass.getConstructors()) {
+            Class<?>[] params = c.getParameterTypes();
+            Annotation[][] anns = c.getParameterAnnotations();
+            boolean match = true;
+            for (int i = 0; i < params.length; i++) {
+                if (!perRequest) {
+                    if (AnnotationUtils.getAnnotation(anns[i], Context.class) == null) {
+                        match = false;
+                        break;
+                    }
+                } else if (!AnnotationUtils.isValidParamAnnotations(anns[i])) {
+                    match = false;
+                    break;
+                }
+            }
+            if (match) {
+                cs.add(c);
+            }
+        }
+        Collections.sort(cs, new Comparator<Constructor<?>>() {
+
+            public int compare(Constructor<?> c1, Constructor<?> c2) {
+                int p1 = c1.getParameterTypes().length;
+                int p2 = c2.getParameterTypes().length;
+                return p1 > p2 ? -1 : p1 < p2 ? 1 : 0;
+            }
+
+        });
+        return cs.isEmpty() ? null : cs.get(0);
+    }
+
+    public static List<Parameter> getParameters(Method resourceMethod) {
+        Annotation[][] paramAnns = resourceMethod.getParameterAnnotations();
+        if (paramAnns.length == 0) {
+            return CastUtils.cast(Collections.emptyList(), Parameter.class);
+        }
+        Class<?>[] types = resourceMethod.getParameterTypes();
+        List<Parameter> params = new ArrayList<>(paramAnns.length);
+        for (int i = 0; i < paramAnns.length; i++) {
+            Parameter p = getParameter(i, paramAnns[i], types[i]);
+            params.add(p);
+        }
+        return params;
+    }
+
+    //CHECKSTYLE:OFF
+    public static Parameter getParameter(int index, Annotation[] anns, Class<?> type) {
+
+        Context ctx = AnnotationUtils.getAnnotation(anns, Context.class);
+        if (ctx != null) {
+            return new Parameter(ParameterType.CONTEXT, index, null);
+        }
+
+        boolean isEncoded = AnnotationUtils.getAnnotation(anns, Encoded.class) != null;
+
+        BeanParam bp = AnnotationUtils.getAnnotation(anns, BeanParam.class);
+        if (bp != null) {
+            return new Parameter(ParameterType.BEAN, index, null, isEncoded, null);
+        }
+
+        String dValue = AnnotationUtils.getDefaultParameterValue(anns);
+
+        PathParam a = AnnotationUtils.getAnnotation(anns, PathParam.class);
+        if (a != null) {
+            return new Parameter(ParameterType.PATH, index, a.value(), isEncoded, dValue);
+        }
+        QueryParam q = AnnotationUtils.getAnnotation(anns, QueryParam.class);
+        if (q != null) {
+            return new Parameter(ParameterType.QUERY, index, q.value(), isEncoded, dValue);
+        }
+        MatrixParam m = AnnotationUtils.getAnnotation(anns, MatrixParam.class);
+        if (m != null) {
+            return new Parameter(ParameterType.MATRIX, index, m.value(), isEncoded, dValue);
+        }
+
+        FormParam f = AnnotationUtils.getAnnotation(anns, FormParam.class);
+        if (f != null) {
+            return new Parameter(ParameterType.FORM, index, f.value(), isEncoded, dValue);
+        }
+
+        HeaderParam h = AnnotationUtils.getAnnotation(anns, HeaderParam.class);
+        if (h != null) {
+            return new Parameter(ParameterType.HEADER, index, h.value(), isEncoded, dValue);
+        }
+
+        CookieParam c = AnnotationUtils.getAnnotation(anns, CookieParam.class);
+        if (c != null) {
+            return new Parameter(ParameterType.COOKIE, index, c.value(), isEncoded, dValue);
+        }
+
+        return new Parameter(ParameterType.REQUEST_BODY, index, null);
+
+    }
+    //CHECKSTYLE:ON
+
+    private static OperationResourceInfo createOperationInfo(Method m, Method annotatedMethod,
+                                                      ClassResourceInfo cri, Path path, String httpMethod) {
+        OperationResourceInfo ori = new OperationResourceInfo(m, annotatedMethod, cri);
+        URITemplate t = URITemplate.createTemplate(path);
+        ori.setURITemplate(t);
+        ori.setHttpMethod(httpMethod);
+        return ori;
+    }
+
+
+    private static boolean checkMethodDispatcher(ClassResourceInfo cr) {
+        if (cr.getMethodDispatcher().getOperationResourceInfos().isEmpty()) {
+            LOG.warning(new org.apache.cxf.common.i18n.Message("NO_RESOURCE_OP_EXC",
+                                                               BUNDLE,
+                                                               cr.getServiceClass().getName()).toString());
+            return false;
+        }
+        return true;
+    }
+
+
+    private static Class<?> loadClass(String cName) {
+        try {
+            return ClassLoaderUtils.loadClass(cName.trim(), ResourceUtils.class);
+        } catch (ClassNotFoundException ex) {
+            throw new RuntimeException("No class " + cName.trim() + " can be found", ex);
+        }
+    }
+
+
+    public static List<UserResource> getUserResources(String loc, Bus bus) {
+        try {
+            InputStream is = ResourceUtils.getResourceStream(loc, bus);
+            if (is == null) {
+                return null;
+            }
+            return getUserResources(is);
+        } catch (Exception ex) {
+            LOG.warning("Problem with processing a user model at " + loc);
+        }
+
+        return null;
+    }
+
+    public static InputStream getResourceStream(String loc, Bus bus) throws Exception {
+        URL url = getResourceURL(loc, bus);
+        return url == null ? null : url.openStream();
+    }
+
+    public static URL getResourceURL(String loc, Bus bus) throws Exception {
+        URL url = null;
+        if (loc.startsWith(CLASSPATH_PREFIX)) {
+            String path = loc.substring(CLASSPATH_PREFIX.length());
+            url = ResourceUtils.getClasspathResourceURL(path, ResourceUtils.class, bus);
+        } else {
+            try {
+                url = new URL(loc);
+            } catch (Exception ex) {
+                // it can be either a classpath or file resource without a scheme
+                url = ResourceUtils.getClasspathResourceURL(loc, ResourceUtils.class, bus);
+                if (url == null) {
+                    File file = new File(loc);
+                    if (file.exists()) {
+                        url = file.toURI().toURL();
+                    }
+                }
+            }
+        }
+        if (url == null) {
+            LOG.warning("No resource " + loc + " is available");
+        }
+        return url;
+    }
+
+    public static InputStream getClasspathResourceStream(String path, Class<?> callingClass, Bus bus) {
+        InputStream is = ClassLoaderUtils.getResourceAsStream(path, callingClass);
+        return is == null ? getResource(path, InputStream.class, bus) : is;
+    }
+
+    public static URL getClasspathResourceURL(String path, Class<?> callingClass, Bus bus) {
+        URL url = ClassLoaderUtils.getResource(path, callingClass);
+        return url == null ? getResource(path, URL.class, bus) : url;
+    }
+
+    public static <T> T getResource(String path, Class<T> resourceClass, Bus bus) {
+        if (bus != null) {
+            ResourceManager rm = bus.getExtension(ResourceManager.class);
+            if (rm != null) {
+                return rm.resolveResource(path, resourceClass);
+            }
+        }
+        return null;
+    }
+
+    public static Properties loadProperties(String propertiesLocation, Bus bus) throws Exception {
+        Properties props = new Properties();
+        InputStream is = getResourceStream(propertiesLocation, bus);
+        props.load(is);
+        return props;
+    }
+
+    public static List<UserResource> getUserResources(String loc) {
+        return getUserResources(loc, BusFactory.getThreadDefaultBus());
+    }
+
+    public static List<UserResource> getUserResources(InputStream is) throws Exception {
+        Document doc = StaxUtils.read(new InputStreamReader(is, StandardCharsets.UTF_8));
+        return getResourcesFromElement(doc.getDocumentElement());
+    }
+
+    public static List<UserResource> getResourcesFromElement(Element modelEl) {
+        List<UserResource> resources = new ArrayList<>();
+        List<Element> resourceEls =
+            DOMUtils.findAllElementsByTagNameNS(modelEl,
+                                                "http://cxf.apache.org/jaxrs", "resource");
+        for (Element e : resourceEls) {
+            resources.add(getResourceFromElement(e));
+        }
+        return resources;
+    }
+
+
+    public static ResourceTypes getAllRequestResponseTypes(List<ClassResourceInfo> cris,
+                                                           boolean jaxbOnly) {
+        return getAllRequestResponseTypes(cris, jaxbOnly, null);
+    }
+
+    public static ResourceTypes getAllRequestResponseTypes(List<ClassResourceInfo> cris,
+                                                           boolean jaxbOnly,
+                                                           MessageBodyWriter<?> jaxbWriter) {
+        ResourceTypes types = new ResourceTypes();
+        for (ClassResourceInfo resource : cris) {
+            getAllTypesForResource(resource, types, jaxbOnly, jaxbWriter);
+        }
+        return types;
+    }
+
+    public static Class<?> getActualJaxbType(Class<?> type, Method resourceMethod, boolean inbound) {
+        ElementClass element = resourceMethod.getAnnotation(ElementClass.class);
+        if  (element != null) {
+            Class<?> cls = inbound ? element.request() : element.response();
+            if (cls != Object.class) {
+                return cls;
+            }
+        }
+        return type;
+    }
+
+    private static void getAllTypesForResource(ClassResourceInfo resource,
+                                               ResourceTypes types,
+                                               boolean jaxbOnly,
+                                               MessageBodyWriter<?> jaxbWriter) {
+        for (OperationResourceInfo ori : resource.getMethodDispatcher().getOperationResourceInfos()) {
+            Method method = ori.getAnnotatedMethod() == null ? ori.getMethodToInvoke() : ori.getAnnotatedMethod();
+            Class<?> realReturnType = method.getReturnType();
+            Class<?> cls = realReturnType;
+            if (cls == Response.class || ori.isAsync()) {
+                cls = getActualJaxbType(cls, method, false);
+            }
+            Type type = method.getGenericReturnType();
+            if (jaxbOnly) {
+                checkJaxbType(resource.getServiceClass(), cls, realReturnType == Response.class || ori.isAsync()
+                    ? cls : type, types, method.getAnnotations(), jaxbWriter);
+            } else {
+                types.getAllTypes().put(cls, type);
+            }
+
+            for (Parameter pm : ori.getParameters()) {
+                if (pm.getType() == ParameterType.REQUEST_BODY) {
+                    Class<?> inType = method.getParameterTypes()[pm.getIndex()];
+                    if (inType != AsyncResponse.class) {
+                        Type paramType = method.getGenericParameterTypes()[pm.getIndex()];
+                        if (jaxbOnly) {
+                            checkJaxbType(resource.getServiceClass(), inType, paramType, types,
+                                          method.getParameterAnnotations()[pm.getIndex()], jaxbWriter);
+                        } else {
+                            types.getAllTypes().put(inType, paramType);
+                        }
+                    }
+                }
+            }
+
+        }
+
+        for (ClassResourceInfo sub : resource.getSubResources()) {
+            if (!isRecursiveSubResource(resource, sub)) {
+                getAllTypesForResource(sub, types, jaxbOnly, jaxbWriter);
+            }
+        }
+    }
+
+    private static boolean isRecursiveSubResource(ClassResourceInfo parent, ClassResourceInfo sub) {
+        if (parent == null) {
+            return false;
+        }
+        if (parent == sub) {
+            return true;
+        }
+        return isRecursiveSubResource(parent.getParent(), sub);
+    }
+
+    private static void checkJaxbType(Class<?> serviceClass,
+                                      Class<?> type,
+                                      Type genericType,
+                                      ResourceTypes types,
+                                      Annotation[] anns,
+                                      MessageBodyWriter<?> jaxbWriter) {
+        boolean isCollection = false;
+        if (InjectionUtils.isSupportedCollectionOrArray(type)) {
+            type = InjectionUtils.getActualType(genericType);
+            isCollection = true;
+        }
+        if (type == Object.class && !(genericType instanceof Class)
+            || genericType instanceof TypeVariable) {
+            Type theType = InjectionUtils.processGenericTypeIfNeeded(serviceClass,
+                                                      Object.class,
+                                                      genericType);
+            type = InjectionUtils.getActualType(theType);
+        }
+        if (type == null
+            || InjectionUtils.isPrimitive(type)
+            || JAXBElement.class.isAssignableFrom(type)
+            || Response.class.isAssignableFrom(type)
+            || type.isInterface()) {
+            return;
+        }
+
+        MessageBodyWriter<?> writer = jaxbWriter;
+        if (writer == null) {
+            JAXBElementProvider<Object> defaultWriter = new JAXBElementProvider<Object>();
+            defaultWriter.setMarshallAsJaxbElement(true);
+            defaultWriter.setXmlTypeAsJaxbElementOnly(true);
+            writer = defaultWriter;
+        }
+        if (writer.isWriteable(type, type, anns, MediaType.APPLICATION_XML_TYPE)) {
+            types.getAllTypes().put(type, type);
+            Class<?> genCls = InjectionUtils.getActualType(genericType);
+            if (genCls != type && genCls != null && genCls != Object.class
+                && !InjectionUtils.isSupportedCollectionOrArray(genCls)) {
+                types.getAllTypes().put(genCls, genCls);
+            }
+
+            XMLName name = AnnotationUtils.getAnnotation(anns, XMLName.class);
+            QName qname = name != null ? JAXRSUtils.convertStringToQName(name.value()) : null;
+            if (isCollection) {
+                types.getCollectionMap().put(type, qname);
+            } else {
+                types.getXmlNameMap().put(type, qname);
+            }
+        }
+    }
+
+    private static UserResource getResourceFromElement(Element e) {
+        UserResource resource = new UserResource();
+        resource.setName(e.getAttribute("name"));
+        resource.setPath(e.getAttribute("path"));
+        resource.setConsumes(e.getAttribute("consumes"));
+        resource.setProduces(e.getAttribute("produces"));
+        List<Element> operEls =
+            DOMUtils.findAllElementsByTagNameNS(e,
+                 "http://cxf.apache.org/jaxrs", "operation");
+        List<UserOperation> opers = new ArrayList<>(operEls.size());
+        for (Element operEl : operEls) {
+            opers.add(getOperationFromElement(operEl));
+        }
+        resource.setOperations(opers);
+        return resource;
+    }
+
+    private static UserOperation getOperationFromElement(Element e) {
+        UserOperation op = new UserOperation();
+        op.setName(e.getAttribute("name"));
+        op.setVerb(e.getAttribute("verb"));
+        op.setPath(e.getAttribute("path"));
+        op.setOneway(Boolean.parseBoolean(e.getAttribute("oneway")));
+        op.setConsumes(e.getAttribute("consumes"));
+        op.setProduces(e.getAttribute("produces"));
+        List<Element> paramEls =
+            DOMUtils.findAllElementsByTagNameNS(e,
+                 "http://cxf.apache.org/jaxrs", "param");
+        List<Parameter> params = new ArrayList<>(paramEls.size());
+        for (int i = 0; i < paramEls.size(); i++) {
+            Element paramEl = paramEls.get(i);
+            Parameter p = new Parameter(paramEl.getAttribute("type"), i, paramEl.getAttribute("name"));
+            p.setEncoded(Boolean.valueOf(paramEl.getAttribute("encoded")));
+            p.setDefaultValue(paramEl.getAttribute("defaultValue"));
+            String pClass = paramEl.getAttribute("class");
+            if (!StringUtils.isEmpty(pClass)) {
+                try {
+                    p.setJavaType(ClassLoaderUtils.loadClass(pClass, ResourceUtils.class));
+                } catch (Exception ex) {
+                    throw new RuntimeException(ex);
+                }
+            }
+            params.add(p);
+        }
+        op.setParameters(params);
+        return op;
+    }
+
+    public static Object[] createConstructorArguments(Constructor<?> c,
+                                                      Message m,
+                                                      boolean perRequest) {
+        return createConstructorArguments(c, m, perRequest, null);
+    }
+
+    public static Object[] createConstructorArguments(Constructor<?> c,
+                                                      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();
+        @SuppressWarnings("unchecked")
+        MultivaluedMap<String, String> templateValues = 
+            (MultivaluedMap<String, String>)m.get(URITemplate.TEMPLATE_PARAMETERS);
+        Object[] values = new Object[params.length];
+        for (int i = 0; i < params.length; i++) {
+            if (AnnotationUtils.getAnnotation(anns[i], Context.class) != null) {
+                Object contextValue = contextValues != null ? contextValues.get(params[i]) : null;
+                if (contextValue == null) {
+                    if (perRequest || InjectionUtils.VALUE_CONTEXTS.contains(params[i].getName())) {
+                        values[i] = JAXRSUtils.createContextValue(m, genericTypes[i], params[i]);
+                    } else {
+                        values[i] = InjectionUtils.createThreadLocalProxy(params[i]);
+                    }
+                } else {
+                    values[i] = contextValue;
+                }
+            } else {
+                // this branch won't execute for singletons given that the found constructor
+                // is guaranteed to have only Context parameters, if any, for singletons
+                Parameter p = ResourceUtils.getParameter(i, anns[i], params[i]);
+                values[i] = JAXRSUtils.createHttpParameterValue(
+                                p, params[i], genericTypes[i], anns[i], m, templateValues, null);
+            }
+        }
+        return values;
+    }
+    
+    @SuppressWarnings("unchecked")
+    public static JAXRSServerFactoryBean createApplication(Application app, 
+                                                           boolean ignoreAppPath,
+                                                           boolean staticSubresourceResolution, 
+                                                           boolean useSingletonResourceProvider,
+                                                           Bus bus) {
+
+        Set<Object> singletons = app.getSingletons();
+        verifySingletons(singletons);
+
+        List<Class<?>> resourceClasses = new ArrayList<Class<?>>();
+        List<Object> providers = new ArrayList<>();
+        List<Feature> features = new ArrayList<>();
+        Map<Class<?>, ResourceProvider> map = new HashMap<>();
+
+        // Note, app.getClasses() returns a list of per-request classes
+        // or singleton provider classes
+        for (Class<?> cls : app.getClasses()) {
+            if (isValidApplicationClass(cls, singletons)) {
+                if (isValidProvider(cls)) {
+                    providers.add(createProviderInstance(cls));
+                } else if (Feature.class.isAssignableFrom(cls)) {
+                    features.add(createFeatureInstance((Class<? extends Feature>) cls));
+                } else {
+                    resourceClasses.add(cls);
+                    if (useSingletonResourceProvider) {
+                        map.put(cls, new SingletonResourceProvider(createProviderInstance(cls)));
+                    } else {
+                        map.put(cls, new PerRequestResourceProvider(cls));
+                    }
+                }
+            }
+        }
+
+        // we can get either a provider or resource class here
+        for (Object o : singletons) {
+            if (isValidProvider(o.getClass())) {
+                providers.add(o);
+            } else if (o instanceof Feature) {
+                features.add((Feature) o);
+            } else {
+                resourceClasses.add(o.getClass());
+                map.put(o.getClass(), new SingletonResourceProvider(o));
+            }
+        }
+
+        JAXRSServerFactoryBean bean = new JAXRSServerFactoryBean();
+        if (bus != null) {
+            bean.setBus(bus);
+        }
+
+        String address = "/";
+        if (!ignoreAppPath) {
+            ApplicationPath appPath = locateApplicationPath(app.getClass());
+            if (appPath != null) {
+                address = appPath.value();
+            }
+        }
+        if (!address.startsWith("/")) {
+            address = "/" + address;
+        }
+        bean.setAddress(address);
+        bean.setStaticSubresourceResolution(staticSubresourceResolution);
+        bean.setResourceClasses(resourceClasses);
+        bean.setProviders(providers);
+        bean.setFeatures(features);
+        for (Map.Entry<Class<?>, ResourceProvider> entry : map.entrySet()) {
+            bean.setResourceProvider(entry.getKey(), entry.getValue());
+        }
+        Map<String, Object> appProps = app.getProperties();
+        if (appProps != null) {
+            bean.getProperties(true).putAll(appProps);
+        }
+        bean.setApplication(app);
+        return bean;
+    }
+
+    public static Object createProviderInstance(Class<?> cls) {
+        try {
+            Constructor<?> c = ResourceUtils.findResourceConstructor(cls, false);
+            if (c != null && c.getParameterTypes().length == 0) {
+                return c.newInstance();
+            }
+            return c;
+        } catch (Throwable ex) {
+            throw new RuntimeException("Provider " + cls.getName() + " can not be created", ex);
+        }
+    }
+
+    public static Feature createFeatureInstance(Class<? extends Feature> cls) {
+        try {
+            Constructor<?> c = ResourceUtils.findResourceConstructor(cls, false);
+
+            if (c == null) {
+                throw new RuntimeException("No valid constructor found for " + cls.getName());
+            }
+
+            return (Feature) c.newInstance();
+        } catch (Throwable ex) {
+            throw new RuntimeException("Feature " + cls.getName() + " can not be created", ex);
+        }
+    }
+
+    private static boolean isValidProvider(Class<?> c) {
+        if (c == null || c == Object.class) {
+            return false;
+        }
+        if (c.getAnnotation(Provider.class) != null) {
+            return true;
+        }
+        for (Class<?> itf : c.getInterfaces()) {
+            if (SERVER_PROVIDER_CLASS_NAMES.contains(itf.getName())) {
+                return true;
+            }
+        }
+        return isValidProvider(c.getSuperclass());
+    }
+
+    private static void verifySingletons(Set<Object> singletons) {
+        if (singletons.isEmpty()) {
+            return;
+        }
+        Set<String> map = new HashSet<>();
+        for (Object s : singletons) {
+            if (map.contains(s.getClass().getName())) {
+                throw new RuntimeException("More than one instance of the same singleton class "
+                                           + s.getClass().getName() + " is available");
+            }
+            map.add(s.getClass().getName());
+        }
+    }
+
+    public static boolean isValidResourceClass(Class<?> c) {
+        if (c.isInterface() || Modifier.isAbstract(c.getModifiers())) {
+            LOG.info("Ignoring invalid resource class " + c.getName());
+            return false;
+        }
+        return true;
+    }
+
+    public static ApplicationPath locateApplicationPath(Class<?> appClass) {
+        ApplicationPath appPath = appClass.getAnnotation(ApplicationPath.class);
+        if (appPath == null && appClass.getSuperclass() != Application.class) {
+            return locateApplicationPath(appClass.getSuperclass());
+        }
+        return appPath;
+    }
+
+    private static boolean isValidApplicationClass(Class<?> c, Set<Object> singletons) {
+        if (!isValidResourceClass(c)) {
+            return false;
+        }
+        for (Object s : singletons) {
+            if (c == s.getClass()) {
+                LOG.info("Ignoring per-request resource class " + c.getName()
+                         + " as it is also registered as singleton");
+                return false;
+            }
+        }
+        return true;
+    }
+
+    //TODO : consider moving JAXBDataBinding.createContext to JAXBUtils
+    public static JAXBContext createJaxbContext(Set<Class<?>> classes, Class<?>[] extraClass,
+                                          Map<String, Object> contextProperties) {
+        if (classes == null || classes.isEmpty()) {
+            return null;
+        }
+        JAXBUtils.scanPackages(classes, extraClass, null);
+
+        JAXBContext ctx;
+        try {
+            ctx = JAXBContext.newInstance(classes.toArray(new Class[classes.size()]),
+                                          contextProperties);
+            return ctx;
+        } catch (JAXBException ex) {
+            LOG.log(Level.SEVERE, "No JAXB context can be created", ex);
+        }
+        return null;
+    }
+
+    //CHECKSTYLE:ON
+}
+