proguard.classfile.editor.ElementValuesEditor Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of proguard-core Show documentation
Show all versions of proguard-core Show documentation
ProGuardCORE is a free library to read, analyze, modify, and write Java class files.
/*
* ProGuardCORE -- library to process Java bytecode.
*
* Copyright (c) 2002-2020 Guardsquare NV
*
* 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 proguard.classfile.editor;
import proguard.classfile.ProgramClass;
import proguard.classfile.attribute.annotation.*;
/**
* This class can add and delete element values to and from a given target
* annotation default attribute, annotation, or array element value. Element
* values to be added must be filled out beforehand, including their references
* to the constant pool.
*
* @author Eric Lafortune
*/
public class ElementValuesEditor
{
private final ProgramClass targetClass;
private final Annotation targetAnnotation;
private final ArrayElementValue targetArrayElementValue;
private final boolean replaceElementValues;
/**
* Creates a new ElementValuesEditor that will edit element values in the
* given target annotation.
*/
public ElementValuesEditor(ProgramClass targetClass,
Annotation targetAnnotation,
boolean replaceElementValues)
{
this.targetClass = targetClass;
this.targetAnnotation = targetAnnotation;
this.targetArrayElementValue = null;
this.replaceElementValues = replaceElementValues;
}
/**
* Creates a new ElementValuesEditor that will edit element values in the
* given target array element value.
*/
public ElementValuesEditor(ProgramClass targetClass,
ArrayElementValue targetArrayElementValue,
boolean replaceElementValues)
{
this.targetClass = targetClass;
this.targetAnnotation = null;
this.targetArrayElementValue = targetArrayElementValue;
this.replaceElementValues = replaceElementValues;
}
/**
* Adds the given elementValue to the target.
*/
public void addElementValue(ElementValue elementValue)
{
// What's the target?
if (targetAnnotation != null)
{
// Try to replace an existing element value.
if (!replaceElementValues ||
!replaceElementValue(targetAnnotation.u2elementValuesCount,
targetAnnotation.elementValues,
elementValue))
{
// Otherwise append the element value.
targetAnnotation.elementValues =
addElementValue(targetAnnotation.u2elementValuesCount,
targetAnnotation.elementValues,
elementValue);
targetAnnotation.u2elementValuesCount++;
}
}
else
{
// Try to replace an existing element value.
if (!replaceElementValues ||
!replaceElementValue(targetArrayElementValue.u2elementValuesCount,
targetArrayElementValue.elementValues,
elementValue))
{
// Otherwise append the element value.
targetArrayElementValue.elementValues =
addElementValue(targetArrayElementValue.u2elementValuesCount,
targetArrayElementValue.elementValues,
elementValue);
targetArrayElementValue.u2elementValuesCount++;
}
}
}
/**
* Deletes the given elementValue to the target.
*/
public void deleteElementValue(String elementValueMethodName)
{
// What's the target?
if (targetAnnotation != null)
{
// Delete the element value to the target annotation.
targetAnnotation.u2elementValuesCount =
deleteElementValue(targetAnnotation.u2elementValuesCount,
targetAnnotation.elementValues,
elementValueMethodName);
}
else
{
// Delete the element value to the target array element value.
targetArrayElementValue.u2elementValuesCount =
deleteElementValue(targetArrayElementValue.u2elementValuesCount,
targetArrayElementValue.elementValues,
elementValueMethodName);
}
}
// Small utility methods.
/**
* Tries put the given element value in place of an existing element value
* of the same name, returning whether it was present.
*/
private boolean replaceElementValue(int elementValuesCount,
ElementValue[] elementValues,
ElementValue elementValue)
{
// Find the element value with the same name.
int index = findElementValue(elementValuesCount,
elementValues,
elementValue.getMethodName(targetClass));
if (index < 0)
{
return false;
}
elementValues[index] = elementValue;
return true;
}
/**
* Appends the given element value to the given array of element values,
* creating a new array if necessary.
*/
private ElementValue[] addElementValue(int elementValuesCount,
ElementValue[] elementValues,
ElementValue elementValue)
{
// Is the array too small to contain the additional elementValue?
if (elementValues.length <= elementValuesCount)
{
// Create a new array and copy the elementValues into it.
ElementValue[] newElementValues = new ElementValue[elementValuesCount + 1];
System.arraycopy(elementValues, 0,
newElementValues, 0,
elementValuesCount);
elementValues = newElementValues;
}
// Append the elementValue.
elementValues[elementValuesCount] = elementValue;
return elementValues;
}
/**
* Deletes the element values with the given name from the given array of
* element values, returning the new number of element values.
*/
private int deleteElementValue(int elementValuesCount,
ElementValue[] elementValues,
String elementValueMethodName)
{
// Find the element value.
int index = findElementValue(elementValuesCount,
elementValues,
elementValueMethodName);
if (index < 0)
{
return elementValuesCount;
}
// Shift the other element values in the array.
System.arraycopy(elementValues, index + 1,
elementValues, index,
elementValuesCount - index - 1);
// Clear the last entry in the array.
elementValues[--elementValuesCount] = null;
return elementValuesCount;
}
/**
* Finds the index of the element value with the given name in the given
* array of element values.
*/
private int findElementValue(int elementValuesCount,
ElementValue[] elementValues,
String elementValueName)
{
for (int index = 0; index < elementValuesCount; index++)
{
if (elementValues[index].getMethodName(targetClass).equals(elementValueName))
{
return index;
}
}
return -1;
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy