Path: blob/master/test/functional/cmdLineTests/shareClassTests/utils/src/CustomCLs/CustomPartitioningURLCL.java
6005 views
/*******************************************************************************1* Copyright (c) 2005, 2020 IBM Corp. and others2*3* This program and the accompanying materials are made available under4* the terms of the Eclipse Public License 2.0 which accompanies this5* distribution and is available at https://www.eclipse.org/legal/epl-2.0/6* or the Apache License, Version 2.0 which accompanies this distribution and7* is available at https://www.apache.org/licenses/LICENSE-2.0.8*9* This Source Code may also be made available under the following10* Secondary Licenses when the conditions for such availability set11* forth in the Eclipse Public License, v. 2.0 are satisfied: GNU12* General Public License, version 2 with the GNU Classpath13* Exception [1] and GNU General Public License, version 2 with the14* OpenJDK Assembly Exception [2].15*16* [1] https://www.gnu.org/software/classpath/license.html17* [2] http://openjdk.java.net/legal/assembly-exception.html18*19* SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception20*******************************************************************************/21package CustomCLs;2223import java.io.ByteArrayOutputStream;24import java.io.File;25import java.io.FileInputStream;26import java.io.IOException;27import java.io.InputStream;28import java.net.JarURLConnection;29import java.net.MalformedURLException;30import java.net.URL;31import java.security.CodeSource;32import java.security.SecureClassLoader;33import java.util.Hashtable;34import java.util.jar.Attributes;35import java.util.jar.JarEntry;36import java.util.jar.JarFile;37import java.util.jar.Manifest;38import java.util.jar.Attributes.Name;3940import com.ibm.oti.shared.HelperAlreadyDefinedException;41import com.ibm.oti.shared.Shared;42import com.ibm.oti.shared.SharedClassHelperFactory;43import com.ibm.oti.shared.SharedClassTokenHelper;44import com.ibm.oti.shared.SharedClassURLClasspathHelper;45import com.ibm.oti.shared.SharedClassURLHelper;4647/**48* @author Matthew Kilner49*/50public class CustomPartitioningURLCL extends SecureClassLoader {5152URL[] urls, orgUrls;5354private Hashtable jarCache = new Hashtable(32);55int loaderType;5657String partition = null;5859SharedClassURLClasspathHelper scHelper;6061CustomLoaderMetaDataCache[] metaDataArray;6263FoundAtIndex foundAtIndex = new FoundAtIndex();6465public CustomPartitioningURLCL(URL[] passedUrls, ClassLoader parent){66super(parent);67loaderType = ClassLoaderType.CACHEDURL.ord;68int urlLength = passedUrls.length;69urls = new URL[urlLength];70orgUrls = new URL[urlLength];71for (int i=0; i < urlLength; i++) {72try {73urls[i] = createSearchURL(passedUrls[i]);74} catch (MalformedURLException e) {}75orgUrls[i] = passedUrls[i];76}77metaDataArray = new CustomLoaderMetaDataCache[urls.length];78initMetaData();79SharedClassHelperFactory schFactory = Shared.getSharedClassHelperFactory();80if(schFactory != null){81try{82scHelper = schFactory.getURLClasspathHelper(this, passedUrls);83if(null != scHelper){84scHelper.confirmAllEntries();85}86} catch (HelperAlreadyDefinedException e){87e.printStackTrace();88}89}90}9192public CustomPartitioningURLCL(URL[] passedUrls){93super();94loaderType = ClassLoaderType.CACHEDURL.ord;95int urlLength = passedUrls.length;96urls = new URL[urlLength];97orgUrls = new URL[urlLength];98for (int i=0; i < urlLength; i++) {99try {100urls[i] = createSearchURL(passedUrls[i]);101} catch (MalformedURLException e) {}102orgUrls[i] = passedUrls[i];103}104metaDataArray = new CustomLoaderMetaDataCache[urls.length];105initMetaData();106SharedClassHelperFactory schFactory = Shared.getSharedClassHelperFactory();107if(schFactory != null){108try{109scHelper = schFactory.getURLClasspathHelper(this, passedUrls);110if(null != scHelper){111scHelper.confirmAllEntries();112}113} catch (HelperAlreadyDefinedException e){114e.printStackTrace();115}116}117}118119public void setPartition(String newPartition){120partition = newPartition;121}122123public boolean getHelper(){124SharedClassHelperFactory schFactory = Shared.getSharedClassHelperFactory();125SharedClassURLClasspathHelper newHelper = null;126try{127newHelper = schFactory.getURLClasspathHelper(this, orgUrls);128} catch (HelperAlreadyDefinedException e){129return false;130}131132if(newHelper.equals(scHelper)){133return true;134} else {135return false;136}137}138139public void getHelper(URL[] urls)throws HelperAlreadyDefinedException {140SharedClassHelperFactory schFactory = Shared.getSharedClassHelperFactory();141SharedClassURLClasspathHelper newHelper = null;142newHelper = schFactory.getURLClasspathHelper(this, urls);143}144145public void getURLHelper()throws Exception {146SharedClassHelperFactory schFactory = Shared.getSharedClassHelperFactory();147SharedClassURLHelper newHelper = null;148newHelper = schFactory.getURLHelper(this);149}150151public void getTokenHelper()throws Exception {152SharedClassHelperFactory schFactory = Shared.getSharedClassHelperFactory();153SharedClassTokenHelper newHelper = null;154newHelper = schFactory.getTokenHelper(this);155}156157public boolean duplicateStore(String name){158Class clazz = null;159try{160clazz = this.loadClass(name);161} catch (ClassNotFoundException e){162e.printStackTrace();163}164if (clazz != null){165int indexFoundAt = locateClass(name);166if(indexFoundAt != -1){167scHelper.storeSharedClass(clazz, indexFoundAt);168return true;169}170}171return false;172}173174private static boolean isDirectory(URL url) {175String file = url.getFile();176return (file.length() > 0 && file.charAt(file.length()-1) == '/');177}178179private URL createSearchURL(URL url) throws MalformedURLException {180if (url == null) return url;181String protocol = url.getProtocol();182183if (isDirectory(url) || protocol.equals("jar")) {184return url;185} else {186return new URL("jar", "", -1, url.toString() + "!/");187}188}189190private void initMetaData(){191for(int loopIndex = 0; loopIndex < metaDataArray.length; loopIndex++){192metaDataArray[loopIndex] = null;193}194}195196private void addMetaDataEntry(){197CustomLoaderMetaDataCache[] newArray = new CustomLoaderMetaDataCache[(metaDataArray.length)];198System.arraycopy(metaDataArray,0,newArray,0,metaDataArray.length);199metaDataArray = newArray;200metaDataArray[(metaDataArray.length - 1)] = null;201}202203public void addUrl(URL url){204URL searchURL = null;205try{206searchURL = createSearchURL(url);207} catch (Exception e){208e.printStackTrace();209}210URL[] newOrgUrls = new URL[(orgUrls.length)];211System.arraycopy(orgUrls,0,newOrgUrls,0,orgUrls.length);212orgUrls = newOrgUrls;213orgUrls[(orgUrls.length - 1)] = url;214URL[] newUrls = new URL[urls.length];215System.arraycopy(urls,0,newUrls,0,urls.length);216urls = newUrls;217urls[(urls.length - 1)] = searchURL;218scHelper.addClasspathEntry(url);219scHelper.confirmAllEntries();220addMetaDataEntry();221}222223public URL[] getURLS(){224return orgUrls;225}226227private static byte[] getBytes(InputStream is, boolean readAvailable) throws IOException {228if (readAvailable) {229byte[] buf = new byte[is.available()];230is.read(buf, 0, buf.length);231is.close();232return buf;233}234byte[] buf = new byte[4096];235int size = is.available();236if (size < 1024) size = 1024;237ByteArrayOutputStream bos = new ByteArrayOutputStream(size);238int count;239while ((count = is.read(buf)) > 0)240bos.write(buf, 0, count);241return bos.toByteArray();242}243244private int locateClass(String className){245int classAtEntry = -1;246String name = className.replace('.','/').concat(".class");247for(int index = 0; index < urls.length; index ++){248URL currentUrl = urls[index];249if(currentUrl.getProtocol().equals("jar")){250JarEntry entry = null;251JarFile jf = (JarFile)jarCache.get(currentUrl);252if(jf == null){253/* First time we have encountered this jar.254* Lets cache its metaData.255*/256try{257URL jarFileUrl = ((JarURLConnection)currentUrl.openConnection()).getJarFileURL();258JarURLConnection jarUrlConnection = (JarURLConnection)new URL("jar", "", jarFileUrl.toExternalForm() + "!/").openConnection();259try{260jf = jarUrlConnection.getJarFile();261}catch(Exception e){262}263if(jf != null){264jarCache.put(currentUrl, jf);265}266} catch (Exception e){267e.printStackTrace();268}269if(jf != null){270Manifest manifest = null;271java.security.cert.Certificate[] certs = null;272URL csUrl = currentUrl;273CodeSource codeSource;274try{275manifest = jf.getManifest();276} catch(Exception e){277e.printStackTrace();278}279entry = jf.getJarEntry(name);280if(entry != null){281certs = entry.getCertificates();282}283codeSource = new CodeSource(csUrl, certs);284CustomLoaderMetaDataCache metaData = new CustomLoaderMetaDataCache();285metaData.manifest = manifest;286metaData.codeSource = codeSource;287metaDataArray[index] = metaData;288}289}290if(entry == null && jf != null){291entry = jf.getJarEntry(name);292}293if(entry != null){294/* We have the first match on the class path, return the current url index */295return index;296}297} else {298String filename = currentUrl.getFile();299String host = currentUrl.getHost();300if (host != null && host.length() > 0) {301filename = new StringBuffer(host.length() + filename.length() + name.length() + 2).302append("//").append(host).append(filename).append(name).toString();303} else {304filename = new StringBuffer(filename.length() + name.length()).305append(filename).append(name).toString();306}307File file = new File(filename);308// Don't throw exceptions for speed309if (file.exists()) {310if(metaDataArray[index] == null){311java.security.cert.Certificate[] certs = null;312CustomLoaderMetaDataCache metaData = new CustomLoaderMetaDataCache();313metaData.manifest = null;314metaData.codeSource = new CodeSource(currentUrl, certs);315metaDataArray[index] = metaData;316}317return index;318}319}320}321return classAtEntry;322}323324private byte[] loadClassBytes(String className, int urlIndex){325byte[] bytes = null;326String name = className.replace('.','/').concat(".class");327URL classLocation = urls[urlIndex];328if(classLocation.getProtocol().equals("jar")){329JarFile jf = (JarFile)jarCache.get(classLocation);330JarEntry entry = jf.getJarEntry(name);331try{332InputStream stream = jf.getInputStream(entry);333bytes = getBytes(stream, true);334} catch (Exception e){335e.printStackTrace();336}337} else {338String filename = classLocation.getFile();339String host = classLocation.getHost();340if (host != null && host.length() > 0) {341filename = new StringBuffer(host.length() + filename.length() + name.length() + 2).342append("//").append(host).append(filename).append(name).toString();343} else {344filename = new StringBuffer(filename.length() + name.length()).345append(filename).append(name).toString();346}347File file = new File(filename);348// Don't throw exceptions for speed349if (file.exists()) {350try{351FileInputStream stream = new FileInputStream(file);352bytes = getBytes(stream, true);353} catch(Exception e){354e.printStackTrace();355}356}357}358return bytes;359}360361public Class findClass(String name) throws ClassNotFoundException {362Class clazz = null;363if(scHelper != null){364byte[] classBytes = scHelper.findSharedClass(partition, name, foundAtIndex);365if(classBytes != null){366if(metaDataArray[foundAtIndex.getIndex()] != null){367checkPackage(name, foundAtIndex.getIndex());368CustomLoaderMetaDataCache metadata = metaDataArray[foundAtIndex.getIndex()];369CodeSource codeSource = metadata.codeSource;370clazz = defineClass(name, classBytes, 0, classBytes.length, codeSource);371}372}373}374if(clazz == null) {375int indexFoundAt = locateClass(name);376if(indexFoundAt != -1){377try{378byte[] classBytes = loadClassBytes(name, indexFoundAt);379checkPackage(name, indexFoundAt);380CustomLoaderMetaDataCache metadata = metaDataArray[indexFoundAt];381CodeSource codeSource = metadata.codeSource;382clazz = defineClass(name, classBytes, 0, classBytes.length, codeSource);383if(clazz != null){384System.out.println("\n** Storing class: "+name+" on partition: "+partition);385scHelper.storeSharedClass(partition, clazz, indexFoundAt);386}387} catch (Exception e){388e.printStackTrace();389}390}391if(clazz == null){392throw new ClassNotFoundException(name);393}394}395return clazz;396}397398private void checkPackage(String name, int urlIndex){399int index = name.lastIndexOf('.');400if(index != -1){401String packageString = name.substring(0, index);402Manifest manifest = metaDataArray[urlIndex].manifest;403CodeSource codeSource = metaDataArray[urlIndex].codeSource;404synchronized(this){405Package packageInst = getPackage(packageString);406if(packageInst == null){407if (manifest != null){408definePackage(packageString, manifest, codeSource.getLocation());409} else {410definePackage(packageString, null, null, null, null, null, null, null);411}412} else {413boolean exception = false;414if (manifest != null) {415String dirName = packageString.replace('.', '/') + "/";416if (isSealed(manifest, dirName))417exception = !packageInst.isSealed(codeSource.getLocation());418} else419exception = packageInst.isSealed();420if (exception)421throw new SecurityException(com.ibm.oti.util.Msg.getString("Package exception"));422}423}424}425}426427private boolean isSealed(Manifest manifest, String dirName) {428Attributes mainAttributes = manifest.getMainAttributes();429String value = mainAttributes.getValue(Attributes.Name.SEALED);430boolean sealed = value != null &&431value.toLowerCase().equals ("true");432Attributes attributes = manifest.getAttributes(dirName);433if (attributes != null) {434value = attributes.getValue(Attributes.Name.SEALED);435if (value != null)436sealed = value.toLowerCase().equals("true");437}438return sealed;439}440441protected Package definePackage(String name, Manifest man, URL url) throws IllegalArgumentException {442String path = name.replace('.','/').concat("/");443String[] attrs = new String[7];444URL sealedAtURL = null;445446Attributes attr = man.getAttributes(path);447Attributes mainAttr = man.getMainAttributes();448449if(attr != null){450attrs[0] = attr.getValue(Name.SPECIFICATION_TITLE);451attrs[1] = attr.getValue(Name.SPECIFICATION_VERSION);452attrs[2] = attr.getValue(Name.SPECIFICATION_VENDOR);453attrs[3] = attr.getValue(Name.IMPLEMENTATION_TITLE);454attrs[4] = attr.getValue(Name.IMPLEMENTATION_VERSION);455attrs[5] = attr.getValue(Name.IMPLEMENTATION_VENDOR);456attrs[6] = attr.getValue(Name.SEALED);457}458459if(mainAttr != null){460if (attrs[0] == null) {461attrs[0] = mainAttr.getValue(Name.SPECIFICATION_TITLE);462}463if (attrs[1] == null) {464attrs[1] = mainAttr.getValue(Name.SPECIFICATION_VERSION);465}466if (attrs[2] == null) {467attrs[2] = mainAttr.getValue(Name.SPECIFICATION_VENDOR);468}469if (attrs[3] == null) {470attrs[3] = mainAttr.getValue(Name.IMPLEMENTATION_TITLE);471}472if (attrs[4] == null) {473attrs[4] = mainAttr.getValue(Name.IMPLEMENTATION_VERSION);474}475if (attrs[5] == null) {476attrs[5] = mainAttr.getValue(Name.IMPLEMENTATION_VENDOR);477}478if (attrs[6] == null) {479attrs[6] = mainAttr.getValue(Name.SEALED);480}481}482if ("true".equalsIgnoreCase(attrs[6])){483sealedAtURL = url;484}485return definePackage(name, attrs[0], attrs[1], attrs[2], attrs[3], attrs[4], attrs[5], sealedAtURL);486}487488public boolean isClassInSharedCache(String className){489byte[] sharedClass = null;490System.out.println("\n** Checking for class: "+className+" on partition: "+partition);491if (scHelper!=null) {492sharedClass = scHelper.findSharedClass(partition, className, foundAtIndex);493if (sharedClass !=null){494return true;495} else {496return false;497}498}499return false;500}501502public Class getClassFromCache(String name){503Class clazz = null;504byte[] classBytes = scHelper.findSharedClass(partition, name, foundAtIndex);505if(classBytes != null){506CodeSource cs = null;507clazz = defineClass(name, classBytes, 0, classBytes.length, cs);508}509return clazz;510}511512public static class FoundAtIndex implements SharedClassURLClasspathHelper.IndexHolder {513514int indexFoundAt = -1;515516public void setIndex(int index) {517indexFoundAt = index;518}519520public int getIndex(){521return indexFoundAt;522}523524public void reset(){525indexFoundAt = -1;526}527528}529}530531532