/*
* Copyright 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.gradle.tooling.internal.provider.serialization;
import org.gradle.internal.serialize.ExceptionReplacingObjectInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectStreamClass;
import java.lang.reflect.Proxy;
import java.util.Map;
import static org.gradle.tooling.internal.provider.serialization.PayloadSerializerObjectOutputStream.SAME_CLASSLOADER_TOKEN;
class PayloadSerializerObjectInputStream extends ExceptionReplacingObjectInputStream {
private final Map<Short, ClassLoaderDetails> classLoaderDetails;
private final DeserializeMap map;
public PayloadSerializerObjectInputStream(InputStream inputStream, ClassLoader classLoader, Map<Short, ClassLoaderDetails> classLoaderDetails, DeserializeMap map) throws IOException {
super(inputStream, classLoader);
this.classLoaderDetails = classLoaderDetails;
this.map = map;
}
@Override
protected ExceptionReplacingObjectInputStream createNewInstance(InputStream inputStream) throws IOException {
return new PayloadSerializerObjectInputStream(inputStream, getClassLoader(), classLoaderDetails, map);
}
@Override
protected ObjectStreamClass readClassDescriptor() throws IOException, ClassNotFoundException {
Class<?> aClass = readClass();
ObjectStreamClass descriptor = ObjectStreamClass.lookupAny(aClass);
if (descriptor == null) {
throw new ClassNotFoundException(aClass.getName());
}
return descriptor;
}
@Override
protected Class<?> resolveClass(ObjectStreamClass desc) throws IOException, ClassNotFoundException {
return desc.forClass();
}
private Class<?> readClass() throws IOException, ClassNotFoundException {
short id = readShort();
String className = readUTF();
if (id == SAME_CLASSLOADER_TOKEN) {
return super.lookupClass(className);
}
ClassLoaderDetails classLoader = classLoaderDetails.get(id);
return map.resolveClass(classLoader, className);
}
@Override
protected Class<?> resolveProxyClass(String[] interfaces) throws IOException, ClassNotFoundException {
int count = readInt();
Class<?>[] actualInterfaces = new Class<?>[count];
for (int i = 0; i < count; i++) {
actualInterfaces[i] = readClass();
}
return Proxy.getProxyClass(actualInterfaces[0].getClassLoader(), actualInterfaces);
}
@Override
protected Class<?> lookupClass(String type) throws ClassNotFoundException {
try {
return super.lookupClass(type);
} catch (ClassNotFoundException e) {
// lookup class in all classloaders
for (ClassLoaderDetails details : classLoaderDetails.values()) {
try {
return map.resolveClass(details, type);
} catch (ClassNotFoundException ignored) {
// ignore
}
}
throw e;
}
}
}