package org.eclipse.osgi.internal.cds;
import com.ibm.oti.shared.HelperAlreadyDefinedException;
import com.ibm.oti.shared.Shared;
import com.ibm.oti.shared.SharedClassHelperFactory;
import com.ibm.oti.shared.SharedClassURLHelper;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import org.eclipse.osgi.internal.hookregistry.BundleFileWrapperFactoryHook;
import org.eclipse.osgi.internal.hookregistry.ClassLoaderHook;
import org.eclipse.osgi.internal.hookregistry.HookRegistry;
import org.eclipse.osgi.internal.loader.ModuleClassLoader;
import org.eclipse.osgi.internal.loader.classpath.ClasspathEntry;
import org.eclipse.osgi.internal.loader.classpath.ClasspathManager;
import org.eclipse.osgi.internal.loader.classpath.FragmentClasspath;
import org.eclipse.osgi.storage.BundleInfo.Generation;
import org.eclipse.osgi.storage.bundlefile.BundleEntry;
import org.eclipse.osgi.storage.bundlefile.BundleFile;
import org.eclipse.osgi.storage.bundlefile.BundleFileWrapper;
import org.eclipse.osgi.storage.bundlefile.BundleFileWrapperChain;
public class CDSHookImpls extends ClassLoaderHook implements BundleFileWrapperFactoryHook {
private static SharedClassHelperFactory factory = Shared.getSharedClassHelperFactory();
private static CDSBundleFile getCDSBundleFile(BundleFile bundleFile) {
if (bundleFile instanceof BundleFileWrapperChain) {
return ((BundleFileWrapperChain) bundleFile).getWrappedType(CDSBundleFile.class);
}
return null;
}
@Override
public void recordClassDefine(String name, Class<?> clazz, byte[] classbytes, ClasspathEntry classpathEntry, BundleEntry entry, ClasspathManager manager) {
if ((null == clazz) || (false == hasMagicClassNumber(classbytes)) || (null == getCDSBundleFile(classpathEntry.getBundleFile()))) {
return;
}
try {
byte originalClassBytes[] = entry.getBytes();
if (originalClassBytes != classbytes) {
boolean modified = false;
if (originalClassBytes.length == classbytes.length) {
modified = !Arrays.equals(classbytes, originalClassBytes);
} else {
modified = true;
}
if (modified) {
return;
}
}
} catch (IOException e) {
return;
}
CDSBundleFile cdsFile = getCDSBundleFile(classpathEntry.getBundleFile());
if (null == cdsFile.getURL()) {
return;
}
SharedClassURLHelper urlHelper = cdsFile.getURLHelper();
if (urlHelper == null) {
CDSBundleFile hostBundleFile = getCDSBundleFile(manager.getGeneration().getBundleFile());
if (null != hostBundleFile) {
urlHelper = hostBundleFile.getURLHelper();
}
if (null != urlHelper) {
cdsFile.setURLHelper(urlHelper);
}
}
if (null != urlHelper) {
urlHelper.storeSharedClass(null, cdsFile.getURL(), clazz);
cdsFile.setPrimed(true);
}
}
private boolean hasMagicClassNumber(byte[] classbytes) {
if (classbytes == null || classbytes.length < 4)
return false;
return (classbytes[0] & 0xCA) == 0xCA && (classbytes[1] & 0xFE) == 0xFE && (classbytes[2] & 0xBA) == 0xBA && (classbytes[3] & 0xBE) == 0xBE;
}
@Override
public void classLoaderCreated(ModuleClassLoader classLoader) {
if (factory == null) {
return;
}
try {
SharedClassURLHelper urlHelper = factory.getURLHelper(classLoader);
boolean minimizeUpdateChecks = urlHelper.setMinimizeUpdateChecks();
CDSBundleFile hostFile = getCDSBundleFile(classLoader.getClasspathManager().getGeneration().getBundleFile());
if (hostFile != null) {
hostFile.setURLHelper(urlHelper);
if (minimizeUpdateChecks) {
hostFile.setPrimed(true);
}
}
ClasspathManager cpManager = classLoader.getClasspathManager();
for (ClasspathEntry entry : cpManager.getHostClasspathEntries()) {
CDSBundleFile cdsBundleFile = getCDSBundleFile(entry.getBundleFile());
if (cdsBundleFile != null) {
cdsBundleFile.setURLHelper(urlHelper);
if (minimizeUpdateChecks) {
cdsBundleFile.setPrimed(true);
}
}
}
for (FragmentClasspath fragCP : cpManager.getFragmentClasspaths()) {
for (ClasspathEntry entry : fragCP.getEntries()) {
CDSBundleFile cdsBundleFile = getCDSBundleFile(entry.getBundleFile());
if (cdsBundleFile != null) {
cdsBundleFile.setURLHelper(urlHelper);
if (minimizeUpdateChecks) {
cdsBundleFile.setPrimed(true);
}
}
}
}
} catch (HelperAlreadyDefinedException e) {
}
}
@Override
public boolean addClassPathEntry(ArrayList<ClasspathEntry> cpEntries, String cp, ClasspathManager hostmanager, Generation sourceGeneration) {
CDSBundleFile hostFile = getCDSBundleFile(hostmanager.getGeneration().getBundleFile());
CDSBundleFile sourceFile = getCDSBundleFile(sourceGeneration.getBundleFile());
if ((hostFile != sourceFile) && (null != hostFile) && (null != sourceFile)) {
SharedClassURLHelper urlHelper = hostFile.getURLHelper();
sourceFile.setURLHelper(urlHelper);
sourceFile.setPrimed(hostFile.getPrimed());
}
return false;
}
@Override
public BundleFileWrapper wrapBundleFile(BundleFile bundleFile, Generation generation, boolean base) {
CDSBundleFile newBundleFile;
if (!base && generation.getBundleInfo().getBundleId() != 0) {
SharedClassURLHelper urlHelper = null;
BundleFile baseFile = generation.getBundleFile();
if ((baseFile = getCDSBundleFile(baseFile)) != null) {
urlHelper = ((CDSBundleFile) baseFile).getURLHelper();
}
newBundleFile = new CDSBundleFile(bundleFile, urlHelper);
} else {
newBundleFile = new CDSBundleFile(bundleFile);
}
return newBundleFile;
}
void registerHooks(HookRegistry hookRegistry) {
if (!Shared.isSharingEnabled()) {
return;
}
hookRegistry.addClassLoaderHook(this);
hookRegistry.addBundleFileWrapperFactoryHook(this);
}
}