001    // Copyright 2004, 2005 The Apache Software Foundation
002    //
003    // Licensed under the Apache License, Version 2.0 (the "License");
004    // you may not use this file except in compliance with the License.
005    // You may obtain a copy of the License at
006    //
007    //     http://www.apache.org/licenses/LICENSE-2.0
008    //
009    // Unless required by applicable law or agreed to in writing, software
010    // distributed under the License is distributed on an "AS IS" BASIS,
011    // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
012    // See the License for the specific language governing permissions and
013    // limitations under the License.
014    
015    package org.apache.tapestry.junit.parse;
016    
017    import org.apache.commons.logging.Log;
018    import org.apache.hivemind.Locatable;
019    import org.apache.hivemind.Resource;
020    import org.apache.hivemind.impl.DefaultClassResolver;
021    import org.apache.hivemind.impl.DefaultErrorHandler;
022    import org.apache.tapestry.bean.BindingBeanInitializer;
023    import org.apache.tapestry.bean.LightweightBeanInitializer;
024    import org.apache.tapestry.junit.TapestryTestCase;
025    import org.apache.tapestry.parse.SpecificationParser;
026    import org.apache.tapestry.spec.*;
027    import org.apache.tapestry.util.xml.DocumentParseException;
028    import org.testng.annotations.Test;
029    
030    import java.util.List;
031    
032    /**
033     * Tests the specification parser (which reads page and component specifications). Came into being
034     * somewhat late, so it just tests new features for the meantime.
035     * 
036     * @author Howard Lewis Ship
037     * @since 2.0.4
038     */
039    @Test
040    public class TestSpecificationParser extends TapestryTestCase
041    {
042    
043        private void checkLine(Locatable locatable, int line)
044        {
045            assertEquals(line, locatable.getLocation().getLineNumber());
046        }
047    
048        /**
049         * Test 3.0 <message-binding> element.
050         */
051    
052        public void tes_Message_Binding() throws Exception
053        {
054            IComponentSpecification spec = parseComponent("TestMessageBinding.jwc");
055    
056            IBindingSpecification bs = spec.getComponent("hello").getBinding("value");
057    
058            assertEquals(BindingType.PREFIXED, bs.getType());
059            assertEquals("message:label.hello", bs.getValue());
060    
061            checkLine(bs, 25);
062        }
063    
064        /**
065         * Tests the 4.0 style <binding> element.
066         */
067    
068        public void testBinding40() throws Exception
069        {
070            IComponentSpecification spec = parseComponent("Binding40.jwc");
071            IContainedComponent cc = spec.getComponent("component");
072    
073            IBindingSpecification bs = cc.getBinding("simple");
074    
075            assertEquals(BindingType.PREFIXED, bs.getType());
076            assertEquals("message:some-key", bs.getValue());
077    
078            bs = cc.getBinding("enclosed");
079    
080            assertEquals(BindingType.PREFIXED, bs.getType());
081            assertEquals("ognl:zip.zap.zoop", bs.getValue());
082        }
083    
084        /**
085         * Test valid parameter name.
086         * 
087         * @since 2.2
088         */
089    
090        public void testValidParameterName() throws Exception
091        {
092            IComponentSpecification spec = parseComponent("ValidParameterName.jwc");
093    
094            IParameterSpecification ps = spec.getParameter("valid");
095    
096            assertNotNull(ps);
097            checkLine(ps, 24);
098        }
099    
100        /**
101         * Test invalid parameter name.
102         * 
103         * @since 2.2
104         */
105    
106        public void testInvalidParameterName() throws Exception
107        {
108            try
109            {
110                parseComponent("InvalidParameterName.jwc");
111    
112                unreachable();
113            }
114            catch (DocumentParseException ex)
115            {
116                checkException(ex, "in-valid");
117                checkException(ex, "Parameter");
118            }
119        }
120    
121        /**
122         * Test invalid component id.
123         * 
124         * @since 2.2
125         */
126    
127        public void testInvalidComponentId() throws Exception
128        {
129            try
130            {
131                parseComponent("InvalidComponentId.jwc");
132    
133                unreachable();
134            }
135            catch (DocumentParseException ex)
136            {
137                checkException(ex, "in.valid");
138                checkException(ex, "component id");
139            }
140        }
141    
142        /**
143         * Test invalid library id in a library specification.
144         * 
145         * @since 2.2
146         */
147    
148        public void testInvalidLibraryId() throws Exception
149        {
150            try
151            {
152                parseLib("InvalidLibraryId.library");
153    
154                unreachable();
155            }
156            catch (DocumentParseException ex)
157            {
158                checkException(ex, "in.valid");
159                checkException(ex, "library id");
160            }
161        }
162    
163        /**
164         * Parse a valid library.
165         * 
166         * @since 2.2
167         */
168    
169        public void testValidLibrary() throws Exception
170        {
171            ILibrarySpecification spec = parseLib("ValidLibrary.library");
172    
173            checkLine(spec, 24);
174    
175            checkList("pageNames", new String[]
176            { "FirstPage", "SecondPage" }, spec.getPageNames());
177    
178            checkList("componentAliases", new String[]
179            { "FirstComponent", "SecondComponent" }, spec.getComponentTypes());
180    
181            checkList("libraryIds", new String[]
182            { "lib1", "lib2" }, spec.getLibraryIds());
183    
184            assertNotNull(spec.getSpecificationLocation());
185        }
186    
187        /**
188         * Test invalid parameter name.
189         * 
190         * @since 2.2
191         */
192    
193        public void testInvalidAssetName() throws Exception
194        {
195            try
196            {
197                parseComponent("InvalidAssetName.jwc");
198    
199                unreachable();
200            }
201            catch (DocumentParseException ex)
202            {
203                checkException(ex, "in.valid");
204                checkException(ex, "asset name");
205            }
206        }
207    
208        /**
209         * Test invalid page name.
210         * 
211         * @since 2.2
212         */
213    
214        public void testInvalidPageName() throws Exception
215        {
216            try
217            {
218                parseApp("InvalidPageName.application");
219    
220                unreachable();
221            }
222            catch (DocumentParseException ex)
223            {
224                checkException(ex, "in$valid");
225                checkException(ex, "page name");
226            }
227        }
228    
229        /**
230         * Test invalid component type ("alias" in older parlance).
231         * 
232         * @since 2.2
233         */
234    
235        public void testInvalidComponentAlias() throws Exception
236        {
237            try
238            {
239                parseApp("InvalidComponentAlias.application");
240    
241                unreachable();
242            }
243            catch (DocumentParseException ex)
244            {
245                checkException(ex, "Invalid$Component");
246                checkException(ex, "type");
247            }
248        }
249    
250        /**
251         * Test invalid extension name.
252         * 
253         * @since 2.2
254         */
255    
256        public void testInvalidExtensionName() throws Exception
257        {
258            try
259            {
260                parseApp("InvalidExtensionName.application");
261    
262                unreachable();
263            }
264            catch (DocumentParseException ex)
265            {
266                checkException(ex, "Invalid$Extension");
267                checkException(ex, "extension name");
268            }
269        }
270    
271        public void test_Malformed_Xml_Tag() throws Exception
272        {
273            try
274            {
275                 parsePage("MalformedXmlTag.page");
276    
277                unreachable();
278            }
279            catch (DocumentParseException ex)
280            {
281                checkException(ex, "Element type \"binding\" must be followed by either attribute");
282            }
283        }
284    
285        /**
286         * Test case where the document does not have a DOCTYPE
287         * 
288         * @since 2.2
289         */
290    
291        public void testMissingDoctype() throws Exception
292        {
293            try
294            {
295                parseApp("MissingDoctype.application");
296    
297                unreachable();
298            }
299            catch (DocumentParseException ex)
300            {
301                // XML parsers tend to generate different exception messages,
302                // so make the condition as unspecific as possible
303                checkException(ex, "DOCTYPE");
304            }
305        }
306    
307        /**
308         * Test case where the public id of the document is not known.
309         */
310    
311        public void testInvalidPublicId() throws Exception
312        {
313            try
314            {
315                parseApp("InvalidPublicId.application");
316    
317                unreachable();
318            }
319            catch (DocumentParseException ex)
320            {
321                checkException(ex, "has an unexpected public id");
322            }
323        }
324    
325        /**
326         * Test an an application specification can omit the name and engine-class attributes.
327         * 
328         * @since 3.0
329         */
330    
331        public void testNulledApplication() throws Exception
332        {
333            IApplicationSpecification spec = parseApp("NulledApplication.application");
334    
335            assertNull(spec.getEngineClassName());
336            assertNull(spec.getName());
337            checkLine(spec, 25);
338    
339            assertNotNull(spec.getSpecificationLocation());
340        }
341    
342        /**
343         * Test new DTD 1.4 syntax for declaring components.
344         * 
345         * @since 3.0
346         */
347    
348        public void testComponentType() throws Exception
349        {
350            IApplicationSpecification spec = parseApp("ComponentType.application");
351    
352            assertEquals("/path/Fred.jwc", spec.getComponentSpecificationPath("Fred"));
353        }
354    
355        /**
356         * Test omitting the class name from a component specification (new, in DTD 1.4).
357         */
358    
359        public void testNulledComponent() throws Exception
360        {
361            IComponentSpecification spec = parseComponent("NulledComponent.jwc");
362    
363            assertNull(spec.getComponentClassName());
364            checkLine(spec, 22);
365    
366            assertEquals(false, spec.isPageSpecification());
367            assertNotNull(spec.getSpecificationLocation());
368    
369            assertEquals(false, spec.isDeprecated());
370        }
371    
372        /**
373         * Test omitting the class name from a component specification (new, in DTD 1.4).
374         */
375    
376        public void testNulledPage() throws Exception
377        {
378            IComponentSpecification spec = parsePage("NulledPage.page");
379    
380            assertNull(spec.getComponentClassName());
381            checkLine(spec, 22);
382    
383            assertEquals(true, spec.isPageSpecification());
384            assertNotNull(spec.getSpecificationLocation());
385        }
386    
387        /**
388         * Test the value attribute for the property element (which is new in DTD 1.4).
389         * 
390         * @since 3.0
391         */
392    
393        public void testPropertyValue() throws Exception
394        {
395            IComponentSpecification spec = parsePage("PropertyValue.page");
396    
397            checkLine(spec, 22);
398    
399            assertEquals("rubble", spec.getProperty("barney"));
400            assertEquals("flintstone", spec.getProperty("wilma"));
401        }
402    
403        /**
404         * Tests the new (in DTD 1.4) value attribute on static-binding element.
405         * 
406         * @since 3.0
407         */
408    
409        public void testStaticBindingValue() throws Exception
410        {
411            IComponentSpecification spec = parsePage("StaticBindingValue.page");
412    
413            checkLine(spec, 22);
414    
415            IContainedComponent c = spec.getComponent("c");
416    
417            checkLine(c, 24);
418    
419            IBindingSpecification b = c.getBinding("fred");
420            checkLine(b, 25);
421    
422            assertEquals("literal:flintstone", b.getValue());
423    
424            b = c.getBinding("barney");
425            checkLine(b, 26);
426    
427            assertEquals("literal:rubble", b.getValue());
428    
429            b = c.getBinding("rock");
430            checkLine(b, 27);
431            assertEquals("literal:hudson", b.getValue());
432        }
433    
434        public void testAttributeAndBody() throws Exception
435        {
436            try
437            {
438                parsePage("AttributeAndBody.page");
439    
440                unreachable();
441            }
442            catch (DocumentParseException ex)
443            {
444                checkException(
445                        ex,
446                        "It is not valid to specify a value for attribute 'value' of <static-binding> and provide a value in the body of the element.");
447            }
448        }
449    
450        /**
451         * Tests the new (in DTD 1.4) value attribute on a configure element.
452         * 
453         * @since 3.0
454         */
455    
456        public void testConfigureValue() throws Exception
457        {
458            ILibrarySpecification spec = parseLib("ConfigureValue.library");
459    
460            checkLine(spec, 22);
461            checkLine(spec.getExtensionSpecification("bedrock"), 24);
462    
463            Bedrock bedrock = (Bedrock) spec.getExtension("bedrock", Bedrock.class);
464    
465            assertEquals("flintstone", bedrock.getFred());
466        }
467    
468        /**
469         * Tests the new &lt;listener-binding&gt; element in the 1.4 DTD.
470         * 
471         * @since 3.0
472         */
473    
474        public void testListenerBinding() throws Exception
475        {
476            Log log = newMock(Log.class);
477    
478            SpecificationParser parser = new SpecificationParser(new DefaultErrorHandler(), log,
479                    new DefaultClassResolver(), new SpecFactory());
480    
481            parser.setBindingSource(newBindingSource());
482    
483            Resource location = getSpecificationResourceLocation("ListenerBinding.page");
484    
485            log
486                    .warn("The <listener-binding> element is no longer supported (at classpath:/org/apache/tapestry/junit/parse/ListenerBinding.page, line 25, column 56).");
487    
488            replay();
489    
490            IComponentSpecification spec = parser.parsePageSpecification(location);
491    
492            verify();
493    
494            IContainedComponent cc = spec.getComponent("c");
495    
496            assertNull(cc.getBinding("listener"));
497    
498            IBindingSpecification bs = cc.getBinding("foo");
499    
500            assertEquals(BindingType.PREFIXED, bs.getType());
501            assertEquals("literal:bar", bs.getValue());
502        }
503    
504        /** @since 3.0 * */
505    
506        public void testPropertySpecifications() throws Exception
507        {
508            IComponentSpecification spec = parsePage("PropertySpecifications.page");
509    
510            checkList("propertySpecificationNames", new String[]
511            { "bool", "init", "longInitialValue", "persist" }, spec.getPropertySpecificationNames());
512    
513            IPropertySpecification ps = spec.getPropertySpecification("bool");
514            assertEquals("bool", ps.getName());
515            assertEquals(false, ps.isPersistent());
516            assertEquals("boolean", ps.getType());
517            assertNull(ps.getInitialValue());
518            checkLine(ps, 24);
519    
520            ps = spec.getPropertySpecification("init");
521            assertEquals("init", ps.getName());
522            assertEquals(false, ps.isPersistent());
523            assertNull(ps.getType());
524    
525            // Starting with release 4.0, the initial value is a binding reference
526            // with an appropriate prefix. In 3.0 it was always an OGNL expression.
527    
528            assertEquals("ognl:pageName", ps.getInitialValue());
529            checkLine(ps, 26);
530    
531            ps = spec.getPropertySpecification("persist");
532            assertEquals("persist", ps.getName());
533            assertEquals(true, ps.isPersistent());
534            assertNull(ps.getType());
535            assertNull(ps.getInitialValue());
536            checkLine(ps, 25);
537    
538            ps = spec.getPropertySpecification("longInitialValue");
539            assertEquals("ognl:long.initial.value", ps.getInitialValue());
540    
541            ps = spec.getPropertySpecification("unknown");
542    
543            assertNull(ps);
544        }
545    
546        /** @since 3.0 * */
547    
548        public void testMissingRequiredExtendedAttribute() throws Exception
549        {
550            try
551            {
552                parsePage("MissingRequiredExtendedAttribute.page");
553    
554                unreachable();
555            }
556            catch (DocumentParseException ex)
557            {
558                checkException(
559                        ex,
560                        "Element <binding> does not specify a value for attribute 'expression', or contain a body value.");
561            }
562        }
563    
564        /** @since 3.0 * */
565    
566        public void testMessageBeanInitializer() throws Exception
567        {
568            IComponentSpecification spec = parsePage("MessageBeanInitializer.page");
569    
570            IBeanSpecification bs = spec.getBeanSpecification("fred");
571            checkLine(bs, 24);
572            BindingBeanInitializer i = (BindingBeanInitializer) bs.getInitializers().get(0);
573    
574            assertEquals("barney", i.getPropertyName());
575            assertEquals("message:rubble", i.getBindingReference());
576            checkLine(i, 25);
577        }
578    
579        /**
580         * Tests the DTD 3.0 <set-property>element
581         * 
582         * @since 4.0
583         */
584    
585        public void testExpressionBeanInitializer() throws Exception
586        {
587            IComponentSpecification spec = parsePage("ExpressionBeanInitializer_3_0.page");
588    
589            IBeanSpecification bs = spec.getBeanSpecification("zebean");
590    
591            BindingBeanInitializer i = (BindingBeanInitializer) bs.getInitializers().get(0);
592    
593            assertEquals("barney", i.getPropertyName());
594            assertEquals("ognl:rubble", i.getBindingReference());
595    
596            i = (BindingBeanInitializer) bs.getInitializers().get(1);
597    
598            assertEquals("fred", i.getPropertyName());
599            assertEquals("ognl:flintstone", i.getBindingReference());
600        }
601    
602        /** @since 4.0 */
603    
604        public void testBeanSet() throws Exception
605        {
606            IComponentSpecification spec = parsePage("BeanSet.page");
607            IBeanSpecification bs = spec.getBeanSpecification("target");
608    
609            BindingBeanInitializer i = (BindingBeanInitializer) bs.getInitializers().get(0);
610    
611            assertEquals("literal", i.getPropertyName());
612            assertEquals("literal-string", i.getBindingReference());
613    
614        }
615    
616        public void testInheritInformalParameters() throws Exception
617        {
618            IComponentSpecification spec = parseComponent("TestInheritInformal.jwc");
619    
620            IContainedComponent border = spec.getComponent("border");
621            assertEquals(border.getInheritInformalParameters(), false);
622    
623            IContainedComponent textField = spec.getComponent("textField");
624            assertEquals(textField.getInheritInformalParameters(), true);
625        }
626    
627        /** @since 4.0 */
628    
629        public void testConfigureExtension() throws Exception
630        {
631            IApplicationSpecification spec = parseApp("ConfigureExtension.application");
632            IExtensionSpecification es = spec.getExtensionSpecification("my-extension");
633    
634            // Note: this is in transition; under 3.0 and earlier, the spec parser was
635            // responsible for converting values into object types ... that is now
636            // done futher down stream.
637    
638            assertEquals("-227", es.getConfiguration().get("long"));
639            assertEquals("22.7", es.getConfiguration().get("double"));
640            assertEquals("true", es.getConfiguration().get("boolean"));
641            assertEquals("An extended string.", es.getConfiguration().get("string"));
642        }
643    
644        public void testConfigureExtensionProperty() throws Exception
645        {
646            IApplicationSpecification spec = parseApp("ConfigureExtension.application");
647            IExtensionSpecification es = spec.getExtensionSpecification("my-extension");
648    
649            assertEquals("my-value", es.getProperty("my-property"));
650        }
651    
652        /** @since 4.0 */
653    
654        public void testComponentProperty() throws Exception
655        {
656            IComponentSpecification cs = parseComponent("ComponentProperty.jwc");
657    
658            IContainedComponent cc = cs.getComponent("body");
659    
660            assertEquals("my-value", cc.getProperty("my-property"));
661        }
662    
663        /** @since 4.0 */
664    
665        public void testComponentInjectProperty() throws Exception
666        {
667            IComponentSpecification cs = parseComponent("ComponentInjectProperty.jwc");
668    
669            IContainedComponent cc = cs.getComponent("body");
670    
671            assertEquals("myProperty", cc.getPropertyName());
672    
673            cc = cs.getComponent("fred");
674    
675            assertNull(cc.getPropertyName());
676        }
677    
678        /** @since 4.0 */
679    
680        public void testBeanDescription() throws Exception
681        {
682            IComponentSpecification cs = parseComponent("BeanDescription.jwc");
683            IBeanSpecification bs = cs.getBeanSpecification("mybean");
684    
685            assertEquals("Description of mybean.", bs.getDescription());
686            assertNotNull(bs.getLocation());
687        }
688    
689        /** @since 4.0 */
690    
691        public void testBeanProperty() throws Exception
692        {
693            IComponentSpecification cs = parseComponent("BeanDescription.jwc");
694            IBeanSpecification bs = cs.getBeanSpecification("mybean");
695    
696            assertEquals("myvalue", bs.getProperty("myproperty"));
697        }
698    
699        /**
700         * @since 4.0
701         */
702    
703        public void testBeanInject() throws Exception
704        {
705            IComponentSpecification cs = parseComponent("BeanInject.jwc");
706            IBeanSpecification bs = cs.getBeanSpecification("bean");
707            assertEquals("myProperty", bs.getPropertyName());
708        }
709    
710        /**
711         * @since 4.0
712         */
713    
714        public void testBeanInitializer() throws Exception
715        {
716            IComponentSpecification cs = parseComponent("BeanInitializer.jwc");
717            IBeanSpecification bs = cs.getBeanSpecification("bean");
718    
719            List l = bs.getInitializers();
720            LightweightBeanInitializer lbi = (LightweightBeanInitializer) l.get(0);
721    
722            assertEquals("foo=bar", lbi.getPropertyName());
723        }
724    
725        /** @since 4.0 */
726    
727        public void testLibraryDescription() throws Exception
728        {
729            ILibrarySpecification ls = parseLib("LibraryDescription.library");
730    
731            assertEquals("Often, these are just placeholders.", ls.getDescription());
732        }
733    
734        /** @since 4.0 */
735    
736        public void testPageDescription() throws Exception
737        {
738            IComponentSpecification spec = parsePage("PageDescription.page");
739    
740            assertEquals("Description of this page.", spec.getDescription());
741        }
742    
743        /**
744         * Excercies the check that the correct root element is used.
745         * 
746         * @since 4.0
747         */
748    
749        public void testRootElementMismatch() throws Exception
750        {
751            try
752            {
753                parseComponent("NulledPage.page");
754                unreachable();
755            }
756            catch (Exception ex)
757            {
758                checkException(
759                        ex,
760                        "Incorrect document type; expected page-specification but received component-specification.");
761            }
762        }
763    
764        /**
765         * Checks to make sure that a application or library may not defined a lbirary with id
766         * 'framework'.
767         * 
768         * @since 4.0
769         */
770    
771        public void testLibraryFrameworkNamespace() throws Exception
772        {
773            try
774            {
775                parseLib("LibraryFrameworkNamespace.library");
776                unreachable();
777            }
778            catch (Exception ex)
779            {
780                checkException(ex, "The library id 'framework' is reserved and may not be used.");
781            }
782        }
783    
784        /**
785         * Tests that a &lt;component&gt; element may not have both type and copy-of attributes.
786         * 
787         * @since 4.0
788         */
789    
790        public void testComponentWithTypeAndCopyOf() throws Exception
791        {
792            try
793            {
794                parseComponent("ComponentWithTypeAndCopyOf.jwc");
795                unreachable();
796            }
797            catch (Exception ex)
798            {
799                checkException(ex, "Contained component bad contains both type and copy-of attributes.");
800            }
801        }
802    
803        /**
804         * Tests that &lt;component&gt; must have either type or copy-of attribute.
805         * 
806         * @since 4.0
807         */
808    
809        public void testComponentWithoutType() throws Exception
810        {
811            try
812            {
813                parseComponent("ComponentWithoutType.jwc");
814                unreachable();
815            }
816            catch (Exception ex)
817            {
818                checkException(
819                        ex,
820                        "Contained component bad does not specify attribute type or copy-of.");
821            }
822        }
823    
824        /**
825         * Tests the use of copy-of attribute inside &lt;component&gt;.
826         * 
827         * @since 4.0
828         */
829    
830        public void testComponentCopyOf() throws Exception
831        {
832            IComponentSpecification cs = parseComponent("ComponentCopyOf.jwc");
833    
834            IContainedComponent source = cs.getComponent("source");
835            IContainedComponent copy = cs.getComponent("copy");
836            IContainedComponent override = cs.getComponent("override");
837    
838            assertEquals("Insert", source.getType());
839            assertEquals("Insert", copy.getType());
840            assertEquals("Insert", override.getType());
841    
842            IBindingSpecification b = source.getBinding("value");
843    
844            assertEquals(BindingType.PREFIXED, b.getType());
845            assertEquals("ognl:date", b.getValue());
846    
847            assertSame(b, copy.getBinding("value"));
848    
849            IBindingSpecification b2 = override.getBinding("value");
850            assertEquals("ognl:tomorrow", b2.getValue());
851    
852            b = copy.getBinding("foo");
853    
854            assertSame(b, override.getBinding("foo"));
855    
856            b = copy.getBinding("formatter");
857    
858            assertSame(b, override.getBinding("formatter"));
859        }
860    
861        /**
862         * And here's what happens when copy-of doesn't match a known component.
863         * 
864         * @since 4.0
865         */
866        public void testComponentBadCopy()
867        {
868            try
869            {
870                parseComponent("ComponentBadCopy.jwc");
871                unreachable();
872            }
873            catch (Exception ex)
874            {
875                checkException(ex, "Unable to copy component missing, which does not exist.");
876            }
877        }
878    
879        /** @since 4.0 */
880        public void testMeta() throws Exception
881        {
882            ILibrarySpecification spec = parseLib("Meta.library");
883    
884            assertEquals("bar", spec.getProperty("foo"));
885            assertEquals("long value", spec.getProperty("long"));
886        }
887    
888        /** @since 4.0 */
889        public void testInject() throws Exception
890        {
891            IComponentSpecification spec = parseComponent("Inject.jwc");
892    
893            List l = spec.getInjectSpecifications();
894    
895            assertEquals(2, l.size());
896    
897            InjectSpecification i1 = (InjectSpecification) l.get(0);
898    
899            assertEquals("fred", i1.getProperty());
900            assertEquals("object", i1.getType());
901            assertEquals("flintstone", i1.getObject());
902            assertNotNull(i1.getLocation());
903    
904            InjectSpecification i2 = (InjectSpecification) l.get(1);
905            assertEquals("barney", i2.getProperty());
906            assertEquals("state", i2.getType());
907            assertEquals("rubble", i2.getObject());
908            assertNotNull(i2.getLocation());
909        }
910    
911        /**
912         * Test that the new &lt;property&gt; element (was &lt;property-specification&gt; in release
913         * 3.0) works correctly.
914         * 
915         * @since 4.0
916         */
917    
918        public void testProperty() throws Exception
919        {
920            IComponentSpecification spec = parsePage("Property.page");
921    
922            checkList("propertySpecificationNames", new String[]
923            { "bool", "init", "longInit", "persist" }, spec.getPropertySpecificationNames());
924    
925            IPropertySpecification ps = spec.getPropertySpecification("bool");
926            assertEquals("bool", ps.getName());
927            assertEquals(false, ps.isPersistent());
928    
929            // In a 4.0 DTD, type is always null.
930            assertNull(ps.getType());
931    
932            // Note that no prefix is added. Initial value will be a string literal,
933            // or have a prefix and be something else.
934    
935            assertNull(ps.getInitialValue());
936            checkLine(ps, 24);
937    
938            ps = spec.getPropertySpecification("init");
939            assertEquals("init", ps.getName());
940            assertEquals(false, ps.isPersistent());
941    
942            assertEquals("ognl:pageName", ps.getInitialValue());
943            checkLine(ps, 26);
944    
945            ps = spec.getPropertySpecification("persist");
946            assertEquals("persist", ps.getName());
947            assertEquals(true, ps.isPersistent());
948            assertNull(ps.getInitialValue());
949            checkLine(ps, 25);
950    
951            ps = spec.getPropertySpecification("longInit");
952            assertEquals("message:long-init-key", ps.getInitialValue());
953    
954            ps = spec.getPropertySpecification("unknown");
955    
956            assertNull(ps);
957        }
958    
959        /**
960         * Tests parameters specification from a 3.0 DTD
961         * 
962         * @since 4.0
963         */
964    
965        public void testParameter_3_0() throws Exception
966        {
967            IComponentSpecification spec = parseComponent("Parameter_3_0.jwc");
968    
969            IParameterSpecification ps = spec.getParameter("noDefault");
970    
971            assertEquals("noDefault", ps.getPropertyName());
972            assertEquals("noDefault", ps.getParameterName());
973            assertEquals(true, ps.isRequired());
974            assertEquals("bar", ps.getType());
975            assertNull(ps.getDefaultValue());
976            assertEquals(false, ps.isDeprecated());
977    
978            ps = spec.getParameter("withDefault");
979            assertEquals("withDefault", ps.getParameterName());
980            assertNull(ps.getType());
981            assertEquals(false, ps.isRequired());
982    
983            // For 3.0 DTDs, where the default value was always an OGNL expression,
984            // the parser will provide the "ognl:" prefix.
985    
986            assertEquals("ognl:an.expression", ps.getDefaultValue());
987    
988            ps = spec.getParameter("withDescription");
989            assertEquals("A parameter with a description.", ps.getDescription());
990    
991            ps = spec.getParameter("altName");
992            assertEquals("altNameParameter", ps.getPropertyName());
993    
994            ps = spec.getParameter("directionIn");
995            assertEquals(true, ps.getCache());
996    
997            ps = spec.getParameter("directionAuto");
998            assertEquals(false, ps.getCache());
999        }
1000    
1001        /**
1002         * Tests the new way default-value is interpreted (as a binding-like value, prefixed to indicate
1003         * type).
1004         * 
1005         * @since 4.0
1006         */
1007    
1008        public void testParameter() throws Exception
1009        {
1010            IComponentSpecification spec = parseComponent("Parameter.jwc");
1011    
1012            IParameterSpecification ps = spec.getParameter("noDefault");
1013    
1014            assertNull(ps.getDefaultValue());
1015            assertEquals(true, ps.getCache());
1016            assertTrue(ps.getAliasNames().isEmpty());
1017            assertEquals(false, ps.isDeprecated());
1018    
1019            ps = spec.getParameter("literalDefault");
1020    
1021            assertEquals("literal-value", ps.getDefaultValue());
1022    
1023            ps = spec.getParameter("expressionDefault");
1024    
1025            assertEquals("ognl:an.expression", ps.getDefaultValue());
1026    
1027            ps = spec.getParameter("noCache");
1028            assertEquals(false, ps.getCache());
1029    
1030            ps = spec.getParameter("withAliases");
1031            assertListEquals(new String[]
1032            { "fred", "barney" }, ps.getAliasNames().toArray());
1033    
1034            assertSame(ps, spec.getParameter("fred"));
1035            assertSame(ps, spec.getParameter("barney"));
1036    
1037            ps = spec.getParameter("deprecated");
1038            assertEquals(true, ps.isDeprecated());
1039        }
1040    
1041        /**
1042         * Tests that assets read using the 3.0 DTD are converted properly into paths with the proper
1043         * prefix.
1044         * 
1045         * @since 4.0
1046         */
1047        public void testAssets_3_0() throws Exception
1048        {
1049            IComponentSpecification cs = parsePage("Assets_3_0.page");
1050    
1051            IAssetSpecification as = cs.getAsset("mycontext");
1052    
1053            assertEquals("context:path/to/context", as.getPath());
1054    
1055            as = cs.getAsset("myprivate");
1056    
1057            assertEquals("classpath:path/to/private", as.getPath());
1058    
1059            as = cs.getAsset("myexternal");
1060    
1061            assertEquals("http://myexternal/asset", as.getPath());
1062    
1063            assertListEquals(new String[]
1064            { "mycontext", "myexternal", "myprivate" }, cs.getAssetNames());
1065        }
1066    
1067        /** @since 4.0 */
1068    
1069        public void testAssets() throws Exception
1070        {
1071            IComponentSpecification cs = parsePage("Assets.page");
1072    
1073            IAssetSpecification as = cs.getAsset("myasset");
1074    
1075            assertEquals("path/to/asset", as.getPath());
1076            assertEquals("myProperty", as.getPropertyName());
1077        }
1078    
1079        /** @since 4.0 */
1080    
1081        public void testDeprecatedComponent() throws Exception
1082        {
1083            IComponentSpecification cs = parseComponent("DeprecatedComponent.jwc");
1084    
1085            assertEquals(true, cs.isDeprecated());
1086        }
1087    
1088        /** @since 4.0 */
1089    
1090        public void testLibrarySlashInComponentType() throws Exception
1091        {
1092            ILibrarySpecification ls = parseLib("SlashInComponentType.library");
1093    
1094            List types = ls.getComponentTypes();
1095    
1096            assertEquals(1, types.size());
1097    
1098            assertEquals("foo/Bar", types.get(0));
1099    
1100            assertEquals("foocomponents/BarComponent.jwc", ls.getComponentSpecificationPath("foo/Bar"));
1101        }
1102    
1103        /** @since 4.0 */
1104    
1105        public void testComponentSlashInComponentType() throws Exception
1106        {
1107            IComponentSpecification cs = parseComponent("SlashInComponentType.jwc");
1108    
1109            IContainedComponent cc = cs.getComponent("fred");
1110    
1111            assertEquals("rubble/Barney", cc.getType());
1112        }
1113    }