Path: blob/master/test/functional/cmdLineTests/shareClassTests/utils/src/CustomCLs/CustomTokenClassLoader.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 CustomTokenClassLoader extends SecureClassLoader {5152URL[] urls, orgUrls;5354private Hashtable jarCache = new Hashtable(32);55int loaderType;5657SharedClassTokenHelper scHelper;5859CustomLoaderMetaDataCache[] metaDataArray;6061String token = null;6263boolean checkCache = true;6465public CustomTokenClassLoader(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.getTokenHelper(this);83} catch (Exception e){84e.printStackTrace();85}86}87}8889public CustomTokenClassLoader(URL[] passedUrls){90super();91loaderType = ClassLoaderType.CACHEDURL.ord;92int urlLength = passedUrls.length;93urls = new URL[urlLength];94orgUrls = new URL[urlLength];95for (int i=0; i < urlLength; i++) {96try {97urls[i] = createSearchURL(passedUrls[i]);98} catch (MalformedURLException e) {}99orgUrls[i] = passedUrls[i];100}101metaDataArray = new CustomLoaderMetaDataCache[urls.length];102initMetaData();103SharedClassHelperFactory schFactory = Shared.getSharedClassHelperFactory();104if(schFactory != null){105try{106scHelper = schFactory.getTokenHelper(this);107} catch (Exception e){108e.printStackTrace();109}110}111}112113public void setToken(String setTo){114token = setTo;115}116117public boolean getHelper(){118SharedClassHelperFactory schFactory = Shared.getSharedClassHelperFactory();119SharedClassTokenHelper newHelper = null;120try{121newHelper = schFactory.getTokenHelper(this);122} catch (Exception e){123return false;124}125126if(newHelper.equals(scHelper)){127return true;128} else {129return false;130}131}132133public void getURLClasspathHelper()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 boolean duplicateStore(String name){146Class clazz = null;147try{148clazz = this.loadClass(name);149} catch (ClassNotFoundException e){150e.printStackTrace();151}152if (clazz != null){153int indexFoundAt = locateClass(name);154if(indexFoundAt != -1){155scHelper.storeSharedClass(token, clazz);156return true;157}158}159return false;160}161162private void initMetaData(){163for(int loopIndex = 0; loopIndex < metaDataArray.length; loopIndex++){164metaDataArray[loopIndex] = null;165}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 static boolean isDirectory(URL url) {180String file = url.getFile();181return (file.length() > 0 && file.charAt(file.length()-1) == '/');182}183184public Class findClass(String name) throws ClassNotFoundException {185Class clazz = null;186int indexFoundAt = locateClass(name);187if(checkCache){188if(scHelper != null){189byte[] classBytes = scHelper.findSharedClass(token, name);190if(classBytes != null){191if(metaDataArray[indexFoundAt] != null){192checkPackage(name, indexFoundAt);193CustomLoaderMetaDataCache metadata = metaDataArray[indexFoundAt];194CodeSource codeSource = metadata.codeSource;195clazz = defineClass(name, classBytes, 0, classBytes.length, codeSource);196}197}198}199}200if(clazz == null) {201if(indexFoundAt != -1){202try{203byte[] classBytes = loadClassBytes(name, indexFoundAt);204checkPackage(name, indexFoundAt);205CustomLoaderMetaDataCache metadata = metaDataArray[indexFoundAt];206CodeSource codeSource = metadata.codeSource;207clazz = defineClass(name, classBytes, 0, classBytes.length, codeSource);208if(clazz != null){209scHelper.storeSharedClass(token, clazz);210}211} catch (Exception e){212e.printStackTrace();213}214}215if(clazz == null){216throw new ClassNotFoundException(name);217}218}219return clazz;220}221222private void checkPackage(String name, int urlIndex){223int index = name.lastIndexOf('.');224if(index != -1){225String packageString = name.substring(0, index);226Manifest manifest = metaDataArray[urlIndex].manifest;227CodeSource codeSource = metaDataArray[urlIndex].codeSource;228synchronized(this){229Package packageInst = getPackage(packageString);230if(packageInst == null){231if (manifest != null){232definePackage(packageString, manifest, codeSource.getLocation());233} else {234definePackage(packageString, null, null, null, null, null, null, null);235}236} else {237boolean exception = false;238if (manifest != null) {239String dirName = packageString.replace('.', '/') + "/";240if (isSealed(manifest, dirName))241exception = !packageInst.isSealed(codeSource.getLocation());242} else243exception = packageInst.isSealed();244if (exception)245throw new SecurityException(com.ibm.oti.util.Msg.getString("Package exception"));246}247}248}249}250251private static byte[] getBytes(InputStream is, boolean readAvailable) throws IOException {252if (readAvailable) {253byte[] buf = new byte[is.available()];254is.read(buf, 0, buf.length);255is.close();256return buf;257}258byte[] buf = new byte[4096];259int size = is.available();260if (size < 1024) size = 1024;261ByteArrayOutputStream bos = new ByteArrayOutputStream(size);262int count;263while ((count = is.read(buf)) > 0)264bos.write(buf, 0, count);265return bos.toByteArray();266}267268private byte[] loadClassBytes(String className, int urlIndex){269byte[] bytes = null;270String name = className.replace('.','/').concat(".class");271URL classLocation = urls[urlIndex];272if(classLocation.getProtocol().equals("jar")){273JarFile jf = (JarFile)jarCache.get(classLocation);274JarEntry entry = jf.getJarEntry(name);275try{276InputStream stream = jf.getInputStream(entry);277bytes = getBytes(stream, true);278} catch (Exception e){279e.printStackTrace();280}281} else {282String filename = classLocation.getFile();283String host = classLocation.getHost();284if (host != null && host.length() > 0) {285filename = new StringBuffer(host.length() + filename.length() + name.length() + 2).286append("//").append(host).append(filename).append(name).toString();287} else {288filename = new StringBuffer(filename.length() + name.length()).289append(filename).append(name).toString();290}291File file = new File(filename);292// Don't throw exceptions for speed293if (file.exists()) {294try{295FileInputStream stream = new FileInputStream(file);296bytes = getBytes(stream, true);297} catch(Exception e){298e.printStackTrace();299}300}301}302return bytes;303}304305private int locateClass(String className){306int classAtEntry = -1;307String name = className.replace('.','/').concat(".class");308for(int index = 0; index < urls.length; index ++){309URL currentUrl = urls[index];310if(currentUrl.getProtocol().equals("jar")){311JarEntry entry = null;312JarFile jf = (JarFile)jarCache.get(currentUrl);313if(jf == null){314/* First time we have encountered this jar.315* Lets cache its metaData.316*/317try{318URL jarFileUrl = ((JarURLConnection)currentUrl.openConnection()).getJarFileURL();319JarURLConnection jarUrlConnection = (JarURLConnection)new URL("jar", "", jarFileUrl.toExternalForm() + "!/").openConnection();320try{321jf = jarUrlConnection.getJarFile();322}catch(Exception e){323}324if(jf != null){325jarCache.put(currentUrl, jf);326}327} catch (Exception e){328e.printStackTrace();329}330if(jf != null){331Manifest manifest = null;332java.security.cert.Certificate[] certs = null;333URL csUrl = currentUrl;334CodeSource codeSource;335try{336manifest = jf.getManifest();337} catch(Exception e){338e.printStackTrace();339}340entry = jf.getJarEntry(name);341if(entry != null){342certs = entry.getCertificates();343}344codeSource = new CodeSource(csUrl, certs);345CustomLoaderMetaDataCache metaData = new CustomLoaderMetaDataCache();346metaData.manifest = manifest;347metaData.codeSource = codeSource;348metaDataArray[index] = metaData;349}350}351if(entry == null && jf != null){352entry = jf.getJarEntry(name);353}354if(entry != null){355/* We have the first match on the class path, return the current url index */356return index;357}358} else {359String filename = currentUrl.getFile();360String host = currentUrl.getHost();361if (host != null && host.length() > 0) {362filename = new StringBuffer(host.length() + filename.length() + name.length() + 2).363append("//").append(host).append(filename).append(name).toString();364} else {365filename = new StringBuffer(filename.length() + name.length()).366append(filename).append(name).toString();367}368File file = new File(filename);369// Don't throw exceptions for speed370if (file.exists()) {371if(metaDataArray[index] == null){372java.security.cert.Certificate[] certs = null;373CustomLoaderMetaDataCache metaData = new CustomLoaderMetaDataCache();374metaData.manifest = null;375metaData.codeSource = new CodeSource(currentUrl, certs);376metaDataArray[index] = metaData;377}378return index;379}380}381}382return classAtEntry;383}384385private boolean isSealed(Manifest manifest, String dirName) {386Attributes mainAttributes = manifest.getMainAttributes();387String value = mainAttributes.getValue(Attributes.Name.SEALED);388boolean sealed = value != null &&389value.toLowerCase().equals ("true");390Attributes attributes = manifest.getAttributes(dirName);391if (attributes != null) {392value = attributes.getValue(Attributes.Name.SEALED);393if (value != null)394sealed = value.toLowerCase().equals("true");395}396return sealed;397}398399protected Package definePackage(String name, Manifest man, URL url) throws IllegalArgumentException {400String path = name.replace('.','/').concat("/");401String[] attrs = new String[7];402URL sealedAtURL = null;403404Attributes attr = man.getAttributes(path);405Attributes mainAttr = man.getMainAttributes();406407if(attr != null){408attrs[0] = attr.getValue(Name.SPECIFICATION_TITLE);409attrs[1] = attr.getValue(Name.SPECIFICATION_VERSION);410attrs[2] = attr.getValue(Name.SPECIFICATION_VENDOR);411attrs[3] = attr.getValue(Name.IMPLEMENTATION_TITLE);412attrs[4] = attr.getValue(Name.IMPLEMENTATION_VERSION);413attrs[5] = attr.getValue(Name.IMPLEMENTATION_VENDOR);414attrs[6] = attr.getValue(Name.SEALED);415}416417if(mainAttr != null){418if (attrs[0] == null) {419attrs[0] = mainAttr.getValue(Name.SPECIFICATION_TITLE);420}421if (attrs[1] == null) {422attrs[1] = mainAttr.getValue(Name.SPECIFICATION_VERSION);423}424if (attrs[2] == null) {425attrs[2] = mainAttr.getValue(Name.SPECIFICATION_VENDOR);426}427if (attrs[3] == null) {428attrs[3] = mainAttr.getValue(Name.IMPLEMENTATION_TITLE);429}430if (attrs[4] == null) {431attrs[4] = mainAttr.getValue(Name.IMPLEMENTATION_VERSION);432}433if (attrs[5] == null) {434attrs[5] = mainAttr.getValue(Name.IMPLEMENTATION_VENDOR);435}436if (attrs[6] == null) {437attrs[6] = mainAttr.getValue(Name.SEALED);438}439}440if ("true".equalsIgnoreCase(attrs[6])){441sealedAtURL = url;442}443return definePackage(name, attrs[0], attrs[1], attrs[2], attrs[3], attrs[4], attrs[5], sealedAtURL);444}445446public boolean isClassInSharedCache(String token, String className){447byte[] sharedClass = null;448if (scHelper!=null) {449sharedClass = scHelper.findSharedClass(token, className);450if (sharedClass !=null){451return true;452} else {453return false;454}455}456System.out.println("CustomTokenClassLoader::isClassInSharedCache scHelper is null");457return false;458}459460public Class getClassFromCache(String name){461Class clazz = null;462byte[] classBytes = scHelper.findSharedClass(token, name);463if(classBytes != null){464CodeSource cs = null;465clazz = defineClass(name, classBytes, 0, classBytes.length, cs);466}467return clazz;468}469470public Class loadClassNoCache(String name) {471Class clazz = null;472checkCache = false;473try{474clazz = this.loadClass(name);475}catch(ClassNotFoundException e){476e.printStackTrace();477}478checkCache = true;479return clazz;480}481482}483484485