blob: b6e6ce2bf60d8ca9f6fcd88de10c2fe9a9cba983 [file] [log] [blame]
/**********************************************************************
* This file is part of the "Object Teams Runtime Environment"
*
* Copyright 2009 Stephan Herrmann
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
* $Id$
*
* Please visit http://www.objectteams.org for updates and contact.
*
* Contributors:
* Stephan Herrmann - Initial API and implementation
**********************************************************************/
package org.eclipse.objectteams.otre.util;
import org.eclipse.objectteams.otre.ObjectTeamsTransformation;
import org.objectteams.ImplicitTeamActivation;
import org.apache.bcel.classfile.Attribute;
import org.apache.bcel.classfile.Unknown;
import org.apache.bcel.generic.ConstantPoolGen;
/**
* Helper class for parsing / skipping runtime visible annotations.
*
* @author stephan
* @since 1.4.0
*/
public class AnnotationHelper {
/**
* Does any of the given attributes contain an {@link ImplicitTeamActivation} annotation?
* @param attrs attributes to inspect
* @param cpg constant pool for string lookup
* @return true if an {@link ImplicitTeamActivation} annotation was found.
*/
public static boolean containsImplicitActivationAttribute(Attribute[] attrs, ConstantPoolGen cpg) {
if (attrs != null) {
for (Attribute attr : attrs) {
if (attr instanceof Unknown && ((Unknown)attr).getName().equals("RuntimeVisibleAnnotations")) {
Unknown unknown = (Unknown) attr;
byte[] bytes = unknown.getBytes();
int len = ObjectTeamsTransformation.combineTwoBytes(bytes, 0);
int i = 2;
String[] names = new String[1];
for (int n=0; n<len; n++) {
i = ObjectTeamsTransformation.scanStrings(names, bytes, i, cpg);
if ("Lorg/objectteams/ImplicitTeamActivation;".equals(names[0]))
return true;
i = skipNameValuePairs(bytes, i, names[0], cpg);
}
}
}
}
return false;
}
private static int skipNameValuePairs(byte[] bytes, int i, String typeName, ConstantPoolGen cpg) {
int numPairs = ObjectTeamsTransformation.combineTwoBytes(bytes, i);
i+=2;
for (int p=0; p<numPairs; p++)
i = skipElementValue(bytes, i+2 /*skip name*/, typeName, cpg);
return i;
}
private static int skipElementValue(byte[] bytes, int i, String typeName, ConstantPoolGen cpg) {
short tag = bytes[i++];
switch (tag) {
case 'B': // byte
case 'C': // char
case 'D': // double
case 'F': // float
case 'I': // int
case 'J': // long
case 'S': // short
case 'Z': // boolean
case 's': // String
case 'c': // Class
i+=2; break;
case 'e': // Enum constant
i+=4; break;
case '@': // Annotation
String[] typeName2 = new String[1];
i = ObjectTeamsTransformation.scanStrings(typeName2, bytes, i, cpg); // nested annotation type
i = skipNameValuePairs(bytes, i, typeName2[0], cpg);
break;
case '[': // Array
int numArrayVals = ObjectTeamsTransformation.combineTwoBytes(bytes, i);
i+=2;
for (int j = 0; j < numArrayVals; j++)
i = skipElementValue(bytes, i, typeName, cpg);
break;
default:
throw new RuntimeException("Unexpected element value kind in annotation: " + typeName);
}
return i;
}
}