forked from fanruan/easyexcel
Jiaju Zhuang
4 years ago
committed by
GitHub
193 changed files with 4903 additions and 1592 deletions
@ -0,0 +1,8 @@
|
||||
## 前言 |
||||
非常感谢您愿意协助EasyExcel的开发,EasyExcel成长离不开大家的贡献。但是为了合作的更有效率,希望我们在贡献代码的时候能按照如下约定。 |
||||
## 提前沟通 |
||||
尽量把自己的想法和实现思路提前沟通,可以通过issue,钉钉,QQ都可以,可能很多问题我们内部已经讨论过,由于各种原因后续不会支持,但是您这边又开发好了,这样容易浪费您的时间。 |
||||
## 代码规范 |
||||
目前代码规范已经集成了自动校验,然后源代码尽量不要有中文注释。在新增功能的时候,尽量注意补充junit。core代表每次travis-ci都会跑的测试案例,然后demo用于对外看到,temp里面随便写。 |
||||
## 提交分支 |
||||
建议提交到最新的版本号.x上面,比如 3.x之类的版本,为了方便其他同学阅读源代码,所以目前的思路是master和maven center的最新版本代码保持一致,然后您提交过来的代码我们可能会稍微做一些修改。所以提交到开发分支会比较好。fork也可以直接fork该分支。 |
@ -0,0 +1,13 @@
|
||||
package com.alibaba.excel.constant; |
||||
|
||||
/** |
||||
* Order constant. |
||||
* |
||||
* @author Jiaju Zhuang |
||||
*/ |
||||
public class OrderConstant { |
||||
/** |
||||
* Sorting of styles written to cells. |
||||
*/ |
||||
public static final int FILL_DATA_FORMAT = 10000; |
||||
} |
@ -0,0 +1,47 @@
|
||||
package com.alibaba.excel.converters.date; |
||||
|
||||
import java.util.Date; |
||||
|
||||
import com.alibaba.excel.converters.Converter; |
||||
import com.alibaba.excel.enums.CellDataTypeEnum; |
||||
import com.alibaba.excel.metadata.CellData; |
||||
import com.alibaba.excel.metadata.GlobalConfiguration; |
||||
import com.alibaba.excel.metadata.property.ExcelContentProperty; |
||||
import com.alibaba.excel.util.WorkBookUtil; |
||||
import com.alibaba.excel.write.metadata.holder.WriteHolder; |
||||
|
||||
/** |
||||
* Date and date converter |
||||
* |
||||
* @author Jiaju Zhuang |
||||
*/ |
||||
public class DateDateConverter implements Converter<Date> { |
||||
@Override |
||||
public Class<Date> supportJavaTypeKey() { |
||||
return Date.class; |
||||
} |
||||
|
||||
@Override |
||||
public CellDataTypeEnum supportExcelTypeKey() { |
||||
return CellDataTypeEnum.DATE; |
||||
} |
||||
|
||||
@Override |
||||
public Date convertToJavaData(CellData<?> cellData, ExcelContentProperty contentProperty, |
||||
GlobalConfiguration globalConfiguration) { |
||||
return cellData.getDateValue(); |
||||
} |
||||
|
||||
@Override |
||||
public CellData<?> convertToExcelData(Date value, ExcelContentProperty contentProperty, |
||||
WriteHolder currentWriteHolder) throws Exception { |
||||
CellData<?> cellData = new CellData<>(value); |
||||
if (contentProperty == null || contentProperty.getDateTimeFormatProperty() == null |
||||
|| contentProperty.getDateTimeFormatProperty().getFormat() == null) { |
||||
return cellData; |
||||
} |
||||
WorkBookUtil.fillDataFormat(cellData, currentWriteHolder, |
||||
contentProperty.getDateTimeFormatProperty().getFormat()); |
||||
return cellData; |
||||
} |
||||
} |
@ -0,0 +1,81 @@
|
||||
package com.alibaba.excel.metadata.format; |
||||
|
||||
import java.math.BigDecimal; |
||||
import java.math.MathContext; |
||||
import java.math.RoundingMode; |
||||
import java.text.DecimalFormat; |
||||
import java.text.DecimalFormatSymbols; |
||||
import java.text.FieldPosition; |
||||
import java.text.Format; |
||||
import java.text.ParsePosition; |
||||
import java.util.Locale; |
||||
|
||||
import org.apache.poi.ss.usermodel.DataFormatter; |
||||
|
||||
/** |
||||
* Written with reference to {@link org.apache.poi.ss.usermodel.ExcelGeneralNumberFormat }. |
||||
* <p> |
||||
* Supported Do not use scientific notation. |
||||
* |
||||
* @author JiaJu Zhuang |
||||
**/ |
||||
public class ExcelGeneralNumberFormat extends Format { |
||||
|
||||
private static final long serialVersionUID = 1L; |
||||
|
||||
private static final MathContext TO_10_SF = new MathContext(10, RoundingMode.HALF_UP); |
||||
|
||||
private final DecimalFormatSymbols decimalSymbols; |
||||
private final DecimalFormat integerFormat; |
||||
private final DecimalFormat decimalFormat; |
||||
private final DecimalFormat scientificFormat; |
||||
|
||||
public ExcelGeneralNumberFormat(final Locale locale, final boolean useScientificFormat) { |
||||
decimalSymbols = DecimalFormatSymbols.getInstance(locale); |
||||
// Supported Do not use scientific notation.
|
||||
if (useScientificFormat) { |
||||
scientificFormat = new DecimalFormat("0.#####E0", decimalSymbols); |
||||
} else { |
||||
scientificFormat = new DecimalFormat("#", decimalSymbols); |
||||
} |
||||
org.apache.poi.ss.usermodel.DataFormatter.setExcelStyleRoundingMode(scientificFormat); |
||||
integerFormat = new DecimalFormat("#", decimalSymbols); |
||||
org.apache.poi.ss.usermodel.DataFormatter.setExcelStyleRoundingMode(integerFormat); |
||||
decimalFormat = new DecimalFormat("#.##########", decimalSymbols); |
||||
DataFormatter.setExcelStyleRoundingMode(decimalFormat); |
||||
} |
||||
|
||||
@Override |
||||
public StringBuffer format(Object number, StringBuffer toAppendTo, FieldPosition pos) { |
||||
final double value; |
||||
if (number instanceof Number) { |
||||
value = ((Number) number).doubleValue(); |
||||
if (Double.isInfinite(value) || Double.isNaN(value)) { |
||||
return integerFormat.format(number, toAppendTo, pos); |
||||
} |
||||
} else { |
||||
// testBug54786 gets here with a date, so retain previous behaviour
|
||||
return integerFormat.format(number, toAppendTo, pos); |
||||
} |
||||
|
||||
final double abs = Math.abs(value); |
||||
if (abs >= 1E11 || (abs <= 1E-10 && abs > 0)) { |
||||
return scientificFormat.format(number, toAppendTo, pos); |
||||
} else if (Math.floor(value) == value || abs >= 1E10) { |
||||
// integer, or integer portion uses all 11 allowed digits
|
||||
return integerFormat.format(number, toAppendTo, pos); |
||||
} |
||||
// Non-integers of non-scientific magnitude are formatted as "up to 11
|
||||
// numeric characters, with the decimal point counting as a numeric
|
||||
// character". We know there is a decimal point, so limit to 10 digits.
|
||||
// https://support.microsoft.com/en-us/kb/65903
|
||||
final double rounded = new BigDecimal(value).round(TO_10_SF).doubleValue(); |
||||
return decimalFormat.format(rounded, toAppendTo, pos); |
||||
} |
||||
|
||||
@Override |
||||
public Object parseObject(String source, ParsePosition pos) { |
||||
throw new UnsupportedOperationException(); |
||||
} |
||||
|
||||
} |
@ -1,22 +0,0 @@
|
||||
package com.alibaba.excel.util; |
||||
|
||||
import java.util.Collection; |
||||
import java.util.Map; |
||||
|
||||
/** |
||||
* Collection utils |
||||
* |
||||
* @author jipengfei |
||||
*/ |
||||
public class CollectionUtils { |
||||
|
||||
private CollectionUtils() {} |
||||
|
||||
public static boolean isEmpty(Collection<?> collection) { |
||||
return (collection == null || collection.isEmpty()); |
||||
} |
||||
|
||||
public static boolean isEmpty(Map<?, ?> map) { |
||||
return (map == null || map.isEmpty()); |
||||
} |
||||
} |
@ -0,0 +1,145 @@
|
||||
package com.alibaba.excel.util; |
||||
|
||||
import java.lang.reflect.Field; |
||||
import java.lang.reflect.Modifier; |
||||
|
||||
|
||||
/** |
||||
* Field utils |
||||
* |
||||
* @author Jiaju Zhuang |
||||
**/ |
||||
public class FieldUtils { |
||||
|
||||
private static final int START_RESOLVE_FIELD_LENGTH = 2; |
||||
|
||||
/** |
||||
* Parsing the name matching cglib。 |
||||
* <ul> |
||||
* <ul>null -> null</ul> |
||||
* <ul>string1 -> string1</ul> |
||||
* <ul>String2 -> string2</ul> |
||||
* <ul>sTring3 -> STring3</ul> |
||||
* <ul>STring4 -> STring4</ul> |
||||
* <ul>STRING5 -> STRING5</ul> |
||||
* <ul>STRing6 -> STRing6</ul> |
||||
* </ul> |
||||
* |
||||
* @param field field |
||||
* @return field name. |
||||
*/ |
||||
public static String resolveCglibFieldName(Field field) { |
||||
if (field == null) { |
||||
return null; |
||||
} |
||||
String fieldName = field.getName(); |
||||
if (StringUtils.isBlank(fieldName) || fieldName.length() < START_RESOLVE_FIELD_LENGTH) { |
||||
return fieldName; |
||||
} |
||||
char firstChar = fieldName.charAt(0); |
||||
char secondChar = fieldName.charAt(1); |
||||
if (Character.isUpperCase(firstChar) == Character.isUpperCase(secondChar)) { |
||||
return fieldName; |
||||
} |
||||
if (Character.isUpperCase(firstChar)) { |
||||
return buildFieldName(Character.toLowerCase(firstChar), fieldName); |
||||
} |
||||
return buildFieldName(Character.toUpperCase(firstChar), fieldName); |
||||
} |
||||
|
||||
private static String buildFieldName(char firstChar, String fieldName) { |
||||
return firstChar + fieldName.substring(1); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Gets an accessible {@link Field} by name respecting scope. Superclasses/interfaces will be considered. |
||||
* |
||||
* @param cls |
||||
* the {@link Class} to reflect, must not be {@code null} |
||||
* @param fieldName |
||||
* the field name to obtain |
||||
* @return the Field object |
||||
* @throws IllegalArgumentException |
||||
* if the class is {@code null}, or the field name is blank or empty |
||||
*/ |
||||
public static Field getField(final Class<?> cls, final String fieldName) { |
||||
final Field field = getField(cls, fieldName, false); |
||||
MemberUtils.setAccessibleWorkaround(field); |
||||
return field; |
||||
} |
||||
|
||||
|
||||
|
||||
/** |
||||
* Gets an accessible {@link Field} by name, breaking scope if requested. Superclasses/interfaces will be |
||||
* considered. |
||||
* |
||||
* @param cls |
||||
* the {@link Class} to reflect, must not be {@code null} |
||||
* @param fieldName |
||||
* the field name to obtain |
||||
* @param forceAccess |
||||
* whether to break scope restrictions using the |
||||
* {@link java.lang.reflect.AccessibleObject#setAccessible(boolean)} method. {@code false} will only |
||||
* match {@code public} fields. |
||||
* @return the Field object |
||||
* @throws NullPointerException if the class is {@code null} |
||||
* @throws IllegalArgumentException if the field name is blank or empty or is matched at multiple places |
||||
* in the inheritance hierarchy |
||||
*/ |
||||
public static Field getField(final Class<?> cls, final String fieldName, final boolean forceAccess) { |
||||
Validate.isTrue(cls != null, "The class must not be null"); |
||||
Validate.isTrue(StringUtils.isNotBlank(fieldName), "The field name must not be blank/empty"); |
||||
// FIXME is this workaround still needed? lang requires Java 6
|
||||
// Sun Java 1.3 has a bugged implementation of getField hence we write the
|
||||
// code ourselves
|
||||
|
||||
// getField() will return the Field object with the declaring class
|
||||
// set correctly to the class that declares the field. Thus requesting the
|
||||
// field on a subclass will return the field from the superclass.
|
||||
//
|
||||
// priority order for lookup:
|
||||
// searchclass private/protected/package/public
|
||||
// superclass protected/package/public
|
||||
// private/different package blocks access to further superclasses
|
||||
// implementedinterface public
|
||||
|
||||
// check up the superclass hierarchy
|
||||
for (Class<?> acls = cls; acls != null; acls = acls.getSuperclass()) { |
||||
try { |
||||
final Field field = acls.getDeclaredField(fieldName); |
||||
// getDeclaredField checks for non-public scopes as well
|
||||
// and it returns accurate results
|
||||
if (!Modifier.isPublic(field.getModifiers())) { |
||||
if (forceAccess) { |
||||
field.setAccessible(true); |
||||
} else { |
||||
continue; |
||||
} |
||||
} |
||||
return field; |
||||
} catch (final NoSuchFieldException ex) { // NOPMD
|
||||
// ignore
|
||||
} |
||||
} |
||||
// check the public interface case. This must be manually searched for
|
||||
// incase there is a public supersuperclass field hidden by a private/package
|
||||
// superclass field.
|
||||
Field match = null; |
||||
for (final Class<?> class1 : ClassUtils.getAllInterfaces(cls)) { |
||||
try { |
||||
final Field test = class1.getField(fieldName); |
||||
Validate.isTrue(match == null, "Reference to field %s is ambiguous relative to %s" |
||||
+ "; a matching field exists on two or more implemented interfaces.", fieldName, cls); |
||||
match = test; |
||||
} catch (final NoSuchFieldException ex) { // NOPMD
|
||||
// ignore
|
||||
} |
||||
} |
||||
return match; |
||||
} |
||||
|
||||
|
||||
|
||||
} |
@ -0,0 +1,39 @@
|
||||
package com.alibaba.excel.util; |
||||
|
||||
import java.util.ArrayList; |
||||
import java.util.List; |
||||
|
||||
/** |
||||
* Int utils |
||||
* |
||||
* @author Jiaju Zhuang |
||||
**/ |
||||
public class IntUtils { |
||||
private IntUtils() {} |
||||
|
||||
|
||||
/** |
||||
* The largest power of two that can be represented as an {@code int}. |
||||
* |
||||
* @since 10.0 |
||||
*/ |
||||
public static final int MAX_POWER_OF_TWO = 1 << (Integer.SIZE - 2); |
||||
|
||||
/** |
||||
* Returns the {@code int} nearest in value to {@code value}. |
||||
* |
||||
* @param value any {@code long} value |
||||
* @return the same value cast to {@code int} if it is in the range of the {@code int} type, |
||||
* {@link Integer#MAX_VALUE} if it is too large, or {@link Integer#MIN_VALUE} if it is too |
||||
* small |
||||
*/ |
||||
public static int saturatedCast(long value) { |
||||
if (value > Integer.MAX_VALUE) { |
||||
return Integer.MAX_VALUE; |
||||
} |
||||
if (value < Integer.MIN_VALUE) { |
||||
return Integer.MIN_VALUE; |
||||
} |
||||
return (int) value; |
||||
} |
||||
} |
@ -0,0 +1,121 @@
|
||||
package com.alibaba.excel.util; |
||||
|
||||
import java.util.ArrayList; |
||||
import java.util.Collection; |
||||
import java.util.Iterator; |
||||
import java.util.List; |
||||
|
||||
import lombok.NonNull; |
||||
import org.apache.commons.compress.utils.Iterators; |
||||
|
||||
/** |
||||
* List utils |
||||
* |
||||
* @author Jiaju Zhuang |
||||
**/ |
||||
public class ListUtils { |
||||
private ListUtils() {} |
||||
|
||||
/** |
||||
* Creates a <i>mutable</i>, empty {@code ArrayList} instance (for Java 6 and earlier). |
||||
* |
||||
* <p><b>Note for Java 7 and later:</b> this method is now unnecessary and should be treated as |
||||
* deprecated. Instead, use the {@code ArrayList} {@linkplain ArrayList#ArrayList() constructor} |
||||
* directly, taking advantage of the new <a href="http://goo.gl/iz2Wi">"diamond" syntax</a>. |
||||
*/ |
||||
public static <E> ArrayList<E> newArrayList() { |
||||
return new ArrayList<>(); |
||||
} |
||||
|
||||
/** |
||||
* Creates a <i>mutable</i> {@code ArrayList} instance containing the given elements; a very thin |
||||
* shortcut for creating an empty list and then calling {@link Iterators#addAll}. |
||||
* |
||||
*/ |
||||
public static <E> ArrayList<E> newArrayList(Iterator<? extends E> elements) { |
||||
ArrayList<E> list = newArrayList(); |
||||
Iterators.addAll(list, elements); |
||||
return list; |
||||
} |
||||
|
||||
/** |
||||
* Creates a <i>mutable</i> {@code ArrayList} instance containing the given elements; |
||||
* |
||||
* |
||||
* <p><b>Note for Java 7 and later:</b> if {@code elements} is a {@link Collection}, you don't |
||||
* need this method. Use the {@code ArrayList} {@linkplain ArrayList#ArrayList(Collection) |
||||
* constructor} directly, taking advantage of the new <a href="http://goo.gl/iz2Wi">"diamond" |
||||
* syntax</a>. |
||||
*/ |
||||
public static <E> ArrayList<E> newArrayList(Iterable<? extends E> elements) { |
||||
checkNotNull(elements); // for GWT
|
||||
// Let ArrayList's sizing logic work, if possible
|
||||
return (elements instanceof Collection) |
||||
? new ArrayList<>((Collection<? extends E>)elements) |
||||
: newArrayList(elements.iterator()); |
||||
} |
||||
|
||||
/** |
||||
* Creates an {@code ArrayList} instance backed by an array with the specified initial size; |
||||
* simply delegates to {@link ArrayList#ArrayList(int)}. |
||||
* |
||||
* <p><b>Note for Java 7 and later:</b> this method is now unnecessary and should be treated as |
||||
* deprecated. Instead, use {@code new }{@link ArrayList#ArrayList(int) ArrayList}{@code <>(int)} |
||||
* directly, taking advantage of the new <a href="http://goo.gl/iz2Wi">"diamond" syntax</a>. |
||||
* (Unlike here, there is no risk of overload ambiguity, since the {@code ArrayList} constructors |
||||
* very wisely did not accept varargs.) |
||||
* |
||||
* @param initialArraySize the exact size of the initial backing array for the returned array list |
||||
* ({@code ArrayList} documentation calls this value the "capacity") |
||||
* @return a new, empty {@code ArrayList} which is guaranteed not to resize itself unless its size |
||||
* reaches {@code initialArraySize + 1} |
||||
* @throws IllegalArgumentException if {@code initialArraySize} is negative |
||||
*/ |
||||
public static <E> ArrayList<E> newArrayListWithCapacity(int initialArraySize) { |
||||
checkNonnegative(initialArraySize, "initialArraySize"); |
||||
return new ArrayList<>(initialArraySize); |
||||
} |
||||
|
||||
/** |
||||
* Creates an {@code ArrayList} instance to hold {@code estimatedSize} elements, <i>plus</i> an |
||||
* unspecified amount of padding; you almost certainly mean to call {@link |
||||
* #newArrayListWithCapacity} (see that method for further advice on usage). |
||||
* |
||||
* <p><b>Note:</b> This method will soon be deprecated. Even in the rare case that you do want |
||||
* some amount of padding, it's best if you choose your desired amount explicitly. |
||||
* |
||||
* @param estimatedSize an estimate of the eventual {@link List#size()} of the new list |
||||
* @return a new, empty {@code ArrayList}, sized appropriately to hold the estimated number of |
||||
* elements |
||||
* @throws IllegalArgumentException if {@code estimatedSize} is negative |
||||
*/ |
||||
public static <E> ArrayList<E> newArrayListWithExpectedSize(int estimatedSize) { |
||||
return new ArrayList<>(computeArrayListCapacity(estimatedSize)); |
||||
} |
||||
|
||||
static int computeArrayListCapacity(int arraySize) { |
||||
checkNonnegative(arraySize, "arraySize"); |
||||
return IntUtils.saturatedCast(5L + arraySize + (arraySize / 10)); |
||||
} |
||||
|
||||
static int checkNonnegative(int value, String name) { |
||||
if (value < 0) { |
||||
throw new IllegalArgumentException(name + " cannot be negative but was: " + value); |
||||
} |
||||
return value; |
||||
} |
||||
|
||||
/** |
||||
* Ensures that an object reference passed as a parameter to the calling method is not null. |
||||
* |
||||
* @param reference an object reference |
||||
* @return the non-null reference that was validated |
||||
* @throws NullPointerException if {@code reference} is null |
||||
*/ |
||||
public static <T extends @NonNull Object> T checkNotNull(T reference) { |
||||
if (reference == null) { |
||||
throw new NullPointerException(); |
||||
} |
||||
return reference; |
||||
} |
||||
} |
@ -0,0 +1,63 @@
|
||||
package com.alibaba.excel.util; |
||||
|
||||
import java.util.ArrayList; |
||||
import java.util.HashMap; |
||||
import java.util.List; |
||||
import java.util.Map; |
||||
|
||||
/** |
||||
* Map utils |
||||
* |
||||
* @author Jiaju Zhuang |
||||
**/ |
||||
public class MapUtils { |
||||
private MapUtils() {} |
||||
/** |
||||
* Creates a <i>mutable</i>, empty {@code HashMap} instance. |
||||
* |
||||
* <p><b>Note:</b> if mutability is not required, use {@link ImmutableMap#of()} instead. |
||||
* |
||||
* <p><b>Note:</b> if {@code K} is an {@code enum} type, use {@link #newEnumMap} instead. |
||||
* |
||||
* <p><b>Note for Java 7 and later:</b> this method is now unnecessary and should be treated as |
||||
* deprecated. Instead, use the {@code HashMap} constructor directly, taking advantage of the new |
||||
* <a href="http://goo.gl/iz2Wi">"diamond" syntax</a>. |
||||
* |
||||
* @return a new, empty {@code HashMap} |
||||
*/ |
||||
public static <K, V> HashMap<K, V> newHashMap() { |
||||
return new HashMap<>(); |
||||
} |
||||
|
||||
/** |
||||
* Creates a {@code HashMap} instance, with a high enough "initial capacity" that it <i>should</i> |
||||
* hold {@code expectedSize} elements without growth. This behavior cannot be broadly guaranteed, |
||||
* but it is observed to be true for OpenJDK 1.7. It also can't be guaranteed that the method |
||||
* isn't inadvertently <i>oversizing</i> the returned map. |
||||
* |
||||
* @param expectedSize the number of entries you expect to add to the returned map |
||||
* @return a new, empty {@code HashMap} with enough capacity to hold {@code expectedSize} entries |
||||
* without resizing |
||||
* @throws IllegalArgumentException if {@code expectedSize} is negative |
||||
*/ |
||||
public static <K, V> HashMap<K, V> newHashMapWithExpectedSize(int expectedSize) { |
||||
return new HashMap<>(capacity(expectedSize)); |
||||
} |
||||
|
||||
/** |
||||
* Returns a capacity that is sufficient to keep the map from being resized as long as it grows no |
||||
* larger than expectedSize and the load factor is ≥ its default (0.75). |
||||
*/ |
||||
static int capacity(int expectedSize) { |
||||
if (expectedSize < 3) { |
||||
return expectedSize + 1; |
||||
} |
||||
if (expectedSize < IntUtils.MAX_POWER_OF_TWO) { |
||||
// This is the calculation used in JDK8 to resize when a putAll
|
||||
// happens; it seems to be the most conservative calculation we
|
||||
// can make. 0.75 is the default load factor.
|
||||
return (int) ((float) expectedSize / 0.75F + 1.0F); |
||||
} |
||||
return Integer.MAX_VALUE; |
||||
} |
||||
} |
@ -0,0 +1,54 @@
|
||||
package com.alibaba.excel.util; |
||||
|
||||
import java.lang.reflect.AccessibleObject; |
||||
import java.lang.reflect.Member; |
||||
import java.lang.reflect.Modifier; |
||||
|
||||
/** |
||||
* Member utils. |
||||
* |
||||
* @author Jiaju Zhuang |
||||
*/ |
||||
public class MemberUtils { |
||||
|
||||
private static final int ACCESS_TEST = Modifier.PUBLIC | Modifier.PROTECTED | Modifier.PRIVATE; |
||||
|
||||
|
||||
/** |
||||
* XXX Default access superclass workaround. |
||||
* |
||||
* When a {@code public} class has a default access superclass with {@code public} members, |
||||
* these members are accessible. Calling them from compiled code works fine. |
||||
* Unfortunately, on some JVMs, using reflection to invoke these members |
||||
* seems to (wrongly) prevent access even when the modifier is {@code public}. |
||||
* Calling {@code setAccessible(true)} solves the problem but will only work from |
||||
* sufficiently privileged code. Better workarounds would be gratefully |
||||
* accepted. |
||||
* @param o the AccessibleObject to set as accessible |
||||
* @return a boolean indicating whether the accessibility of the object was set to true. |
||||
*/ |
||||
static boolean setAccessibleWorkaround(final AccessibleObject o) { |
||||
if (o == null || o.isAccessible()) { |
||||
return false; |
||||
} |
||||
final Member m = (Member) o; |
||||
if (!o.isAccessible() && Modifier.isPublic(m.getModifiers()) && isPackageAccess(m.getDeclaringClass().getModifiers())) { |
||||
try { |
||||
o.setAccessible(true); |
||||
return true; |
||||
} catch (final SecurityException e) { // NOPMD
|
||||
// ignore in favor of subsequent IllegalAccessException
|
||||
} |
||||
} |
||||
return false; |
||||
} |
||||
|
||||
/** |
||||
* Returns whether a given set of modifiers implies package access. |
||||
* @param modifiers to test |
||||
* @return {@code true} unless {@code package}/{@code protected}/{@code private} modifier detected |
||||
*/ |
||||
static boolean isPackageAccess(final int modifiers) { |
||||
return (modifiers & ACCESS_TEST) == 0; |
||||
} |
||||
} |
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue