org.jboss.marshalling.AbstractClassResolver Maven / Gradle / Ivy
Go to download
This artifact provides a single jar that contains all classes required to use remote EJB and JMS, including
all dependencies. It is intended for use by those not using maven, maven users should just import the EJB and
JMS BOM's instead (shaded JAR's cause lots of problems with maven, as it is very easy to inadvertently end up
with different versions on classes on the class path).
/*
* JBoss, Home of Professional Open Source.
* Copyright 2014 Red Hat, Inc., and individual contributors
* as indicated by the @author tags.
*
* 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 org.jboss.marshalling;
import static java.lang.System.getSecurityManager;
import static java.security.AccessController.doPrivileged;
import java.io.IOException;
import java.io.StreamCorruptedException;
import java.lang.reflect.Proxy;
import java.security.PrivilegedAction;
import java.util.Map;
import java.util.HashMap;
import org.jboss.marshalling.reflect.SerializableClassRegistry;
/**
* A base implementation of {@code ClassResolver} which simply resolves the class
* against a classloader which is specified by the subclass implementation.
*/
public abstract class AbstractClassResolver implements ClassResolver {
/**
* Specifies whether an exception should be thrown on an incorrect serialVersionUID.
*/
protected final boolean enforceSerialVersionUid;
private static final SerializableClassRegistry registry;
static {
if (getSecurityManager() == null) {
registry = SerializableClassRegistry.getInstance();
} else {
registry = doPrivileged(new PrivilegedAction() {
public SerializableClassRegistry run() {
return SerializableClassRegistry.getInstance();
}
});
}
}
/**
* Construct a new instance.
*/
protected AbstractClassResolver() {
this(false);
}
/**
* Construct a new instance.
*
* @param enforceSerialVersionUid {@code true} if an exception should be thrown on an incorrect serialVersionUID
*/
protected AbstractClassResolver(final boolean enforceSerialVersionUid) {
this.enforceSerialVersionUid = enforceSerialVersionUid;
}
/**
* Get the classloader to use to resolve classes for this resolver.
*
* @return the classloader
*/
protected abstract ClassLoader getClassLoader();
/** {@inheritDoc} The base implementation takes no action. */
public void annotateClass(final Marshaller marshaller, final Class> clazz) throws IOException {
// no operation
}
/** {@inheritDoc} The base implementation takes no action. */
public void annotateProxyClass(final Marshaller marshaller, final Class> proxyClass) throws IOException {
// no operation
}
/** {@inheritDoc} The base implementation returns the name of the class. */
public String getClassName(final Class> clazz) throws IOException {
return clazz.getName();
}
/** {@inheritDoc} The base implementation returns the name of each interface (via {@link #getClassName(Class) getClassName()} implemented by the given class. */
public String[] getProxyInterfaces(final Class> proxyClass) throws IOException {
final Class>[] interfaces = proxyClass.getInterfaces();
final String[] names = new String[interfaces.length];
for (int i = 0; i < interfaces.length; i++) {
names[i] = getClassName(interfaces[i]);
}
return names;
}
/**
* {@inheritDoc} The base implementation uses the class loader returned from {@code getClassLoader()} and
* loads the class by name.
*/
public Class> resolveClass(final Unmarshaller unmarshaller, final String name, final long serialVersionUID) throws IOException, ClassNotFoundException {
final Class> clazz = loadClass(name);
if (enforceSerialVersionUid && serialVersionUID != 0L) {
final long uid = registry.lookup(clazz).getEffectiveSerialVersionUID();
if (uid != serialVersionUID) {
throw new StreamCorruptedException("serialVersionUID does not match!");
}
}
return clazz;
}
/**
* Load a class with the given name. The base implementation uses the classloader returned from {@link #getClassLoader()}.
*
* @param name the name of the class
* @return the class
* @throws ClassNotFoundException if the class is not found, or if there is no classloader
*/
protected Class> loadClass(final String name) throws ClassNotFoundException {
final Class> prim = primitives.get(name);
return prim != null ? prim : Class.forName(name, false, getClassLoader());
}
/**
* {@inheritDoc} The base implementation uses the class loader returned from {@code getClassLoader()} and loads
* each interface by name, returning a proxy class from that class loader.
*/
public Class> resolveProxyClass(final Unmarshaller unmarshaller, final String[] interfaces) throws IOException, ClassNotFoundException {
final ClassLoader classLoader = getClassLoader();
final int length = interfaces.length;
Class>[] classes = new Class>[length];
for (int i = 0; i < length; i ++) {
classes[i] = loadClass(interfaces[i]);
}
return Proxy.getProxyClass(classLoader, classes);
}
private static final Map> primitives;
static {
final Map> map = new HashMap>();
map.put("void", void.class);
map.put("byte", byte.class);
map.put("short", short.class);
map.put("int", int.class);
map.put("long", long.class);
map.put("char", char.class);
map.put("boolean", boolean.class);
map.put("float", float.class);
map.put("double", double.class);
primitives = map;
}
}