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

org.eclipse.persistence.jaxb.javamodel.AnnotationProxy Maven / Gradle / Ivy

There is a newer version: 5.0.0-B03
Show newest version
/*
 * Copyright (c) 1998, 2024 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,
 * or the Eclipse Distribution License v. 1.0 which is available at
 * http://www.eclipse.org/org/documents/edl-v10.php.
 *
 * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
 */

// Contributors:
// dmccann - December 10/2009 - 2.0.1 - Initial implementation
package org.eclipse.persistence.jaxb.javamodel;

import java.lang.annotation.Annotation;
import java.lang.reflect.Array;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.HashMap;
import java.util.Map;

import org.eclipse.persistence.internal.helper.ConversionManager;

/**
 * 

* Purpose:The purpose of this class is to act as a dynamic proxy that * allows JDK Annotation method calls to be made on a non Annotation object. * *

* Responsibilities: *

    *
  • Create and return a dynamic proxy instance based on an Annotation class * and a Map of components (method name to value pairs)
  • *
  • Allow JDK Annotation method calls to be invoked on the proxy object
  • *
*

* This class provides a means to invoke JDK Annotation method calls on a non * Annotation instance. * * @see java.lang.reflect.Proxy */ public class AnnotationProxy implements InvocationHandler { private Map components; private ConversionManager conversionMgr; private static final String ANNOTATION_TYPE_METHOD_NAME = "annotationType"; /** * This constructor sets the Map of components (method name to * value pairs)and the ConversionManager to be used when converting values * in the Map based on the return type of the associated * Method Note that the preferred method of obtaining an * instance of this proxy class is via * {@code getProxy(Map, Class, ClassLoader, ConversionManager)} * * @param components * Map of method name to value pairs * @param conversionMgr * ConversionManager instance for converting to the * correct return type in the invoke method */ private AnnotationProxy(Map components, ConversionManager conversionMgr) { this.components = components; this.conversionMgr = conversionMgr; } /** * This is the preferred way to obtain an instance of a dynamic proxy. * * The method takes a ClassLoader (which is used to load the * target Annotation), a Class (which indicates * the target Annotation, i.e. * jakarta.xml.bind.annotation.XmlElement.class), and a * Map of method name to value pairs, which represent the * method names on the Annotation and the values that are to be * returned from each method call. For example, if this proxy is to be used * for an @XmlElement, the Map should contain the * following keys: * *

* * Following are example key/value pairs : * *
    *
  • "defaultValue", "##default"
  • "name", "employee"
  • * "namespace", "www.example.org"
  • "nillable", false
  • * "required", false
  • "type", * jakarta.xml.bind.annotation.XmlElement.DEFAULT.class
  • *
* * @param components * Map of method name/value pairs for this proxy * instance * @param annoClass * The interface for the proxy class to implement * @param cl * The ClassLoader to define the proxy class * @param conversionMgr * ConversionManager instance for converting to the * correct return type in the invoke method * @return A dynamic proxy instance based on a Java model JavaAnnotation */ public static
A getProxy(Map components, Class annoClass, ClassLoader cl, ConversionManager conversionMgr) { // add the 'annotationType' method name/value pair to the components map if (components == null) { components = new HashMap<>(); } components.put(ANNOTATION_TYPE_METHOD_NAME, annoClass.getName()); // Pass the classloader to the ConversionManager as well // conversionMgr.setLoader(cl); return (A) Proxy.newProxyInstance(cl, new Class[] { annoClass }, new AnnotationProxy(components, conversionMgr)); } /** * Return the Map of method name/value pairs for this proxy * instance. * * @return Map of method name/value pairs for this proxy * instance */ public Map getComponents() { return this.components; } /** * Invoke a given Method on this proxy. The component * Map will be accessed using the given Method's * name, and if an entry exists, the associated value is returned. * * @param proxy * Satisfy the InvocationHandler interface - not * used * @param method * The Method instance corresponding to the * interface method invoked on the proxy instance * @param args * Satisfy the InvocationHandler interface - not * used * @return The value from the method invocation on the proxy instance */ @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { if (components == null) { return null; } Class returnType = method.getReturnType(); Object value = getComponents().get(method.getName()); if (value == null && returnType == boolean.class) { return false; } if (value == null && returnType == Boolean.class) { return Boolean.FALSE; } if (returnType.isArray()) { return handleArrayData(returnType, value); } // use the ConversionManager to ensure that the correct type is returned return conversionMgr.convertObject(value, returnType); } private Object handleArrayData(Class returnType, Object value) { if (value == null) { return null; } Object[] data = (Object[]) value; Class componentType = returnType.getComponentType(); Object[] convertedArray = (Object[]) Array.newInstance(componentType, data.length); for (int i = 0; i < data.length; i++) { convertedArray[i] = conversionMgr.convertObject(data[i], componentType); } return convertedArray; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy