All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.glassfish.jersey.client.proxy.RequestParameters Maven / Gradle / Ivy

Go to download

Jersey extension module providing support for (proxy-based) high-level client API.

There is a newer version: 4.0.0-M1
Show newest version
/*
 * Copyright (c) 2012, 2023 Oracle and/or its affiliates. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0, which is available at
 * http://www.eclipse.org/legal/epl-2.0.
 *
 * This Source Code may also be made available under the following Secondary
 * Licenses when the conditions for such availability set forth in the
 * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
 * version 2 with the GNU Classpath Exception, which is available at
 * https://www.gnu.org/software/classpath/license.html.
 *
 * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
 */

package org.glassfish.jersey.client.proxy;

import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import javax.ws.rs.BeanParam;
import javax.ws.rs.CookieParam;
import javax.ws.rs.FormParam;
import javax.ws.rs.HeaderParam;
import javax.ws.rs.MatrixParam;
import javax.ws.rs.PathParam;
import javax.ws.rs.QueryParam;
import javax.ws.rs.client.WebTarget;
import javax.ws.rs.core.Cookie;
import javax.ws.rs.core.Form;
import javax.ws.rs.core.MultivaluedHashMap;
import javax.ws.rs.core.MultivaluedMap;

/**
 * Collector to retrieve parameters for setting up the HTTP request sent in the invoke method of WebResourceFactory
 * The addParameter method takes a single annotated method parameter or annotated field or property of a BeanParam
 * and adds the information to the web target, headers, cookie list or form.
 */
class RequestParameters {

    private WebTarget newTarget;
    private final MultivaluedHashMap headers;
    private final LinkedList cookies;
    private final Form form;

    private static final List> PARAM_ANNOTATION_CLASSES = Arrays.asList(PathParam.class, QueryParam.class,
            HeaderParam.class, CookieParam.class, MatrixParam.class, FormParam.class, BeanParam.class);

    RequestParameters(final WebTarget newTarget, final MultivaluedMap headers,
                      final List cookies, final Form form) {

        this.headers = new MultivaluedHashMap(headers);
        this.cookies = new LinkedList<>(cookies);
        this.form = new Form();
        this.form.asMap().putAll(form.asMap());

        this.newTarget = newTarget;
    }

    void addParameter(final Object value, final Map, Annotation> anns)
            throws IntrospectionException, InvocationTargetException, IllegalAccessException {

        Annotation ann;
        if ((ann = anns.get(PathParam.class)) != null) {
            newTarget = newTarget.resolveTemplate(((PathParam) ann).value(), value);
        } else if ((ann = anns.get((QueryParam.class))) != null) {
            if (value instanceof Collection) {
                newTarget = newTarget.queryParam(((QueryParam) ann).value(), convert((Collection) value, true));
            } else {
                newTarget = newTarget.queryParam(((QueryParam) ann).value(), encodeTemplate(value));
            }
        } else if ((ann = anns.get((HeaderParam.class))) != null) {
            if (value instanceof Collection) {
                headers.addAll(((HeaderParam) ann).value(), convert((Collection) value, false));
            } else {
                headers.addAll(((HeaderParam) ann).value(), value);
            }

        } else if ((ann = anns.get((CookieParam.class))) != null) {
            final String name = ((CookieParam) ann).value();
            Cookie c;
            if (value instanceof Collection) {
                for (final Object v : ((Collection) value)) {
                    if (!(v instanceof Cookie)) {
                        c = new Cookie(name, v.toString());
                    } else {
                        c = (Cookie) v;
                        if (!name.equals(((Cookie) v).getName())) {
                            // is this the right thing to do? or should I fail? or ignore the difference?
                            c = new Cookie(name, c.getValue(), c.getPath(), c.getDomain(), c.getVersion());
                        }
                    }
                    cookies.add(c);
                }
            } else {
                if (!(value instanceof Cookie)) {
                    cookies.add(new Cookie(name, value.toString()));
                } else {
                    c = (Cookie) value;
                    if (!name.equals(((Cookie) value).getName())) {
                        // is this the right thing to do? or should I fail? or ignore the difference?
                        cookies.add(new Cookie(name, c.getValue(), c.getPath(), c.getDomain(), c.getVersion()));
                    }
                }
            }
        } else if ((ann = anns.get((MatrixParam.class))) != null) {
            if (value instanceof Collection) {
                newTarget = newTarget.matrixParam(((MatrixParam) ann).value(), convert((Collection) value, true));
            } else {
                newTarget = newTarget.matrixParam(((MatrixParam) ann).value(), encodeTemplate(value));
            }
        } else if ((ann = anns.get((FormParam.class))) != null) {
            if (value instanceof Collection) {
                for (final Object v : ((Collection) value)) {
                    form.param(((FormParam) ann).value(), v.toString());
                }
            } else {
                form.param(((FormParam) ann).value(), value.toString());
            }
        } else if ((anns.get((BeanParam.class))) != null) {
            if (value instanceof Collection) {
                for (final Object v : ((Collection) value)) {
                    addBeanParameter(v);
                }
            } else {
                addBeanParameter(value);
            }
        }
    }

