Permalink
Browse files

HHH-8107 - JandexHelper.getValue() returns Boolean instead of boolean…

…, causing ClassCastException
  • Loading branch information...
1 parent d184cb3 commit 31219e25d7b4b232705de5af92a6043e2277a793 @sebersole sebersole committed Mar 25, 2013
@@ -0,0 +1,269 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2013, Red Hat Inc. or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors. All third-party contributions are
+ * distributed under license by Red Hat Inc.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02110-1301 USA
+ */
+package org.hibernate.internal.util.type;
+
+/**
+ * Helper for primitive/wrapper utilities.
+ *
+ * @author Steve Ebersole
+ */
+public class PrimitiveWrapperHelper {
+ /**
+ * Describes a particular primitive/wrapper combo
+ */
+ public static interface PrimitiveWrapperDescriptor<T> {
+ public Class<T> getPrimitiveClass();
+ public Class<T> getWrapperClass();
+ }
+
+ public static class BooleanDescriptor implements PrimitiveWrapperDescriptor<Boolean> {
+ public static final BooleanDescriptor INSTANCE = new BooleanDescriptor();
+
+ private BooleanDescriptor() {
+ }
+
+ @Override
+ public Class<Boolean> getPrimitiveClass() {
+ return boolean.class;
+ }
+
+ @Override
+ public Class<Boolean> getWrapperClass() {
+ return Boolean.class;
+ }
+ }
+
+ public static class CharacterDescriptor implements PrimitiveWrapperDescriptor<Character> {
+ public static final CharacterDescriptor INSTANCE = new CharacterDescriptor();
+
+ private CharacterDescriptor() {
+ }
+
+ @Override
+ public Class<Character> getPrimitiveClass() {
+ return char.class;
+ }
+
+ @Override
+ public Class<Character> getWrapperClass() {
+ return Character.class;
+ }
+ }
+
+ public static class ByteDescriptor implements PrimitiveWrapperDescriptor<Byte> {
+ public static final ByteDescriptor INSTANCE = new ByteDescriptor();
+
+ private ByteDescriptor() {
+ }
+
+ @Override
+ public Class<Byte> getPrimitiveClass() {
+ return byte.class;
+ }
+
+ @Override
+ public Class<Byte> getWrapperClass() {
+ return Byte.class;
+ }
+ }
+
+ public static class ShortDescriptor implements PrimitiveWrapperDescriptor<Short> {
+ public static final ShortDescriptor INSTANCE = new ShortDescriptor();
+
+ private ShortDescriptor() {
+ }
+
+ @Override
+ public Class<Short> getPrimitiveClass() {
+ return short.class;
+ }
+
+ @Override
+ public Class<Short> getWrapperClass() {
+ return Short.class;
+ }
+ }
+
+ public static class IntegerDescriptor implements PrimitiveWrapperDescriptor<Integer> {
+ public static final IntegerDescriptor INSTANCE = new IntegerDescriptor();
+
+ private IntegerDescriptor() {
+ }
+
+ @Override
+ public Class<Integer> getPrimitiveClass() {
+ return int.class;
+ }
+
+ @Override
+ public Class<Integer> getWrapperClass() {
+ return Integer.class;
+ }
+ }
+
+ public static class LongDescriptor implements PrimitiveWrapperDescriptor<Long> {
+ public static final LongDescriptor INSTANCE = new LongDescriptor();
+
+ private LongDescriptor() {
+ }
+
+ @Override
+ public Class<Long> getPrimitiveClass() {
+ return long.class;
+ }
+
+ @Override
+ public Class<Long> getWrapperClass() {
+ return Long.class;
+ }
+ }
+
+ public static class FloatDescriptor implements PrimitiveWrapperDescriptor<Float> {
+ public static final FloatDescriptor INSTANCE = new FloatDescriptor();
+
+ private FloatDescriptor() {
+ }
+
+ @Override
+ public Class<Float> getPrimitiveClass() {
+ return float.class;
+ }
+
+ @Override
+ public Class<Float> getWrapperClass() {
+ return Float.class;
+ }
+ }
+
+ public static class DoubleDescriptor implements PrimitiveWrapperDescriptor<Double> {
+ public static final DoubleDescriptor INSTANCE = new DoubleDescriptor();
+
+ private DoubleDescriptor() {
+ }
+
+ @Override
+ public Class<Double> getPrimitiveClass() {
+ return double.class;
+ }
+
+ @Override
+ public Class<Double> getWrapperClass() {
+ return Double.class;
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ public static <X> PrimitiveWrapperDescriptor<X> getDescriptorByPrimitiveType(Class<X> primitiveClazz) {
+ if ( ! primitiveClazz.isPrimitive() ) {
+ throw new IllegalArgumentException( "Given class is not a primitive type : " + primitiveClazz.getName() );
+ }
+
+ if ( boolean.class == primitiveClazz ) {
+ return (PrimitiveWrapperDescriptor<X>) BooleanDescriptor.INSTANCE;
+ }
+
+ if ( char.class == primitiveClazz ) {
+ return (PrimitiveWrapperDescriptor<X>) CharacterDescriptor.INSTANCE;
+ }
+
+ if ( byte.class == primitiveClazz ) {
+ return (PrimitiveWrapperDescriptor<X>) ByteDescriptor.INSTANCE;
+ }
+
+ if ( short.class == primitiveClazz ) {
+ return (PrimitiveWrapperDescriptor<X>) ShortDescriptor.INSTANCE;
+ }
+
+ if ( int.class == primitiveClazz ) {
+ return (PrimitiveWrapperDescriptor<X>) IntegerDescriptor.INSTANCE;
+ }
+
+ if ( long.class == primitiveClazz ) {
+ return (PrimitiveWrapperDescriptor<X>) LongDescriptor.INSTANCE;
+ }
+
+ if ( float.class == primitiveClazz ) {
+ return (PrimitiveWrapperDescriptor<X>) FloatDescriptor.INSTANCE;
+ }
+
+ if ( double.class == primitiveClazz ) {
+ return (PrimitiveWrapperDescriptor<X>) DoubleDescriptor.INSTANCE;
+ }
+
+ // most likely void.class, which we can't really handle here
+ throw new IllegalArgumentException( "Unrecognized primitive type class : " + primitiveClazz.getName() );
+ }
+
+ @SuppressWarnings("unchecked")
+ public static <X> PrimitiveWrapperDescriptor<X> getDescriptorByWrapperType(Class<X> wrapperClass) {
+ if ( wrapperClass.isPrimitive() ) {
+ throw new IllegalArgumentException( "Given class is a primitive type : " + wrapperClass.getName() );
+ }
+
+ if ( Boolean.class.equals( wrapperClass ) ) {
+ return (PrimitiveWrapperDescriptor<X>) BooleanDescriptor.INSTANCE;
+ }
+
+ if ( Character.class == wrapperClass ) {
+ return (PrimitiveWrapperDescriptor<X>) CharacterDescriptor.INSTANCE;
+ }
+
+ if ( Byte.class == wrapperClass ) {
+ return (PrimitiveWrapperDescriptor<X>) ByteDescriptor.INSTANCE;
+ }
+
+ if ( Short.class == wrapperClass ) {
+ return (PrimitiveWrapperDescriptor<X>) ShortDescriptor.INSTANCE;
+ }
+
+ if ( Integer.class == wrapperClass ) {
+ return (PrimitiveWrapperDescriptor<X>) IntegerDescriptor.INSTANCE;
+ }
+
+ if ( Long.class == wrapperClass ) {
+ return (PrimitiveWrapperDescriptor<X>) LongDescriptor.INSTANCE;
+ }
+
+ if ( Float.class == wrapperClass ) {
+ return (PrimitiveWrapperDescriptor<X>) FloatDescriptor.INSTANCE;
+ }
+
+ if ( Double.class == wrapperClass ) {
+ return (PrimitiveWrapperDescriptor<X>) DoubleDescriptor.INSTANCE;
+ }
+
+ // most likely void.class, which we can't really handle here
+ throw new IllegalArgumentException( "Unrecognized wrapper type class : " + wrapperClass.getName() );
+ }
+
+ public static boolean isWrapper(Class<?> clazz) {
+ try {
+ getDescriptorByWrapperType( clazz );
+ return true;
+ }
+ catch (Exception e) {
+ return false;
+ }
+ }
+}
@@ -46,6 +46,7 @@
import org.hibernate.AssertionFailure;
import org.hibernate.HibernateException;
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
+import org.hibernate.internal.util.type.PrimitiveWrapperHelper;
/**
* Utility methods for working with the jandex annotation index.
@@ -95,6 +96,10 @@ private JandexHelper() {
);
}
+ if ( type.isPrimitive() ) {
+ type = PrimitiveWrapperHelper.getDescriptorByPrimitiveType( type ).getWrapperClass();
+ }
+
// try getting the untyped value from Jandex
AnnotationValue annotationValue = annotation.value( element );
@@ -113,7 +118,8 @@ private JandexHelper() {
element,
annotation.name(),
type.getName()
- )
+ ),
+ e
);
}
}
@@ -23,11 +23,15 @@
*/
package org.hibernate.metamodel.source.annotations.util;
+import java.net.MalformedURLException;
+import java.net.URL;
import java.util.List;
import java.util.Map;
+import javax.persistence.AttributeConverter;
import javax.persistence.AttributeOverride;
import javax.persistence.Basic;
import javax.persistence.Column;
+import javax.persistence.Converter;
import javax.persistence.Entity;
import javax.persistence.LockModeType;
import javax.persistence.NamedQuery;
@@ -42,6 +46,7 @@
import org.junit.Test;
import org.hibernate.AssertionFailure;
+import org.hibernate.HibernateException;
import org.hibernate.annotations.NamedNativeQuery;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.metamodel.source.annotations.HibernateDotNames;
@@ -244,6 +249,36 @@ public void testRetrieveUnknownParameter() {
}
}
+
+ @Test
+ public void testPrimitiveAnnotationAttributeTypes() {
+ @Converter( autoApply = true )
+ class MyConverter implements AttributeConverter<URL,String> {
+
+ @Override
+ public String convertToDatabaseColumn(URL attribute) {
+ return attribute.toExternalForm();
+ }
+
+ @Override
+ public URL convertToEntityAttribute(String dbData) {
+ try {
+ return new URL( dbData );
+ }
+ catch (MalformedURLException e) {
+ throw new HibernateException( "Could not convert string [" + dbData + "] to url", e );
+ }
+ }
+ }
+
+ Index index = JandexHelper.indexForClass( classLoaderService, MyConverter.class );
+ List<AnnotationInstance> annotationInstances = index.getAnnotations( JPADotNames.CONVERTER );
+ assertTrue( annotationInstances.size() == 1 );
+ AnnotationInstance annotationInstance = annotationInstances.get( 0 );
+
+ boolean value = JandexHelper.getValue( annotationInstance, "autoApply", boolean.class );
+ Assert.assertTrue( value );
+ }
}

0 comments on commit 31219e2

Please sign in to comment.