/* * Copyright 2015 ArcBees Inc. * * Licensed 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 com.gwtplatform.dispatch.rest.processors.resolvers.parameters; import java.util.Collection; import java.util.Date; import java.util.List; import javax.lang.model.element.Name; import javax.lang.model.element.VariableElement; import javax.lang.model.type.DeclaredType; import javax.lang.model.type.PrimitiveType; import javax.lang.model.type.TypeMirror; import javax.lang.model.util.SimpleTypeVisitor6; import javax.ws.rs.CookieParam; import javax.ws.rs.core.Cookie; import com.google.auto.service.AutoService; import com.google.common.base.Optional; import com.gwtplatform.dispatch.rest.shared.HttpParameter.Type; import com.gwtplatform.processors.tools.exceptions.UnableToProcessException; import static com.google.auto.common.MoreTypes.asTypeElement; import static com.google.auto.common.MoreTypes.isType; import static com.gwtplatform.dispatch.rest.processors.NameUtils.parentName; @AutoService(HttpParamValueResolver.class) public class CookieParamValueResolver extends HttpParamValueResolver { private static final String COOKIE_BAD_RETURN_TYPE = "Method `%s` parameter's `%s` is annotated with @CookieParam " + "but has a bad return type. It may only be a primitive, `Cookie` or a `Collection<Cookie>`."; private static final SimpleTypeVisitor6<Boolean, CookieParamValueResolver> VALID_COOKIE_TYPE_VISITOR = new SimpleTypeVisitor6<Boolean, CookieParamValueResolver>(false) { @Override public Boolean visitPrimitive(PrimitiveType type, CookieParamValueResolver resolver) { return true; } @Override public Boolean visitDeclared(DeclaredType type, CookieParamValueResolver resolver) { return resolver.isValidCookieType(type); } }; @Override public Class<CookieParam> getAssociatedClass() { return CookieParam.class; } @Override public Type getAssociatedType() { return Type.COOKIE; } @Override public String resolve(VariableElement element) { if (isPresent(element) && !element.asType().accept(VALID_COOKIE_TYPE_VISITOR, this)) { logger.error().context(element).log(COOKIE_BAD_RETURN_TYPE, parentName(element), element.getSimpleName()); throw new UnableToProcessException(); } return super.resolve(element); } private boolean isValidCookieType(DeclaredType type) { Name qualifiedName = asTypeElement(type).getQualifiedName(); return qualifiedName.contentEquals(Date.class.getCanonicalName()) || qualifiedName.contentEquals(String.class.getCanonicalName()) || qualifiedName.contentEquals(Cookie.class.getCanonicalName()) || isBoxed(type) || isCookieCollection(type); } private boolean isBoxed(DeclaredType type) { try { PrimitiveType primitiveType = utils.getTypes().unboxedType(type); return primitiveType != null; } catch (IllegalArgumentException e) { return false; } } private boolean isCookieCollection(DeclaredType type) { TypeMirror collectionType = utils.createWithWildcard(Collection.class); Optional<TypeMirror> typeArg = extractCollectionTypeArg(type); return utils.getTypes().isAssignable(type, collectionType) && typeArg.isPresent() && isType(typeArg.get()) && asTypeElement(typeArg.get()).getQualifiedName().contentEquals(Cookie.class.getCanonicalName()); } private Optional<TypeMirror> extractCollectionTypeArg(DeclaredType type) { List<? extends TypeMirror> typeArguments = type.getTypeArguments(); return Optional.fromNullable(typeArguments.size() == 1 ? typeArguments.get(0) : null); } }