001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: * The Original Software is NetBeans. The Initial Developer of the Original
026: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
027: * Microsystems, Inc. All Rights Reserved.
028: *
029: * If you wish your version of this file to be governed by only the CDDL
030: * or only the GPL Version 2, indicate your decision by adding
031: * "[Contributor] elects to include this software in this distribution
032: * under the [CDDL or GPL Version 2] license." If you do not indicate a
033: * single choice of license, a recipient has the option to distribute
034: * your version of this file under either the CDDL, the GPL Version 2 or
035: * to extend the choice of license to its licensees as provided above.
036: * However, if you add GPL Version 2 code and therefore, elected the GPL
037: * Version 2 license, then the option applies only if the new code is
038: * made subject to such option by the copyright holder.
039: */
040:
041: package org.netbeans.lib.profiler.server;
042:
043: import java.io.File;
044: import java.io.IOException;
045: import java.io.InputStream;
046: import java.io.RandomAccessFile;
047: import java.net.URI;
048: import java.net.URISyntaxException;
049: import java.net.URL;
050: import java.util.HashMap;
051: import java.util.Map;
052: import java.util.zip.ZipEntry;
053: import java.util.zip.ZipFile;
054:
055: /**
056: * Loading bytes for classes that are known to be loaded by system and bootstrap class loaders.
057: *
058: * @author Tomas Hurka
059: * @author Misha Dmitriev
060: */
061: public class ClassBytesLoader {
062: //~ Static fields/initializers -----------------------------------------------------------------------------------------------
063:
064: private static Map jarCache = new HashMap();
065:
066: //~ Methods ------------------------------------------------------------------------------------------------------------------
067:
068: public static byte[] getClassFileBytes(String className) {
069: String resourceName = className.replace('.', '/') + ".class"; // NOI18N
070: URL classUrl = ClassLoader.getSystemResource(resourceName);
071: // in case the classname is a synthetic class there is no resource defining its bytecode
072: if (classUrl == null) {
073: System.err
074: .println("***Profiler agent warning: could not get .class file for a synthetic class "
075: + className
076: + " in ClassBytesLoader.getClassFileBytes"); // NOI18N
077: return null;
078: }
079: String proto = classUrl.getProtocol();
080:
081: if (proto == null) { // Should not happen, this is a critical error message
082: System.err
083: .println("***Profiler agent critical error: could not get .class file for class "
084: + className
085: + " in ClassBytesLoader.getClassFileBytes"); // NOI18N
086:
087: return null;
088: }
089:
090: //System.err.println("Reading "+classUrl);
091: try {
092: if (proto.equals("jar")) { // NOI18N
093:
094: return readJar(classUrl);
095: } else if (proto.equals("file")) { // NOI18N
096:
097: return readFile(classUrl);
098: } else {
099: System.err
100: .println("***Profiler agent critical error: Invalid URL "
101: + classUrl); // NOI18N
102:
103: return null;
104: }
105: } catch (IOException ex) {
106: System.err
107: .println("*** Profiler agent critical error: caught IOException in ClassBytesLoadergetClassFileBytes: "
108: + ex); // NOI18N
109: ex.printStackTrace();
110: System.err
111: .println("*** End Profiler agent critical error message ---------------------------"); // NOI18N
112:
113: return null;
114: } catch (URISyntaxException ex) {
115: System.err
116: .println("*** Profiler agent critical error: caught URISyntaxException in ClassBytesLoadergetClassFileBytes: "
117: + ex); // NOI18N
118: ex.printStackTrace();
119: System.err
120: .println("*** End Profiler agent critical error message ---------------------------"); // NOI18N
121:
122: return null;
123: }
124: }
125:
126: /** This method just initializes an experimentally determined set of classes that may be called indirectly by
127: * getClassFileBytes() above (through ClassLoader.getSystemResourceAsStream().
128: */
129: public static void preloadClasses() {
130: getClassFileBytes("sun.misc.Launcher"); // NOI18N
131: new java.io.FilePermission("*", "read"); // NOI18N
132:
133: java.util.HashMap h = new java.util.HashMap();
134: h.keySet().iterator();
135: }
136:
137: private static byte[] readFile(final URL classUrl)
138: throws IOException, URISyntaxException {
139: URI uri = new URI(classUrl.toString());
140: File file = new File(uri);
141: RandomAccessFile f = new RandomAccessFile(file, "r");
142: byte[] buf = new byte[(int) f.length()];
143:
144: f.readFully(buf);
145: //System.err.println("Size "+buf.length);
146: f.close();
147:
148: return buf;
149: }
150:
151: private static byte[] readJar(final URL classUrl)
152: throws IOException {
153: String filePart = classUrl.getFile();
154: int sep = filePart.lastIndexOf('!');
155: String file = filePart.substring(0, sep);
156: String entry = filePart.substring(sep + 2);
157: ZipFile jarFile = (ZipFile) jarCache.get(file);
158: InputStream is;
159: ZipEntry zipEntry;
160: byte[] buf;
161: int pos = 0;
162:
163: if (jarFile == null) {
164: jarFile = new ZipFile(new File(URI.create(file)));
165: jarCache.put(file, jarFile);
166: }
167:
168: zipEntry = jarFile.getEntry(entry);
169: is = jarFile.getInputStream(zipEntry);
170: buf = new byte[(int) zipEntry.getSize()];
171:
172: while (pos < buf.length) {
173: pos += is.read(buf, pos, buf.length - pos);
174: }
175:
176: is.close();
177:
178: //System.err.println("Size "+buf.length);
179: return buf;
180: }
181: }
|