Path: blob/master/test/functional/cmdLineTests/shareClassTests/utils/src/CustomCLs/CustomURLClassLoaderNonConfirming.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.CannotSetClasspathException;41import com.ibm.oti.shared.HelperAlreadyDefinedException;42import com.ibm.oti.shared.Shared;43import com.ibm.oti.shared.SharedClassHelperFactory;44import com.ibm.oti.shared.SharedClassTokenHelper;45import com.ibm.oti.shared.SharedClassURLClasspathHelper;46import com.ibm.oti.shared.SharedClassURLHelper;4748/**49* @author Matthew Kilner50*/51public class CustomURLClassLoaderNonConfirming extends SecureClassLoader {5253URL[] urls, orgUrls;5455private Hashtable jarCache = new Hashtable(32);56int loaderType;5758SharedClassURLClasspathHelper scHelper;5960CustomLoaderMetaDataCache[] metaDataArray;6162FoundAtIndex foundAtIndex = new FoundAtIndex();6364public CustomURLClassLoaderNonConfirming(URL[] passedUrls, ClassLoader parent){65super(parent);66loaderType = ClassLoaderType.CACHEDURL.ord;67int urlLength = passedUrls.length;68urls = new URL[urlLength];69orgUrls = new URL[urlLength];70for (int i=0; i < urlLength; i++) {71try {72urls[i] = createSearchURL(passedUrls[i]);73} catch (MalformedURLException e) {}74orgUrls[i] = passedUrls[i];75}76metaDataArray = new CustomLoaderMetaDataCache[urls.length];77initMetaData();78SharedClassHelperFactory schFactory = Shared.getSharedClassHelperFactory();79if(schFactory != null){80try{81scHelper = schFactory.getURLClasspathHelper(this, passedUrls);82} catch (HelperAlreadyDefinedException e){83e.printStackTrace();84}85}86}8788public CustomURLClassLoaderNonConfirming(URL[] passedUrls){89super();90loaderType = ClassLoaderType.CACHEDURL.ord;91int urlLength = passedUrls.length;92urls = new URL[urlLength];93orgUrls = new URL[urlLength];94for (int i=0; i < urlLength; i++) {95try {96urls[i] = createSearchURL(passedUrls[i]);97} catch (MalformedURLException e) {}98orgUrls[i] = passedUrls[i];99}100metaDataArray = new CustomLoaderMetaDataCache[urls.length];101initMetaData();102SharedClassHelperFactory schFactory = Shared.getSharedClassHelperFactory();103if(schFactory != null){104try{105scHelper = schFactory.getURLClasspathHelper(this, passedUrls);106} catch (HelperAlreadyDefinedException e){107e.printStackTrace();108}109}110}111112public boolean getHelper(){113SharedClassHelperFactory schFactory = Shared.getSharedClassHelperFactory();114SharedClassURLClasspathHelper newHelper = null;115try{116newHelper = schFactory.getURLClasspathHelper(this, orgUrls);117} catch (HelperAlreadyDefinedException e){118return false;119}120121if(newHelper.equals(scHelper)){122return true;123} else {124return false;125}126}127128public void getHelper(URL[] urls)throws HelperAlreadyDefinedException {129SharedClassHelperFactory schFactory = Shared.getSharedClassHelperFactory();130SharedClassURLClasspathHelper newHelper = null;131newHelper = schFactory.getURLClasspathHelper(this, urls);132}133134public void getURLHelper()throws Exception {135SharedClassHelperFactory schFactory = Shared.getSharedClassHelperFactory();136SharedClassURLHelper newHelper = null;137newHelper = schFactory.getURLHelper(this);138}139140public void getTokenHelper()throws Exception {141SharedClassHelperFactory schFactory = Shared.getSharedClassHelperFactory();142SharedClassTokenHelper newHelper = null;143newHelper = schFactory.getTokenHelper(this);144}145146public boolean duplicateStore(String name){147Class clazz = null;148try{149clazz = this.loadClass(name);150} catch (ClassNotFoundException e){151e.printStackTrace();152}153if (clazz != null){154int indexFoundAt = locateClass(name);155if(indexFoundAt != -1){156scHelper.storeSharedClass(clazz, indexFoundAt);157return true;158}159}160return false;161}162163private static boolean isDirectory(URL url) {164String file = url.getFile();165return (file.length() > 0 && file.charAt(file.length()-1) == '/');166}167168private URL createSearchURL(URL url) throws MalformedURLException {169if (url == null) return url;170String protocol = url.getProtocol();171172if (isDirectory(url) || protocol.equals("jar")) {173return url;174} else {175return new URL("jar", "", -1, url.toString() + "!/");176}177}178179private void initMetaData(){180for(int loopIndex = 0; loopIndex < metaDataArray.length; loopIndex++){181metaDataArray[loopIndex] = null;182}183}184185private void addMetaDataEntry(){186CustomLoaderMetaDataCache[] newArray = new CustomLoaderMetaDataCache[(metaDataArray.length)];187System.arraycopy(metaDataArray,0,newArray,0,metaDataArray.length);188metaDataArray = newArray;189metaDataArray[(metaDataArray.length - 1)] = null;190}191192public void addUrl(URL url){193URL searchURL = null;194try{195searchURL = createSearchURL(url);196} catch (Exception e){197e.printStackTrace();198}199URL[] newOrgUrls = new URL[(orgUrls.length)];200System.arraycopy(orgUrls,0,newOrgUrls,0,orgUrls.length);201orgUrls = newOrgUrls;202orgUrls[(orgUrls.length - 1)] = url;203URL[] newUrls = new URL[urls.length];204System.arraycopy(urls,0,newUrls,0,urls.length);205urls = newUrls;206urls[(urls.length - 1)] = searchURL;207scHelper.addClasspathEntry(url);208addMetaDataEntry();209}210211public URL[] getURLS(){212return orgUrls;213}214215private static byte[] getBytes(InputStream is, boolean readAvailable) throws IOException {216if (readAvailable) {217byte[] buf = new byte[is.available()];218is.read(buf, 0, buf.length);219is.close();220return buf;221}222byte[] buf = new byte[4096];223int size = is.available();224if (size < 1024) size = 1024;225ByteArrayOutputStream bos = new ByteArrayOutputStream(size);226int count;227while ((count = is.read(buf)) > 0)228bos.write(buf, 0, count);229return bos.toByteArray();230}231232private int locateClass(String className){233int classAtEntry = -1;234String name = className.replace('.','/').concat(".class");235for(int index = 0; index < urls.length; index ++){236URL currentUrl = urls[index];237if(currentUrl.getProtocol().equals("jar")){238JarEntry entry = null;239JarFile jf = (JarFile)jarCache.get(currentUrl);240if(jf == null){241/* First time we have encountered this jar.242* Lets cache its metaData.243*/244try{245URL jarFileUrl = ((JarURLConnection)currentUrl.openConnection()).getJarFileURL();246JarURLConnection jarUrlConnection = (JarURLConnection)new URL("jar", "", jarFileUrl.toExternalForm() + "!/").openConnection();247try{248jf = jarUrlConnection.getJarFile();249}catch(Exception e){250}251if(jf != null){252jarCache.put(currentUrl, jf);253}254} catch (Exception e){255e.printStackTrace();256}257if(jf != null){258Manifest manifest = null;259java.security.cert.Certificate[] certs = null;260URL csUrl = currentUrl;261CodeSource codeSource;262try{263manifest = jf.getManifest();264} catch(Exception e){265e.printStackTrace();266}267entry = jf.getJarEntry(name);268if(entry != null){269certs = entry.getCertificates();270}271codeSource = new CodeSource(csUrl, certs);272CustomLoaderMetaDataCache metaData = new CustomLoaderMetaDataCache();273metaData.manifest = manifest;274metaData.codeSource = codeSource;275metaDataArray[index] = metaData;276}277}278if(entry == null && jf != null){279entry = jf.getJarEntry(name);280}281if(entry != null){282/* We have the first match on the class path, return the current url index */283return index;284}285} else {286String filename = currentUrl.getFile();287String host = currentUrl.getHost();288if (host != null && host.length() > 0) {289filename = new StringBuffer(host.length() + filename.length() + name.length() + 2).290append("//").append(host).append(filename).append(name).toString();291} else {292filename = new StringBuffer(filename.length() + name.length()).293append(filename).append(name).toString();294}295File file = new File(filename);296// Don't throw exceptions for speed297if (file.exists()) {298if(metaDataArray[index] == null){299java.security.cert.Certificate[] certs = null;300CustomLoaderMetaDataCache metaData = new CustomLoaderMetaDataCache();301metaData.manifest = null;302metaData.codeSource = new CodeSource(currentUrl, certs);303metaDataArray[index] = metaData;304}305return index;306}307}308}309return classAtEntry;310}311312private byte[] loadClassBytes(String className, int urlIndex){313byte[] bytes = null;314String name = className.replace('.','/').concat(".class");315URL classLocation = urls[urlIndex];316if(classLocation.getProtocol().equals("jar")){317JarFile jf = (JarFile)jarCache.get(classLocation);318JarEntry entry = jf.getJarEntry(name);319try{320InputStream stream = jf.getInputStream(entry);321bytes = getBytes(stream, true);322} catch (Exception e){323e.printStackTrace();324}325} else {326String filename = classLocation.getFile();327String host = classLocation.getHost();328if (host != null && host.length() > 0) {329filename = new StringBuffer(host.length() + filename.length() + name.length() + 2).330append("//").append(host).append(filename).append(name).toString();331} else {332filename = new StringBuffer(filename.length() + name.length()).333append(filename).append(name).toString();334}335File file = new File(filename);336// Don't throw exceptions for speed337if (file.exists()) {338try{339FileInputStream stream = new FileInputStream(file);340bytes = getBytes(stream, true);341} catch(Exception e){342e.printStackTrace();343}344}345}346return bytes;347}348349public Class findClass(String name) throws ClassNotFoundException {350Class clazz = null;351if(scHelper != null){352byte[] classBytes = scHelper.findSharedClass(name, foundAtIndex);353if(classBytes != null){354if(metaDataArray[foundAtIndex.getIndex()] != null){355checkPackage(name, foundAtIndex.getIndex());356CustomLoaderMetaDataCache metadata = metaDataArray[foundAtIndex.getIndex()];357CodeSource codeSource = metadata.codeSource;358clazz = defineClass(name, classBytes, 0, classBytes.length, codeSource);359}360}361}362if(clazz == null) {363int indexFoundAt = locateClass(name);364if(indexFoundAt != -1){365try{366byte[] classBytes = loadClassBytes(name, indexFoundAt);367checkPackage(name, indexFoundAt);368CustomLoaderMetaDataCache metadata = metaDataArray[indexFoundAt];369CodeSource codeSource = metadata.codeSource;370clazz = defineClass(name, classBytes, 0, classBytes.length, codeSource);371if(clazz != null){372scHelper.storeSharedClass(clazz, indexFoundAt);373}374} catch (Exception e){375e.printStackTrace();376}377}378if(clazz == null){379throw new ClassNotFoundException(name);380}381}382return clazz;383}384385private void checkPackage(String name, int urlIndex){386int index = name.lastIndexOf('.');387if(index != -1){388String packageString = name.substring(0, index);389Manifest manifest = metaDataArray[urlIndex].manifest;390CodeSource codeSource = metaDataArray[urlIndex].codeSource;391synchronized(this){392Package packageInst = getPackage(packageString);393if(packageInst == null){394if (manifest != null){395definePackage(packageString, manifest, codeSource.getLocation());396} else {397definePackage(packageString, null, null, null, null, null, null, null);398}399} else {400boolean exception = false;401if (manifest != null) {402String dirName = packageString.replace('.', '/') + "/";403if (isSealed(manifest, dirName))404exception = !packageInst.isSealed(codeSource.getLocation());405} else406exception = packageInst.isSealed();407if (exception)408throw new SecurityException(com.ibm.oti.util.Msg.getString("Package exception"));409}410}411}412}413414private boolean isSealed(Manifest manifest, String dirName) {415Attributes mainAttributes = manifest.getMainAttributes();416String value = mainAttributes.getValue(Attributes.Name.SEALED);417boolean sealed = value != null &&418value.toLowerCase().equals ("true");419Attributes attributes = manifest.getAttributes(dirName);420if (attributes != null) {421value = attributes.getValue(Attributes.Name.SEALED);422if (value != null)423sealed = value.toLowerCase().equals("true");424}425return sealed;426}427428protected Package definePackage(String name, Manifest man, URL url) throws IllegalArgumentException {429String path = name.replace('.','/').concat("/");430String[] attrs = new String[7];431URL sealedAtURL = null;432433Attributes attr = man.getAttributes(path);434Attributes mainAttr = man.getMainAttributes();435436if(attr != null){437attrs[0] = attr.getValue(Name.SPECIFICATION_TITLE);438attrs[1] = attr.getValue(Name.SPECIFICATION_VERSION);439attrs[2] = attr.getValue(Name.SPECIFICATION_VENDOR);440attrs[3] = attr.getValue(Name.IMPLEMENTATION_TITLE);441attrs[4] = attr.getValue(Name.IMPLEMENTATION_VERSION);442attrs[5] = attr.getValue(Name.IMPLEMENTATION_VENDOR);443attrs[6] = attr.getValue(Name.SEALED);444}445446if(mainAttr != null){447if (attrs[0] == null) {448attrs[0] = mainAttr.getValue(Name.SPECIFICATION_TITLE);449}450if (attrs[1] == null) {451attrs[1] = mainAttr.getValue(Name.SPECIFICATION_VERSION);452}453if (attrs[2] == null) {454attrs[2] = mainAttr.getValue(Name.SPECIFICATION_VENDOR);455}456if (attrs[3] == null) {457attrs[3] = mainAttr.getValue(Name.IMPLEMENTATION_TITLE);458}459if (attrs[4] == null) {460attrs[4] = mainAttr.getValue(Name.IMPLEMENTATION_VERSION);461}462if (attrs[5] == null) {463attrs[5] = mainAttr.getValue(Name.IMPLEMENTATION_VENDOR);464}465if (attrs[6] == null) {466attrs[6] = mainAttr.getValue(Name.SEALED);467}468}469if ("true".equalsIgnoreCase(attrs[6])){470sealedAtURL = url;471}472return definePackage(name, attrs[0], attrs[1], attrs[2], attrs[3], attrs[4], attrs[5], sealedAtURL);473}474475public boolean isClassInSharedCache(String className){476byte[] sharedClass = null;477if (scHelper!=null) {478sharedClass = scHelper.findSharedClass(className, foundAtIndex);479if (sharedClass !=null){480return true;481} else {482return false;483}484}485return false;486}487488public Class getClassFromCache(String name){489Class clazz = null;490byte[] classBytes = scHelper.findSharedClass(name, foundAtIndex);491if(classBytes != null){492CodeSource cs = null;493clazz = defineClass(name, classBytes, 0, classBytes.length, cs);494}495return clazz;496}497498public void confirmAllEntries(){499scHelper.confirmAllEntries();500}501502public boolean changeClassPath(URL[] newUrls){503boolean changed = true;504int urlLength = newUrls.length;505urls = new URL[urlLength];506orgUrls = new URL[urlLength];507for (int i=0; i < urlLength; i++) {508try {509urls[i] = createSearchURL(newUrls[i]);510} catch (MalformedURLException e) {}511orgUrls[i] = newUrls[i];512}513metaDataArray = new CustomLoaderMetaDataCache[urls.length];514initMetaData();515try{516scHelper.setClasspath(newUrls);517} catch (CannotSetClasspathException e){518changed = false;519}520return changed;521}522523public static class FoundAtIndex implements SharedClassURLClasspathHelper.IndexHolder {524525int indexFoundAt = -1;526527public void setIndex(int index) {528indexFoundAt = index;529}530531public int getIndex(){532return indexFoundAt;533}534535public void reset(){536indexFoundAt = -1;537}538539}540}541542543