Path: blob/master/test/functional/cmdLineTests/shareClassTests/utils/src/CustomCLs/CustomURLClassLoaderNoAPIUse.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 CustomURLClassLoaderNoAPIUse extends SecureClassLoader {5152URL[] urls, orgUrls;5354private Hashtable jarCache = new Hashtable(32);55int loaderType;5657SharedClassURLClasspathHelper scHelper;5859CustomLoaderMetaDataCache[] metaDataArray;6061FoundAtIndex foundAtIndex = new FoundAtIndex();6263public CustomURLClassLoaderNoAPIUse(URL[] passedUrls, ClassLoader parent){64super(parent);65loaderType = ClassLoaderType.CACHEDURL.ord;66int urlLength = passedUrls.length;67urls = new URL[urlLength];68orgUrls = new URL[urlLength];69for (int i=0; i < urlLength; i++) {70try {71urls[i] = createSearchURL(passedUrls[i]);72} catch (MalformedURLException e) {}73orgUrls[i] = passedUrls[i];74}75metaDataArray = new CustomLoaderMetaDataCache[urls.length];76initMetaData();77SharedClassHelperFactory schFactory = Shared.getSharedClassHelperFactory();78if(schFactory != null){79try{80scHelper = schFactory.getURLClasspathHelper(this, passedUrls);81if(null != scHelper){82scHelper.confirmAllEntries();83}84} catch (HelperAlreadyDefinedException e){85e.printStackTrace();86}87}88}8990public CustomURLClassLoaderNoAPIUse(URL[] passedUrls){91super();92loaderType = ClassLoaderType.CACHEDURL.ord;93int urlLength = passedUrls.length;94urls = new URL[urlLength];95orgUrls = new URL[urlLength];96for (int i=0; i < urlLength; i++) {97try {98urls[i] = createSearchURL(passedUrls[i]);99} catch (MalformedURLException e) {}100orgUrls[i] = passedUrls[i];101}102metaDataArray = new CustomLoaderMetaDataCache[urls.length];103initMetaData();104SharedClassHelperFactory schFactory = Shared.getSharedClassHelperFactory();105if(schFactory != null){106try{107scHelper = schFactory.getURLClasspathHelper(this, passedUrls);108if(null != scHelper){109scHelper.confirmAllEntries();110}111} catch (HelperAlreadyDefinedException e){112e.printStackTrace();113}114}115}116117public boolean getHelper(){118SharedClassHelperFactory schFactory = Shared.getSharedClassHelperFactory();119SharedClassURLClasspathHelper newHelper = null;120try{121newHelper = schFactory.getURLClasspathHelper(this, orgUrls);122} catch (HelperAlreadyDefinedException e){123return false;124}125126if(newHelper.equals(scHelper)){127return true;128} else {129return false;130}131}132133public void getHelper(URL[] urls)throws HelperAlreadyDefinedException {134SharedClassHelperFactory schFactory = Shared.getSharedClassHelperFactory();135SharedClassURLClasspathHelper newHelper = null;136newHelper = schFactory.getURLClasspathHelper(this, urls);137}138139public void getURLHelper()throws Exception {140SharedClassHelperFactory schFactory = Shared.getSharedClassHelperFactory();141SharedClassURLHelper newHelper = null;142newHelper = schFactory.getURLHelper(this);143}144145public void getTokenHelper()throws Exception {146SharedClassHelperFactory schFactory = Shared.getSharedClassHelperFactory();147SharedClassTokenHelper newHelper = null;148newHelper = schFactory.getTokenHelper(this);149}150151public boolean duplicateStore(String name){152Class clazz = null;153try{154clazz = this.loadClass(name);155} catch (ClassNotFoundException e){156e.printStackTrace();157}158if (clazz != null){159int indexFoundAt = locateClass(name);160if(indexFoundAt != -1){161scHelper.storeSharedClass(clazz, indexFoundAt);162return true;163}164}165return false;166}167168private static boolean isDirectory(URL url) {169String file = url.getFile();170return (file.length() > 0 && file.charAt(file.length()-1) == '/');171}172173private URL createSearchURL(URL url) throws MalformedURLException {174if (url == null) return url;175String protocol = url.getProtocol();176177if (isDirectory(url) || protocol.equals("jar")) {178return url;179} else {180return new URL("jar", "", -1, url.toString() + "!/");181}182}183184private void initMetaData(){185for(int loopIndex = 0; loopIndex < metaDataArray.length; loopIndex++){186metaDataArray[loopIndex] = null;187}188}189190private void addMetaDataEntry(){191CustomLoaderMetaDataCache[] newArray = new CustomLoaderMetaDataCache[(metaDataArray.length)];192System.arraycopy(metaDataArray,0,newArray,0,metaDataArray.length);193metaDataArray = newArray;194metaDataArray[(metaDataArray.length - 1)] = null;195}196197public void addUrl(URL url){198URL searchURL = null;199try{200searchURL = createSearchURL(url);201} catch (Exception e){202e.printStackTrace();203}204URL[] newOrgUrls = new URL[(orgUrls.length)];205System.arraycopy(orgUrls,0,newOrgUrls,0,orgUrls.length);206orgUrls = newOrgUrls;207orgUrls[(orgUrls.length - 1)] = url;208URL[] newUrls = new URL[urls.length];209System.arraycopy(urls,0,newUrls,0,urls.length);210urls = newUrls;211urls[(urls.length - 1)] = searchURL;212scHelper.addClasspathEntry(url);213scHelper.confirmAllEntries();214addMetaDataEntry();215}216217public URL[] getURLS(){218return orgUrls;219}220221private static byte[] getBytes(InputStream is, boolean readAvailable) throws IOException {222if (readAvailable) {223byte[] buf = new byte[is.available()];224is.read(buf, 0, buf.length);225is.close();226return buf;227}228byte[] buf = new byte[4096];229int size = is.available();230if (size < 1024) size = 1024;231ByteArrayOutputStream bos = new ByteArrayOutputStream(size);232int count;233while ((count = is.read(buf)) > 0)234bos.write(buf, 0, count);235return bos.toByteArray();236}237238private int locateClass(String className){239int classAtEntry = -1;240String name = className.replace('.','/').concat(".class");241for(int index = 0; index < urls.length; index ++){242URL currentUrl = urls[index];243if(currentUrl.getProtocol().equals("jar")){244JarEntry entry = null;245JarFile jf = (JarFile)jarCache.get(currentUrl);246if(jf == null){247/* First time we have encountered this jar.248* Lets cache its metaData.249*/250try{251URL jarFileUrl = ((JarURLConnection)currentUrl.openConnection()).getJarFileURL();252JarURLConnection jarUrlConnection = (JarURLConnection)new URL("jar", "", jarFileUrl.toExternalForm() + "!/").openConnection();253try{254jf = jarUrlConnection.getJarFile();255}catch(Exception e){256}257if(jf != null){258jarCache.put(currentUrl, jf);259}260} catch (Exception e){261e.printStackTrace();262}263if(jf != null){264Manifest manifest = null;265java.security.cert.Certificate[] certs = null;266URL csUrl = currentUrl;267CodeSource codeSource;268try{269manifest = jf.getManifest();270} catch(Exception e){271e.printStackTrace();272}273entry = jf.getJarEntry(name);274if(entry != null){275certs = entry.getCertificates();276}277codeSource = new CodeSource(csUrl, certs);278CustomLoaderMetaDataCache metaData = new CustomLoaderMetaDataCache();279metaData.manifest = manifest;280metaData.codeSource = codeSource;281metaDataArray[index] = metaData;282}283}284if(entry == null && jf != null){285entry = jf.getJarEntry(name);286}287if(entry != null){288/* We have the first match on the class path, return the current url index */289return index;290}291} else {292String filename = currentUrl.getFile();293String host = currentUrl.getHost();294if (host != null && host.length() > 0) {295filename = new StringBuffer(host.length() + filename.length() + name.length() + 2).296append("//").append(host).append(filename).append(name).toString();297} else {298filename = new StringBuffer(filename.length() + name.length()).299append(filename).append(name).toString();300}301File file = new File(filename);302// Don't throw exceptions for speed303if (file.exists()) {304if(metaDataArray[index] == null){305java.security.cert.Certificate[] certs = null;306CustomLoaderMetaDataCache metaData = new CustomLoaderMetaDataCache();307metaData.manifest = null;308metaData.codeSource = new CodeSource(currentUrl, certs);309metaDataArray[index] = metaData;310}311return index;312}313}314}315return classAtEntry;316}317318private byte[] loadClassBytes(String className, int urlIndex){319byte[] bytes = null;320String name = className.replace('.','/').concat(".class");321URL classLocation = urls[urlIndex];322if(classLocation.getProtocol().equals("jar")){323JarFile jf = (JarFile)jarCache.get(classLocation);324JarEntry entry = jf.getJarEntry(name);325try{326InputStream stream = jf.getInputStream(entry);327bytes = getBytes(stream, true);328} catch (Exception e){329e.printStackTrace();330}331} else {332String filename = classLocation.getFile();333String host = classLocation.getHost();334if (host != null && host.length() > 0) {335filename = new StringBuffer(host.length() + filename.length() + name.length() + 2).336append("//").append(host).append(filename).append(name).toString();337} else {338filename = new StringBuffer(filename.length() + name.length()).339append(filename).append(name).toString();340}341File file = new File(filename);342// Don't throw exceptions for speed343if (file.exists()) {344try{345FileInputStream stream = new FileInputStream(file);346bytes = getBytes(stream, true);347} catch(Exception e){348e.printStackTrace();349}350}351}352return bytes;353}354355public Class findClass(String name) throws ClassNotFoundException {356Class clazz = null;357if(scHelper != null){358//byte[] classBytes = scHelper.findSharedClass(name, foundAtIndex);359byte[] classBytes = null;360if(classBytes != null){361if(metaDataArray[foundAtIndex.getIndex()] != null){362checkPackage(name, foundAtIndex.getIndex());363CustomLoaderMetaDataCache metadata = metaDataArray[foundAtIndex.getIndex()];364CodeSource codeSource = metadata.codeSource;365clazz = defineClass(name, classBytes, 0, classBytes.length, codeSource);366}367}368}369if(clazz == null) {370int indexFoundAt = locateClass(name);371if(indexFoundAt != -1){372try{373byte[] classBytes = loadClassBytes(name, indexFoundAt);374checkPackage(name, indexFoundAt);375CustomLoaderMetaDataCache metadata = metaDataArray[indexFoundAt];376CodeSource codeSource = metadata.codeSource;377clazz = defineClass(name, classBytes, 0, classBytes.length, codeSource);378if(clazz != null){379//scHelper.storeSharedClass(clazz, indexFoundAt);380}381} catch (Exception e){382e.printStackTrace();383}384}385if(clazz == null){386throw new ClassNotFoundException(name);387}388}389return clazz;390}391392private void checkPackage(String name, int urlIndex){393int index = name.lastIndexOf('.');394if(index != -1){395String packageString = name.substring(0, index);396Manifest manifest = metaDataArray[urlIndex].manifest;397CodeSource codeSource = metaDataArray[urlIndex].codeSource;398synchronized(this){399Package packageInst = getPackage(packageString);400if(packageInst == null){401if (manifest != null){402definePackage(packageString, manifest, codeSource.getLocation());403} else {404definePackage(packageString, null, null, null, null, null, null, null);405}406} else {407boolean exception = false;408if (manifest != null) {409String dirName = packageString.replace('.', '/') + "/";410if (isSealed(manifest, dirName))411exception = !packageInst.isSealed(codeSource.getLocation());412} else413exception = packageInst.isSealed();414if (exception)415throw new SecurityException(com.ibm.oti.util.Msg.getString("Package exception"));416}417}418}419}420421private boolean isSealed(Manifest manifest, String dirName) {422Attributes mainAttributes = manifest.getMainAttributes();423String value = mainAttributes.getValue(Attributes.Name.SEALED);424boolean sealed = value != null &&425value.toLowerCase().equals ("true");426Attributes attributes = manifest.getAttributes(dirName);427if (attributes != null) {428value = attributes.getValue(Attributes.Name.SEALED);429if (value != null)430sealed = value.toLowerCase().equals("true");431}432return sealed;433}434435protected Package definePackage(String name, Manifest man, URL url) throws IllegalArgumentException {436String path = name.replace('.','/').concat("/");437String[] attrs = new String[7];438URL sealedAtURL = null;439440Attributes attr = man.getAttributes(path);441Attributes mainAttr = man.getMainAttributes();442443if(attr != null){444attrs[0] = attr.getValue(Name.SPECIFICATION_TITLE);445attrs[1] = attr.getValue(Name.SPECIFICATION_VERSION);446attrs[2] = attr.getValue(Name.SPECIFICATION_VENDOR);447attrs[3] = attr.getValue(Name.IMPLEMENTATION_TITLE);448attrs[4] = attr.getValue(Name.IMPLEMENTATION_VERSION);449attrs[5] = attr.getValue(Name.IMPLEMENTATION_VENDOR);450attrs[6] = attr.getValue(Name.SEALED);451}452453if(mainAttr != null){454if (attrs[0] == null) {455attrs[0] = mainAttr.getValue(Name.SPECIFICATION_TITLE);456}457if (attrs[1] == null) {458attrs[1] = mainAttr.getValue(Name.SPECIFICATION_VERSION);459}460if (attrs[2] == null) {461attrs[2] = mainAttr.getValue(Name.SPECIFICATION_VENDOR);462}463if (attrs[3] == null) {464attrs[3] = mainAttr.getValue(Name.IMPLEMENTATION_TITLE);465}466if (attrs[4] == null) {467attrs[4] = mainAttr.getValue(Name.IMPLEMENTATION_VERSION);468}469if (attrs[5] == null) {470attrs[5] = mainAttr.getValue(Name.IMPLEMENTATION_VENDOR);471}472if (attrs[6] == null) {473attrs[6] = mainAttr.getValue(Name.SEALED);474}475}476if ("true".equalsIgnoreCase(attrs[6])){477sealedAtURL = url;478}479return definePackage(name, attrs[0], attrs[1], attrs[2], attrs[3], attrs[4], attrs[5], sealedAtURL);480}481482public boolean isClassInSharedCache(String className){483byte[] sharedClass = null;484if (scHelper!=null) {485sharedClass = scHelper.findSharedClass(className, foundAtIndex);486if (sharedClass !=null){487return true;488} else {489return false;490}491}492return false;493}494495public static class FoundAtIndex implements SharedClassURLClasspathHelper.IndexHolder {496497int indexFoundAt = -1;498499public void setIndex(int index) {500indexFoundAt = index;501}502503public int getIndex(){504return indexFoundAt;505}506507public void reset(){508indexFoundAt = -1;509}510511}512}513514515