You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by da...@apache.org on 2016/02/08 18:23:55 UTC
[5/6] camel git commit: CAMEL-9576: fix deserializing proxies with
mixed JDK & non-JDK interfaces
CAMEL-9576: fix deserializing proxies with mixed JDK & non-JDK interfaces
Project: http://git-wip-us.apache.org/repos/asf/camel/repo
Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/148cac17
Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/148cac17
Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/148cac17
Branch: refs/heads/camel-2.15.x
Commit: 148cac176a8a9180a901bb797a84d975e8edaf4c
Parents: 66801bf
Author: Lien Deboosere <le...@melexis.com>
Authored: Mon Feb 8 15:29:47 2016 +0100
Committer: Claus Ibsen <da...@apache.org>
Committed: Mon Feb 8 18:23:35 2016 +0100
----------------------------------------------------------------------
.../ClassLoadingAwareObjectInputStream.java | 71 +++++++++++++--
.../ClassLoadingAwareObjectInputStreamTest.java | 93 ++++++++++++++++++++
2 files changed, 157 insertions(+), 7 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/camel/blob/148cac17/components/camel-sql/src/main/java/org/apache/camel/processor/aggregate/jdbc/ClassLoadingAwareObjectInputStream.java
----------------------------------------------------------------------
diff --git a/components/camel-sql/src/main/java/org/apache/camel/processor/aggregate/jdbc/ClassLoadingAwareObjectInputStream.java b/components/camel-sql/src/main/java/org/apache/camel/processor/aggregate/jdbc/ClassLoadingAwareObjectInputStream.java
index 12535f3..80a1278 100644
--- a/components/camel-sql/src/main/java/org/apache/camel/processor/aggregate/jdbc/ClassLoadingAwareObjectInputStream.java
+++ b/components/camel-sql/src/main/java/org/apache/camel/processor/aggregate/jdbc/ClassLoadingAwareObjectInputStream.java
@@ -21,38 +21,95 @@ import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectStreamClass;
import java.lang.reflect.Proxy;
+import java.util.HashMap;
import org.apache.camel.CamelContext;
/**
* This class is copied from the Apache ActiveMQ project.
*/
+@SuppressWarnings("rawtypes")
public class ClassLoadingAwareObjectInputStream extends ObjectInputStream {
private CamelContext camelContext;
+ private static final ClassLoader FALLBACK_CLASS_LOADER =
+ ClassLoadingAwareObjectInputStream.class.getClassLoader();
+
+ /**
+ * Maps primitive type names to corresponding class objects.
+ */
+ private static final HashMap<String, Class> primClasses = new HashMap<String, Class>(8, 1.0F);
+
+ private final ClassLoader inLoader;
+
+ public ClassLoadingAwareObjectInputStream(InputStream in) throws IOException {
+ super(in);
+ inLoader = in.getClass().getClassLoader();
+ }
+
public ClassLoadingAwareObjectInputStream(CamelContext camelContext, InputStream in) throws IOException {
super(in);
- this.camelContext = camelContext;
+ inLoader = camelContext.getApplicationContextClassLoader();
}
- @Override
+
protected Class<?> resolveClass(ObjectStreamClass classDesc) throws IOException, ClassNotFoundException {
- return camelContext.getClassResolver().resolveClass(classDesc.getName());
+ ClassLoader cl = Thread.currentThread().getContextClassLoader();
+ return load(classDesc.getName(), cl, inLoader);
}
- @Override
protected Class<?> resolveProxyClass(String[] interfaces) throws IOException, ClassNotFoundException {
- Class<?>[] cinterfaces = new Class[interfaces.length];
+ ClassLoader cl = Thread.currentThread().getContextClassLoader();
+ Class[] cinterfaces = new Class[interfaces.length];
for (int i = 0; i < interfaces.length; i++) {
- cinterfaces[i] = camelContext.getClassResolver().resolveClass(interfaces[i]);
+ cinterfaces[i] = load(interfaces[i], cl);
}
try {
- return Proxy.getProxyClass(cinterfaces[0].getClassLoader(), cinterfaces);
+ return Proxy.getProxyClass(cl, cinterfaces);
} catch (IllegalArgumentException e) {
+ try {
+ return Proxy.getProxyClass(inLoader, cinterfaces);
+ } catch (IllegalArgumentException e1) {
+ // ignore
+ }
+ try {
+ return Proxy.getProxyClass(FALLBACK_CLASS_LOADER, cinterfaces);
+ } catch (IllegalArgumentException e2) {
+ // ignore
+ }
+
throw new ClassNotFoundException(null, e);
}
}
+ private Class<?> load(String className, ClassLoader... cl) throws ClassNotFoundException {
+ for (ClassLoader loader : cl) {
+ try {
+ return Class.forName(className, false, loader);
+ } catch (ClassNotFoundException e) {
+ // ignore
+ }
+ }
+ // fallback
+ final Class<?> clazz = (Class<?>) primClasses.get(className);
+ if (clazz != null) {
+ return clazz;
+ } else {
+ return Class.forName(className, false, FALLBACK_CLASS_LOADER);
+ }
+ }
+
+ static {
+ primClasses.put("boolean", boolean.class);
+ primClasses.put("byte", byte.class);
+ primClasses.put("char", char.class);
+ primClasses.put("short", short.class);
+ primClasses.put("int", int.class);
+ primClasses.put("long", long.class);
+ primClasses.put("float", float.class);
+ primClasses.put("double", double.class);
+ primClasses.put("void", void.class);
+ }
}
http://git-wip-us.apache.org/repos/asf/camel/blob/148cac17/components/camel-sql/src/test/java/org/apache/camel/processor/aggregate/jdbc/ClassLoadingAwareObjectInputStreamTest.java
----------------------------------------------------------------------
diff --git a/components/camel-sql/src/test/java/org/apache/camel/processor/aggregate/jdbc/ClassLoadingAwareObjectInputStreamTest.java b/components/camel-sql/src/test/java/org/apache/camel/processor/aggregate/jdbc/ClassLoadingAwareObjectInputStreamTest.java
new file mode 100644
index 0000000..e0695ac
--- /dev/null
+++ b/components/camel-sql/src/test/java/org/apache/camel/processor/aggregate/jdbc/ClassLoadingAwareObjectInputStreamTest.java
@@ -0,0 +1,93 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.camel.processor.aggregate.jdbc;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.impl.DefaultCamelContext;
+import org.apache.camel.impl.DefaultExchange;
+import org.apache.camel.impl.DefaultExchangeHolder;
+import org.junit.Test;
+
+import java.io.*;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import static junit.framework.Assert.assertEquals;
+
+public class ClassLoadingAwareObjectInputStreamTest {
+
+ @Test
+ public void deserialize() throws IOException, ClassNotFoundException {
+ CamelContext context = new DefaultCamelContext();
+
+ final DefaultExchange exchange = new DefaultExchange(context);
+
+ final List<MyObject> objects = new ArrayList<>();
+ final MyObject o = new MyObject("leb", "hello".getBytes());
+ objects.add(o);
+
+ exchange.getIn().setBody(objects);
+ final DefaultExchangeHolder deh = DefaultExchangeHolder.marshal(exchange);
+
+ final ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ final ObjectOutputStream oos = new ObjectOutputStream(baos);
+ oos.writeObject(deh);
+ oos.flush();
+ final byte[] serialized = baos.toByteArray();
+
+ final ObjectInputStream bis = new ClassLoadingAwareObjectInputStream(context, new ByteArrayInputStream(serialized));
+ final DefaultExchangeHolder deserialized = (DefaultExchangeHolder) bis.readObject();
+
+ final DefaultExchange exchange2 = new DefaultExchange(context);
+ DefaultExchangeHolder.unmarshal(exchange2, deserialized);
+
+ List<MyObject> receivedObjects = exchange2.getIn().getBody(List.class);
+ assertEquals(1, receivedObjects.size());
+ assertEquals(o, receivedObjects.get(0));
+ }
+
+}
+
+
+class MyObject implements Serializable {
+ final String name;
+ final byte[] content;
+
+ public MyObject(String name, byte[] content) {
+ this.name = name;
+ this.content = content;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ MyObject myObject = (MyObject) o;
+
+ if (name != null ? !name.equals(myObject.name) : myObject.name != null) return false;
+ return Arrays.equals(content, myObject.content);
+ }
+
+ @Override
+ public int hashCode() {
+ int result = name != null ? name.hashCode() : 0;
+ result = 31 * result + Arrays.hashCode(content);
+ return result;
+ }
+}