/* * $Id$ * * Copyright (C) 2003-2015 JNode.org * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published * by the Free Software Foundation; either version 2.1 of the License, or * (at your option) any later version. * * This library 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 library; If not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ package org.jnode.vm.classmgr; import java.lang.annotation.Annotation; import java.lang.reflect.AnnotatedElement; import org.jnode.vm.objects.VmSystemObject; import org.jnode.annotation.PrivilegedActionPragma; /** * Base class for annoted elements. * * @author Ewout Prangsma (epr@users.sourceforge.net) */ abstract class VmAnnotatedElement extends VmSystemObject implements AnnotatedElement { /** * Runtime annotations */ private VmAnnotation[] runtimeAnnotations; /** * @param runtimeAnnotations The runtimeAnnotations to set. */ final void setRuntimeAnnotations(VmAnnotation[] runtimeAnnotations) { if (this.runtimeAnnotations == null) { if (runtimeAnnotations == null) { this.runtimeAnnotations = VmAnnotation.EMPTY_ARR; } else { this.runtimeAnnotations = runtimeAnnotations; } } else { throw new SecurityException("Cannot override runtime annotations"); } } /** * @see java.lang.reflect.AnnotatedElement#getAnnotation(java.lang.Class) */ @PrivilegedActionPragma public final <T extends Annotation> T getAnnotation(Class<T> annotationClass) { if (runtimeAnnotations.length > 0) { final VmClassLoader loader = getLoader(); final VmType<T> reqType = VmType.fromClass(annotationClass); for (VmAnnotation ann : runtimeAnnotations) { if (ann.annotationType(loader) == reqType) { try { return annotationClass.cast(ann.getValue(loader)); } catch (ClassNotFoundException ex) { throw new NoClassDefFoundError(ex.getMessage()); } } } } return null; } /** * @see java.lang.reflect.AnnotatedElement#getAnnotations() */ public final Annotation[] getAnnotations() { final Annotation[] ann = getDeclaredAnnotations(); final VmAnnotatedElement parent = getSuperElement(); if (parent != null) { final Annotation[] parentAnn = parent.getAnnotations(); int cnt = 0; for (Annotation a : parentAnn) { if (((VmAnnotation.ImplBase) a).isInheritable()) { cnt++; } } if (cnt > 0) { int j = ann.length; final Annotation[] result = new Annotation[j + cnt]; System.arraycopy(ann, 0, result, 0, j); for (Annotation a : parentAnn) { if (((VmAnnotation.ImplBase) a).isInheritable()) { result[j++] = a; } } return result; } } return ann; } /** * @see java.lang.reflect.AnnotatedElement#getDeclaredAnnotations() */ public final Annotation[] getDeclaredAnnotations() { final int max = runtimeAnnotations.length; final Annotation[] arr = new Annotation[max]; if (max > 0) { final VmClassLoader loader = getLoader(); for (int i = 0; i < max; i++) { try { arr[i] = runtimeAnnotations[i].getValue(loader); } catch (ClassNotFoundException e) { throw new NoClassDefFoundError(e.getMessage()); } } } return arr; } /** * @see java.lang.reflect.AnnotatedElement#isAnnotationPresent(java.lang.Class) */ @PrivilegedActionPragma public final boolean isAnnotationPresent( Class<? extends Annotation> annotationClass) { if (runtimeAnnotations.length > 0) { final VmClassLoader loader = getLoader(); final VmType<?> reqType = VmType.fromClass((Class<? extends Annotation>) annotationClass); for (VmAnnotation ann : runtimeAnnotations) { if (ann.annotationType(loader) == reqType) { return true; } } } return false; } /** * Return the loader of this class * * @return The loader */ protected abstract VmClassLoader getLoader(); /** * Gets the parent of this element. * * @return the parent element */ protected abstract VmAnnotatedElement getSuperElement(); /** * Raw runtime annotations to be parsed by java.lang.Class of OpenJDK. */ private byte[] rawAnnotations; /** * Returns the raw runtime annotations. * @return the raw annotation data as a byte[] */ public byte[] getRawAnnotations() { return rawAnnotations; } /** * Sets the raw runtime annotations. * @param rawAnnotations the raw annotation data as a byte[] */ public void setRawAnnotations(byte[] rawAnnotations) { this.rawAnnotations = rawAnnotations; } }