001: /*
002: * Copyright (c) 1998-2008 Caucho Technology -- all rights reserved
003: *
004: * This file is part of Resin(R) Open Source
005: *
006: * Each copy or derived work must preserve the copyright notice and this
007: * notice unmodified.
008: *
009: * Resin Open Source is free software; you can redistribute it and/or modify
010: * it under the terms of the GNU General Public License as published by
011: * the Free Software Foundation; either version 2 of the License, or
012: * (at your option) any later version.
013: *
014: * Resin Open Source is distributed in the hope that it will be useful,
015: * but WITHOUT ANY WARRANTY; without even the implied warranty of
016: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
017: * of NON-INFRINGEMENT. See the GNU General Public License for more
018: * details.
019: *
020: * You should have received a copy of the GNU General Public License
021: * along with Resin Open Source; if not, write to the
022: *
023: * Free Software Foundation, Inc.
024: * 59 Temple Place, Suite 330
025: * Boston, MA 02111-1307 USA
026: *
027: * @author Scott Ferguson
028: */
029:
030: package com.caucho.bytecode;
031:
032: import com.caucho.log.Log;
033:
034: import java.io.IOException;
035: import java.util.ArrayList;
036: import java.util.HashMap;
037: import java.util.logging.Logger;
038:
039: /**
040: * Represents a constant pool entry.
041: */
042: public class ConstantPool {
043: static private final Logger log = Log.open(ConstantPool.class);
044:
045: public static final int CP_CLASS = 7;
046: public static final int CP_FIELD_REF = 9;
047: public static final int CP_METHOD_REF = 10;
048: public static final int CP_INTERFACE_METHOD_REF = 11;
049: public static final int CP_STRING = 8;
050: public static final int CP_INTEGER = 3;
051: public static final int CP_FLOAT = 4;
052: public static final int CP_LONG = 5;
053: public static final int CP_DOUBLE = 6;
054: public static final int CP_NAME_AND_TYPE = 12;
055: public static final int CP_UTF8 = 1;
056:
057: private ArrayList<ConstantPoolEntry> _entries;
058: private HashMap<String, Utf8Constant> _utf8Map = new HashMap<String, Utf8Constant>();
059:
060: ConstantPool() {
061: _entries = new ArrayList<ConstantPoolEntry>();
062: _entries.add(null);
063: }
064:
065: /**
066: * Returns an entry
067: */
068: public ConstantPoolEntry getEntry(int index) {
069: return _entries.get(index);
070: }
071:
072: /**
073: * Returns all the entries.
074: */
075: public ArrayList<ConstantPoolEntry> getEntries() {
076: return _entries;
077: }
078:
079: /**
080: * Returns a class constant
081: */
082: public ClassConstant getClass(int index) {
083: return (ClassConstant) _entries.get(index);
084: }
085:
086: /**
087: * Returns a field ref entry
088: */
089: public FieldRefConstant getFieldRef(int index) {
090: return (FieldRefConstant) _entries.get(index);
091: }
092:
093: /**
094: * Returns a method ref entry
095: */
096: public MethodRefConstant getMethodRef(int index) {
097: return (MethodRefConstant) _entries.get(index);
098: }
099:
100: /**
101: * Returns an interface method ref entry
102: */
103: public InterfaceMethodRefConstant getInterfaceMethodRef(int index) {
104: return (InterfaceMethodRefConstant) _entries.get(index);
105: }
106:
107: /**
108: * Returns a string constant
109: */
110: public StringConstant getString(int index) {
111: return (StringConstant) _entries.get(index);
112: }
113:
114: /**
115: * Returns an integer constant
116: */
117: public IntegerConstant getInteger(int index) {
118: return (IntegerConstant) _entries.get(index);
119: }
120:
121: /**
122: * Returns a long constant
123: */
124: public LongConstant getLong(int index) {
125: return (LongConstant) _entries.get(index);
126: }
127:
128: /**
129: * Returns a float constant
130: */
131: public FloatConstant getFloat(int index) {
132: return (FloatConstant) _entries.get(index);
133: }
134:
135: /**
136: * Returns a double constant
137: */
138: public DoubleConstant getDouble(int index) {
139: return (DoubleConstant) _entries.get(index);
140: }
141:
142: /**
143: * Returns a name-and-type constant
144: */
145: public NameAndTypeConstant getNameAndType(int index) {
146: return (NameAndTypeConstant) _entries.get(index);
147: }
148:
149: /**
150: * Returns a utf-8 constant
151: */
152: public Utf8Constant getUtf8(int index) {
153: return (Utf8Constant) _entries.get(index);
154: }
155:
156: /**
157: * Returns a utf-8 constant as a string
158: */
159: public String getUtf8AsString(int index) {
160: Utf8Constant utf8 = (Utf8Constant) _entries.get(index);
161:
162: if (utf8 == null)
163: return null;
164: else
165: return utf8.getValue();
166: }
167:
168: /**
169: * Adds a new constant.
170: */
171: public void addConstant(ConstantPoolEntry entry) {
172: if (entry instanceof Utf8Constant) {
173: Utf8Constant utf8 = (Utf8Constant) entry;
174:
175: _utf8Map.put(utf8.getValue(), utf8);
176: }
177:
178: _entries.add(entry);
179: }
180:
181: /**
182: * Gets a UTF-8 constant.
183: */
184: public Utf8Constant getUTF8(String value) {
185: return _utf8Map.get(value);
186: }
187:
188: /**
189: * Adds a UTF-8 constant.
190: */
191: public Utf8Constant addUTF8(String value) {
192: Utf8Constant entry = getUTF8(value);
193:
194: if (entry != null)
195: return entry;
196:
197: entry = new Utf8Constant(this , _entries.size(), value);
198:
199: addConstant(entry);
200:
201: return entry;
202: }
203:
204: /**
205: * Gets a string constant.
206: */
207: public StringConstant getString(String name) {
208: for (int i = 0; i < _entries.size(); i++) {
209: ConstantPoolEntry entry = _entries.get(i);
210:
211: if (!(entry instanceof StringConstant))
212: continue;
213:
214: StringConstant stringEntry = (StringConstant) entry;
215:
216: if (stringEntry.getString().equals(name))
217: return stringEntry;
218: }
219:
220: return null;
221: }
222:
223: /**
224: * Adds a string constant.
225: */
226: public StringConstant addString(String name) {
227: StringConstant entry = getString(name);
228:
229: if (entry != null)
230: return entry;
231:
232: Utf8Constant utf8 = addUTF8(name);
233:
234: entry = new StringConstant(this , _entries.size(), utf8
235: .getIndex());
236:
237: addConstant(entry);
238:
239: return entry;
240: }
241:
242: /**
243: * Gets a integer constant.
244: */
245: public IntegerConstant getIntegerByValue(int value) {
246: for (int i = 0; i < _entries.size(); i++) {
247: ConstantPoolEntry entry = _entries.get(i);
248:
249: if (!(entry instanceof IntegerConstant))
250: continue;
251:
252: IntegerConstant integerEntry = (IntegerConstant) entry;
253:
254: if (integerEntry.getValue() == value)
255: return integerEntry;
256: }
257:
258: return null;
259: }
260:
261: /**
262: * Adds a integer constant.
263: */
264: public IntegerConstant addInteger(int value) {
265: IntegerConstant entry = getIntegerByValue(value);
266:
267: if (entry != null)
268: return entry;
269:
270: entry = new IntegerConstant(this , _entries.size(), value);
271:
272: addConstant(entry);
273:
274: return entry;
275: }
276:
277: /**
278: * Gets a long constant.
279: */
280: public LongConstant getLongByValue(long value) {
281: for (int i = 0; i < _entries.size(); i++) {
282: ConstantPoolEntry entry = _entries.get(i);
283:
284: if (!(entry instanceof LongConstant))
285: continue;
286:
287: LongConstant longEntry = (LongConstant) entry;
288:
289: if (longEntry.getValue() == value)
290: return longEntry;
291: }
292:
293: return null;
294: }
295:
296: /**
297: * Adds a long constant.
298: */
299: public LongConstant addLong(long value) {
300: LongConstant entry = getLongByValue(value);
301:
302: if (entry != null)
303: return entry;
304:
305: entry = new LongConstant(this , _entries.size(), value);
306:
307: addConstant(entry);
308: addConstant(null);
309:
310: return entry;
311: }
312:
313: /**
314: * Gets a float constant.
315: */
316: public FloatConstant getFloatByValue(float value) {
317: for (int i = 0; i < _entries.size(); i++) {
318: ConstantPoolEntry entry = _entries.get(i);
319:
320: if (!(entry instanceof FloatConstant))
321: continue;
322:
323: FloatConstant floatEntry = (FloatConstant) entry;
324:
325: if (floatEntry.getValue() == value)
326: return floatEntry;
327: }
328:
329: return null;
330: }
331:
332: /**
333: * Adds a float constant.
334: */
335: public FloatConstant addFloat(float value) {
336: FloatConstant entry = getFloatByValue(value);
337:
338: if (entry != null)
339: return entry;
340:
341: entry = new FloatConstant(this , _entries.size(), value);
342:
343: addConstant(entry);
344:
345: return entry;
346: }
347:
348: /**
349: * Gets a double constant.
350: */
351: public DoubleConstant getDoubleByValue(double value) {
352: for (int i = 0; i < _entries.size(); i++) {
353: ConstantPoolEntry entry = _entries.get(i);
354:
355: if (!(entry instanceof DoubleConstant))
356: continue;
357:
358: DoubleConstant doubleEntry = (DoubleConstant) entry;
359:
360: if (doubleEntry.getValue() == value)
361: return doubleEntry;
362: }
363:
364: return null;
365: }
366:
367: /**
368: * Adds a double constant.
369: */
370: public DoubleConstant addDouble(double value) {
371: DoubleConstant entry = getDoubleByValue(value);
372:
373: if (entry != null)
374: return entry;
375:
376: entry = new DoubleConstant(this , _entries.size(), value);
377:
378: addConstant(entry);
379: addConstant(null);
380:
381: return entry;
382: }
383:
384: /**
385: * Gets a class constant.
386: */
387: public ClassConstant getClass(String name) {
388: for (int i = 0; i < _entries.size(); i++) {
389: ConstantPoolEntry entry = _entries.get(i);
390:
391: if (!(entry instanceof ClassConstant))
392: continue;
393:
394: ClassConstant classEntry = (ClassConstant) entry;
395:
396: if (classEntry.getName().equals(name))
397: return classEntry;
398: }
399:
400: return null;
401: }
402:
403: /**
404: * Adds a class constant.
405: */
406: public ClassConstant addClass(String name) {
407: ClassConstant entry = getClass(name);
408:
409: if (entry != null)
410: return entry;
411:
412: Utf8Constant utf8 = addUTF8(name);
413:
414: entry = new ClassConstant(this , _entries.size(), utf8
415: .getIndex());
416:
417: addConstant(entry);
418:
419: return entry;
420: }
421:
422: /**
423: * Gets a name-and-type constant.
424: */
425: public NameAndTypeConstant getNameAndType(String name, String type) {
426: for (int i = 0; i < _entries.size(); i++) {
427: ConstantPoolEntry entry = _entries.get(i);
428:
429: if (!(entry instanceof NameAndTypeConstant))
430: continue;
431:
432: NameAndTypeConstant methodEntry = (NameAndTypeConstant) entry;
433:
434: if (methodEntry.getName().equals(name)
435: && methodEntry.getType().equals(type))
436: return methodEntry;
437: }
438:
439: return null;
440: }
441:
442: /**
443: * Adds a name-and-type constant.
444: */
445: public NameAndTypeConstant addNameAndType(String name, String type) {
446: NameAndTypeConstant entry = getNameAndType(name, type);
447:
448: if (entry != null)
449: return entry;
450:
451: Utf8Constant nameEntry = addUTF8(name);
452: Utf8Constant typeEntry = addUTF8(type);
453:
454: entry = new NameAndTypeConstant(this , _entries.size(),
455: nameEntry.getIndex(), typeEntry.getIndex());
456:
457: addConstant(entry);
458:
459: return entry;
460: }
461:
462: /**
463: * Gets a field ref constant.
464: */
465: public FieldRefConstant getFieldRef(String className, String name,
466: String type) {
467: for (int i = 0; i < _entries.size(); i++) {
468: ConstantPoolEntry entry = _entries.get(i);
469:
470: if (!(entry instanceof FieldRefConstant))
471: continue;
472:
473: FieldRefConstant fieldEntry = (FieldRefConstant) entry;
474:
475: if (fieldEntry.getClassName().equals(className)
476: && fieldEntry.getName().equals(name)
477: && fieldEntry.getType().equals(type))
478: return fieldEntry;
479: }
480:
481: return null;
482: }
483:
484: /**
485: * Gets a field ref constant.
486: */
487: public FieldRefConstant getFieldRef(String name) {
488: for (int i = 0; i < _entries.size(); i++) {
489: ConstantPoolEntry entry = _entries.get(i);
490:
491: if (!(entry instanceof FieldRefConstant))
492: continue;
493:
494: FieldRefConstant fieldEntry = (FieldRefConstant) entry;
495:
496: if (fieldEntry.getName().equals(name))
497: return fieldEntry;
498: }
499:
500: return null;
501: }
502:
503: /**
504: * Adds a field ref constant.
505: */
506: public FieldRefConstant addFieldRef(String className, String name,
507: String type) {
508: FieldRefConstant entry = getFieldRef(className, name, type);
509:
510: if (entry != null)
511: return entry;
512:
513: ClassConstant classEntry = addClass(className);
514: NameAndTypeConstant typeEntry = addNameAndType(name, type);
515:
516: entry = new FieldRefConstant(this , _entries.size(), classEntry
517: .getIndex(), typeEntry.getIndex());
518:
519: addConstant(entry);
520:
521: return entry;
522: }
523:
524: /**
525: * Gets a method ref constant.
526: */
527: public MethodRefConstant getMethodRef(String className,
528: String name, String type) {
529: for (int i = 0; i < _entries.size(); i++) {
530: ConstantPoolEntry entry = _entries.get(i);
531:
532: if (!(entry instanceof MethodRefConstant))
533: continue;
534:
535: MethodRefConstant methodEntry = (MethodRefConstant) entry;
536:
537: if (methodEntry.getClassName().equals(className)
538: && methodEntry.getName().equals(name)
539: && methodEntry.getType().equals(type))
540: return methodEntry;
541: }
542:
543: return null;
544: }
545:
546: /**
547: * Adds a method ref constant.
548: */
549: public MethodRefConstant addMethodRef(String className,
550: String name, String type) {
551: MethodRefConstant entry = getMethodRef(className, name, type);
552:
553: if (entry != null)
554: return entry;
555:
556: ClassConstant classEntry = addClass(className);
557: NameAndTypeConstant typeEntry = addNameAndType(name, type);
558:
559: entry = new MethodRefConstant(this , _entries.size(), classEntry
560: .getIndex(), typeEntry.getIndex());
561:
562: addConstant(entry);
563:
564: return entry;
565: }
566:
567: /**
568: * Gets an interface constant.
569: */
570: public InterfaceMethodRefConstant getInterfaceRef(String className,
571: String name, String type) {
572: for (int i = 0; i < _entries.size(); i++) {
573: ConstantPoolEntry entry = _entries.get(i);
574:
575: if (!(entry instanceof InterfaceMethodRefConstant))
576: continue;
577:
578: InterfaceMethodRefConstant methodEntry;
579: methodEntry = (InterfaceMethodRefConstant) entry;
580:
581: if (methodEntry.getClassName().equals(className)
582: && methodEntry.getName().equals(name)
583: && methodEntry.getType().equals(type))
584: return methodEntry;
585: }
586:
587: return null;
588: }
589:
590: /**
591: * Adds an interface ref constant.
592: */
593: public InterfaceMethodRefConstant addInterfaceRef(String className,
594: String name, String type) {
595: InterfaceMethodRefConstant entry = getInterfaceRef(className,
596: name, type);
597:
598: if (entry != null)
599: return entry;
600:
601: ClassConstant classEntry = addClass(className);
602: NameAndTypeConstant typeEntry = addNameAndType(name, type);
603:
604: entry = new InterfaceMethodRefConstant(this , _entries.size(),
605: classEntry.getIndex(), typeEntry.getIndex());
606:
607: addConstant(entry);
608:
609: return entry;
610: }
611:
612: /**
613: * Writes the contents of the pool.
614: */
615: void write(ByteCodeWriter out) throws IOException {
616: out.writeShort(_entries.size());
617:
618: for (int i = 1; i < _entries.size(); i++) {
619: ConstantPoolEntry entry = _entries.get(i);
620:
621: if (entry != null)
622: entry.write(out);
623: }
624: }
625: }
|