@Test void serialization() throws Exception { try { assertFalse(Serializable.class.isInstance(new CatService())); final ProxyGenerator generator = new ProxyGenerator(); final Class<?> proxyType = generator .generateProxy(Thread.currentThread().getContextClassLoader(), CatService.class, "test", CatService.class.getName()); assertNotNull(proxyType); final Object proxy = proxyType.getConstructor().newInstance(); assertProxy(proxy); DynamicContainerFinder.SERVICES.put(CatService.class, proxy); DynamicContainerFinder.LOADERS.put("test", Thread.currentThread().getContextClassLoader()); final ByteArrayOutputStream out = new ByteArrayOutputStream(); try (final ObjectOutputStream oos = new ObjectOutputStream(out)) { oos.writeObject(proxy); } try (final ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(out.toByteArray()))) { final Object deserialized = ois.readObject(); assertProxy(deserialized); assertSame(deserialized, proxy); } } finally { DynamicContainerFinder.LOADERS.clear(); DynamicContainerFinder.SERVICES.remove(CatService.class); } }
public Class<?> generateProxy(final ClassLoader loader, final Class<?> classToProxy, final String plugin, final String key) { final ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES); final String proxyClassName = fixPreservedPackages( (classToProxy.getSigners() != null ? getSignedClassProxyName(classToProxy) : classToProxy.getName()) + "$$TalendServiceProxy"); final String classFileName = proxyClassName.replace('.', '/'); final String[] interfaceNames = { Type.getInternalName(Serializable.class) }; final String superClassName = Type.getInternalName(classToProxy); cw .visit(findJavaVersion(classToProxy), ACC_PUBLIC + ACC_SUPER + ACC_SYNTHETIC, classFileName, null, superClassName, interfaceNames); cw.visitSource(classFileName + ".java", null); if (!Serializable.class.isAssignableFrom(classToProxy)) { try { classToProxy.getMethod("writeReplace"); } catch (final NoSuchMethodException e) { createSerialisation(cw, plugin, key); } } final boolean hasInterceptors = hasInterceptors(classToProxy); if (hasInterceptors) { cw .visitField(ACC_PRIVATE, FIELD_INTERCEPTOR_HANDLER, Type.getDescriptor(InterceptorHandler.class), null, null) .visitEnd(); cw .visitField(ACC_PRIVATE | ACC_STATIC, FIELD_INTERCEPTED_METHODS, Type.getDescriptor(Method[].class), null, null) .visitEnd(); } createConstructor(cw, classToProxy, superClassName, classFileName, Stream.of(classToProxy.getDeclaredConstructors()).filter(c -> { final int modifiers = c.getModifiers(); return Modifier.isPublic(modifiers) || Modifier.isProtected(modifiers); }).sorted((o1, o2) -> { final int mod1 = o1.getModifiers(); final int mod2 = o2.getModifiers(); if (Modifier.isProtected(mod1) && !Modifier.isPublic(mod2)) { return 1; } if (Modifier.isProtected(mod2) && !Modifier.isPublic(mod1)) { return -1; } return o1.getParameterCount() - o2.getParameterCount(); }) .findFirst() .orElseThrow(() -> new IllegalArgumentException( classToProxy + " has no default constructor, put at least a protected one")), hasInterceptors); final Method[] interceptedMethods; if (hasInterceptors) { final Collection<Annotation> globalInterceptors = Stream.of(classToProxy.getAnnotations()).filter(this::isInterceptor).collect(toList()); final AtomicInteger methodIndex = new AtomicInteger(); interceptedMethods = Stream .of(classToProxy.getMethods()) .filter(m -> !"<init>".equals(m.getName()) && (!globalInterceptors.isEmpty() || Stream.of(m.getAnnotations()).anyMatch(this::isInterceptor))) .peek(method -> delegateMethod(cw, method, classFileName, methodIndex.getAndIncrement())) .toArray(Method[]::new); } else { interceptedMethods = null; } final Class<Object> objectClass = Unsafes.defineAndLoadClass(loader, proxyClassName, cw.toByteArray()); if (hasInterceptors) { try { final Field interceptedMethodsField = objectClass.getDeclaredField(FIELD_INTERCEPTED_METHODS); interceptedMethodsField.setAccessible(true); interceptedMethodsField.set(null, interceptedMethods); } catch (final Exception e) { throw new IllegalStateException(e); } } return objectClass; }
ProxyGenerator implements Serializable { public Class<?> generateProxy(final ClassLoader loader, final Class<?> classToProxy, final String plugin, final String key) { final ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES); final String proxyClassName = fixPreservedPackages( (classToProxy.getSigners() != null ? getSignedClassProxyName(classToProxy) : classToProxy.getName()) + "$$TalendServiceProxy"); final String classFileName = proxyClassName.replace('.', '/'); final String[] interfaceNames = { Type.getInternalName(Serializable.class) }; final String superClassName = Type.getInternalName(classToProxy); cw .visit(findJavaVersion(classToProxy), ACC_PUBLIC + ACC_SUPER + ACC_SYNTHETIC, classFileName, null, superClassName, interfaceNames); cw.visitSource(classFileName + ".java", null); if (!Serializable.class.isAssignableFrom(classToProxy)) { try { classToProxy.getMethod("writeReplace"); } catch (final NoSuchMethodException e) { createSerialisation(cw, plugin, key); } } final boolean hasInterceptors = hasInterceptors(classToProxy); if (hasInterceptors) { cw .visitField(ACC_PRIVATE, FIELD_INTERCEPTOR_HANDLER, Type.getDescriptor(InterceptorHandler.class), null, null) .visitEnd(); cw .visitField(ACC_PRIVATE | ACC_STATIC, FIELD_INTERCEPTED_METHODS, Type.getDescriptor(Method[].class), null, null) .visitEnd(); } createConstructor(cw, classToProxy, superClassName, classFileName, Stream.of(classToProxy.getDeclaredConstructors()).filter(c -> { final int modifiers = c.getModifiers(); return Modifier.isPublic(modifiers) || Modifier.isProtected(modifiers); }).sorted((o1, o2) -> { final int mod1 = o1.getModifiers(); final int mod2 = o2.getModifiers(); if (Modifier.isProtected(mod1) && !Modifier.isPublic(mod2)) { return 1; } if (Modifier.isProtected(mod2) && !Modifier.isPublic(mod1)) { return -1; } return o1.getParameterCount() - o2.getParameterCount(); }) .findFirst() .orElseThrow(() -> new IllegalArgumentException( classToProxy + " has no default constructor, put at least a protected one")), hasInterceptors); final Method[] interceptedMethods; if (hasInterceptors) { final Collection<Annotation> globalInterceptors = Stream.of(classToProxy.getAnnotations()).filter(this::isInterceptor).collect(toList()); final AtomicInteger methodIndex = new AtomicInteger(); interceptedMethods = Stream .of(classToProxy.getMethods()) .filter(m -> !"<init>".equals(m.getName()) && (!globalInterceptors.isEmpty() || Stream.of(m.getAnnotations()).anyMatch(this::isInterceptor))) .peek(method -> delegateMethod(cw, method, classFileName, methodIndex.getAndIncrement())) .toArray(Method[]::new); } else { interceptedMethods = null; } final Class<Object> objectClass = Unsafes.defineAndLoadClass(loader, proxyClassName, cw.toByteArray()); if (hasInterceptors) { try { final Field interceptedMethodsField = objectClass.getDeclaredField(FIELD_INTERCEPTED_METHODS); interceptedMethodsField.setAccessible(true); interceptedMethodsField.set(null, interceptedMethods); } catch (final Exception e) { throw new IllegalStateException(e); } } return objectClass; } }
ProxyGenerator implements Serializable { public Class<?> generateProxy(final ClassLoader loader, final Class<?> classToProxy, final String plugin, final String key) { final ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES); final String proxyClassName = fixPreservedPackages( (classToProxy.getSigners() != null ? getSignedClassProxyName(classToProxy) : classToProxy.getName()) + "$$TalendServiceProxy"); final String classFileName = proxyClassName.replace('.', '/'); final String[] interfaceNames = { Type.getInternalName(Serializable.class) }; final String superClassName = Type.getInternalName(classToProxy); cw .visit(findJavaVersion(classToProxy), ACC_PUBLIC + ACC_SUPER + ACC_SYNTHETIC, classFileName, null, superClassName, interfaceNames); cw.visitSource(classFileName + ".java", null); if (!Serializable.class.isAssignableFrom(classToProxy)) { try { classToProxy.getMethod("writeReplace"); } catch (final NoSuchMethodException e) { createSerialisation(cw, plugin, key); } } final boolean hasInterceptors = hasInterceptors(classToProxy); if (hasInterceptors) { cw .visitField(ACC_PRIVATE, FIELD_INTERCEPTOR_HANDLER, Type.getDescriptor(InterceptorHandler.class), null, null) .visitEnd(); cw .visitField(ACC_PRIVATE | ACC_STATIC, FIELD_INTERCEPTED_METHODS, Type.getDescriptor(Method[].class), null, null) .visitEnd(); } createConstructor(cw, classToProxy, superClassName, classFileName, Stream.of(classToProxy.getDeclaredConstructors()).filter(c -> { final int modifiers = c.getModifiers(); return Modifier.isPublic(modifiers) || Modifier.isProtected(modifiers); }).sorted((o1, o2) -> { final int mod1 = o1.getModifiers(); final int mod2 = o2.getModifiers(); if (Modifier.isProtected(mod1) && !Modifier.isPublic(mod2)) { return 1; } if (Modifier.isProtected(mod2) && !Modifier.isPublic(mod1)) { return -1; } return o1.getParameterCount() - o2.getParameterCount(); }) .findFirst() .orElseThrow(() -> new IllegalArgumentException( classToProxy + " has no default constructor, put at least a protected one")), hasInterceptors); final Method[] interceptedMethods; if (hasInterceptors) { final Collection<Annotation> globalInterceptors = Stream.of(classToProxy.getAnnotations()).filter(this::isInterceptor).collect(toList()); final AtomicInteger methodIndex = new AtomicInteger(); interceptedMethods = Stream .of(classToProxy.getMethods()) .filter(m -> !"<init>".equals(m.getName()) && (!globalInterceptors.isEmpty() || Stream.of(m.getAnnotations()).anyMatch(this::isInterceptor))) .peek(method -> delegateMethod(cw, method, classFileName, methodIndex.getAndIncrement())) .toArray(Method[]::new); } else { interceptedMethods = null; } final Class<Object> objectClass = Unsafes.defineAndLoadClass(loader, proxyClassName, cw.toByteArray()); if (hasInterceptors) { try { final Field interceptedMethodsField = objectClass.getDeclaredField(FIELD_INTERCEPTED_METHODS); interceptedMethodsField.setAccessible(true); interceptedMethodsField.set(null, interceptedMethods); } catch (final Exception e) { throw new IllegalStateException(e); } } return objectClass; } ProxyGenerator(); }
ProxyGenerator implements Serializable { public Class<?> generateProxy(final ClassLoader loader, final Class<?> classToProxy, final String plugin, final String key) { final ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES); final String proxyClassName = fixPreservedPackages( (classToProxy.getSigners() != null ? getSignedClassProxyName(classToProxy) : classToProxy.getName()) + "$$TalendServiceProxy"); final String classFileName = proxyClassName.replace('.', '/'); final String[] interfaceNames = { Type.getInternalName(Serializable.class) }; final String superClassName = Type.getInternalName(classToProxy); cw .visit(findJavaVersion(classToProxy), ACC_PUBLIC + ACC_SUPER + ACC_SYNTHETIC, classFileName, null, superClassName, interfaceNames); cw.visitSource(classFileName + ".java", null); if (!Serializable.class.isAssignableFrom(classToProxy)) { try { classToProxy.getMethod("writeReplace"); } catch (final NoSuchMethodException e) { createSerialisation(cw, plugin, key); } } final boolean hasInterceptors = hasInterceptors(classToProxy); if (hasInterceptors) { cw .visitField(ACC_PRIVATE, FIELD_INTERCEPTOR_HANDLER, Type.getDescriptor(InterceptorHandler.class), null, null) .visitEnd(); cw .visitField(ACC_PRIVATE | ACC_STATIC, FIELD_INTERCEPTED_METHODS, Type.getDescriptor(Method[].class), null, null) .visitEnd(); } createConstructor(cw, classToProxy, superClassName, classFileName, Stream.of(classToProxy.getDeclaredConstructors()).filter(c -> { final int modifiers = c.getModifiers(); return Modifier.isPublic(modifiers) || Modifier.isProtected(modifiers); }).sorted((o1, o2) -> { final int mod1 = o1.getModifiers(); final int mod2 = o2.getModifiers(); if (Modifier.isProtected(mod1) && !Modifier.isPublic(mod2)) { return 1; } if (Modifier.isProtected(mod2) && !Modifier.isPublic(mod1)) { return -1; } return o1.getParameterCount() - o2.getParameterCount(); }) .findFirst() .orElseThrow(() -> new IllegalArgumentException( classToProxy + " has no default constructor, put at least a protected one")), hasInterceptors); final Method[] interceptedMethods; if (hasInterceptors) { final Collection<Annotation> globalInterceptors = Stream.of(classToProxy.getAnnotations()).filter(this::isInterceptor).collect(toList()); final AtomicInteger methodIndex = new AtomicInteger(); interceptedMethods = Stream .of(classToProxy.getMethods()) .filter(m -> !"<init>".equals(m.getName()) && (!globalInterceptors.isEmpty() || Stream.of(m.getAnnotations()).anyMatch(this::isInterceptor))) .peek(method -> delegateMethod(cw, method, classFileName, methodIndex.getAndIncrement())) .toArray(Method[]::new); } else { interceptedMethods = null; } final Class<Object> objectClass = Unsafes.defineAndLoadClass(loader, proxyClassName, cw.toByteArray()); if (hasInterceptors) { try { final Field interceptedMethodsField = objectClass.getDeclaredField(FIELD_INTERCEPTED_METHODS); interceptedMethodsField.setAccessible(true); interceptedMethodsField.set(null, interceptedMethods); } catch (final Exception e) { throw new IllegalStateException(e); } } return objectClass; } ProxyGenerator(); boolean hasInterceptors(final Class<?> type); boolean isSerializable(final Class<?> type); Class<?> generateProxy(final ClassLoader loader, final Class<?> classToProxy, final String plugin,
            final String key); void initialize(final Object proxy, final InterceptorHandler handler); InterceptorHandlerFacade getHandler(final Object instance); }
