/* * Copyright 2015 Odnoklassniki Ltd, Mail.Ru Group * * 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 one.nio.serial; import one.nio.gen.BytecodeGenerator; import java.io.IOException; import java.io.ObjectInput; import java.io.ObjectOutput; import java.util.concurrent.atomic.AtomicInteger; public class TypeDescriptor { private static final Class[] PRIMITIVE_CLASSES = { int.class, // 0 long.class, // 1 boolean.class, // 2 byte.class, // 3 short.class, // 4 char.class, // 5 float.class, // 6 double.class, // 7 void.class // 8 }; static final AtomicInteger unknownTypes = new AtomicInteger(); private Class cls; private String descriptor; TypeDescriptor(Class cls) { this.cls = cls; this.descriptor = classDescriptor(cls); } TypeDescriptor(String descriptor) { this.descriptor = descriptor; } @Override public String toString() { return descriptor; } public static TypeDescriptor read(ObjectInput in) throws IOException { int primitiveIndex = in.readByte(); if (primitiveIndex >= 0) { return new TypeDescriptor(PRIMITIVE_CLASSES[primitiveIndex]); } else { return new TypeDescriptor(in.readUTF()); } } public void write(ObjectOutput out) throws IOException { if (cls != null && cls.isPrimitive()) { writeClass(out, cls); } else { out.writeByte(-1); out.writeUTF(descriptor); } } public Class resolve() { if (cls == null) { try { cls = resolve(descriptor); } catch (ClassNotFoundException e) { Repository.log.warn("Local type not found: " + descriptor); unknownTypes.incrementAndGet(); cls = Object.class; } } return cls; } public static Class<?> resolve(String descriptor) throws ClassNotFoundException { int p = descriptor.indexOf('|'); if (p >= 0) { try { return Class.forName(descriptor.substring(0, p), true, BytecodeGenerator.INSTANCE); } catch (ClassNotFoundException e) { // New class is missed, try old name descriptor = descriptor.substring(p + 1); } } Class renamedClass = Repository.renamedClasses.get(descriptor); return renamedClass != null ? renamedClass : Class.forName(descriptor, true, BytecodeGenerator.INSTANCE); } public static String classDescriptor(Class<?> cls) { Renamed renamed = cls.getAnnotation(Renamed.class); return renamed == null ? cls.getName() : cls.getName() + '|' + renamed.from(); } public static Class<?> readClass(ObjectInput in) throws IOException, ClassNotFoundException { int index = in.readByte(); if (index >= 0) { return PRIMITIVE_CLASSES[index]; } else { return resolve(in.readUTF()); } } public static void writeClass(ObjectOutput out, Class<?> cls) throws IOException { if (cls.isPrimitive()) { for (int i = 0; i < PRIMITIVE_CLASSES.length; i++) { if (cls == PRIMITIVE_CLASSES[i]) { out.writeByte(i); return; } } } out.writeByte(-1); out.writeUTF(classDescriptor(cls)); } }