Source Code Cross Referenced for NewAttributeBands.java in  » Apache-Harmony-Java-SE » org-package » org » apache » harmony » pack200 » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Apache Harmony Java SE » org package » org.apache.harmony.pack200 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         *  Licensed to the Apache Software Foundation (ASF) under one or more
003:         *  contributor license agreements.  See the NOTICE file distributed with
004:         *  this work for additional information regarding copyright ownership.
005:         *  The ASF licenses this file to You under the Apache License, Version 2.0
006:         *  (the "License"); you may not use this file except in compliance with
007:         *  the License.  You may obtain a copy of the License at
008:         *
009:         *     http://www.apache.org/licenses/LICENSE-2.0
010:         *
011:         *  Unless required by applicable law or agreed to in writing, software
012:         *  distributed under the License is distributed on an "AS IS" BASIS,
013:         *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014:         *  See the License for the specific language governing permissions and
015:         *  limitations under the License.
016:         */
017:        package org.apache.harmony.pack200;
018:
019:        import java.io.IOException;
020:        import java.io.InputStream;
021:        import java.io.StringReader;
022:        import java.util.ArrayList;
023:        import java.util.Iterator;
024:        import java.util.List;
025:
026:        import org.apache.harmony.pack200.bytecode.Attribute;
027:        import org.apache.harmony.pack200.bytecode.CPClass;
028:        import org.apache.harmony.pack200.bytecode.CPDouble;
029:        import org.apache.harmony.pack200.bytecode.CPFieldRef;
030:        import org.apache.harmony.pack200.bytecode.CPFloat;
031:        import org.apache.harmony.pack200.bytecode.CPInteger;
032:        import org.apache.harmony.pack200.bytecode.CPInterfaceMethodRef;
033:        import org.apache.harmony.pack200.bytecode.CPLong;
034:        import org.apache.harmony.pack200.bytecode.CPMethodRef;
035:        import org.apache.harmony.pack200.bytecode.CPNameAndType;
036:        import org.apache.harmony.pack200.bytecode.CPString;
037:        import org.apache.harmony.pack200.bytecode.CPUTF8;
038:        import org.apache.harmony.pack200.bytecode.NewAttribute;
039:
040:        /**
041:         * Set of bands relating to a non-predefined attribute
042:         */
043:        public class NewAttributeBands extends BandSet {
044:
045:            private AttributeLayout attributeLayout;
046:
047:            private List attributes;
048:
049:            private int backwardsCallCount;
050:
051:            private List attributeLayoutElements;
052:
053:            public NewAttributeBands(Segment segment,
054:                    AttributeLayout attributeLayout) throws IOException {
055:                super (segment);
056:                this .attributeLayout = attributeLayout;
057:                parseLayout();
058:                attributeLayout.setBackwardsCallCount(backwardsCallCount);
059:            }
060:
061:            /*
062:             * (non-Javadoc)
063:             *
064:             * @see org.apache.harmony.pack200.BandSet#unpack(java.io.InputStream)
065:             */
066:            public void unpack(InputStream in) throws IOException,
067:                    Pack200Exception {
068:                // does nothing - use parseAttributes instead
069:            }
070:
071:            /**
072:             * Returns the list of attributes read in by this band set.  This method
073:             * should only be called after unpack() or it will return null.
074:             * @return List of Attributes
075:             */
076:            public List getAttributes() {
077:                return attributes;
078:            }
079:
080:            /**
081:             * Parse the bands relating to this AttributeLayout and return the correct
082:             * class file attributes as a List of {@link Attribute}
083:             * @throws Pack200Exception
084:             */
085:            public List parseAttributes(InputStream in, int occurrenceCount)
086:                    throws IOException, Pack200Exception {
087:                for (Iterator iter = attributeLayoutElements.iterator(); iter
088:                        .hasNext();) {
089:                    AttributeLayoutElement element = (AttributeLayoutElement) iter
090:                            .next();
091:                    element.readBands(in, occurrenceCount);
092:                }
093:
094:                List attributes = new ArrayList();
095:                for (int i = 0; i < occurrenceCount; i++) {
096:                    attributes.add(getOneAttribute(i, attributeLayoutElements));
097:                }
098:                return attributes;
099:            }
100:
101:            /**
102:             * Get one attribute at the given index from the various bands.
103:             * The correct bands must have already been read in.
104:             * @param index
105:             * @param elements
106:             * @return
107:             */
108:            private Attribute getOneAttribute(int index, List elements) {
109:                NewAttribute attribute = new NewAttribute(attributeLayout
110:                        .getName());
111:                for (Iterator iter = elements.iterator(); iter.hasNext();) {
112:                    AttributeLayoutElement element = (AttributeLayoutElement) iter
113:                            .next();
114:                    element.addToAttribute(index, attribute);
115:                }
116:                return attribute;
117:            }
118:
119:            /**
120:             * Tokenise the layout into AttributeElements
121:             * @return a List of AttributeElements
122:             * @throws IOException
123:             */
124:            private void parseLayout() throws IOException {
125:                if (attributeLayoutElements == null) {
126:                    attributeLayoutElements = new ArrayList();
127:                    StringReader stream = new StringReader(attributeLayout
128:                            .getLayout());
129:                    AttributeLayoutElement e;
130:                    while ((e = readNextAttributeElement(stream)) != null) {
131:                        attributeLayoutElements.add(e);
132:                    }
133:                    resolveCalls();
134:                }
135:            }
136:
137:            /**
138:             * Resolve calls in the attribute layout and returns the number of backwards calls
139:             *
140:             * @param tokens -
141:             *            the attribute layout as a List of AttributeElements
142:             */
143:            private void resolveCalls() {
144:                int backwardsCalls = 0;
145:                for (int i = 0; i < attributeLayoutElements.size(); i++) {
146:                    AttributeLayoutElement element = (AttributeLayoutElement) attributeLayoutElements
147:                            .get(i);
148:                    if (element instanceof  Callable) {
149:                        Callable callable = (Callable) element;
150:                        List body = callable.body; // Look for calls in the body
151:                        for (Iterator iter = body.iterator(); iter.hasNext();) {
152:                            LayoutElement layoutElement = (LayoutElement) iter
153:                                    .next();
154:                            if (layoutElement instanceof  Call) {
155:                                // Set the callable for each call
156:                                Call call = (Call) layoutElement;
157:                                int index = call.callableIndex;
158:                                if (index == 0) { // Calls the parent callable
159:                                    backwardsCalls++;
160:                                    call.setCallable(callable);
161:                                } else if (index > 0) { // Forwards call
162:                                    for (int k = i; k < attributeLayoutElements
163:                                            .size(); k++) {
164:                                        AttributeLayoutElement el = (AttributeLayoutElement) attributeLayoutElements
165:                                                .get(k);
166:                                        if (el instanceof  Callable) {
167:                                            index--;
168:                                            if (index == 0) {
169:                                                call.setCallable((Callable) el);
170:                                                break;
171:                                            }
172:                                        }
173:                                    }
174:                                } else { // Backwards call
175:                                    backwardsCalls++;
176:                                    for (int k = i; k >= 0; k--) {
177:                                        AttributeLayoutElement el = (AttributeLayoutElement) attributeLayoutElements
178:                                                .get(k);
179:                                        if (el instanceof  Callable) {
180:                                            index++;
181:                                            if (index == 0) {
182:                                                call.setCallable((Callable) el);
183:                                                break;
184:                                            }
185:                                        }
186:                                    }
187:                                }
188:                            }
189:                        }
190:                    }
191:                }
192:                backwardsCallCount = backwardsCalls;
193:            }
194:
195:            private AttributeLayoutElement readNextAttributeElement(
196:                    StringReader stream) throws IOException {
197:                int nextChar = stream.read();
198:                if (nextChar == -1) {
199:                    return null;
200:                }
201:                if (nextChar == '[') {
202:                    List body = readBody(getStreamUpToMatchingBracket(stream));
203:                    return new Callable(body);
204:                } else {
205:                    return readNextLayoutElement(stream);
206:                }
207:            }
208:
209:            private LayoutElement readNextLayoutElement(StringReader stream)
210:                    throws IOException {
211:                int nextChar = stream.read();
212:                if (nextChar == -1) {
213:                    return null;
214:                }
215:                switch (nextChar) {
216:                // Integrals
217:                case 'B':
218:                case 'H':
219:                case 'I':
220:                case 'V':
221:                    return new Integral(new String(
222:                            new char[] { (char) nextChar }));
223:                case 'S':
224:                case 'F':
225:                    return new Integral(new String(new char[] {
226:                            (char) nextChar, (char) stream.read() }));
227:                case 'P':
228:                    stream.mark(1);
229:                    if (stream.read() != 'O') {
230:                        stream.reset();
231:                        return new Integral("P" + (char) stream.read());
232:                    } else {
233:                        return new Integral("PO" + (char) stream.read());
234:                    }
235:                case 'O':
236:                    stream.mark(1);
237:                    if (stream.read() != 'S') {
238:                        stream.reset();
239:                        return new Integral("O" + (char) stream.read());
240:                    } else {
241:                        return new Integral("OS" + (char) stream.read());
242:                    }
243:
244:                    // Replication
245:                case 'N':
246:                    char uint_type = (char) stream.read();
247:                    stream.read(); // '['
248:                    String str = readUpToMatchingBracket(stream);
249:                    return new Replication("" + uint_type, str);
250:
251:                    // Union
252:                case 'T':
253:                    String int_type = "" + (char) stream.read();
254:                    if (int_type.equals("S")) {
255:                        int_type += (char) stream.read();
256:                    }
257:                    List unionCases = new ArrayList();
258:                    UnionCase c;
259:                    while ((c = readNextUnionCase(stream)) != null) {
260:                        unionCases.add(c);
261:                    }
262:                    stream.read(); // '('
263:                    stream.read(); // '('
264:                    stream.read(); // '['
265:                    List body = null;
266:                    stream.mark(1);
267:                    char next = (char) stream.read();
268:                    if (next != ']') {
269:                        stream.reset();
270:                        body = readBody(getStreamUpToMatchingBracket(stream));
271:                    }
272:                    return new Union(int_type, unionCases, body);
273:
274:                    // Call
275:                case '(':
276:                    int number = readNumber(stream);
277:                    stream.read(); // ')'
278:                    return new Call(number);
279:                    // Reference
280:                case 'K':
281:                case 'R':
282:                    String string = "" + nextChar + (char) stream.read();
283:                    char nxt = (char) stream.read();
284:                    string += nxt;
285:                    if (nxt == 'N') {
286:                        string += (char) stream.read();
287:                    }
288:                    return new Reference(string);
289:                }
290:                return null;
291:            }
292:
293:            /**
294:             * Read a UnionCase from the stream
295:             * @param stream
296:             * @return
297:             * @throws IOException
298:             */
299:            private UnionCase readNextUnionCase(StringReader stream)
300:                    throws IOException {
301:                stream.mark(2);
302:                stream.read(); // '('
303:                char next = (char) stream.read();
304:                if (next == ')') {
305:                    stream.reset();
306:                    return null;
307:                }
308:                List tags = new ArrayList();
309:                while (next != ')') {
310:                    tags.add(new Integer(readNumber(stream)));
311:                    next = (char) stream.read();
312:                }
313:                stream.read(); // '['
314:                stream.mark(1);
315:                next = (char) stream.read();
316:                if (next == ']') {
317:                    return new UnionCase(tags);
318:                } else {
319:                    stream.reset();
320:                    return new UnionCase(tags,
321:                            readBody(getStreamUpToMatchingBracket(stream)));
322:                }
323:            }
324:
325:            /**
326:             * An AttributeLayoutElement is a part of an attribute layout and has one or more
327:             * bands associated with it, which transmit the AttributeElement data for
328:             * successive Attributes of this type.
329:             */
330:            private interface AttributeLayoutElement {
331:
332:                /**
333:                 * Read the bands associated with this part of the layout
334:                 *
335:                 * @param in
336:                 * @param count
337:                 * @throws Pack200Exception
338:                 * @throws IOException
339:                 */
340:                public void readBands(InputStream in, int count)
341:                        throws IOException, Pack200Exception;
342:
343:                /**
344:                 * Add the band data for this element at the given index to the attribute
345:                 *
346:                 * @param index
347:                 * @param attribute
348:                 */
349:                public void addToAttribute(int index, NewAttribute attribute);
350:
351:            }
352:
353:            private abstract class LayoutElement implements 
354:                    AttributeLayoutElement {
355:
356:                protected int getLength(char uint_type) {
357:                    int length = 0;
358:                    ;
359:                    switch (uint_type) {
360:                    case 'B':
361:                        length = 1;
362:                        break;
363:                    case 'H':
364:                        length = 2;
365:                        break;
366:                    case 'I':
367:                        length = 4;
368:                        break;
369:                    case 'V':
370:                        length = 0;
371:                        break;
372:                    }
373:                    return length;
374:                }
375:            }
376:
377:            private class Integral extends LayoutElement {
378:
379:                private String tag;
380:                private long[] band;
381:
382:                public Integral(String tag) {
383:                    this .tag = tag;
384:                }
385:
386:                public void readBands(InputStream in, int count)
387:                        throws IOException, Pack200Exception {
388:                    band = decodeBandLong(
389:                            attributeLayout.getName() + "_" + tag, in,
390:                            getCodec(tag), count);
391:                }
392:
393:                public void addToAttribute(int n, NewAttribute attribute) {
394:                    long value = band[n];
395:                    if (tag.equals("B") || tag.equals("FB")) {
396:                        attribute.addInteger(1, value);
397:                    } else if (tag.equals("SB")) {
398:                        attribute.addInteger(1, (byte) value);
399:                    } else if (tag.equals("H") || tag.equals("FH")) {
400:                        attribute.addInteger(2, value);
401:                    } else if (tag.equals("SH")) {
402:                        attribute.addInteger(2, (short) value);
403:                    } else if (tag.equals("I") || tag.equals("FI")) {
404:                        attribute.addInteger(4, value);
405:                    } else if (tag.equals("SI")) {
406:                        attribute.addInteger(4, (int) value);
407:                    } else if (tag.equals("V") || tag.equals("FV")
408:                            || tag.equals("SV")) {
409:                        // Don't add V's - they shouldn't be written out to the class file
410:                    } else if (tag.startsWith("PO")) {
411:                        char uint_type = tag.substring(2).toCharArray()[0];
412:                        int length = getLength(uint_type);
413:                        attribute.addBCOffset(length, (int) value);
414:                    } else if (tag.startsWith("P")) {
415:                        char uint_type = tag.substring(1).toCharArray()[0];
416:                        int length = getLength(uint_type);
417:                        attribute.addBCIndex(length, (int) value);
418:                    } else if (tag.startsWith("OS")) {
419:                        char uint_type = tag.substring(1).toCharArray()[0];
420:                        int length = getLength(uint_type);
421:                        if (length == 1) {
422:                            value = (byte) value;
423:                        } else if (length == 2) {
424:                            value = (short) value;
425:                        } else if (length == 4) {
426:                            value = (int) value;
427:                        }
428:                        attribute.addBCLength(length, (int) value);
429:                    } else if (tag.startsWith("O")) {
430:                        char uint_type = tag.substring(1).toCharArray()[0];
431:                        int length = getLength(uint_type);
432:                        attribute.addBCLength(length, (int) value);
433:                    }
434:                }
435:
436:                long getValue(int index) {
437:                    return band[index];
438:                }
439:
440:            }
441:
442:            /**
443:             * A replication is an array of layout elements, with an associated count
444:             */
445:            private class Replication extends LayoutElement {
446:
447:                private Integral countElement;
448:
449:                private List layoutElements = new ArrayList();
450:
451:                public Replication(String tag, String contents)
452:                        throws IOException {
453:                    this .countElement = new Integral(tag);
454:                    StringReader stream = new StringReader(contents);
455:                    LayoutElement e;
456:                    while ((e = readNextLayoutElement(stream)) != null) {
457:                        layoutElements.add(e);
458:                    }
459:                }
460:
461:                public void readBands(InputStream in, int count)
462:                        throws IOException, Pack200Exception {
463:                    countElement.readBands(in, count);
464:                    int arrayCount = 0;
465:                    for (int i = 0; i < count; i++) {
466:                        arrayCount += countElement.getValue(i);
467:                    }
468:                    for (Iterator iter = layoutElements.iterator(); iter
469:                            .hasNext();) {
470:                        LayoutElement element = (LayoutElement) iter.next();
471:                        element.readBands(in, arrayCount);
472:                    }
473:                }
474:
475:                public void addToAttribute(int index, NewAttribute attribute) {
476:                    // Add the count value
477:                    countElement.addToAttribute(index, attribute);
478:
479:                    // Add the corresponding array values
480:                    int offset = 0;
481:                    for (int i = 0; i < index; i++) {
482:                        offset += countElement.getValue(i);
483:                    }
484:                    long numElements = countElement.getValue(index);
485:                    for (int i = offset; i < offset + numElements; i++) {
486:                        for (Iterator iter = layoutElements.iterator(); iter
487:                                .hasNext();) {
488:                            LayoutElement element = (LayoutElement) iter.next();
489:                            element.addToAttribute(i, attribute);
490:                        }
491:                    }
492:                }
493:            }
494:
495:            /**
496:             * A Union is a type of layout element where the tag value acts as a
497:             * selector for one of the union cases
498:             */
499:            private class Union extends LayoutElement {
500:
501:                private Integral unionTag;
502:                private List unionCases;
503:                private List defaultCaseBody;
504:                private int[] caseCounts;
505:                private int defaultCount;
506:
507:                public Union(String tag, List unionCases, List body) {
508:                    this .unionTag = new Integral(tag);
509:                    this .unionCases = unionCases;
510:                    this .defaultCaseBody = body;
511:                }
512:
513:                public void readBands(InputStream in, int count)
514:                        throws IOException, Pack200Exception {
515:                    unionTag.readBands(in, count);
516:                    long[] values = unionTag.band;
517:                    // Count the band size for each union case then read the bands
518:                    caseCounts = new int[unionCases.size()];
519:                    for (int i = 0; i < caseCounts.length; i++) {
520:                        UnionCase unionCase = (UnionCase) unionCases.get(i);
521:                        for (int j = 0; j < values.length; j++) {
522:                            if (unionCase.hasTag(values[j])) {
523:                                caseCounts[i]++;
524:                            }
525:                        }
526:                        unionCase.readBands(in, caseCounts[i]);
527:                    }
528:                    // Count number of default cases then read the default bands
529:                    for (int i = 0; i < values.length; i++) {
530:                        boolean found = false;
531:                        for (Iterator iter = unionCases.iterator(); iter
532:                                .hasNext();) {
533:                            UnionCase unionCase = (UnionCase) iter.next();
534:                            if (unionCase.hasTag(values[i])) {
535:                                found = true;
536:                            }
537:                        }
538:                        if (!found) {
539:                            defaultCount++;
540:                        }
541:                    }
542:                    if (defaultCaseBody != null) {
543:                        for (Iterator iter = defaultCaseBody.iterator(); iter
544:                                .hasNext();) {
545:                            LayoutElement element = (LayoutElement) iter.next();
546:                            element.readBands(in, defaultCount);
547:                        }
548:                    }
549:                }
550:
551:                public void addToAttribute(int n, NewAttribute attribute) {
552:                    unionTag.addToAttribute(n, attribute);
553:                    int offset = 0;
554:                    long[] tagBand = unionTag.band;
555:                    long tag = unionTag.getValue(n);
556:                    boolean defaultCase = true;
557:                    for (Iterator iter = unionCases.iterator(); iter.hasNext();) {
558:                        UnionCase element = (UnionCase) iter.next();
559:                        if (element.hasTag(tag)) {
560:                            defaultCase = false;
561:                            for (int j = 0; j < n; j++) {
562:                                if (element.hasTag(tagBand[j])) {
563:                                    offset++;
564:                                }
565:                            }
566:                            element.addToAttribute(offset, attribute);
567:                        }
568:                    }
569:                    if (defaultCase) {
570:                        // default case
571:                        int defaultOffset = 0;
572:                        for (int j = 0; j < n; j++) {
573:                            boolean found = false;
574:                            for (Iterator iter = unionCases.iterator(); iter
575:                                    .hasNext();) {
576:                                UnionCase element = (UnionCase) iter.next();
577:                                if (element.hasTag(tagBand[j])) {
578:                                    found = true;
579:                                }
580:                            }
581:                            if (!found) {
582:                                defaultOffset++;
583:                            }
584:                        }
585:                        if (defaultCaseBody != null) {
586:                            for (Iterator iter = defaultCaseBody.iterator(); iter
587:                                    .hasNext();) {
588:                                LayoutElement element = (LayoutElement) iter
589:                                        .next();
590:                                element
591:                                        .addToAttribute(defaultOffset,
592:                                                attribute);
593:                            }
594:                        }
595:                    }
596:                }
597:
598:            }
599:
600:            private class Call extends LayoutElement {
601:
602:                private int callableIndex;
603:                private Callable callable;
604:
605:                public Call(int callableIndex) {
606:                    this .callableIndex = callableIndex;
607:                }
608:
609:                public void setCallable(Callable callable) {
610:                    this .callable = callable;
611:                    if (callableIndex < 1) {
612:                        callable.setBackwardsCallable();
613:                    }
614:                }
615:
616:                public void readBands(InputStream in, int count) {
617:                    /*
618:                     * We don't read anything here, but we need to pass the extra count
619:                     * to the callable if it's a forwards call. For backwards callables
620:                     * the count is transmitted directly in the attribute bands and
621:                     * so it is added later.
622:                     */
623:                    if (callableIndex > 0) {
624:                        callable.addCount(count);
625:                    }
626:                }
627:
628:                public void addToAttribute(int n, NewAttribute attribute) {
629:                    callable.addNextToAttribute(attribute);
630:                }
631:            }
632:
633:            /**
634:             * Constant Pool Reference
635:             */
636:            private class Reference extends LayoutElement {
637:
638:                private String tag;
639:
640:                private Object band;
641:
642:                private int length;
643:
644:                public Reference(String tag) {
645:                    this .tag = tag;
646:                    length = getLength(tag.charAt(tag.length()));
647:                }
648:
649:                public void readBands(InputStream in, int count)
650:                        throws IOException, Pack200Exception {
651:                    if (tag.startsWith("KI")) { // Integer
652:                        band = parseCPIntReferences(attributeLayout.getName(),
653:                                in, Codec.UNSIGNED5, count);
654:                    } else if (tag.startsWith("KJ")) { // Long
655:                        band = parseCPLongReferences(attributeLayout.getName(),
656:                                in, Codec.UNSIGNED5, count);
657:                    } else if (tag.startsWith("KF")) { // Float
658:                        band = parseCPFloatReferences(
659:                                attributeLayout.getName(), in, Codec.UNSIGNED5,
660:                                count);
661:                    } else if (tag.startsWith("KD")) { // Double
662:                        band = parseCPDoubleReferences(attributeLayout
663:                                .getName(), in, Codec.UNSIGNED5, count);
664:                    } else if (tag.startsWith("KS")) { // String
665:                        band = parseCPStringReferences(attributeLayout
666:                                .getName(), in, Codec.UNSIGNED5, count);
667:                    } else if (tag.startsWith("RC")) { // Class
668:                        band = parseCPClassReferences(
669:                                attributeLayout.getName(), in, Codec.UNSIGNED5,
670:                                count);
671:                    } else if (tag.startsWith("RS")) { // Signature
672:                        band = parseCPSignatureReferences(attributeLayout
673:                                .getName(), in, Codec.UNSIGNED5, count);
674:                    } else if (tag.startsWith("RD")) { // Descriptor
675:                        band = parseCPDescriptorReferences(attributeLayout
676:                                .getName(), in, Codec.UNSIGNED5, count);
677:                    } else if (tag.startsWith("RF")) { // Field Reference
678:                        band = parseCPFieldRefReferences(attributeLayout
679:                                .getName(), in, Codec.UNSIGNED5, count);
680:                    } else if (tag.startsWith("RM")) { // Method Reference
681:                        band = parseCPMethodRefReferences(attributeLayout
682:                                .getName(), in, Codec.UNSIGNED5, count);
683:                    } else if (tag.startsWith("RI")) { // Interface Method Reference
684:                        band = parseCPInterfaceMethodRefReferences(
685:                                attributeLayout.getName(), in, Codec.UNSIGNED5,
686:                                count);
687:                    } else if (tag.startsWith("RU")) { // UTF8 String
688:                        band = parseCPUTF8References(attributeLayout.getName(),
689:                                in, Codec.UNSIGNED5, count);
690:                    }
691:                }
692:
693:                public void addToAttribute(int n, NewAttribute attribute) {
694:                    if (tag.startsWith("KI")) { // Integer
695:                        attribute
696:                                .addCPConstant(length, ((CPInteger[]) band)[n]);
697:                    } else if (tag.startsWith("KJ")) { // Long
698:                        attribute.addCPConstant(length, ((CPLong[]) band)[n]);
699:                    } else if (tag.startsWith("KF")) { // Float
700:                        attribute.addCPConstant(length, ((CPFloat[]) band)[n]);
701:                    } else if (tag.startsWith("KD")) { // Double
702:                        attribute.addCPConstant(length, ((CPDouble[]) band)[n]);
703:                    } else if (tag.startsWith("KS")) { // String
704:                        attribute.addCPConstant(length, ((CPString[]) band)[n]);
705:                    } else if (tag.startsWith("RC")) { // Class
706:                        attribute.addCPClass(length, ((CPClass[]) band)[n]);
707:                    } else if (tag.startsWith("RS")) { // Signature
708:                        attribute.addCPUTF8(length, ((CPUTF8[]) band)[n]);
709:                    } else if (tag.startsWith("RD")) { // Descriptor
710:                        attribute.addCPNameAndType(length,
711:                                ((CPNameAndType[]) band)[n]);
712:                    } else if (tag.startsWith("RF")) { // Field Reference
713:                        attribute.addCPFieldRef(length,
714:                                ((CPFieldRef[]) band)[n]);
715:                    } else if (tag.startsWith("RM")) { // Method Reference
716:                        attribute.addCPMethodRef(length,
717:                                ((CPMethodRef[]) band)[n]);
718:                    } else if (tag.startsWith("RI")) { // Interface Method Reference
719:                        attribute.addCPIMethodRef(length,
720:                                ((CPInterfaceMethodRef[]) band)[n]);
721:                    } else if (tag.startsWith("RU")) { // UTF8 String
722:                        attribute.addCPUTF8(length, ((CPUTF8[]) band)[n]);
723:                    }
724:                }
725:
726:            }
727:
728:            private class Callable implements  AttributeLayoutElement {
729:
730:                private List body;
731:
732:                private boolean isBackwardsCallable;
733:
734:                public Callable(List body) throws IOException {
735:                    this .body = body;
736:                }
737:
738:                private int count;
739:                private int index;
740:
741:                /**
742:                 * Used by calls when adding band contents to attributes
743:                 * so they don't have to keep track of the internal index
744:                 * of the callable
745:                 * @param attribute
746:                 */
747:                public void addNextToAttribute(NewAttribute attribute) {
748:                    for (Iterator iter = body.iterator(); iter.hasNext();) {
749:                        LayoutElement element = (LayoutElement) iter.next();
750:                        element.addToAttribute(index, attribute);
751:                    }
752:                    index++;
753:                }
754:
755:                /**
756:                 * Adds the count of a call to this callable (ie the number of calls)
757:                 * @param count
758:                 */
759:                public void addCount(int count) {
760:                    this .count += count;
761:                }
762:
763:                public void readBands(InputStream in, int count)
764:                        throws IOException, Pack200Exception {
765:                    count += this .count;
766:                    for (Iterator iter = body.iterator(); iter.hasNext();) {
767:                        LayoutElement element = (LayoutElement) iter.next();
768:                        element.readBands(in, count);
769:                    }
770:                }
771:
772:                public void addToAttribute(int n, NewAttribute attribute) {
773:                    // Ignore n because bands also contain element parts from calls
774:                    for (Iterator iter = body.iterator(); iter.hasNext();) {
775:                        LayoutElement element = (LayoutElement) iter.next();
776:                        element.addToAttribute(index, attribute);
777:                    }
778:                    index++;
779:                }
780:
781:                public boolean isBackwardsCallable() {
782:                    return isBackwardsCallable;
783:                }
784:
785:                /**
786:                 * Tells this Callable that it is a backwards callable
787:                 */
788:                public void setBackwardsCallable() {
789:                    this .isBackwardsCallable = true;
790:                }
791:            }
792:
793:            /**
794:             * A Union case
795:             */
796:            private class UnionCase extends LayoutElement {
797:
798:                private List body;
799:
800:                private List tags;
801:
802:                public UnionCase(List tags) {
803:                    this .tags = tags;
804:                }
805:
806:                public boolean hasTag(long l) {
807:                    return tags.contains(new Integer((int) l));
808:                }
809:
810:                public UnionCase(List tags, List body) throws IOException {
811:                    this .tags = tags;
812:                    this .body = body;
813:                }
814:
815:                public void readBands(InputStream in, int count)
816:                        throws IOException, Pack200Exception {
817:                    if (body != null) {
818:                        for (Iterator iter = body.iterator(); iter.hasNext();) {
819:                            LayoutElement element = (LayoutElement) iter.next();
820:                            element.readBands(in, count);
821:                        }
822:                    }
823:                }
824:
825:                public void addToAttribute(int index, NewAttribute attribute) {
826:                    if (body != null) {
827:                        for (Iterator iter = body.iterator(); iter.hasNext();) {
828:                            LayoutElement element = (LayoutElement) iter.next();
829:                            element.addToAttribute(index, attribute);
830:                        }
831:                    }
832:                }
833:            }
834:
835:            /**
836:             * Utility method to get the contents of the given stream, up to the next ']',
837:             * (ignoring pairs of brackets '[' and ']')
838:             * @param stream
839:             * @return
840:             * @throws IOException
841:             */
842:            private StringReader getStreamUpToMatchingBracket(
843:                    StringReader stream) throws IOException {
844:                StringBuffer sb = new StringBuffer();
845:                int foundBracket = -1;
846:                while (foundBracket != 0) {
847:                    char c = (char) stream.read();
848:                    if (c == ']') {
849:                        foundBracket++;
850:                    }
851:                    if (c == '[') {
852:                        foundBracket--;
853:                    }
854:                    if (!(foundBracket == 0)) {
855:                        sb.append(c);
856:                    }
857:                }
858:                return new StringReader(sb.toString());
859:            }
860:
861:            /**
862:             * Returns the codec that should be used for the given layout element
863:             * @param layoutElement
864:             * @return
865:             */
866:            public BHSDCodec getCodec(String layoutElement) {
867:                if (layoutElement.indexOf("O") >= 0) { //$NON-NLS-1$
868:                    return Codec.BRANCH5;
869:                } else if (layoutElement.indexOf("P") >= 0) { //$NON-NLS-1$
870:                    return Codec.BCI5;
871:                } else if (layoutElement.indexOf("S") >= 0 && layoutElement.indexOf("KS") < 0 //$NON-NLS-1$ //$NON-NLS-2$
872:                        && layoutElement.indexOf("RS") < 0) { //$NON-NLS-1$
873:                    return Codec.SIGNED5;
874:                } else if (layoutElement.indexOf("B") >= 0) { //$NON-NLS-1$
875:                    return Codec.BYTE1;
876:                } else {
877:                    return Codec.UNSIGNED5;
878:                }
879:            }
880:
881:            /**
882:             * Utility method to get the contents of the given stream, up to the next ']',
883:             * (ignoring pairs of brackets '[' and ']')
884:             * @param stream
885:             * @return
886:             * @throws IOException
887:             */
888:            private String readUpToMatchingBracket(StringReader stream)
889:                    throws IOException {
890:                StringBuffer sb = new StringBuffer();
891:                int foundBracket = -1;
892:                while (foundBracket != 0) {
893:                    char c = (char) stream.read();
894:                    if (c == ']') {
895:                        foundBracket++;
896:                    }
897:                    if (c == '[') {
898:                        foundBracket--;
899:                    }
900:                    if (!(foundBracket == 0)) {
901:                        sb.append(c);
902:                    }
903:                }
904:                return sb.toString();
905:            }
906:
907:            /**
908:             * Read a number from the stream and return it
909:             * @param stream
910:             * @return
911:             * @throws IOException
912:             */
913:            private int readNumber(StringReader stream) throws IOException {
914:                stream.mark(1);
915:                char first = (char) stream.read();
916:                boolean negative = first == '-';
917:                if (!negative) {
918:                    stream.reset();
919:                }
920:                stream.mark(100);
921:                int i;
922:                int length = 0;
923:                while ((i = (stream.read())) != -1
924:                        && Character.isDigit((char) i)) {
925:                    length++;
926:                }
927:                stream.reset();
928:                char[] digits = new char[length];
929:                stream.read(digits);
930:                return Integer.parseInt((negative ? "-" : "")
931:                        + new String(digits));
932:            }
933:
934:            /**
935:             * Read a 'body' section of the layout from the given stream
936:             * @param stream
937:             * @return List of LayoutElements
938:             * @throws IOException
939:             */
940:            private List readBody(StringReader stream) throws IOException {
941:                List layoutElements = new ArrayList();
942:                LayoutElement e;
943:                while ((e = readNextLayoutElement(stream)) != null) {
944:                    layoutElements.add(e);
945:                }
946:                return layoutElements;
947:            }
948:
949:            public int getBackwardsCallCount() {
950:                return backwardsCallCount;
951:            }
952:
953:            /**
954:             * Once the attribute bands have been read the callables can be informed
955:             * about the number of times each is subject to a backwards call. This
956:             * method is used to set this information.
957:             *
958:             * @param backwardsCalls
959:             *            one int for each backwards callable, which contains the number
960:             *            of times that callable is subject to a backwards call.
961:             * @throws IOException
962:             */
963:            public void setBackwardsCalls(int[] backwardsCalls)
964:                    throws IOException {
965:                int index = 0;
966:                parseLayout();
967:                for (Iterator iter = attributeLayoutElements.iterator(); iter
968:                        .hasNext();) {
969:                    AttributeLayoutElement element = (AttributeLayoutElement) iter
970:                            .next();
971:                    if (element instanceof  Callable
972:                            && ((Callable) element).isBackwardsCallable()) {
973:                        ((Callable) element).addCount(backwardsCalls[index]);
974:                        index++;
975:                    }
976:                }
977:            }
978:
979:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.