Source Code Cross Referenced for InternalClassTransformationImplTest.java in  » Web-Framework » Tapestry » org » apache » tapestry » internal » services » 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 » Web Framework » Tapestry » org.apache.tapestry.internal.services 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        // Copyright 2006, 2007 The Apache Software Foundation
0002:        //
0003:        // Licensed under the Apache License, Version 2.0 (the "License");
0004:        // you may not use this file except in compliance with the License.
0005:        // You may obtain a copy of the License at
0006:        //
0007:        //     http://www.apache.org/licenses/LICENSE-2.0
0008:        //
0009:        // Unless required by applicable law or agreed to in writing, software
0010:        // distributed under the License is distributed on an "AS IS" BASIS,
0011:        // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0012:        // See the License for the specific language governing permissions and
0013:        // limitations under the License.
0014:
0015:        package org.apache.tapestry.internal.services;
0016:
0017:        import static java.lang.Thread.currentThread;
0018:        import static java.util.Arrays.asList;
0019:
0020:        import java.lang.annotation.Documented;
0021:        import java.lang.annotation.Target;
0022:        import java.lang.reflect.Field;
0023:        import java.lang.reflect.Modifier;
0024:        import java.util.Arrays;
0025:        import java.util.List;
0026:        import java.util.Map;
0027:
0028:        import javassist.ClassPool;
0029:        import javassist.CtClass;
0030:        import javassist.CtMethod;
0031:        import javassist.Loader;
0032:        import javassist.LoaderClassPath;
0033:        import javassist.NotFoundException;
0034:
0035:        import org.apache.commons.logging.Log;
0036:        import org.apache.tapestry.annotations.Meta;
0037:        import org.apache.tapestry.annotations.OnEvent;
0038:        import org.apache.tapestry.annotations.Retain;
0039:        import org.apache.tapestry.annotations.SetupRender;
0040:        import org.apache.tapestry.internal.InternalComponentResources;
0041:        import org.apache.tapestry.internal.test.InternalBaseTestCase;
0042:        import org.apache.tapestry.internal.transform.InheritedAnnotation;
0043:        import org.apache.tapestry.internal.transform.pages.AbstractFoo;
0044:        import org.apache.tapestry.internal.transform.pages.BarImpl;
0045:        import org.apache.tapestry.internal.transform.pages.BasicComponent;
0046:        import org.apache.tapestry.internal.transform.pages.ChildClassInheritsAnnotation;
0047:        import org.apache.tapestry.internal.transform.pages.ClaimedFields;
0048:        import org.apache.tapestry.internal.transform.pages.EventHandlerTarget;
0049:        import org.apache.tapestry.internal.transform.pages.FindFieldClass;
0050:        import org.apache.tapestry.internal.transform.pages.MethodIdentifier;
0051:        import org.apache.tapestry.internal.transform.pages.ParentClass;
0052:        import org.apache.tapestry.internal.transform.pages.TargetObject;
0053:        import org.apache.tapestry.internal.transform.pages.TargetObjectSubclass;
0054:        import org.apache.tapestry.ioc.internal.services.PropertyAccessImpl;
0055:        import org.apache.tapestry.ioc.services.PropertyAccess;
0056:        import org.apache.tapestry.runtime.Component;
0057:        import org.apache.tapestry.runtime.ComponentResourcesAware;
0058:        import org.apache.tapestry.services.ClassTransformation;
0059:        import org.apache.tapestry.services.MethodFilter;
0060:        import org.apache.tapestry.services.MethodSignature;
0061:        import org.testng.annotations.AfterClass;
0062:        import org.testng.annotations.BeforeClass;
0063:        import org.testng.annotations.BeforeMethod;
0064:        import org.testng.annotations.Test;
0065:
0066:        /**
0067:         * The tests share a number of resources, and so are run sequentially.
0068:         */
0069:        @Test(sequential=true)
0070:        public class InternalClassTransformationImplTest extends
0071:                InternalBaseTestCase {
0072:            private static final String STRING_CLASS_NAME = "java.lang.String";
0073:
0074:            private ClassPool _classPool;
0075:
0076:            private final ClassLoader _contextClassLoader = currentThread()
0077:                    .getContextClassLoader();
0078:
0079:            private Loader _loader;
0080:
0081:            private PropertyAccess _access;
0082:
0083:            @BeforeClass
0084:            public void setup_access() {
0085:                _access = getService("PropertyAccess", PropertyAccess.class);
0086:            }
0087:
0088:            @AfterClass
0089:            public void cleanup_access() {
0090:                _access = null;
0091:            }
0092:
0093:            /**
0094:             * We need a new ClassPool for each individual test, since many of the tests will end up
0095:             * modifying one or more CtClass instances.
0096:             */
0097:            @BeforeMethod
0098:            public void setup_classpool() {
0099:                _classPool = new ClassPool();
0100:
0101:                _loader = new Loader(_contextClassLoader, _classPool);
0102:
0103:                // This ensures that only the classes we explicitly access and modify
0104:                // are loaded by the new loader; everthing else comes out of the common
0105:                // context class loader, which prevents a lot of nasty class cast exceptions.
0106:
0107:                _loader.delegateLoadingOf("org.apache.tapestry.");
0108:
0109:                // Inside Maven Surefire, the system classpath is not sufficient to find all
0110:                // the necessary files.
0111:                _classPool.appendClassPath(new LoaderClassPath(_loader));
0112:            }
0113:
0114:            private CtClass findCtClass(Class targetClass)
0115:                    throws NotFoundException {
0116:                return _classPool.get(targetClass.getName());
0117:            }
0118:
0119:            @Test
0120:            public void new_member_name() throws Exception {
0121:                Log log = mockLog();
0122:
0123:                replay();
0124:
0125:                ClassTransformation ct = createClassTransformation(
0126:                        ParentClass.class, log);
0127:
0128:                assertEquals(ct.newMemberName("fred"), "_$fred");
0129:                assertEquals(ct.newMemberName("fred"), "_$fred_0");
0130:
0131:                // Here we're exposing a bit of the internal algorithm, which strips
0132:                // off '$' and '_' before tacking "_$" in front.
0133:
0134:                assertEquals(ct.newMemberName("_fred"), "_$fred_1");
0135:                assertEquals(ct.newMemberName("_$fred"), "_$fred_2");
0136:                assertEquals(ct.newMemberName("__$___$____$_fred"), "_$fred_3");
0137:
0138:                // Here we're trying to force conflicts with existing declared
0139:                // fields and methods of the class.
0140:
0141:                assertEquals(ct.newMemberName("_parentField"), "_$parentField");
0142:                assertEquals(ct.newMemberName("conflictField"),
0143:                        "_$conflictField_0");
0144:                assertEquals(ct.newMemberName("conflictMethod"),
0145:                        "_$conflictMethod_0");
0146:
0147:                verify();
0148:            }
0149:
0150:            @Test
0151:            public void new_member_name_with_prefix() throws Exception {
0152:                Log log = mockLog();
0153:
0154:                replay();
0155:
0156:                ClassTransformation ct = createClassTransformation(
0157:                        ParentClass.class, log);
0158:
0159:                assertEquals(ct.newMemberName("prefix", "fred"),
0160:                        "_$prefix_fred");
0161:                assertEquals(ct.newMemberName("prefix", "fred"),
0162:                        "_$prefix_fred_0");
0163:
0164:                // Here we're exposing a bit of the internal algorithm, which strips
0165:                // off '$' and '_' before tacking "_$" in front.
0166:
0167:                assertEquals(ct.newMemberName("prefix", "_fred"),
0168:                        "_$prefix_fred_1");
0169:                assertEquals(ct.newMemberName("prefix", "_$fred"),
0170:                        "_$prefix_fred_2");
0171:                assertEquals(ct.newMemberName("prefix", "__$___$____$_fred"),
0172:                        "_$prefix_fred_3");
0173:
0174:                verify();
0175:            }
0176:
0177:            private InternalClassTransformation createClassTransformation(
0178:                    Class targetClass, Log log) throws NotFoundException {
0179:                CtClass ctClass = findCtClass(targetClass);
0180:
0181:                return new InternalClassTransformationImpl(ctClass,
0182:                        _contextClassLoader, log, null);
0183:            }
0184:
0185:            @Test
0186:            public void find_annotation_on_unknown_field() throws Exception {
0187:                Log log = mockLog();
0188:
0189:                replay();
0190:
0191:                ClassTransformation ct = createClassTransformation(
0192:                        ParentClass.class, log);
0193:
0194:                try {
0195:                    ct.getFieldAnnotation("unknownField", Retain.class);
0196:                    unreachable();
0197:                } catch (RuntimeException ex) {
0198:                    assertEquals(
0199:                            ex.getMessage(),
0200:                            "Class org.apache.tapestry.internal.transform.pages.ParentClass does not contain a field named 'unknownField'.");
0201:                }
0202:
0203:                verify();
0204:            }
0205:
0206:            @Test
0207:            public void find_field_annotation() throws Exception {
0208:                Log log = mockLog();
0209:
0210:                replay();
0211:
0212:                ClassTransformation ct = createClassTransformation(
0213:                        ParentClass.class, log);
0214:
0215:                Retain retain = ct.getFieldAnnotation("_annotatedField",
0216:                        Retain.class);
0217:
0218:                assertNotNull(retain);
0219:
0220:                verify();
0221:            }
0222:
0223:            @Test
0224:            public void field_does_not_contain_requested_annotation()
0225:                    throws Exception {
0226:                Log log = mockLog();
0227:
0228:                replay();
0229:
0230:                ClassTransformation ct = createClassTransformation(
0231:                        ParentClass.class, log);
0232:
0233:                // Field with annotations, but not that annotation
0234:                assertNull(ct.getFieldAnnotation("_annotatedField",
0235:                        Override.class));
0236:
0237:                // Field with no annotations
0238:                assertNull(ct
0239:                        .getFieldAnnotation("_parentField", Override.class));
0240:
0241:                verify();
0242:            }
0243:
0244:            @Test
0245:            public void find_fields_with_annotation() throws Exception {
0246:                Log log = mockLog();
0247:
0248:                replay();
0249:
0250:                ClassTransformation ct = createClassTransformation(
0251:                        ParentClass.class, log);
0252:
0253:                List<String> fields = ct.findFieldsWithAnnotation(Retain.class);
0254:
0255:                assertEquals(fields.size(), 1);
0256:                assertEquals(fields.get(0), "_annotatedField");
0257:
0258:                verify();
0259:            }
0260:
0261:            @Test
0262:            public void find_fields_of_type() throws Exception {
0263:                Log log = mockLog();
0264:
0265:                replay();
0266:
0267:                ClassTransformation ct = createClassTransformation(
0268:                        FindFieldClass.class, log);
0269:
0270:                checkFindFields(ct, "boolean", "_booleanValue");
0271:                checkFindFields(ct, "int[]", "_intArrayValue");
0272:                checkFindFields(ct, "java.lang.String", "_stringValue");
0273:                checkFindFields(ct, "java.util.Date[]", "_dateArrayValue");
0274:
0275:                verify();
0276:            }
0277:
0278:            @Test
0279:            public void get_field_modifiers() throws Exception {
0280:                Log log = mockLog();
0281:
0282:                replay();
0283:
0284:                ClassTransformation ct = createClassTransformation(
0285:                        CheckFieldType.class, log);
0286:
0287:                assertEquals(ct.getFieldModifiers("_privateField"),
0288:                        Modifier.PRIVATE);
0289:                assertEquals(ct.getFieldModifiers("_map"), Modifier.PRIVATE
0290:                        + Modifier.FINAL);
0291:            }
0292:
0293:            @Test
0294:            public void get_field_exists() throws Exception {
0295:                Log log = mockLog();
0296:
0297:                replay();
0298:
0299:                ClassTransformation ct = createClassTransformation(
0300:                        CheckFieldType.class, log);
0301:
0302:                assertTrue(ct.isField("_privateField"));
0303:                assertFalse(ct.isField("_doesNotExist"));
0304:
0305:                verify();
0306:            }
0307:
0308:            @Test
0309:            public void find_fields_of_type_excludes_claimed_fields()
0310:                    throws Exception {
0311:                Log log = mockLog();
0312:
0313:                replay();
0314:
0315:                ClassTransformation ct = createClassTransformation(
0316:                        FindFieldClass.class, log);
0317:
0318:                ct.claimField("_booleanValue", this );
0319:
0320:                checkFindFields(ct, "boolean");
0321:
0322:                verify();
0323:            }
0324:
0325:            private void checkFindFields(ClassTransformation ct,
0326:                    String fieldType, String... expectedNames) {
0327:                List<String> actual = ct.findFieldsOfType(fieldType);
0328:
0329:                assertEquals(actual, Arrays.asList(expectedNames));
0330:            }
0331:
0332:            @Test
0333:            public void find_fields_with_annotation_excludes_claimed_files()
0334:                    throws Exception {
0335:                Log log = mockLog();
0336:
0337:                replay();
0338:
0339:                ClassTransformation ct = createClassTransformation(
0340:                        ParentClass.class, log);
0341:
0342:                ct.claimField("_annotatedField", this );
0343:
0344:                List<String> fields = ct.findFieldsWithAnnotation(Retain.class);
0345:
0346:                assertTrue(fields.isEmpty());
0347:
0348:                verify();
0349:            }
0350:
0351:            @Test
0352:            public void no_fields_contain_requested_annotation()
0353:                    throws Exception {
0354:                Log log = mockLog();
0355:
0356:                replay();
0357:
0358:                ClassTransformation ct = createClassTransformation(
0359:                        ParentClass.class, log);
0360:
0361:                List<String> fields = ct
0362:                        .findFieldsWithAnnotation(Documented.class);
0363:
0364:                assertTrue(fields.isEmpty());
0365:
0366:                verify();
0367:            }
0368:
0369:            @Test
0370:            public void claim_fields() throws Exception {
0371:                Log log = mockLog();
0372:
0373:                replay();
0374:
0375:                ClassTransformation ct = createClassTransformation(
0376:                        ClaimedFields.class, log);
0377:
0378:                List<String> unclaimed = ct.findUnclaimedFields();
0379:
0380:                assertEquals(unclaimed,
0381:                        asList("_field1", "_field4", "_zzfield"));
0382:
0383:                ct.claimField("_field4", "Fred");
0384:
0385:                unclaimed = ct.findUnclaimedFields();
0386:
0387:                assertEquals(unclaimed, asList("_field1", "_zzfield"));
0388:
0389:                try {
0390:                    ct.claimField("_field4", "Barney");
0391:                    unreachable();
0392:                } catch (RuntimeException ex) {
0393:                    assertEquals(
0394:                            ex.getMessage(),
0395:                            "Field _field4 of class org.apache.tapestry.internal.transform.pages.ClaimedFields is already claimed by Fred and can not be claimed by Barney.");
0396:                }
0397:
0398:                verify();
0399:            }
0400:
0401:            @Test
0402:            public void added_fields_are_not_listed_as_unclaimed_fields()
0403:                    throws Exception {
0404:                Log log = mockLog();
0405:
0406:                replay();
0407:
0408:                ClassTransformation ct = createClassTransformation(
0409:                        ClaimedFields.class, log);
0410:
0411:                ct.addField(Modifier.PRIVATE, "int", "newField");
0412:
0413:                List<String> unclaimed = ct.findUnclaimedFields();
0414:
0415:                assertEquals(unclaimed,
0416:                        asList("_field1", "_field4", "_zzfield"));
0417:
0418:                verify();
0419:            }
0420:
0421:            @Test
0422:            public void find_class_annotations() throws Exception {
0423:                Log log = mockLog();
0424:
0425:                replay();
0426:
0427:                ClassTransformation ct = createClassTransformation(
0428:                        ParentClass.class, log);
0429:
0430:                Meta meta = ct.getAnnotation(Meta.class);
0431:
0432:                assertNotNull(meta);
0433:
0434:                // Try again (the annotations will be cached). Use an annotation
0435:                // that will not be present.
0436:
0437:                Target t = ct.getAnnotation(Target.class);
0438:
0439:                assertNull(t);
0440:
0441:                verify();
0442:            }
0443:
0444:            /**
0445:             * More a test of how Javassist works. Javassist does not honor the Inherited annotation for
0446:             * classes (this kind of makes sense, since it won't necessarily have the super-class in
0447:             * memory).
0448:             */
0449:            @Test
0450:            public void ensure_subclasses_inherit_parent_class_annotations()
0451:                    throws Exception {
0452:                // The Java runtime does honor @Inherited
0453:                assertNotNull(ChildClassInheritsAnnotation.class
0454:                        .getAnnotation(InheritedAnnotation.class));
0455:
0456:                Log log = mockLog();
0457:
0458:                replay();
0459:
0460:                ClassTransformation ct = createClassTransformation(
0461:                        ChildClassInheritsAnnotation.class, log);
0462:
0463:                InheritedAnnotation ia = ct
0464:                        .getAnnotation(InheritedAnnotation.class);
0465:
0466:                // Javassist does not, but ClassTransformation patches around that.
0467:
0468:                assertNotNull(ia);
0469:
0470:                verify();
0471:            }
0472:
0473:            /**
0474:             * These tests are really to assert my understanding of Javassist's API. I guess we should keep
0475:             * them around to make sure that future versions of Javassist work the same as our expectations.
0476:             */
0477:            @Test
0478:            public void ensure_javassist_still_does_not_show_inherited_interfaces()
0479:                    throws Exception {
0480:                CtClass ctClass = findCtClass(BarImpl.class);
0481:
0482:                CtClass[] interfaces = ctClass.getInterfaces();
0483:
0484:                // Just the interfaces implemented by this particular class, not
0485:                // inherited interfaces.
0486:
0487:                assertEquals(interfaces.length, 1);
0488:
0489:                assertEquals(interfaces[0].getName(), BarInterface.class
0490:                        .getName());
0491:
0492:                CtClass parentClass = ctClass.getSuperclass();
0493:
0494:                interfaces = parentClass.getInterfaces();
0495:
0496:                assertEquals(interfaces.length, 1);
0497:
0498:                assertEquals(interfaces[0].getName(), FooInterface.class
0499:                        .getName());
0500:            }
0501:
0502:            @Test
0503:            public void ensure_javassist_does_not_show_interface_methods_on_abstract_class()
0504:                    throws Exception {
0505:                CtClass ctClass = findCtClass(AbstractFoo.class);
0506:
0507:                CtClass[] interfaces = ctClass.getInterfaces();
0508:
0509:                assertEquals(interfaces.length, 1);
0510:
0511:                assertEquals(interfaces[0].getName(), FooInterface.class
0512:                        .getName());
0513:
0514:                // In some cases, Java reflection on an abstract class implementing an interface
0515:                // will show the interface methods as abstract methods on the class. This seems
0516:                // to vary from JVM to JVM. I believe Javassist is more consistent here.
0517:
0518:                CtMethod[] methods = ctClass.getDeclaredMethods();
0519:
0520:                assertEquals(methods.length, 0);
0521:            }
0522:
0523:            @Test
0524:            public void ensure_javassist_does_not_show_extended_interface_methods_on_interface()
0525:                    throws Exception {
0526:                CtClass ctClass = findCtClass(FooBarInterface.class);
0527:
0528:                // Just want to check that an interface that extends other interfaces
0529:                // doesn't show those other interface's methods.
0530:
0531:                CtMethod[] methods = ctClass.getDeclaredMethods();
0532:
0533:                assertEquals(methods.length, 0);
0534:            }
0535:
0536:            @Test
0537:            public void add_injected_field() throws Exception {
0538:                InternalComponentResources resources = mockInternalComponentResources();
0539:
0540:                CtClass targetObjectCtClass = findCtClass(TargetObject.class);
0541:
0542:                Log log = mockLog();
0543:
0544:                replay();
0545:
0546:                InternalClassTransformation ct = new InternalClassTransformationImpl(
0547:                        targetObjectCtClass, _contextClassLoader, log, null);
0548:
0549:                // Default behavior is to add an injected field for the InternalComponentResources object,
0550:                // so we'll just check that.
0551:
0552:                ct.finish();
0553:
0554:                Class transformed = _classPool.toClass(targetObjectCtClass,
0555:                        _loader);
0556:
0557:                Instantiator instantiator = ct.createInstantiator(transformed);
0558:
0559:                ComponentResourcesAware instance = instantiator
0560:                        .newInstance(resources);
0561:
0562:                assertSame(instance.getComponentResources(), resources);
0563:
0564:                verify();
0565:            }
0566:
0567:            @Test
0568:            public void add_injected_field_from_parent_transformation()
0569:                    throws Exception {
0570:                final String value = "from the parent";
0571:
0572:                InternalComponentResources resources = mockInternalComponentResources();
0573:
0574:                CtClass targetObjectCtClass = findCtClass(TargetObject.class);
0575:
0576:                Log log = mockLog();
0577:
0578:                replay();
0579:
0580:                InternalClassTransformation ct = new InternalClassTransformationImpl(
0581:                        targetObjectCtClass, _loader, log, null);
0582:
0583:                String parentFieldName = ct.addInjectedField(String.class,
0584:                        "_value", value);
0585:
0586:                // Default behavior is to add an injected field for the InternalComponentResources object,
0587:                // so we'll just check that.
0588:
0589:                ct.finish();
0590:
0591:                // Instantiate the transformed base class, so that we can create a transformed
0592:                // subclass.
0593:
0594:                _classPool.toClass(targetObjectCtClass, _loader);
0595:
0596:                // Now lets work on the subclass
0597:
0598:                CtClass subclassCtClass = findCtClass(TargetObjectSubclass.class);
0599:
0600:                ct = new InternalClassTransformationImpl(subclassCtClass, ct,
0601:                        _loader, log, null);
0602:
0603:                String subclassFieldName = ct.addInjectedField(String.class,
0604:                        "_childValue", value);
0605:
0606:                // This is what proves it is cached.
0607:
0608:                assertEquals(subclassFieldName, parentFieldName);
0609:
0610:                // This proves the the field is protected and can be used in subclasses.
0611:
0612:                ct.addMethod(new MethodSignature(Modifier.PUBLIC,
0613:                        "java.lang.String", "getValue", null, null), "return "
0614:                        + subclassFieldName + ";");
0615:
0616:                ct.finish();
0617:
0618:                Class transformed = _classPool
0619:                        .toClass(subclassCtClass, _loader);
0620:
0621:                Instantiator instantiator = ct.createInstantiator(transformed);
0622:
0623:                Object instance = instantiator.newInstance(resources);
0624:
0625:                Object actual = _access.get(instance, "value");
0626:
0627:                assertSame(actual, value);
0628:
0629:                verify();
0630:            }
0631:
0632:            @Test
0633:            public void wrong_instance_type_passed_to_create_instantiator()
0634:                    throws Exception {
0635:                CtClass ctClass = findCtClass(BasicComponent.class);
0636:
0637:                Log log = mockLog();
0638:
0639:                replay();
0640:
0641:                InternalClassTransformation ct = new InternalClassTransformationImpl(
0642:                        ctClass, _contextClassLoader, log, null);
0643:
0644:                _classPool.toClass(ctClass, _loader);
0645:
0646:                try {
0647:                    ct.createInstantiator(Boolean.class);
0648:                    unreachable();
0649:                } catch (IllegalArgumentException ex) {
0650:                    assertEquals(ex.getMessage(), ServicesMessages
0651:                            .incorrectClassForInstantiator(BasicComponent.class
0652:                                    .getName(), Boolean.class));
0653:                }
0654:
0655:                verify();
0656:            }
0657:
0658:            @Test
0659:            public void add_interface_to_class() throws Exception {
0660:                InternalComponentResources resources = mockInternalComponentResources();
0661:
0662:                CtClass targetObjectCtClass = findCtClass(TargetObject.class);
0663:
0664:                Log log = mockLog();
0665:
0666:                replay();
0667:
0668:                InternalClassTransformation ct = new InternalClassTransformationImpl(
0669:                        targetObjectCtClass, _contextClassLoader, log, null);
0670:
0671:                ct.addImplementedInterface(FooInterface.class);
0672:                ct.addImplementedInterface(GetterMethodsInterface.class);
0673:
0674:                ct.finish();
0675:
0676:                Class transformed = _classPool.toClass(targetObjectCtClass,
0677:                        _loader);
0678:
0679:                Class[] interfaces = transformed.getInterfaces();
0680:
0681:                assertEquals(interfaces, new Class[] { Component.class,
0682:                        FooInterface.class, GetterMethodsInterface.class });
0683:
0684:                Object target = ct.createInstantiator(transformed).newInstance(
0685:                        resources);
0686:
0687:                FooInterface asFoo = (FooInterface) target;
0688:
0689:                asFoo.foo();
0690:
0691:                GetterMethodsInterface getters = (GetterMethodsInterface) target;
0692:
0693:                assertEquals(getters.getBoolean(), false);
0694:                assertEquals(getters.getByte(), (byte) 0);
0695:                assertEquals(getters.getShort(), (short) 0);
0696:                assertEquals(getters.getInt(), 0);
0697:                assertEquals(getters.getLong(), 0l);
0698:                assertEquals(getters.getFloat(), 0.0f);
0699:                assertEquals(getters.getDouble(), 0.0d);
0700:                assertNull(getters.getString());
0701:                assertNull(getters.getObjectArray());
0702:                assertNull(getters.getIntArray());
0703:
0704:                verify();
0705:            }
0706:
0707:            @Test
0708:            public void make_field_read_only() throws Exception {
0709:                InternalComponentResources resources = mockInternalComponentResources();
0710:
0711:                Log log = mockLog();
0712:
0713:                replay();
0714:
0715:                CtClass targetObjectCtClass = findCtClass(ReadOnlyBean.class);
0716:
0717:                InternalClassTransformation ct = new InternalClassTransformationImpl(
0718:                        targetObjectCtClass, _contextClassLoader, log, null);
0719:
0720:                ct.makeReadOnly("_value");
0721:
0722:                ct.finish();
0723:
0724:                Class transformed = _classPool.toClass(targetObjectCtClass,
0725:                        _loader);
0726:
0727:                Object target = ct.createInstantiator(transformed).newInstance(
0728:                        resources);
0729:
0730:                PropertyAccess access = new PropertyAccessImpl();
0731:
0732:                try {
0733:                    access.set(target, "value", "anything");
0734:                    unreachable();
0735:                } catch (RuntimeException ex) {
0736:                    // The PropertyAccess layer adds a wrapper exception around the real one.
0737:
0738:                    assertEquals(ex.getCause().getMessage(),
0739:                            "Field org.apache.tapestry.internal.services.ReadOnlyBean._value is read-only.");
0740:                }
0741:
0742:                verify();
0743:            }
0744:
0745:            @Test
0746:            public void removed_fields_should_not_show_up_as_unclaimed()
0747:                    throws Exception {
0748:                Log log = mockLog();
0749:
0750:                replay();
0751:
0752:                CtClass targetObjectCtClass = findCtClass(RemoveFieldBean.class);
0753:
0754:                InternalClassTransformation ct = new InternalClassTransformationImpl(
0755:                        targetObjectCtClass, _contextClassLoader, log, null);
0756:
0757:                ct.removeField("_barney");
0758:
0759:                assertEquals(ct.findUnclaimedFields(), asList("_fred"));
0760:
0761:                verify();
0762:            }
0763:
0764:            @Test
0765:            public void add_to_constructor() throws Exception {
0766:                InternalComponentResources resources = mockInternalComponentResources();
0767:
0768:                Log log = mockLog();
0769:
0770:                replay();
0771:
0772:                CtClass targetObjectCtClass = findCtClass(ReadOnlyBean.class);
0773:
0774:                InternalClassTransformation ct = new InternalClassTransformationImpl(
0775:                        targetObjectCtClass, _contextClassLoader, log, null);
0776:
0777:                ct.extendConstructor("_value = \"from constructor\";");
0778:
0779:                ct.finish();
0780:
0781:                Class transformed = _classPool.toClass(targetObjectCtClass,
0782:                        _loader);
0783:
0784:                Object target = ct.createInstantiator(transformed).newInstance(
0785:                        resources);
0786:
0787:                PropertyAccess access = new PropertyAccessImpl();
0788:
0789:                assertEquals(access.get(target, "value"), "from constructor");
0790:
0791:                verify();
0792:            }
0793:
0794:            @Test
0795:            public void inject_field() throws Exception {
0796:                InternalComponentResources resources = mockInternalComponentResources();
0797:
0798:                Log log = mockLog();
0799:
0800:                replay();
0801:
0802:                CtClass targetObjectCtClass = findCtClass(ReadOnlyBean.class);
0803:
0804:                InternalClassTransformation ct = new InternalClassTransformationImpl(
0805:                        targetObjectCtClass, _contextClassLoader, log, null);
0806:
0807:                ct.injectField("_value", "Tapestry");
0808:
0809:                ct.finish();
0810:
0811:                Class transformed = _classPool.toClass(targetObjectCtClass,
0812:                        _loader);
0813:
0814:                Object target = ct.createInstantiator(transformed).newInstance(
0815:                        resources);
0816:
0817:                PropertyAccess access = new PropertyAccessImpl();
0818:
0819:                assertEquals(access.get(target, "value"), "Tapestry");
0820:
0821:                try {
0822:                    access.set(target, "value", "anything");
0823:                    unreachable();
0824:                } catch (RuntimeException ex) {
0825:                    // The PropertyAccess layer adds a wrapper exception around the real one.
0826:
0827:                    assertEquals(ex.getCause().getMessage(),
0828:                            "Field org.apache.tapestry.internal.services.ReadOnlyBean._value is read-only.");
0829:                }
0830:
0831:                verify();
0832:            }
0833:
0834:            /**
0835:             * Tests the basic functionality of overriding read and write; also tests the case for multiple
0836:             * field read/field write substitions.
0837:             */
0838:            @Test
0839:            public void override_field_read_and_write() throws Exception {
0840:                InternalComponentResources resources = mockInternalComponentResources();
0841:
0842:                Log log = mockLog();
0843:
0844:                replay();
0845:
0846:                CtClass targetObjectCtClass = findCtClass(FieldAccessBean.class);
0847:
0848:                InternalClassTransformation ct = new InternalClassTransformationImpl(
0849:                        targetObjectCtClass, _contextClassLoader, log, null);
0850:
0851:                replaceAccessToField(ct, "foo");
0852:                replaceAccessToField(ct, "bar");
0853:
0854:                // Stuff ...
0855:
0856:                ct.finish();
0857:
0858:                Class transformed = _classPool.toClass(targetObjectCtClass,
0859:                        _loader);
0860:
0861:                Object target = ct.createInstantiator(transformed).newInstance(
0862:                        resources);
0863:
0864:                // target is no longer assignable to FieldAccessBean; its a new class from a new class
0865:                // loader. So we use reflective access, which doesn't care about such things.
0866:
0867:                PropertyAccess access = new PropertyAccessImpl();
0868:
0869:                checkReplacedFieldAccess(access, target, "foo");
0870:                checkReplacedFieldAccess(access, target, "bar");
0871:
0872:                verify();
0873:            }
0874:
0875:            private void checkReplacedFieldAccess(PropertyAccess access,
0876:                    Object target, String propertyName) {
0877:
0878:                try {
0879:                    access.get(target, propertyName);
0880:                    unreachable();
0881:                } catch (RuntimeException ex) {
0882:                    // PropertyAccess adds a wrapper exception
0883:                    assertEquals(ex.getCause().getMessage(), "read "
0884:                            + propertyName);
0885:                }
0886:
0887:                try {
0888:                    access.set(target, propertyName, "new value");
0889:                    unreachable();
0890:                } catch (RuntimeException ex) {
0891:                    // PropertyAccess adds a wrapper exception
0892:                    assertEquals(ex.getCause().getMessage(), "write "
0893:                            + propertyName);
0894:                }
0895:            }
0896:
0897:            private void replaceAccessToField(InternalClassTransformation ct,
0898:                    String baseName) {
0899:                String fieldName = "_" + baseName;
0900:                String readMethodName = "_read_" + baseName;
0901:
0902:                MethodSignature readMethodSignature = new MethodSignature(
0903:                        Modifier.PRIVATE, STRING_CLASS_NAME, readMethodName,
0904:                        null, null);
0905:
0906:                ct.addMethod(readMethodSignature, String.format(
0907:                        "throw new RuntimeException(\"read %s\");", baseName));
0908:
0909:                ct.replaceReadAccess(fieldName, readMethodName);
0910:
0911:                String writeMethodName = "_write_" + baseName;
0912:
0913:                MethodSignature writeMethodSignature = new MethodSignature(
0914:                        Modifier.PRIVATE, "void", writeMethodName,
0915:                        new String[] { STRING_CLASS_NAME }, null);
0916:                ct.addMethod(writeMethodSignature, String.format(
0917:                        "throw new RuntimeException(\"write %s\");", baseName));
0918:
0919:                ct.replaceWriteAccess(fieldName, writeMethodName);
0920:            }
0921:
0922:            @Test
0923:            public void find_methods_with_annotation() throws Exception {
0924:                Log log = mockLog();
0925:
0926:                replay();
0927:
0928:                ClassTransformation ct = createClassTransformation(
0929:                        AnnotatedPage.class, log);
0930:
0931:                List<MethodSignature> l = ct
0932:                        .findMethodsWithAnnotation(SetupRender.class);
0933:
0934:                // Check order
0935:
0936:                assertEquals(l.size(), 2);
0937:                assertEquals(l.get(0).toString(), "void beforeRender()");
0938:                assertEquals(l.get(1).toString(),
0939:                        "boolean earlyRender(org.apache.tapestry.MarkupWriter)");
0940:
0941:                // Check up on cacheing
0942:
0943:                assertEquals(ct.findMethodsWithAnnotation(SetupRender.class), l);
0944:
0945:                // Check up on no match.
0946:
0947:                assertTrue(ct.findFieldsWithAnnotation(Deprecated.class)
0948:                        .isEmpty());
0949:
0950:                verify();
0951:            }
0952:
0953:            @Test
0954:            public void find_methods_using_filter() throws Exception {
0955:                Log log = mockLog();
0956:
0957:                replay();
0958:
0959:                final ClassTransformation ct = createClassTransformation(
0960:                        AnnotatedPage.class, log);
0961:
0962:                // Duplicates, somewhat less efficiently, the logic in find_methods_with_annotation().
0963:
0964:                MethodFilter filter = new MethodFilter() {
0965:                    public boolean accept(MethodSignature signature) {
0966:                        return ct.getMethodAnnotation(signature,
0967:                                SetupRender.class) != null;
0968:                    }
0969:                };
0970:
0971:                List<MethodSignature> l = ct.findMethods(filter);
0972:
0973:                // Check order
0974:
0975:                assertEquals(l.size(), 2);
0976:                assertEquals(l.get(0).toString(), "void beforeRender()");
0977:                assertEquals(l.get(1).toString(),
0978:                        "boolean earlyRender(org.apache.tapestry.MarkupWriter)");
0979:
0980:                // Check up on cacheing
0981:
0982:                assertEquals(ct.findMethodsWithAnnotation(SetupRender.class), l);
0983:
0984:                // Check up on no match.
0985:
0986:                assertTrue(ct.findFieldsWithAnnotation(Deprecated.class)
0987:                        .isEmpty());
0988:
0989:                verify();
0990:            }
0991:
0992:            @Test
0993:            public void to_class_with_primitive_type() throws Exception {
0994:                Log log = mockLog();
0995:
0996:                replay();
0997:
0998:                ClassTransformation ct = createClassTransformation(
0999:                        AnnotatedPage.class, log);
1000:
1001:                assertSame(ct.toClass("float"), Float.class);
1002:
1003:                verify();
1004:            }
1005:
1006:            @Test
1007:            public void to_class_with_object_type() throws Exception {
1008:                Log log = mockLog();
1009:
1010:                replay();
1011:
1012:                ClassTransformation ct = createClassTransformation(
1013:                        AnnotatedPage.class, log);
1014:
1015:                assertSame(ct.toClass("java.util.Map"), Map.class);
1016:
1017:                verify();
1018:            }
1019:
1020:            @Test
1021:            public void non_private_fields_log_an_error() throws Exception {
1022:                Log log = mockLog();
1023:
1024:                log.error(ServicesMessages.nonPrivateFields(
1025:                        VisibilityBean.class.getName(), Arrays.asList(
1026:                                "_$myPackagePrivate", "_$myProtected",
1027:                                "_$myPublic")));
1028:
1029:                replay();
1030:
1031:                InternalClassTransformation ct = createClassTransformation(
1032:                        VisibilityBean.class, log);
1033:
1034:                List<String> names = ct.findFieldsWithAnnotation(Retain.class);
1035:
1036:                // Only _myLong shows up, because its the only private field
1037:
1038:                assertEquals(names, Arrays.asList("_$myLong"));
1039:
1040:                // However, all the fields are "reserved" via the IdAllocator ...
1041:
1042:                assertEquals(ct.newMemberName("_$myLong"), "_$myLong_0");
1043:                assertEquals(ct.newMemberName("_$myStatic"), "_$myStatic_0");
1044:                assertEquals(ct.newMemberName("_$myProtected"),
1045:                        "_$myProtected_0");
1046:
1047:                // The check for non-private fields has been moved from the ICTI constructor to the finish
1048:                // method.
1049:
1050:                ct.finish();
1051:
1052:                verify();
1053:            }
1054:
1055:            @Test
1056:            public void find_annotation_in_method() throws Exception {
1057:                Log log = mockLog();
1058:
1059:                replay();
1060:
1061:                ClassTransformation ct = createClassTransformation(
1062:                        EventHandlerTarget.class, log);
1063:
1064:                OnEvent annotation = ct.getMethodAnnotation(
1065:                        new MethodSignature("handler"), OnEvent.class);
1066:
1067:                // Check that the attributes of the annotation match the expectation.
1068:
1069:                assertEquals(annotation.value(), "fred");
1070:                assertEquals(annotation.component(), "alpha");
1071:
1072:                verify();
1073:            }
1074:
1075:            @Test
1076:            public void find_annotation_in_unknown_method() throws Exception {
1077:                Log log = mockLog();
1078:
1079:                replay();
1080:
1081:                ClassTransformation ct = createClassTransformation(
1082:                        ParentClass.class, log);
1083:
1084:                try {
1085:                    ct.getMethodAnnotation(new MethodSignature("foo"),
1086:                            OnEvent.class);
1087:                    unreachable();
1088:                } catch (IllegalArgumentException ex) {
1089:                    assertEquals(
1090:                            ex.getMessage(),
1091:                            "Class org.apache.tapestry.internal.transform.pages.ParentClass does not declare method 'public void foo()'.");
1092:                }
1093:
1094:                verify();
1095:            }
1096:
1097:            @Test
1098:            public void remove_field() throws Exception {
1099:                Log log = mockLog();
1100:
1101:                replay();
1102:
1103:                CtClass targetObjectCtClass = findCtClass(FieldRemoval.class);
1104:
1105:                InternalClassTransformation ct = new InternalClassTransformationImpl(
1106:                        targetObjectCtClass, _contextClassLoader, log, null);
1107:
1108:                ct.removeField("_fieldToRemove");
1109:
1110:                ct.finish();
1111:
1112:                Class transformed = _classPool.toClass(targetObjectCtClass,
1113:                        _loader);
1114:
1115:                for (Field f : transformed.getDeclaredFields()) {
1116:                    if (f.getName().equals("_fieldToRemove"))
1117:                        throw new AssertionError(
1118:                                "_fieldToRemove still in transformed class.");
1119:                }
1120:
1121:                verify();
1122:            }
1123:
1124:            @Test
1125:            public void get_method_identifier() throws Exception {
1126:                Log log = mockLog();
1127:
1128:                replay();
1129:
1130:                ClassTransformation ct = createClassTransformation(
1131:                        MethodIdentifier.class, log);
1132:
1133:                List<MethodSignature> sigs = ct
1134:                        .findMethodsWithAnnotation(OnEvent.class);
1135:
1136:                assertEquals(sigs.size(), 1);
1137:
1138:                MethodSignature sig = sigs.get(0);
1139:
1140:                assertEquals(
1141:                        ct.getMethodIdentifier(sig),
1142:                        "org.apache.tapestry.internal.transform.pages.MethodIdentifier.makeWaves(java.lang.String, int[]) (at MethodIdentifier.java:24)");
1143:
1144:                verify();
1145:            }
1146:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.