/* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * * Copyright (c) 2011-2012 Oracle and/or its affiliates. All rights reserved. * * The contents of this file are subject to the terms of either the GNU * General Public License Version 2 only ("GPL") or the Common Development * and Distribution License("CDDL") (collectively, the "License"). You * may not use this file except in compliance with the License. You can * obtain a copy of the License at * http://glassfish.java.net/public/CDDL+GPL_1_1.html * or packager/legal/LICENSE.txt. See the License for the specific * language governing permissions and limitations under the License. * * When distributing the software, include this License Header Notice in each * file and include the License file at packager/legal/LICENSE.txt. * * GPL Classpath Exception: * Oracle designates this particular file as subject to the "Classpath" * exception as provided by Oracle in the GPL Version 2 section of the License * file that accompanied this code. * * Modifications: * If applicable, add the following below the License Header, with the fields * enclosed by brackets [] replaced by your own identifying information: * "Portions Copyright [year] [name of copyright owner]" * * Contributor(s): * If you wish your version of this file to be governed by only the CDDL or * only the GPL Version 2, indicate your decision by adding "[Contributor] * elects to include this software in this distribution under the [CDDL or GPL * Version 2] license." If you don't indicate a single choice of license, a * recipient has the option to distribute your version of this file under * either the CDDL, the GPL Version 2 or to extend the choice of license to * its licensees as provided above. However, if you add GPL Version 2 code * and therefore, elected the GPL Version 2 license, then the option applies * only if the new code is made subject to such option by the copyright * holder. */ package javax.ws.rs.client; import java.lang.annotation.Annotation; import java.lang.reflect.GenericArrayType; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.util.Locale; import javax.ws.rs.core.Form; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.MultivaluedMap; import javax.ws.rs.core.Variant; /** * Encapsulates message entity including the associated variant information. * * @param entity type. * @author Marek Potociar */ public final class Entity { /** * Create an entity using a supplied content media type. * * @param entity Java type. * @param entity entity data. * @param mediaType entity content type. * @return entity instance. */ public static Entity entity(final T entity, final MediaType mediaType) { return new Entity().entity(entity).mediaType(mediaType); } /** * Create an entity using a supplied content media type. * * @param entity Java type. * @param entity entity data. * @param mediaType entity content type. * @return entity instance. * @throws IllegalArgumentException if the supplied string cannot be parsed * or is {@code null}. */ public static Entity entity(final T entity, final String mediaType) throws IllegalArgumentException { return new Entity().entity(entity).mediaType(MediaType.valueOf(mediaType)); } /** * Create an entity using a supplied content media type. * * @param entity Java type. * @param entity entity data. * @param variant entity {@link Variant variant} information. * @return entity instance. */ public static Entity entity(final T entity, final Variant variant) { return new Entity().entity(entity).variant(variant); } /** * Create a {@value javax.ws.rs.core.MediaType#TEXT_PLAIN} entity. * * @param entity Java type. * @param entity entity data. * @return {@value javax.ws.rs.core.MediaType#TEXT_PLAIN} entity instance. */ public static Entity text(final T entity) { return new Entity().entity(entity).mediaType(MediaType.TEXT_PLAIN_TYPE); } /** * Create an {@value javax.ws.rs.core.MediaType#APPLICATION_XML} entity. * * @param entity Java type. * @param entity entity data. * @return {@value javax.ws.rs.core.MediaType#APPLICATION_XML} entity instance. */ public static Entity xml(final T entity) { return new Entity().entity(entity).mediaType(MediaType.APPLICATION_XML_TYPE); } /** * Create an {@value javax.ws.rs.core.MediaType#APPLICATION_JSON} entity. * * @param entity Java type. * @param entity entity data. * @return {@value javax.ws.rs.core.MediaType#APPLICATION_JSON} entity instance. */ public static Entity json(final T entity) { return new Entity().entity(entity).mediaType(MediaType.APPLICATION_JSON_TYPE); } /** * Create a {@value javax.ws.rs.core.MediaType#TEXT_HTML} entity. * * @param entity Java type. * @param entity entity data. * @return {@value javax.ws.rs.core.MediaType#TEXT_HTML} entity instance. */ public static Entity html(final T entity) { return new Entity().entity(entity).mediaType(MediaType.TEXT_HTML_TYPE); } /** * Create an {@value javax.ws.rs.core.MediaType#APPLICATION_XHTML_XML} entity. * * @param entity Java type. * @param entity entity data. * @return {@value javax.ws.rs.core.MediaType#APPLICATION_XHTML_XML} entity * instance. */ public static Entity xhtml(final T entity) { return new Entity().entity(entity).mediaType(MediaType.APPLICATION_XHTML_XML_TYPE); } /** * Create an {@value javax.ws.rs.core.MediaType#APPLICATION_FORM_URLENCODED} * form entity. * * @param form form data. * @return {@value javax.ws.rs.core.MediaType#APPLICATION_FORM_URLENCODED} * form entity instance. */ public static Entity
form(final Form form) { return new Entity().entity(form).mediaType(MediaType.APPLICATION_FORM_URLENCODED_TYPE); } /** * Create an {@value javax.ws.rs.core.MediaType#APPLICATION_FORM_URLENCODED} * form entity. * * @param formData multivalued map representing the form data. * @return {@value javax.ws.rs.core.MediaType#APPLICATION_FORM_URLENCODED} * form entity instance. */ public static Entity form(final MultivaluedMap formData) { return new Entity().entity(new Form(formData)).mediaType(MediaType.APPLICATION_FORM_URLENCODED_TYPE); } private Class rawType; private Type type; private T entity; private Annotation[] annotations; private Locale language; private MediaType mediaType; private String encoding; /** * Constructs a new generic entity. Derives represented class from type * parameter. Note that this constructor is protected, users should create * a (usually anonymous) subclass as shown above. * * @param entity the entity instance, must not be null * @throws IllegalArgumentException if entity is null */ protected Entity(final T entity, MediaType mediaType) throws IllegalArgumentException { if (entity == null) { throw new IllegalArgumentException("The entity must not be null"); } this.entity = entity; this.type = getSuperclassTypeParameter(getClass()); this.rawType = entity.getClass(); mediaType(mediaType); } private Entity() { } protected Entity(final T entity, Variant variant, Annotation[] annotations) throws IllegalArgumentException { this(entity, null); variant(variant); annotations(annotations); } /** * Create a new instance of Entity, supplying the generic type information. * The entity must be assignable to a variable of the * supplied generic type, e.g. if {@code entity} is an instance of * {@code ArrayList} then {@code genericType} could * be the same or a superclass of {@code ArrayList} with the same generic * type like {@code List}. * * @param entity the entity instance, must not be null * @param genericType the generic type, must not be null * @throws IllegalArgumentException if the entity is not assignable to * a variable of the supplied generic type or if entity or genericType * is null. */ public Entity(final T entity, final Type genericType, Variant variant, Annotation[] annotations) throws IllegalArgumentException { if (entity == null || genericType == null) { throw new IllegalArgumentException("Arguments must not be null"); } this.entity = entity; this.rawType = entity.getClass(); checkTypeCompatibility(this.rawType, genericType); this.type = genericType; variant(variant); annotations(annotations); } private void checkTypeCompatibility(final Class c, final Type t) { if (t instanceof Class) { Class ct = (Class) t; if (ct.isAssignableFrom(c)) { return; } } else if (t instanceof ParameterizedType) { ParameterizedType pt = (ParameterizedType) t; Type rt = pt.getRawType(); checkTypeCompatibility(c, rt); return; } else if (c.isArray() && (t instanceof GenericArrayType)) { GenericArrayType at = (GenericArrayType) t; Type rt = at.getGenericComponentType(); checkTypeCompatibility(c.getComponentType(), rt); return; } throw new IllegalArgumentException("The type is incompatible with the class of the entity"); } /** * Returns the type from super class's type parameter. * * @param subclass class to return the super class's type for. * @return super class's type. */ private static Type getSuperclassTypeParameter(final Class subclass) { Type superclass = subclass.getGenericSuperclass(); if (!(superclass instanceof ParameterizedType)) { throw new RuntimeException("Missing type parameter."); } ParameterizedType parameterized = (ParameterizedType) superclass; return parameterized.getActualTypeArguments()[0]; } /** * Gets the raw type of the enclosed entity. Note that this is the raw type of * the instance, not the raw type of the type parameter. I.e. in the example * in the introduction, the raw type is {@code ArrayList} not {@code List}. * * @return the raw type. */ public final Class getRawType() { return rawType; } /** * Gets underlying {@code Type} instance. Note that this is derived from the * type parameter, not the enclosed instance. I.e. in the example * in the introduction, the type is {@code List} not * {@code ArrayList}. * * @return the type */ public final Type getType() { return type; } /** * Get the enclosed entity. * * @return the enclosed entity. */ public final T getEntity() { return entity; } public final Annotation[] getAnnotations() { return annotations; } public final Variant getVariant() { return new Variant(mediaType, language, encoding); } private Entity language(Locale language) { this.language = language; return this; } private Entity mediaType(MediaType mediaType) { this.mediaType = mediaType; return this; } private Entity entity(T entity) { this.entity = entity; return this; } private Entity annotations(Annotation[] annotations) { this.annotations = annotations; return this; } private Entity variant(Variant variant) { this.mediaType = variant.getMediaType(); this.encoding = variant.getEncoding(); this.language = variant.getLanguage(); return this; } }