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.instrumentation;
042:
043: /**
044: * Basic support for adding entries to a class's constant pool.
045: * This class allows one to create a semi-prepared chunk of bytes (class PackedCPoolFragment) representing entries that
046: * should be added to the constant pool of an arbitrary class. Then, by passing a PackedCPoolFragment to the constructor
047: * of ConstantPoolExtension, one obtains a relocated (i.e. with indices adjusted for a concrete class' existing constant pool)
048: * copy of added constant pool.
049: *
050: * @author Misha Dmitriev
051: */
052: public class ConstantPoolExtension implements JavaClassConstants {
053: //~ Inner Classes ------------------------------------------------------------------------------------------------------------
054:
055: //------------------------------------------ Helper classes -------------------------------------------------
056: public static class CPEntry {
057: //~ Instance fields ------------------------------------------------------------------------------------------------------
058:
059: String utf8;
060: byte tag;
061: int index1;
062: int index2;
063:
064: //~ Constructors ---------------------------------------------------------------------------------------------------------
065:
066: public CPEntry(int tag) {
067: this .tag = (byte) tag;
068: }
069:
070: public CPEntry(String utf8) {
071: this .tag = CONSTANT_Utf8;
072: this .utf8 = utf8;
073: }
074:
075: //~ Methods --------------------------------------------------------------------------------------------------------------
076:
077: public void setIndex1(int idx) {
078: index1 = idx;
079: }
080:
081: public void setIndex2(int idx) {
082: index2 = idx;
083: }
084: }
085:
086: /**
087: * Represents an array of bytes containing constant pool contents to append to the real constant pool, in the unrelocated
088: * form. Entries in this cpool fragment may point either to other entries within the same cpool fragment (internalIndicies
089: * array), or to entries in one other cpool fragment (externalIndices array). In either case indices are relative to the
090: * origin of the corresponding cpool fragment. By calling getRelocatedCPoolBytes(intBaseIndex, extBaseIndex), one gets the real
091: * constant pool added contents, with all indices relocated, i.e. pointing at correct absolute locations in the concrete class'
092: * constant pool.
093: */
094: public static class PackedCPFragment {
095: //~ Static fields/initializers -------------------------------------------------------------------------------------------
096:
097: private static byte[] tmpBytes = new byte[64];
098:
099: //~ Instance fields ------------------------------------------------------------------------------------------------------
100:
101: int nEntries;
102: private byte[] cpoolBytes; // Non-relocated cpool bytes
103: private char[] externalIndices; // Positions of all u2 indices in the above array, that need to be adjusted
104: private char[] internalIndices; // Positions of all u2 indices in the above array, that need to be adjusted
105:
106: //~ Constructors ---------------------------------------------------------------------------------------------------------
107:
108: public PackedCPFragment(CPEntry[] entries) {
109: nEntries = entries.length;
110:
111: // First compute the packed size and the number of indices that would need adjustment
112: int packedSize = 0;
113: int nIntIdx = 0;
114: int nExtIdx = 0;
115:
116: for (int i = 0; i < nEntries; i++) {
117: switch (entries[i].tag) {
118: case CONSTANT_Class:
119: packedSize += 3;
120:
121: if (entries[i].index1 <= 0xFFFF) {
122: nIntIdx++;
123: } else {
124: nExtIdx++;
125: }
126:
127: break;
128: case CONSTANT_Fieldref:
129: case CONSTANT_Methodref:
130: case CONSTANT_InterfaceMethodref:
131: case CONSTANT_NameAndType:
132: packedSize += 5;
133:
134: if (entries[i].index1 <= 0xFFFF) {
135: nIntIdx++;
136: } else {
137: nExtIdx++;
138: }
139:
140: if (entries[i].index2 <= 0xFFFF) {
141: nIntIdx++;
142: } else {
143: nExtIdx++;
144: }
145:
146: break;
147: case CONSTANT_Utf8:
148: packedSize += (3 + entries[i].utf8.length());
149:
150: break;
151: default:
152: System.err
153: .println("*** PackedAddedCPool : unsupported constant!"); // NOI18N
154: }
155: }
156:
157: cpoolBytes = new byte[packedSize];
158: internalIndices = new char[nIntIdx];
159: externalIndices = new char[nExtIdx];
160:
161: int curPos = 0;
162: nIntIdx = 0;
163: nExtIdx = 0;
164:
165: for (int i = 0; i < nEntries; i++) {
166: switch (entries[i].tag) {
167: case CONSTANT_Class:
168: cpoolBytes[curPos++] = entries[i].tag;
169:
170: if (entries[i].index1 <= 0xFFFF) {
171: internalIndices[nIntIdx++] = (char) curPos;
172: } else {
173: externalIndices[nExtIdx++] = (char) curPos;
174: }
175:
176: cpoolBytes[curPos++] = (byte) ((entries[i].index1 >> 8) & 0xFF);
177: cpoolBytes[curPos++] = (byte) ((entries[i].index1) & 0xFF);
178:
179: break;
180: case CONSTANT_Fieldref:
181: case CONSTANT_Methodref:
182: case CONSTANT_InterfaceMethodref:
183: case CONSTANT_NameAndType:
184: cpoolBytes[curPos++] = entries[i].tag;
185:
186: if (entries[i].index1 <= 0xFFFF) {
187: internalIndices[nIntIdx++] = (char) curPos;
188: } else {
189: externalIndices[nExtIdx++] = (char) curPos;
190: }
191:
192: cpoolBytes[curPos++] = (byte) ((entries[i].index1 >> 8) & 0xFF);
193: cpoolBytes[curPos++] = (byte) ((entries[i].index1) & 0xFF);
194:
195: if (entries[i].index2 <= 0xFFFF) {
196: internalIndices[nIntIdx++] = (char) curPos;
197: } else {
198: externalIndices[nExtIdx++] = (char) curPos;
199: }
200:
201: cpoolBytes[curPos++] = (byte) ((entries[i].index2 >> 8) & 0xFF);
202: cpoolBytes[curPos++] = (byte) ((entries[i].index2) & 0xFF);
203:
204: break;
205: case CONSTANT_Utf8:
206: cpoolBytes[curPos++] = entries[i].tag;
207:
208: String utf8 = entries[i].utf8;
209: int len = utf8.length();
210: cpoolBytes[curPos++] = (byte) ((len >> 8) & 0xFF);
211: cpoolBytes[curPos++] = (byte) ((len) & 0xFF);
212:
213: for (int j = 0; j < len; j++) {
214: tmpBytes[j] = (byte) utf8.charAt(j);
215: }
216:
217: System.arraycopy(tmpBytes, 0, cpoolBytes, curPos,
218: len);
219: curPos += len;
220:
221: break;
222: default:
223: System.err
224: .println("*** PackedAddedCPool : unsupported constant!"); // NOI18N
225: }
226: }
227: }
228:
229: //~ Methods --------------------------------------------------------------------------------------------------------------
230:
231: public byte[] getRelocatedCPBytes(int intBaseIndex,
232: int extBaseIndex) {
233: byte[] ret = new byte[cpoolBytes.length];
234: System.arraycopy(cpoolBytes, 0, ret, 0, cpoolBytes.length);
235:
236: for (int i = 0; i < internalIndices.length; i++) {
237: int pos = internalIndices[i];
238: int value = (ret[pos] << 8) + ret[pos + 1];
239: value += intBaseIndex;
240: ret[pos] = (byte) ((value >> 8) & 0xFF);
241: ret[pos + 1] = (byte) ((value) & 0xFF);
242: }
243:
244: for (int i = 0; i < externalIndices.length; i++) {
245: int pos = externalIndices[i];
246: int value = (ret[pos] << 8) + ret[pos + 1];
247: value += extBaseIndex;
248: ret[pos] = (byte) ((value >> 8) & 0xFF);
249: ret[pos + 1] = (byte) ((value) & 0xFF);
250: }
251:
252: return ret;
253: }
254: }
255:
256: //~ Instance fields ----------------------------------------------------------------------------------------------------------
257:
258: protected byte[] addedCPContents;
259: protected int nAddedEntries;
260:
261: //~ Constructors -------------------------------------------------------------------------------------------------------------
262:
263: //----------------------------------------- Protected methods ---------------------------------------------------
264:
265: /** Creates a ConstantPoolExtension containing properly relocated contents from pcp. */
266: protected ConstantPoolExtension(PackedCPFragment pcp,
267: int baseCPCount, int secondaryBaseCPCount) {
268: addedCPContents = pcp.getRelocatedCPBytes(baseCPCount,
269: secondaryBaseCPCount);
270: nAddedEntries = pcp.nEntries;
271: }
272:
273: protected ConstantPoolExtension() {
274: }
275:
276: //~ Methods ------------------------------------------------------------------------------------------------------------------
277:
278: public byte[] getConcatenatedContents(ConstantPoolExtension other) {
279: if (this .addedCPContents == null) {
280: return other.getContents();
281: } else if (other.addedCPContents == null) {
282: return this .getContents();
283: } else {
284: byte[] ret = new byte[this .addedCPContents.length
285: + other.addedCPContents.length];
286: System.arraycopy(this .addedCPContents, 0, ret, 0,
287: this .addedCPContents.length);
288: System.arraycopy(other.addedCPContents, 0, ret,
289: this .addedCPContents.length,
290: other.addedCPContents.length);
291:
292: return ret;
293: }
294: }
295:
296: public byte[] getContents() {
297: return addedCPContents;
298: }
299:
300: //-------------------------------------- Public interface --------------------------------------------------------
301: public int getNEntries() {
302: return nAddedEntries;
303: }
304: }
|