/*
* 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 com.hazelcast.config.UserCodeDeploymentConfig;
import com.hazelcast.logging.ILogger;
import com.hazelcast.nio.IOUtil;
import java.io.IOException;
import java.io.InputStream;
import java.util.concurrent.ConcurrentMap;
import static com.hazelcast.nio.IOUtil.toByteArray;
/**
* Provides {@link ClassData} to remote members.
*
* It may consult a local class cache when enabled and then it delegates to a local classloader.
*/
public final class ClassDataProvider {
private final UserCodeDeploymentConfig.ProviderMode providerMode;
private final ClassLoader parent;
private final ConcurrentMap<String, ClassSource> classSourceMap;
private final ILogger logger;
public ClassDataProvider(UserCodeDeploymentConfig.ProviderMode providerMode,
ClassLoader parent,
ConcurrentMap<String, ClassSource> classSourceMap,
ILogger logger) {
this.providerMode = providerMode;
this.parent = parent;
this.classSourceMap = classSourceMap;
this.logger = logger;
}
public ClassData getClassDataOrNull(String className) {
if (providerMode == UserCodeDeploymentConfig.ProviderMode.OFF) {
return null;
}
ClassData classData = null;
byte[] bytecode = loadBytecodeFromParent(className);
if (bytecode == null && providerMode == UserCodeDeploymentConfig.ProviderMode.LOCAL_AND_CACHED_CLASSES) {
bytecode = loadBytecodeFromCache(className);
}
if (bytecode != null) {
classData = new ClassData(bytecode);
}
return classData;
}
private byte[] loadBytecodeFromCache(String className) {
ClassSource classSource = classSourceMap.get(className);
if (classSource == null) {
return null;
}
return classSource.getBytecode();
}
private byte[] loadBytecodeFromParent(String className) {
String resource = className.replace('.', '/').concat(".class");
InputStream is = null;
try {
is = parent.getResourceAsStream(resource);
if (is != null) {
try {
return toByteArray(is);
} catch (IOException e) {
logger.severe(e);
}
}
} finally {
IOUtil.closeResource(is);
}
return null;
}
}