Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

Code Block
languagejava
public class ClassLoaderPessimisticCodec implements ClassLoaderCodec {

    private static final byte FRAMEWORK_CLASS_LOADER_ID = 0;
    private static final byte IGNITE_CLASS_LOADER_ID = 1;
    private static final byte BOOT_CLASS_LOADER_ID = 2;
    private static final byte BUNDLE_CLASS_LOADER_ID = 4;

    private static final ClassLoader FRAMEWOR_CLASS_LOADER = Bundle.class.getClassLoader();


    private final PackageAdmin packageAdmin;

    public ClassLoaderPessimisticCodec(PackageAdmin packageAdmin) {
        this.packageAdmin = packageAdmin;
    }

    @Nullable
    @Override
    public Object encodeClassLoader(Class<?> cls) throws IgniteException {
        ClassLoader classLoader = cls.getClassLoader();

        if (isIgniteClass(classLoader)) {
            return ClassLoaderDesc.newIgniteClassLoaderDesc();
        }

        if (isFrameworkClassLoader(cls.getClassLoader())) {
            return ClassLoaderDesc.newFrameworkClassLoader();
        }
        Bundle bundle = FrameworkUtil.getBundle(cls);

        if (bundle != null) {
            return ClassLoaderDesc.newBundleClassLoaderDesc(bundle);
        }

        return ClassLoaderDesc.newBootClassLoader();
    }

    @Override
    public ClassLoader decodeClassLoader(String fqn, ClassLoader clsLdr, @Nullable Object encodedClsLdr)
            throws IgniteException {
        ClassLoaderDesc classLoaderDesc = (ClassLoaderDesc) encodedClsLdr;
        switch (classLoaderDesc.classLoaderId) {
            case BOOT_CLASS_LOADER_ID:
                return clsLdr;
            case FRAMEWORK_CLASS_LOADER_ID:
                return FRAMEWOR_CLASS_LOADER;
            case IGNITE_CLASS_LOADER_ID:
                return ClassLoaderCodec.class.getClassLoader();
            case BUNDLE_CLASS_LOADER_ID:
                //strict version but we can think about an different strategy here like minor or micro version range
                Bundle[] bundles = packageAdmin.getBundles(classLoaderDesc.bsn, classLoaderDesc.version);
                if (bundles == null) {
                    throw new IgniteException("No bundle found: " + classLoaderDesc.bsn + ":" + classLoaderDesc.version);
                }

                try {
                    //highest ranking bundle
                    return bundles[0].loadClass(fqn).getClassLoader();
                } catch (ClassNotFoundException e) {
                    throw new IgniteException(e);
                }
            default:
                throw new IgniteException("Unsupported class loader description type: " + classLoaderDesc.classLoaderId);
        }
    }

    static final class ClassLoaderDesc implements Externalizable {

        private String version;
        private String bsn;
        private byte classLoaderId;

        public ClassLoaderDesc() {}
        
        public ClassLoaderDesc(byte classLoaderId) {
            this.classLoaderId = classLoaderId;
        }

        public ClassLoaderDesc(Bundle bundle) {
            this.classLoaderId = BUNDLE_CLASS_LOADER_ID;
            this.bsn = bundle.getSymbolicName();
            this.version = bundle.getVersion().toString();
        }

        @Override
        public void writeExternal(ObjectOutput out) throws IOException {
            out.write(classLoaderId);
            if (classLoaderId == BUNDLE_CLASS_LOADER_ID) {
                out.writeUTF(bsn);
                //can be optimized
                out.writeUTF(version);
            }
        }

        @Override
        public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
            classLoaderId = in.readByte();
            if (classLoaderId == BUNDLE_CLASS_LOADER_ID) {

            }
        }

        static ClassLoaderDesc newIgniteClassLoaderDesc() {
            return new ClassLoaderDesc(IGNITE_CLASS_LOADER_ID);
        }

        public static ClassLoaderDesc newBundleClassLoaderDesc(Bundle bundle) {
            return new ClassLoaderDesc(bundle);
        }

        public static ClassLoaderDesc newFrameworkClassLoader() {
            return new ClassLoaderDesc(FRAMEWORK_CLASS_LOADER_ID);
        }

        public static ClassLoaderDesc newBootClassLoader() {
            return new ClassLoaderDesc(BOOT_CLASS_LOADER_ID);
        }
    }
}

...

Warning

It seems to be more interesting to get the ClassLoader clsLdr as a parameter of the decode method instead of the encode one.

 

Optimistic codec

In this strategy we start with a more strict assumption: We will never serialized a