下面列出了java.lang.reflect.Modifier#PUBLIC 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
/**
* @param methodInfo A map contains args mapped by order or name
* @see ClassBuilder#addMethod(String, int, Object, Object[], LuaFunction, List, List)
*/
public ClassBuilder addMethod(Map methodInfo) {
LuaFunction function = mapGet("func", 4, methodInfo);
Map<?, Object> paramTypes = mapGet("paramTypes", 5, methodInfo);
Map<?, Map<Object, Object>> annotations = mapGet("annotations", 6, methodInfo);
Map<?, Map<?, Map<Object, Object>>> paramAnnotations = mapGet("paramAnnotations", 7, methodInfo);
ArrayList<List<Map<Object,Object>>> paraAnnoList=null;
if(paramAnnotations!=null){
paraAnnoList=new ArrayList<>();
for (Map<?, Map<Object, Object>> annolist:paramAnnotations.values()){
paraAnnoList.add(new ArrayList<>(annolist.values()));
}
}
Integer flag = mapGet("flag", 2, methodInfo);
if(flag==null)flag=Modifier.PUBLIC|(function==null?Modifier.ABSTRACT:0);
return addMethod(mapGet("name", 1, methodInfo), flag,
mapGet("returnType", 3, methodInfo)
, paramTypes == null ? null : paramTypes.values().toArray(),
function, annotations == null ? null : new ArrayList<>(annotations.values())
, paraAnnoList);
}
@Override
public void visitEnd() {
if (accumulatorType != null) {
final MethodVisitor getAccumulatorCoder = super.visitMethod(Modifier.PUBLIC, "getAccumulatorCoder",
"(Lorg/apache/beam/sdk/coders/CoderRegistry;Lorg/apache/beam/sdk/coders/Coder;)"
+ "Lorg/apache/beam/sdk/coders/Coder;",
null, null);
getAccumulatorCoder.visitLdcInsn(accumulatorType);
getAccumulatorCoder.visitLdcInsn(plugin);
getAccumulatorCoder
.visitMethodInsn(INVOKESTATIC,
"org/talend/sdk/component/runtime/beam/coder/ContextualSerializableCoder", "of",
"(Ljava/lang/Class;Ljava/lang/String;)Lorg/apache/beam/sdk/coders/SerializableCoder;",
false);
getAccumulatorCoder.visitInsn(ARETURN);
getAccumulatorCoder.visitMaxs(-1, -1);
getAccumulatorCoder.visitEnd();
}
super.visitEnd();
}
/**
* @param type
* @param name
* @return Method
*/
public static Method getSetMethod(Class<?> type, String name) {
Method[] methods = type.getMethods();
String methodName = "set" + Character.toUpperCase(name.charAt(0)) + name.substring(1);
for(Method method : methods) {
if(method.getModifiers() != Modifier.PUBLIC) {
continue;
}
if(method.getName().equals(methodName)) {
if(method.getParameterTypes().length == 1) {
return method;
}
}
}
return null;
}
/**
* Declares a field.
*
* @param flags a bitwise combination of {@link Modifier#PUBLIC}, {@link
* Modifier#PRIVATE}, {@link Modifier#PROTECTED}, {@link Modifier#STATIC},
* {@link Modifier#FINAL}, {@link Modifier#VOLATILE}, and {@link
* Modifier#TRANSIENT}.
* @param staticValue a constant representing the initial value for the
* static field, possibly null. This must be null if this field is
* non-static.
*/
public void declare(FieldId<?, ?> fieldId, int flags, Object staticValue) {
TypeDeclaration typeDeclaration = getTypeDeclaration(fieldId.declaringType);
if (typeDeclaration.fields.containsKey(fieldId)) {
throw new IllegalStateException("already declared: " + fieldId);
}
int supportedFlags = Modifier.PUBLIC | Modifier.PRIVATE | Modifier.PROTECTED
| Modifier.STATIC | Modifier.FINAL | Modifier.VOLATILE | Modifier.TRANSIENT
| AccessFlags.ACC_SYNTHETIC;
if ((flags & ~supportedFlags) != 0) {
throw new IllegalArgumentException("Unexpected flag: "
+ Integer.toHexString(flags));
}
if ((flags & Modifier.STATIC) == 0 && staticValue != null) {
throw new IllegalArgumentException("staticValue is non-null, but field is not static");
}
FieldDeclaration fieldDeclaration = new FieldDeclaration(fieldId, flags, staticValue);
typeDeclaration.fields.put(fieldId, fieldDeclaration);
}
/**
* Returns public no-arg constructor of given class, or null if none found.
* Access checks are disabled on the returned constructor (if any), since
* the defining class may still be non-public.
*/
private static Constructor<?> getExternalizableConstructor(Class<?> cl) {
try {
Constructor<?> cons = cl.getDeclaredConstructor((Class<?>[]) null);
cons.setAccessible(true);
return ((cons.getModifiers() & Modifier.PUBLIC) != 0) ?
cons : null;
} catch (NoSuchMethodException ex) {
return null;
}
}
static String getVKText(int keyCode) {
VKCollection vkCollect = getVKCollection();
Integer key = Integer.valueOf(keyCode);
String name = vkCollect.findName(key);
if (name != null) {
return name.substring(3);
}
int expected_modifiers =
(Modifier.PUBLIC | Modifier.STATIC | Modifier.FINAL);
Field[] fields = KeyEvent.class.getDeclaredFields();
for (int i = 0; i < fields.length; i++) {
try {
if (fields[i].getModifiers() == expected_modifiers
&& fields[i].getType() == Integer.TYPE
&& fields[i].getName().startsWith("VK_")
&& fields[i].getInt(KeyEvent.class) == keyCode)
{
name = fields[i].getName();
vkCollect.put(name, key);
return name.substring(3);
}
} catch (IllegalAccessException e) {
assert(false);
}
}
return "UNKNOWN";
}
private MethodMetadata getHashCodeMethod() {
// Define method parameter types
List<AnnotatedJavaType> parameterTypes = new ArrayList<AnnotatedJavaType>(
0);
// Check if a method exist in type
final MethodMetadata method = helper.methodExists(TO_STRING_METHOD,
parameterTypes);
if (method != null) {
// If it already exists, just return the method
return method;
}
// Define method annotations (none in this case)
List<AnnotationMetadataBuilder> annotations = new ArrayList<AnnotationMetadataBuilder>();
// Define method throws types (none in this case)
List<JavaType> throwsTypes = new ArrayList<JavaType>();
// Define method parameter names (none in this case)
List<JavaSymbolName> parameterNames = new ArrayList<JavaSymbolName>(0);
// Create the method body
InvocableMemberBodyBuilder body = new InvocableMemberBodyBuilder();
body.appendFormalLine(String.format(
"return new %s(17, 31).append(%s).append(%s).toHashCode();",
helper.getFinalTypeName(HASH_CODE_BUILDER), ID_FIELD,
TIMESTAMP_FIELD));
// Use the MethodMetadataBuilder for easy creation of MethodMetadata
MethodMetadataBuilder methodBuilder = new MethodMetadataBuilder(
context.getMetadataId(), Modifier.PUBLIC, HASH_CODE_METHOD,
JavaType.INT_PRIMITIVE, parameterTypes, parameterNames, body);
methodBuilder.setAnnotations(annotations);
methodBuilder.setThrowsTypes(throwsTypes);
return methodBuilder.build(); // Build and return a MethodMetadata
}
static String getVKText(int keyCode) {
VKCollection vkCollect = getVKCollection();
Integer key = Integer.valueOf(keyCode);
String name = vkCollect.findName(key);
if (name != null) {
return name.substring(3);
}
int expected_modifiers =
(Modifier.PUBLIC | Modifier.STATIC | Modifier.FINAL);
Field[] fields = KeyEvent.class.getDeclaredFields();
for (int i = 0; i < fields.length; i++) {
try {
if (fields[i].getModifiers() == expected_modifiers
&& fields[i].getType() == Integer.TYPE
&& fields[i].getName().startsWith("VK_")
&& fields[i].getInt(KeyEvent.class) == keyCode)
{
name = fields[i].getName();
vkCollect.put(name, key);
return name.substring(3);
}
} catch (IllegalAccessException e) {
assert(false);
}
}
return "UNKNOWN";
}
private static Method getPublicMethod(Class<?> clazz, String methodName, Class[] parameterTypes) {
Method method = null;
try {
method = clazz.getMethod(methodName, parameterTypes);
if ((method.getModifiers() & Modifier.PUBLIC) == 0) {
method = null;
}
} catch (NoSuchMethodException e) {
// None.
}
return method;
}
public int getVisibility( )
{
if ( field == null )
return VISIBILITY_PUBLIC;
if ( ( field.getModifiers( ) & Modifier.STATIC ) != 0 )
{
return VISIBILITY_STATIC;
}
else if ( ( field.getModifiers( ) & Modifier.PUBLIC ) != 0 )
{
return VISIBILITY_PUBLIC;
}
else if ( ( field.getModifiers( ) & Modifier.PRIVATE ) != 0 )
{
return VISIBILITY_PRIVATE;
}
else if ( ( field.getModifiers( ) & Modifier.PROTECTED ) != 0 )
{
return VISIBILITY_PROTECTED;
}
else
{
return VISIBILITY_PUBLIC;
}
}
/**
* ObjectInputStream.resolveProxyClass has some funky way of using
* the incorrect class loader to resolve proxy classes, let's do it our way instead
*/
@Override
protected Class<?> resolveProxyClass(String[] interfaces)
throws IOException, ClassNotFoundException {
ClassLoader latestLoader;
if (classLoaders != null && classLoaders.length > 0) {
latestLoader = classLoaders[0];
} else {
latestLoader = null;
}
ClassLoader nonPublicLoader = null;
boolean hasNonPublicInterface = false;
// define proxy in class loader of non-public interface(s), if any
Class<?>[] classObjs = new Class[interfaces.length];
for (int i = 0; i < interfaces.length; i++) {
Class<?> cl = this.resolveClass(interfaces[i]);
if (latestLoader==null) latestLoader = cl.getClassLoader();
if ((cl.getModifiers() & Modifier.PUBLIC) == 0) {
if (hasNonPublicInterface) {
if (nonPublicLoader != cl.getClassLoader()) {
throw new IllegalAccessError(
"conflicting non-public interface class loaders");
}
} else {
nonPublicLoader = cl.getClassLoader();
hasNonPublicInterface = true;
}
}
classObjs[i] = cl;
}
try {
return Proxy.getProxyClass(hasNonPublicInterface ? nonPublicLoader
: latestLoader, classObjs);
} catch (IllegalArgumentException e) {
throw new ClassNotFoundException(null, e);
}
}
/**
* Add to the aspect the MethodMetadata of the generateReportForm method. It
* uses AbstractMetadataItem.builder for add the new method.
*
* @param reportName
* @param entity
* @param reportMethods2
* @return
*/
private MethodMetadata addGenerateReportFormMethod(JavaType entity,
String reportName, String reportFormats) {
// Specify the desired method name
JavaSymbolName methodName = new JavaSymbolName(generateMethodName(
reportName, true));
// Define method parameter types
List<AnnotatedJavaType> parameterTypes = new ArrayList<AnnotatedJavaType>();
parameterTypes.add(new AnnotatedJavaType(MODEL_TYPE,
new ArrayList<AnnotationMetadata>()));
// Check if a method with the same signature already exists in the
// target type
MethodMetadata reportMethod = reportMethodExists(methodName);
if (reportMethod != null) {
// If it already exists, just return the method and omit its
// generation via the ITD
return reportMethod;
}
// Define method parameter names
List<JavaSymbolName> parameterNames = new ArrayList<JavaSymbolName>();
parameterNames.add(new JavaSymbolName("uiModel"));
// Define method annotations
List<AnnotationAttributeValue<?>> requestMappingAttributes = new ArrayList<AnnotationAttributeValue<?>>();
requestMappingAttributes.add(new StringAttributeValue(
VALUE_SYMBOL_NAME, "/reports/".concat(reportName)));
requestMappingAttributes.add(new StringAttributeValue(
PARAMS_SYMBOL_NAME, "form"));
requestMappingAttributes
.add(new EnumAttributeValue(METHOD_SYMBOL_NAME,
new EnumDetails(REQUEST_METHOD_TYPE,
new JavaSymbolName("GET"))));
AnnotationMetadataBuilder requestMapping = new AnnotationMetadataBuilder(
REQUEST_MAPPING_TYPE, requestMappingAttributes);
List<AnnotationMetadataBuilder> annotations = new ArrayList<AnnotationMetadataBuilder>();
annotations.add(requestMapping);
// Create the method body
InvocableMemberBodyBuilder bodyBuilder = new InvocableMemberBodyBuilder();
// Populate report_formats list for select
String reportFormatsAsArray = getReportFormatsAsArray(reportFormats);
bodyBuilder.appendFormalLine("String[] reportFormats = ".concat(
reportFormatsAsArray).concat(";"));
bodyBuilder
.appendFormalLine("Collection<String> reportFormatsList = Arrays.asList(reportFormats);");
bodyBuilder
.appendFormalLine("uiModel.addAttribute(\"report_formats\", reportFormatsList);");
// return the View
bodyBuilder.appendFormalLine("return \""
.concat(annotationValues.getPath()).concat("/")
.concat(reportName).concat("\";"));
// ImportRegistrationResolver gives access to imports in the
// Java/AspectJ source
ImportRegistrationResolver irr = builder
.getImportRegistrationResolver();
irr.addImport(new JavaType("java.util.Arrays"));
irr.addImport(new JavaType("java.util.Collection"));
// Use the MethodMetadataBuilder for easy creation of MethodMetadata
MethodMetadataBuilder methodBuilder = new MethodMetadataBuilder(
getId(), Modifier.PUBLIC, methodName, JavaType.STRING,
parameterTypes, parameterNames, bodyBuilder);
methodBuilder.setAnnotations(annotations);
reportMethod = methodBuilder.build();
builder.addMethod(reportMethod);
controllerMethods.add(reportMethod);
return reportMethod;
}
private MethodMetadata getRevisionDate() {
if (revsionDateGetter == null) {
JavaSymbolName methodName = helper
.getGetterMethodNameForField(REVISION_DATE_TRANSIENT_FIELD);
// Define method parameter types
List<AnnotatedJavaType> parameterTypes = new ArrayList<AnnotatedJavaType>(
0);
// Check if a method exist in type
final MethodMetadata method = helper.methodExists(methodName,
parameterTypes);
if (method != null) {
// If it already exists, just return the method
return method;
}
// Define method annotations (none in this case)
List<AnnotationMetadataBuilder> annotations = helper
.toAnnotationMetadata(JpaJavaType.TRANSIENT);
// Define method throws types (none in this case)
List<JavaType> throwsTypes = new ArrayList<JavaType>();
// Define method parameter names (none in this case)
List<JavaSymbolName> parameterNames = new ArrayList<JavaSymbolName>(
0);
// Create the method body
InvocableMemberBodyBuilder body = new InvocableMemberBodyBuilder();
// return new Date(this.timestamp);
body.appendFormalLine(String.format("return new %s(this.%s);",
helper.getFinalTypeName(JdkJavaType.DATE), TIMESTAMP_FIELD));
// Use the MethodMetadataBuilder for easy creation of MethodMetadata
MethodMetadataBuilder methodBuilder = new MethodMetadataBuilder(
context.getMetadataId(), Modifier.PUBLIC, methodName,
JdkJavaType.DATE, parameterTypes, parameterNames, body);
methodBuilder.setAnnotations(annotations);
methodBuilder.setThrowsTypes(throwsTypes);
revsionDateGetter = methodBuilder.build(); // Build and return a
// MethodMetadata
}
return revsionDateGetter;
}
public static void ensureMemberAccess(Class<?> currentClass,
Class<?> memberClass,
Object target,
int modifiers)
throws IllegalAccessException
{
if (target == null && Modifier.isProtected(modifiers)) {
int mods = modifiers;
mods = mods & (~Modifier.PROTECTED);
mods = mods | Modifier.PUBLIC;
/*
* See if we fail because of class modifiers
*/
Reflection.ensureMemberAccess(currentClass,
memberClass,
target,
mods);
try {
/*
* We're still here so class access was ok.
* Now try with default field access.
*/
mods = mods & (~Modifier.PUBLIC);
Reflection.ensureMemberAccess(currentClass,
memberClass,
target,
mods);
/*
* We're still here so access is ok without
* checking for protected.
*/
return;
} catch (IllegalAccessException e) {
/*
* Access failed but we're 'protected' so
* if the test below succeeds then we're ok.
*/
if (isSubclassOf(currentClass, memberClass)) {
return;
} else {
throw e;
}
}
} else {
Reflection.ensureMemberAccess(currentClass,
memberClass,
target,
modifiers);
}
}
/**
* Create the class for entity which will hold the revision information for
* Hibernate Envers
* <p/>
* This use {@link #REVISION_LOG_ENTITY_NAME} as class name and look for
* <em>the first package which contains a entity</em> to place it.
*
*/
public void installRevisonEntity(JavaType revisionEntity) {
PathResolver pathResolver = projectOperations.getPathResolver();
JavaType target;
if (revisionEntity == null) {
target = generateRevionEntityJavaType();
}
else {
target = revisionEntity;
}
int modifier = Modifier.PUBLIC;
final String declaredByMetadataId = PhysicalTypeIdentifier
.createIdentifier(target,
pathResolver.getFocusedPath(Path.SRC_MAIN_JAVA));
File targetFile = new File(
typeLocationService
.getPhysicalTypeCanonicalPath(declaredByMetadataId));
if (targetFile.exists()) {
Validate.isTrue(!targetFile.exists(), "Type '%s' already exists",
target);
}
// Prepare class builder
final ClassOrInterfaceTypeDetailsBuilder cidBuilder = new ClassOrInterfaceTypeDetailsBuilder(
declaredByMetadataId, modifier, target,
PhysicalTypeCategory.CLASS);
// Prepare annotations array
List<AnnotationMetadataBuilder> annotations = new ArrayList<AnnotationMetadataBuilder>(
1);
// Add @GvNIXJpaAuditListener annotation
AnnotationMetadataBuilder jpaAuditRevEntAnn = new AnnotationMetadataBuilder(
new JavaType(GvNIXJpaAuditRevisionEntity.class));
annotations.add(jpaAuditRevEntAnn);
// Set annotations
cidBuilder.setAnnotations(annotations);
// Create Revision entity class
typeManagementService.createOrUpdateTypeOnDisk(cidBuilder.build());
}
private static Object createObjectProxy(Object realObject, Class realClass, ObjectProxyMethodHook hook) throws Throwable {
ClassPool pool = ClassPool.getDefault();
CtClass cc = pool.makeClass(HackJavaFX.class.getPackage().getName() + "." +
realClass.getSimpleName() + "_Proxy");
cc.setSuperclass(pool.get(realClass.getName()));
CtField realObjectField = new CtField(cc.getSuperclass(), "realObject", cc);
realObjectField.setModifiers(Modifier.FINAL | Modifier.PRIVATE);
cc.addField(realObjectField);
CtField realClassField = new CtField(pool.get("java.lang.Class"), "realClass", cc);
realClassField.setModifiers(Modifier.FINAL | Modifier.PRIVATE);
cc.addField(realClassField);
CtConstructor constructor = new CtConstructor(
new CtClass[]{realObjectField.getType(), realClassField.getType()}, cc
);
constructor.setModifiers(Modifier.PUBLIC);
constructor.setBody("{ realObject = $1; realClass = $2; }");
cc.addConstructor(constructor);
for (CtMethod method : cc.getSuperclass().getDeclaredMethods()) {
if ((method.getModifiers() & Modifier.FINAL) != 0) {
continue;
}
if ((method.getModifiers() & Modifier.STATIC) != 0) {
continue;
}
CtMethod newMethod = new CtMethod(method.getReturnType(), method.getName(),
method.getParameterTypes(), cc);
newMethod.setModifiers(method.getModifiers() & ~(Modifier.NATIVE | Modifier.SYNCHRONIZED));
newMethod.setExceptionTypes(method.getExceptionTypes());
if (newMethod.getReturnType().equals(CtClass.voidType)) {
if ((newMethod.getModifiers() & Modifier.PUBLIC) != 0) {
newMethod.setBody("realObject." + method.getName() + "($$);");
} else {
newMethod.setBody("{ java.lang.reflect.Method method = realClass.getDeclaredMethod(\""
+ method.getName() + "\", $sig);" + "method.setAccessible(true);"
+ "method.invoke(this.realObject, $args); }");
}
} else {
if ((newMethod.getModifiers() & Modifier.PUBLIC) != 0) {
newMethod.setBody("return realObject." + method.getName() + "($$);");
} else {
newMethod.setBody("{ java.lang.reflect.Method method = realClass.getDeclaredMethod(\""
+ method.getName() + "\", $sig);" + "method.setAccessible(true);"
+ "java.lang.Object retVal = method.invoke(realObject, $args);"
+ "return ($r) retVal; }");
}
}
if (hook != null) {
hook.processMethod(newMethod);
}
cc.addMethod(newMethod);
}
Class cls = cc.toClass();
Constructor c = cls.getDeclaredConstructor(cls.getSuperclass(), Class.class);
Object proxy = c.newInstance(realObject, realClass);
for (Field field : realClass.getDeclaredFields()) {
if ((field.getModifiers() & Modifier.STATIC) != 0) {
continue;
}
if ((field.getModifiers() & Modifier.FINAL) != 0) {
continue;
}
field.setAccessible(true);
field.set(proxy, field.get(realObject));
}
return proxy;
}
/**
* Returns a proxy class that implements the interfaces named in a proxy
* class descriptor; subclasses may implement this method to read custom
* data from the stream along with the descriptors for dynamic proxy
* classes, allowing them to use an alternate loading mechanism for the
* interfaces and the proxy class.
*
* <p>This method is called exactly once for each unique proxy class
* descriptor in the stream.
*
* <p>The corresponding method in <code>ObjectOutputStream</code> is
* <code>annotateProxyClass</code>. For a given subclass of
* <code>ObjectInputStream</code> that overrides this method, the
* <code>annotateProxyClass</code> method in the corresponding subclass of
* <code>ObjectOutputStream</code> must write any data or objects read by
* this method.
*
* <p>The default implementation of this method in
* <code>ObjectInputStream</code> returns the result of calling
* <code>Proxy.getProxyClass</code> with the list of <code>Class</code>
* objects for the interfaces that are named in the <code>interfaces</code>
* parameter. The <code>Class</code> object for each interface name
* <code>i</code> is the value returned by calling
* <pre>
* Class.forName(i, false, loader)
* </pre>
* where <code>loader</code> is that of the first non-<code>null</code>
* class loader up the execution stack, or <code>null</code> if no
* non-<code>null</code> class loaders are on the stack (the same class
* loader choice used by the <code>resolveClass</code> method). Unless any
* of the resolved interfaces are non-public, this same value of
* <code>loader</code> is also the class loader passed to
* <code>Proxy.getProxyClass</code>; if non-public interfaces are present,
* their class loader is passed instead (if more than one non-public
* interface class loader is encountered, an
* <code>IllegalAccessError</code> is thrown).
* If <code>Proxy.getProxyClass</code> throws an
* <code>IllegalArgumentException</code>, <code>resolveProxyClass</code>
* will throw a <code>ClassNotFoundException</code> containing the
* <code>IllegalArgumentException</code>.
*
* @param interfaces the list of interface names that were
* deserialized in the proxy class descriptor
* @return a proxy class for the specified interfaces
* @throws IOException any exception thrown by the underlying
* <code>InputStream</code>
* @throws ClassNotFoundException if the proxy class or any of the
* named interfaces could not be found
* @see ObjectOutputStream#annotateProxyClass(Class)
* @since 1.3
*/
protected Class<?> resolveProxyClass(String[] interfaces)
throws IOException, ClassNotFoundException
{
ClassLoader latestLoader = latestUserDefinedLoader();
ClassLoader nonPublicLoader = null;
boolean hasNonPublicInterface = false;
// define proxy in class loader of non-public interface(s), if any
Class<?>[] classObjs = new Class<?>[interfaces.length];
for (int i = 0; i < interfaces.length; i++) {
Class<?> cl = Class.forName(interfaces[i], false, latestLoader);
if ((cl.getModifiers() & Modifier.PUBLIC) == 0) {
if (hasNonPublicInterface) {
if (nonPublicLoader != cl.getClassLoader()) {
throw new IllegalAccessError(
"conflicting non-public interface class loaders");
}
} else {
nonPublicLoader = cl.getClassLoader();
hasNonPublicInterface = true;
}
}
classObjs[i] = cl;
}
try {
return Proxy.getProxyClass(
hasNonPublicInterface ? nonPublicLoader : latestLoader,
classObjs);
} catch (IllegalArgumentException e) {
throw new ClassNotFoundException(null, e);
}
}
/**
* Returns a proxy class that implements the interfaces named in a proxy
* class descriptor; subclasses may implement this method to read custom
* data from the stream along with the descriptors for dynamic proxy
* classes, allowing them to use an alternate loading mechanism for the
* interfaces and the proxy class.
*
* <p>This method is called exactly once for each unique proxy class
* descriptor in the stream.
*
* <p>The corresponding method in <code>ObjectOutputStream</code> is
* <code>annotateProxyClass</code>. For a given subclass of
* <code>ObjectInputStream</code> that overrides this method, the
* <code>annotateProxyClass</code> method in the corresponding subclass of
* <code>ObjectOutputStream</code> must write any data or objects read by
* this method.
*
* <p>The default implementation of this method in
* <code>ObjectInputStream</code> returns the result of calling
* <code>Proxy.getProxyClass</code> with the list of <code>Class</code>
* objects for the interfaces that are named in the <code>interfaces</code>
* parameter. The <code>Class</code> object for each interface name
* <code>i</code> is the value returned by calling
* <pre>
* Class.forName(i, false, loader)
* </pre>
* where <code>loader</code> is that of the first non-<code>null</code>
* class loader up the execution stack, or <code>null</code> if no
* non-<code>null</code> class loaders are on the stack (the same class
* loader choice used by the <code>resolveClass</code> method). Unless any
* of the resolved interfaces are non-public, this same value of
* <code>loader</code> is also the class loader passed to
* <code>Proxy.getProxyClass</code>; if non-public interfaces are present,
* their class loader is passed instead (if more than one non-public
* interface class loader is encountered, an
* <code>IllegalAccessError</code> is thrown).
* If <code>Proxy.getProxyClass</code> throws an
* <code>IllegalArgumentException</code>, <code>resolveProxyClass</code>
* will throw a <code>ClassNotFoundException</code> containing the
* <code>IllegalArgumentException</code>.
*
* @param interfaces the list of interface names that were
* deserialized in the proxy class descriptor
* @return a proxy class for the specified interfaces
* @throws IOException any exception thrown by the underlying
* <code>InputStream</code>
* @throws ClassNotFoundException if the proxy class or any of the
* named interfaces could not be found
* @see ObjectOutputStream#annotateProxyClass(Class)
* @since 1.3
*/
protected Class<?> resolveProxyClass(String[] interfaces)
throws IOException, ClassNotFoundException
{
ClassLoader latestLoader = latestUserDefinedLoader();
ClassLoader nonPublicLoader = null;
boolean hasNonPublicInterface = false;
// define proxy in class loader of non-public interface(s), if any
Class<?>[] classObjs = new Class<?>[interfaces.length];
for (int i = 0; i < interfaces.length; i++) {
Class<?> cl = Class.forName(interfaces[i], false, latestLoader);
if ((cl.getModifiers() & Modifier.PUBLIC) == 0) {
if (hasNonPublicInterface) {
if (nonPublicLoader != cl.getClassLoader()) {
throw new IllegalAccessError(
"conflicting non-public interface class loaders");
}
} else {
nonPublicLoader = cl.getClassLoader();
hasNonPublicInterface = true;
}
}
classObjs[i] = cl;
}
try {
return Proxy.getProxyClass(
hasNonPublicInterface ? nonPublicLoader : latestLoader,
classObjs);
} catch (IllegalArgumentException e) {
throw new ClassNotFoundException(null, e);
}
}
/**
* Returns a proxy class that implements the interfaces named in a proxy
* class descriptor; subclasses may implement this method to read custom
* data from the stream along with the descriptors for dynamic proxy
* classes, allowing them to use an alternate loading mechanism for the
* interfaces and the proxy class.
*
* <p>This method is called exactly once for each unique proxy class
* descriptor in the stream.
*
* <p>The corresponding method in <code>ObjectOutputStream</code> is
* <code>annotateProxyClass</code>. For a given subclass of
* <code>ObjectInputStream</code> that overrides this method, the
* <code>annotateProxyClass</code> method in the corresponding subclass of
* <code>ObjectOutputStream</code> must write any data or objects read by
* this method.
*
* <p>The default implementation of this method in
* <code>ObjectInputStream</code> returns the result of calling
* <code>Proxy.getProxyClass</code> with the list of <code>Class</code>
* objects for the interfaces that are named in the <code>interfaces</code>
* parameter. The <code>Class</code> object for each interface name
* <code>i</code> is the value returned by calling
* <pre>
* Class.forName(i, false, loader)
* </pre>
* where <code>loader</code> is that of the first non-<code>null</code>
* class loader up the execution stack, or <code>null</code> if no
* non-<code>null</code> class loaders are on the stack (the same class
* loader choice used by the <code>resolveClass</code> method). Unless any
* of the resolved interfaces are non-public, this same value of
* <code>loader</code> is also the class loader passed to
* <code>Proxy.getProxyClass</code>; if non-public interfaces are present,
* their class loader is passed instead (if more than one non-public
* interface class loader is encountered, an
* <code>IllegalAccessError</code> is thrown).
* If <code>Proxy.getProxyClass</code> throws an
* <code>IllegalArgumentException</code>, <code>resolveProxyClass</code>
* will throw a <code>ClassNotFoundException</code> containing the
* <code>IllegalArgumentException</code>.
*
* @param interfaces the list of interface names that were
* deserialized in the proxy class descriptor
* @return a proxy class for the specified interfaces
* @throws IOException any exception thrown by the underlying
* <code>InputStream</code>
* @throws ClassNotFoundException if the proxy class or any of the
* named interfaces could not be found
* @see ObjectOutputStream#annotateProxyClass(Class)
* @since 1.3
*/
protected Class<?> resolveProxyClass(String[] interfaces)
throws IOException, ClassNotFoundException
{
ClassLoader latestLoader = latestUserDefinedLoader();
ClassLoader nonPublicLoader = null;
boolean hasNonPublicInterface = false;
// define proxy in class loader of non-public interface(s), if any
Class<?>[] classObjs = new Class<?>[interfaces.length];
for (int i = 0; i < interfaces.length; i++) {
Class<?> cl = Class.forName(interfaces[i], false, latestLoader);
if ((cl.getModifiers() & Modifier.PUBLIC) == 0) {
if (hasNonPublicInterface) {
if (nonPublicLoader != cl.getClassLoader()) {
throw new IllegalAccessError(
"conflicting non-public interface class loaders");
}
} else {
nonPublicLoader = cl.getClassLoader();
hasNonPublicInterface = true;
}
}
classObjs[i] = cl;
}
try {
return Proxy.getProxyClass(
hasNonPublicInterface ? nonPublicLoader : latestLoader,
classObjs);
} catch (IllegalArgumentException e) {
throw new ClassNotFoundException(null, e);
}
}
/**
* Checks the compatibility between two modifier masks. Checks that they are equal
* with regards to access and static modifier.
*
* @return true if the modifiers are compatible
*/
private static boolean compatibleModifiers(int modifiersA, int modifiersB) {
int mask = Modifier.PRIVATE | Modifier.PROTECTED | Modifier.PUBLIC | Modifier.STATIC;
return (modifiersA & mask) == (modifiersB & mask);
}