Path: blob/master/test/functional/cmdLineTests/shareClassTests/utils/src/CustomCLs/CustomPartitioningURLLoader.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 CustomPartitioningURLLoader extends SecureClassLoader {5152URL[] urls, orgUrls, searchUrls;53URL url;5455private Hashtable jarCache = new Hashtable(32);56int loaderType;5758String partition = null;5960SharedClassURLHelper scHelper;6162CustomLoaderMetaDataCache[] metaDataArray;6364public CustomPartitioningURLLoader(URL[] passedUrls, ClassLoader parent){65super(parent);66loaderType = ClassLoaderType.CACHEDURL.ord;67int urlLength = passedUrls.length;68searchUrls = new URL[urlLength];69urls = new URL[1];70orgUrls = new URL[urlLength];71for (int i=0; i < urlLength; i++) {72try {73searchUrls[i] = createSearchURL(passedUrls[i]);74} catch (MalformedURLException e) {}75orgUrls[i] = passedUrls[i];76}77metaDataArray = new CustomLoaderMetaDataCache[searchUrls.length];78initMetaData();79SharedClassHelperFactory schFactory = Shared.getSharedClassHelperFactory();80if(schFactory != null){81try{82scHelper = schFactory.getURLHelper(this);83} catch (Exception e){84e.printStackTrace();85}86}87}8889public CustomPartitioningURLLoader(URL[] passedUrls){90super();91loaderType = ClassLoaderType.CACHEDURL.ord;92int urlLength = passedUrls.length;93searchUrls = new URL[urlLength];94urls = new URL[1];95orgUrls = new URL[urlLength];96for (int i=0; i < urlLength; i++) {97try {98searchUrls[i] = createSearchURL(passedUrls[i]);99} catch (MalformedURLException e) {}100orgUrls[i] = passedUrls[i];101}102metaDataArray = new CustomLoaderMetaDataCache[searchUrls.length];103initMetaData();104SharedClassHelperFactory schFactory = Shared.getSharedClassHelperFactory();105if(schFactory != null){106try{107scHelper = schFactory.getURLHelper(this);108} catch (Exception e){109e.printStackTrace();110}111}112}113114public void setPartition(String newPartition){115partition = newPartition;116}117118public void loadClassFrom(String name, int index){119urls[0] = searchUrls[index];120url = orgUrls[index];121System.out.println("\n** Loading class: "+name+" from index: "+index+" url: "+urls[0]);122try{123this.loadClass(name);124} catch(ClassNotFoundException e){125e.printStackTrace();126}127}128129public void loadClassNullStore(String name){130urls[0] = searchUrls[0];131int indexFoundAt = locateClass(name);132try{133byte[] classBytes = loadClassBytes(name, indexFoundAt);134checkPackage(name, indexFoundAt);135CustomLoaderMetaDataCache metadata = metaDataArray[indexFoundAt];136CodeSource codeSource = metadata.codeSource;137Class clazz = defineClass(name, classBytes, 0, classBytes.length, codeSource);138if(clazz != null){139scHelper.storeSharedClass(null, clazz);140}141} catch (Exception e){142e.printStackTrace();143}144}145146public boolean getHelper(){147SharedClassHelperFactory schFactory = Shared.getSharedClassHelperFactory();148SharedClassURLHelper newHelper = null;149try{150newHelper = schFactory.getURLHelper(this);151} catch (Exception e){152return false;153}154155if(newHelper.equals(scHelper)){156return true;157} else {158return false;159}160}161162public void getURLClasspathHelper()throws HelperAlreadyDefinedException {163SharedClassHelperFactory schFactory = Shared.getSharedClassHelperFactory();164SharedClassURLClasspathHelper newHelper = null;165newHelper = schFactory.getURLClasspathHelper(this, urls);166}167168public void getTokenHelper()throws Exception {169SharedClassHelperFactory schFactory = Shared.getSharedClassHelperFactory();170SharedClassTokenHelper newHelper = null;171newHelper = schFactory.getTokenHelper(this);172}173174public boolean duplicateStore(String name){175Class clazz = null;176try{177clazz = this.loadClass(name);178} catch (ClassNotFoundException e){179e.printStackTrace();180}181if (clazz != null){182int indexFoundAt = locateClass(name);183if(indexFoundAt != -1){184scHelper.storeSharedClass(urls[indexFoundAt], clazz);185return true;186}187}188return false;189}190191private void initMetaData(){192for(int loopIndex = 0; loopIndex < metaDataArray.length; loopIndex++){193metaDataArray[loopIndex] = null;194}195}196197private URL createSearchURL(URL url) throws MalformedURLException {198if (url == null) return url;199String protocol = url.getProtocol();200201if (isDirectory(url) || protocol.equals("jar")) {202return url;203} else {204return new URL("jar", "", -1, url.toString() + "!/");205}206}207208private static boolean isDirectory(URL url) {209String file = url.getFile();210return (file.length() > 0 && file.charAt(file.length()-1) == '/');211}212213public Class findClass(String name) throws ClassNotFoundException {214Class clazz = null;215int indexFoundAt = locateClass(name);216System.out.println("\nIndex found at: "+indexFoundAt);217if(scHelper != null){218byte[] classBytes = scHelper.findSharedClass(url, name);219if(classBytes != null){220if(metaDataArray[indexFoundAt] != null){221checkPackage(name, indexFoundAt);222CustomLoaderMetaDataCache metadata = metaDataArray[indexFoundAt];223CodeSource codeSource = metadata.codeSource;224clazz = defineClass(name, classBytes, 0, classBytes.length, codeSource);225}226}227}228if(clazz == null) {229if(indexFoundAt != -1){230try{231byte[] classBytes = loadClassBytes(name, indexFoundAt);232checkPackage(name, indexFoundAt);233CustomLoaderMetaDataCache metadata = metaDataArray[indexFoundAt];234CodeSource codeSource = metadata.codeSource;235clazz = defineClass(name, classBytes, 0, classBytes.length, codeSource);236if(clazz != null){237scHelper.storeSharedClass(partition, url, clazz);238}239} catch (Exception e){240e.printStackTrace();241}242}243if(clazz == null){244throw new ClassNotFoundException(name);245}246}247return clazz;248}249250private void checkPackage(String name, int urlIndex){251int index = name.lastIndexOf('.');252if(index != -1){253String packageString = name.substring(0, index);254Manifest manifest = metaDataArray[urlIndex].manifest;255CodeSource codeSource = metaDataArray[urlIndex].codeSource;256synchronized(this){257Package packageInst = getPackage(packageString);258if(packageInst == null){259if (manifest != null){260definePackage(packageString, manifest, codeSource.getLocation());261} else {262definePackage(packageString, null, null, null, null, null, null, null);263}264} else {265boolean exception = false;266if (manifest != null) {267String dirName = packageString.replace('.', '/') + "/";268if (isSealed(manifest, dirName))269exception = !packageInst.isSealed(codeSource.getLocation());270} else271exception = packageInst.isSealed();272if (exception)273throw new SecurityException(com.ibm.oti.util.Msg.getString("Package exception"));274}275}276}277}278279private static byte[] getBytes(InputStream is, boolean readAvailable) throws IOException {280if (readAvailable) {281byte[] buf = new byte[is.available()];282is.read(buf, 0, buf.length);283is.close();284return buf;285}286byte[] buf = new byte[4096];287int size = is.available();288if (size < 1024) size = 1024;289ByteArrayOutputStream bos = new ByteArrayOutputStream(size);290int count;291while ((count = is.read(buf)) > 0)292bos.write(buf, 0, count);293return bos.toByteArray();294}295296private byte[] loadClassBytes(String className, int urlIndex){297byte[] bytes = null;298String name = className.replace('.','/').concat(".class");299URL classLocation = urls[urlIndex];300if(classLocation.getProtocol().equals("jar")){301JarFile jf = (JarFile)jarCache.get(classLocation);302JarEntry entry = jf.getJarEntry(name);303try{304InputStream stream = jf.getInputStream(entry);305bytes = getBytes(stream, true);306} catch (Exception e){307e.printStackTrace();308}309} else {310String filename = classLocation.getFile();311String host = classLocation.getHost();312if (host != null && host.length() > 0) {313filename = new StringBuffer(host.length() + filename.length() + name.length() + 2).314append("//").append(host).append(filename).append(name).toString();315} else {316filename = new StringBuffer(filename.length() + name.length()).317append(filename).append(name).toString();318}319File file = new File(filename);320// Don't throw exceptions for speed321if (file.exists()) {322try{323FileInputStream stream = new FileInputStream(file);324bytes = getBytes(stream, true);325} catch(Exception e){326e.printStackTrace();327}328}329}330return bytes;331}332333private int locateClass(String className){334int classAtEntry = -1;335String name = className.replace('.','/').concat(".class");336for(int index = 0; index < urls.length; index ++){337URL currentUrl = urls[index];338if(currentUrl.getProtocol().equals("jar")){339JarEntry entry = null;340JarFile jf = (JarFile)jarCache.get(currentUrl);341if(jf == null){342/* First time we have encountered this jar.343* Lets cache its metaData.344*/345try{346URL jarFileUrl = ((JarURLConnection)currentUrl.openConnection()).getJarFileURL();347JarURLConnection jarUrlConnection = (JarURLConnection)new URL("jar", "", jarFileUrl.toExternalForm() + "!/").openConnection();348try{349jf = jarUrlConnection.getJarFile();350}catch(Exception e){351}352if(jf != null){353jarCache.put(currentUrl, jf);354}355} catch (Exception e){356e.printStackTrace();357}358if(jf != null){359Manifest manifest = null;360java.security.cert.Certificate[] certs = null;361URL csUrl = currentUrl;362CodeSource codeSource;363try{364manifest = jf.getManifest();365} catch(Exception e){366e.printStackTrace();367}368entry = jf.getJarEntry(name);369if(entry != null){370certs = entry.getCertificates();371}372codeSource = new CodeSource(csUrl, certs);373CustomLoaderMetaDataCache metaData = new CustomLoaderMetaDataCache();374metaData.manifest = manifest;375metaData.codeSource = codeSource;376metaDataArray[index] = metaData;377}378}379if(entry == null && jf != null){380entry = jf.getJarEntry(name);381}382if(entry != null){383/* We have the first match on the class path, return the current url index */384return index;385}386} else {387String filename = currentUrl.getFile();388String host = currentUrl.getHost();389if (host != null && host.length() > 0) {390filename = new StringBuffer(host.length() + filename.length() + name.length() + 2).391append("//").append(host).append(filename).append(name).toString();392} else {393filename = new StringBuffer(filename.length() + name.length()).394append(filename).append(name).toString();395}396File file = new File(filename);397// Don't throw exceptions for speed398if (file.exists()) {399if(metaDataArray[index] == null){400java.security.cert.Certificate[] certs = null;401CustomLoaderMetaDataCache metaData = new CustomLoaderMetaDataCache();402metaData.manifest = null;403metaData.codeSource = new CodeSource(currentUrl, certs);404metaDataArray[index] = metaData;405}406return index;407}408}409}410return classAtEntry;411}412413private boolean isSealed(Manifest manifest, String dirName) {414Attributes mainAttributes = manifest.getMainAttributes();415String value = mainAttributes.getValue(Attributes.Name.SEALED);416boolean sealed = value != null &&417value.toLowerCase().equals ("true");418Attributes attributes = manifest.getAttributes(dirName);419if (attributes != null) {420value = attributes.getValue(Attributes.Name.SEALED);421if (value != null)422sealed = value.toLowerCase().equals("true");423}424return sealed;425}426427protected Package definePackage(String name, Manifest man, URL url) throws IllegalArgumentException {428String path = name.replace('.','/').concat("/");429String[] attrs = new String[7];430URL sealedAtURL = null;431432Attributes attr = man.getAttributes(path);433Attributes mainAttr = man.getMainAttributes();434435if(attr != null){436attrs[0] = attr.getValue(Name.SPECIFICATION_TITLE);437attrs[1] = attr.getValue(Name.SPECIFICATION_VERSION);438attrs[2] = attr.getValue(Name.SPECIFICATION_VENDOR);439attrs[3] = attr.getValue(Name.IMPLEMENTATION_TITLE);440attrs[4] = attr.getValue(Name.IMPLEMENTATION_VERSION);441attrs[5] = attr.getValue(Name.IMPLEMENTATION_VENDOR);442attrs[6] = attr.getValue(Name.SEALED);443}444445if(mainAttr != null){446if (attrs[0] == null) {447attrs[0] = mainAttr.getValue(Name.SPECIFICATION_TITLE);448}449if (attrs[1] == null) {450attrs[1] = mainAttr.getValue(Name.SPECIFICATION_VERSION);451}452if (attrs[2] == null) {453attrs[2] = mainAttr.getValue(Name.SPECIFICATION_VENDOR);454}455if (attrs[3] == null) {456attrs[3] = mainAttr.getValue(Name.IMPLEMENTATION_TITLE);457}458if (attrs[4] == null) {459attrs[4] = mainAttr.getValue(Name.IMPLEMENTATION_VERSION);460}461if (attrs[5] == null) {462attrs[5] = mainAttr.getValue(Name.IMPLEMENTATION_VENDOR);463}464if (attrs[6] == null) {465attrs[6] = mainAttr.getValue(Name.SEALED);466}467}468if ("true".equalsIgnoreCase(attrs[6])){469sealedAtURL = url;470}471return definePackage(name, attrs[0], attrs[1], attrs[2], attrs[3], attrs[4], attrs[5], sealedAtURL);472}473474public boolean isClassInSharedCache(int index, String className){475URL url = orgUrls[index];476byte[] sharedClass = null;477if (scHelper!=null) {478sharedClass = scHelper.findSharedClass(partition, url, className);479if (sharedClass !=null){480return true;481} else {482return false;483}484}485return false;486}487488public boolean isClassInSharedCacheNullFind(String className){489byte[] sharedClass = null;490if (scHelper!=null) {491sharedClass = scHelper.findSharedClass(partition, null, className);492if (sharedClass !=null){493return true;494} else {495return false;496}497}498return false;499}500}501502503