/* * Copyright (c) 2008-2017, Hazelcast, Inc. All Rights Reserved. * * 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 com.hazelcast.internal.usercodedeployment.impl; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; /** * Classloader created on a local member to define a class from a bytecode loaded from a remote source. * * We use a classloader per each class loaded from a remote source as it allows us to discard the classloader * and reload the class via another classloader as we see fit. * * Delegation model: * 1. When the request matches the specific classname then it will provide the class on its own * 2. Then it delegates to the parent classloader - that's usually a regular classloader loading classes * from a local classpath only * 3. Finally it delegates to {@link ClassLocator} which may initiate a remote lookup */ public final class ClassSource extends ClassLoader { private final byte[] bytecode; private final ClassLocator classLocator; private Class clazz; private final String name; @SuppressFBWarnings({"MS_EXPOSE_REP", "EI_EXPOSE_REP"}) public ClassSource(String classname, byte[] bytecode, ClassLoader parent, ClassLocator classLocator) { super(parent); this.bytecode = bytecode; this.name = classname; this.classLocator = classLocator; } public Class<?> define() { clazz = defineClass(name, bytecode, 0, bytecode.length); return clazz; } @Override protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException { if (name.equals(this.name)) { return clazz; } try { return super.loadClass(name, resolve); } catch (ClassNotFoundException e) { return classLocator.handleClassNotFoundException(name); } } @SuppressFBWarnings({"MS_EXPOSE_REP", "EI_EXPOSE_REP"}) public byte[] getBytecode() { return bytecode; } public Class getClazz() { return clazz; } }