    private void addBeanParameter(final Object beanParam)
            throws IllegalAccessException, IntrospectionException, InvocationTargetException {
        Class beanClass = beanParam.getClass();
        List fields = new ArrayList<>();
        getAllFields(fields, beanClass);

        for (final Field field : fields) {
            Object value = null;
            final Map, Annotation> anns = new HashMap<>();

            // get field annotations
            for (final Annotation ann : field.getAnnotations()) {
                anns.put(ann.annotationType(), ann);
            }

            if (hasAnyParamAnnotation(anns)) {
                value = field.get(beanParam);
            } else {
                // get getter annotations if there are no field annotations
                for (final PropertyDescriptor pd : Introspector.getBeanInfo(beanClass).getPropertyDescriptors()) {
                    if (pd.getName().equals(field.getName()) && pd.getReadMethod() != null) {
                        for (final Annotation ann : pd.getReadMethod().getAnnotations()) {
                            anns.put(ann.annotationType(), ann);
                        }
                        if (hasAnyParamAnnotation(anns)) {
                            value = pd.getReadMethod().invoke(beanParam);
                        }
                    }
                }
            }

            if (value != null) {
                addParameter(value, anns);
            }
        }
    }

    private List getAllFields(List fields, Class type) {
        fields.addAll(Arrays.asList(type.getDeclaredFields()));

        if (type.getSuperclass() != null) {
            getAllFields(fields, type.getSuperclass());
        }

        return fields;
    }

    private Object[] convert(Collection value, boolean encode) {
        Object[] array = new Object[value.size()];
        int index = 0;
        for (Iterator it = value.iterator(); it.hasNext();) {
            Object o = it.next();
            array[index++] = o == null ? o : (encode ? encodeTemplate(o) : o.toString());
        }
        return array;
    }

    /**
     * The Query and Matrix arguments are never templates
     * @param notNull an Object that is not null
     * @return encoded curly brackets within the string representation of the {@code notNull}
     */
    private String encodeTemplate(Object notNull) {
        return notNull.toString().replace("{", "%7B").replace("}", "%7D");
    }

    public static boolean hasAnyParamAnnotation(final Map, Annotation> anns) {
        for (final Class paramAnnotationClass : PARAM_ANNOTATION_CLASSES) {
            if (anns.containsKey(paramAnnotationClass)) {
                return true;
            }
        }
        return false;
    }

    WebTarget getNewTarget() {
        return newTarget;
    }

    MultivaluedHashMap getHeaders() {
        return headers;
    }

    LinkedList getCookies() {
        return cookies;
    }

    Form getForm() {
        return form;
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy