1 /******************************************************************************* 2 * Copyright (c) 2006, 2018 IBM Corp. and others 3 * 4 * This program and the accompanying materials are made available under 5 * the terms of the Eclipse Public License 2.0 which accompanies this 6 * distribution and is available at https://www.eclipse.org/legal/epl-2.0/ 7 * or the Apache License, Version 2.0 which accompanies this distribution and 8 * is available at https://www.apache.org/licenses/LICENSE-2.0. 9 * 10 * This Source Code may also be made available under the following 11 * Secondary Licenses when the conditions for such availability set 12 * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU 13 * General Public License, version 2 with the GNU Classpath 14 * Exception [1] and GNU General Public License, version 2 with the 15 * OpenJDK Assembly Exception [2]. 16 * 17 * [1] https://www.gnu.org/software/classpath/license.html 18 * [2] http://openjdk.java.net/legal/assembly-exception.html 19 * 20 * 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-exception 21 *******************************************************************************/ 22 23 package org.eclipse.osgi.internal.cds; 24 25 import com.ibm.oti.shared.SharedClassURLHelper; 26 import java.net.MalformedURLException; 27 import java.net.URL; 28 import org.eclipse.osgi.storage.bundlefile.BundleEntry; 29 import org.eclipse.osgi.storage.bundlefile.BundleFile; 30 import org.eclipse.osgi.storage.bundlefile.BundleFileWrapper; 31 32 /** 33 * Wraps an actual BundleFile object for purposes of loading classes from the 34 * shared classes cache. 35 */ 36 public class CDSBundleFile extends BundleFileWrapper { 37 private final static String classFileExt = ".class"; //$NON-NLS-1$ 38 private final URL url; // the URL to the content of the real bundle file 39 private SharedClassURLHelper urlHelper; // the url helper set by the classloader 40 private boolean primed = false; 41 42 /** 43 * The constructor 44 * @param wrapped the real bundle file 45 */ CDSBundleFile(BundleFile wrapped)46 public CDSBundleFile(BundleFile wrapped) { 47 super(wrapped); 48 // get the url to the content of the real bundle file 49 URL content = null; 50 try { 51 content = new URL("file", "", wrapped.getBaseFile().getAbsolutePath()); //$NON-NLS-1$ //$NON-NLS-2$ 52 } catch (MalformedURLException e) { 53 // do nothing 54 } 55 this.url = content; 56 } 57 CDSBundleFile(BundleFile bundleFile, SharedClassURLHelper urlHelper)58 public CDSBundleFile(BundleFile bundleFile, SharedClassURLHelper urlHelper) { 59 this(bundleFile); 60 this.urlHelper = urlHelper; 61 } 62 63 /* 64 * (non-Javadoc) 65 * @see org.eclipse.osgi.storage.bundlefile.BundleFile#getEntry(java.lang.String) 66 * 67 * If path is not for a class then just use the wrapped bundle file to answer the call. 68 * If the path is for a class, it returns a CDSBundleEntry object. 69 * If the path is for a class, it will look for the magic cookie in the 70 * shared classes cache. If found, the bytes representing the magic cookie are stored in CDSBundleEntry object. 71 */ 72 @Override getEntry(String path)73 public BundleEntry getEntry(String path) { 74 if (!primed || !path.endsWith(classFileExt)) { 75 return super.getEntry(path); 76 } 77 byte[] classbytes = getClassBytes(path.substring(0, path.length() - classFileExt.length())); 78 if (classbytes == null) { 79 return super.getEntry(path); 80 } 81 82 BundleEntry be = new CDSBundleEntry(path, classbytes, this); 83 return be; 84 } 85 getWrappedEntry(String path)86 BundleEntry getWrappedEntry(String path) { 87 return super.getEntry(path); 88 } 89 90 /** 91 * Returns the file url to the content of the actual bundle file 92 * @return the file url to the content of the actual bundle file 93 */ getURL()94 URL getURL() { 95 return url; 96 } 97 98 /** 99 * Returns the url helper for this bundle file. This is set by the 100 * class loading hook 101 * @return the url helper for this bundle file 102 */ getURLHelper()103 SharedClassURLHelper getURLHelper() { 104 return urlHelper; 105 } 106 107 /** 108 * Sets the url helper for this bundle file. This is called by the 109 * class loading hook. 110 * @param urlHelper the url helper 111 */ setURLHelper(SharedClassURLHelper urlHelper)112 void setURLHelper(SharedClassURLHelper urlHelper) { 113 this.urlHelper = urlHelper; 114 this.primed = false; // always unprime when a new urlHelper is set 115 } 116 117 /** 118 * Sets the primed flag for the bundle file. This is called by the 119 * class loading hook after the first class has been loaded from disk for 120 * this bundle file. 121 * @param primed the primed flag 122 */ setPrimed(boolean primed)123 void setPrimed(boolean primed) { 124 this.primed = primed; 125 } 126 127 /** 128 * Searches in the shared classes cache for the specified class name. 129 * @param name the name of the class 130 * @return the magic cookie to the shared class or null if the class is not in the cache. 131 */ getClassBytes(String name)132 private byte[] getClassBytes(String name) { 133 if (urlHelper == null || url == null) 134 return null; 135 return urlHelper.findSharedClass(null, url, name); 136 } 137 138 /** 139 * Returns the primed flag for this bundle file. 140 * @return the primed flag 141 */ getPrimed()142 public boolean getPrimed() { 143 return this.primed; 144 } 145 } 146