/*
 * Copyright 2002-2016 the original author or authors.
 *
 * 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.springframework.core;

import java.io.IOException;
import java.io.InputStream;
import java.io.NotSerializableException;
import java.io.ObjectInputStream;
import java.io.ObjectStreamClass;

import org.springframework.lang.Nullable;
import org.springframework.util.ClassUtils;

Special ObjectInputStream subclass that resolves class names against a specific ClassLoader. Serves as base class for CodebaseAwareObjectInputStream.
Author:Juergen Hoeller
Since:2.5.5
/** * Special ObjectInputStream subclass that resolves class names * against a specific ClassLoader. Serves as base class for * {@link org.springframework.remoting.rmi.CodebaseAwareObjectInputStream}. * * @author Juergen Hoeller * @since 2.5.5 */
public class ConfigurableObjectInputStream extends ObjectInputStream { @Nullable private final ClassLoader classLoader; private final boolean acceptProxyClasses;
Create a new ConfigurableObjectInputStream for the given InputStream and ClassLoader.
Params:
  • in – the InputStream to read from
  • classLoader – the ClassLoader to use for loading local classes
See Also:
/** * Create a new ConfigurableObjectInputStream for the given InputStream and ClassLoader. * @param in the InputStream to read from * @param classLoader the ClassLoader to use for loading local classes * @see java.io.ObjectInputStream#ObjectInputStream(java.io.InputStream) */
public ConfigurableObjectInputStream(InputStream in, @Nullable ClassLoader classLoader) throws IOException { this(in, classLoader, true); }
Create a new ConfigurableObjectInputStream for the given InputStream and ClassLoader.
Params:
  • in – the InputStream to read from
  • classLoader – the ClassLoader to use for loading local classes
  • acceptProxyClasses – whether to accept deserialization of proxy classes (may be deactivated as a security measure)
See Also:
/** * Create a new ConfigurableObjectInputStream for the given InputStream and ClassLoader. * @param in the InputStream to read from * @param classLoader the ClassLoader to use for loading local classes * @param acceptProxyClasses whether to accept deserialization of proxy classes * (may be deactivated as a security measure) * @see java.io.ObjectInputStream#ObjectInputStream(java.io.InputStream) */
public ConfigurableObjectInputStream( InputStream in, @Nullable ClassLoader classLoader, boolean acceptProxyClasses) throws IOException { super(in); this.classLoader = classLoader; this.acceptProxyClasses = acceptProxyClasses; } @Override protected Class<?> resolveClass(ObjectStreamClass classDesc) throws IOException, ClassNotFoundException { try { if (this.classLoader != null) { // Use the specified ClassLoader to resolve local classes. return ClassUtils.forName(classDesc.getName(), this.classLoader); } else { // Use the default ClassLoader... return super.resolveClass(classDesc); } } catch (ClassNotFoundException ex) { return resolveFallbackIfPossible(classDesc.getName(), ex); } } @Override protected Class<?> resolveProxyClass(String[] interfaces) throws IOException, ClassNotFoundException { if (!this.acceptProxyClasses) { throw new NotSerializableException("Not allowed to accept serialized proxy classes"); } if (this.classLoader != null) { // Use the specified ClassLoader to resolve local proxy classes. Class<?>[] resolvedInterfaces = new Class<?>[interfaces.length]; for (int i = 0; i < interfaces.length; i++) { try { resolvedInterfaces[i] = ClassUtils.forName(interfaces[i], this.classLoader); } catch (ClassNotFoundException ex) { resolvedInterfaces[i] = resolveFallbackIfPossible(interfaces[i], ex); } } try { return ClassUtils.createCompositeInterface(resolvedInterfaces, this.classLoader); } catch (IllegalArgumentException ex) { throw new ClassNotFoundException(null, ex); } } else { // Use ObjectInputStream's default ClassLoader... try { return super.resolveProxyClass(interfaces); } catch (ClassNotFoundException ex) { Class<?>[] resolvedInterfaces = new Class<?>[interfaces.length]; for (int i = 0; i < interfaces.length; i++) { resolvedInterfaces[i] = resolveFallbackIfPossible(interfaces[i], ex); } return ClassUtils.createCompositeInterface(resolvedInterfaces, getFallbackClassLoader()); } } }
Resolve the given class name against a fallback class loader.

The default implementation simply rethrows the original exception, since there is no fallback available.

Params:
  • className – the class name to resolve
  • ex – the original exception thrown when attempting to load the class
Returns:the newly resolved class (never null)
/** * Resolve the given class name against a fallback class loader. * <p>The default implementation simply rethrows the original exception, * since there is no fallback available. * @param className the class name to resolve * @param ex the original exception thrown when attempting to load the class * @return the newly resolved class (never {@code null}) */
protected Class<?> resolveFallbackIfPossible(String className, ClassNotFoundException ex) throws IOException, ClassNotFoundException{ throw ex; }
Return the fallback ClassLoader to use when no ClassLoader was specified and ObjectInputStream's own default class loader failed.

The default implementation simply returns null, indicating that no specific fallback is available.

/** * Return the fallback ClassLoader to use when no ClassLoader was specified * and ObjectInputStream's own default class loader failed. * <p>The default implementation simply returns {@code null}, indicating * that no specific fallback is available. */
@Nullable protected ClassLoader getFallbackClassLoader() throws IOException { return null; } }