ProxyGenerator implements Serializable { public Class<?> generateProxy(final ClassLoader loader, final Class<?> classToProxy, final String plugin, final String key) { final ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES); final String proxyClassName = fixPreservedPackages( (classToProxy.getSigners() != null ? getSignedClassProxyName(classToProxy) : classToProxy.getName()) + "$$TalendServiceProxy"); final String classFileName = proxyClassName.replace('.', '/'); final String[] interfaceNames = { Type.getInternalName(Serializable.class) }; final String superClassName = Type.getInternalName(classToProxy); cw .visit(findJavaVersion(classToProxy), ACC_PUBLIC + ACC_SUPER + ACC_SYNTHETIC, classFileName, null, superClassName, interfaceNames); cw.visitSource(classFileName + ".java", null); if (!Serializable.class.isAssignableFrom(classToProxy)) { try { classToProxy.getMethod("writeReplace"); } catch (final NoSuchMethodException e) { createSerialisation(cw, plugin, key); } } final boolean hasInterceptors = hasInterceptors(classToProxy); if (hasInterceptors) { cw .visitField(ACC_PRIVATE, FIELD_INTERCEPTOR_HANDLER, Type.getDescriptor(InterceptorHandler.class), null, null) .visitEnd(); cw .visitField(ACC_PRIVATE | ACC_STATIC, FIELD_INTERCEPTED_METHODS, Type.getDescriptor(Method[].class), null, null) .visitEnd(); } createConstructor(cw, classToProxy, superClassName, classFileName, Stream.of(classToProxy.getDeclaredConstructors()).filter(c -> { final int modifiers = c.getModifiers(); return Modifier.isPublic(modifiers) || Modifier.isProtected(modifiers); }).sorted((o1, o2) -> { final int mod1 = o1.getModifiers(); final int mod2 = o2.getModifiers(); if (Modifier.isProtected(mod1) && !Modifier.isPublic(mod2)) { return 1; } if (Modifier.isProtected(mod2) && !Modifier.isPublic(mod1)) { return -1; } return o1.getParameterCount() - o2.getParameterCount(); }) .findFirst() .orElseThrow(() -> new IllegalArgumentException( classToProxy + " has no default constructor, put at least a protected one")), hasInterceptors); final Method[] interceptedMethods; if (hasInterceptors) { final Collection<Annotation> globalInterceptors = Stream.of(classToProxy.getAnnotations()).filter(this::isInterceptor).collect(toList()); final AtomicInteger methodIndex = new AtomicInteger(); interceptedMethods = Stream .of(classToProxy.getMethods()) .filter(m -> !"<init>".equals(m.getName()) && (!globalInterceptors.isEmpty() || Stream.of(m.getAnnotations()).anyMatch(this::isInterceptor))) .peek(method -> delegateMethod(cw, method, classFileName, methodIndex.getAndIncrement())) .toArray(Method[]::new); } else { interceptedMethods = null; } final Class<Object> objectClass = Unsafes.defineAndLoadClass(loader, proxyClassName, cw.toByteArray()); if (hasInterceptors) { try { final Field interceptedMethodsField = objectClass.getDeclaredField(FIELD_INTERCEPTED_METHODS); interceptedMethodsField.setAccessible(true); interceptedMethodsField.set(null, interceptedMethods); } catch (final Exception e) { throw new IllegalStateException(e); } } return objectClass; } ProxyGenerator(); boolean hasInterceptors(final Class<?> type); boolean isSerializable(final Class<?> type); Class<?> generateProxy(final ClassLoader loader, final Class<?> classToProxy, final String plugin,
            final String key); void initialize(final Object proxy, final InterceptorHandler handler); InterceptorHandlerFacade getHandler(final Object instance);  }