All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jboss.marshalling.AbstractClassResolver Maven / Gradle / Ivy

/*
 * 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 java.io.IOException;
import java.io.StreamCorruptedException;
import java.lang.reflect.Proxy;
import java.security.AccessController;
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 {
        registry = AccessController.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;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy