From 10203ed89a66ddeed3f00292cd4c1909ef15f0ef Mon Sep 17 00:00:00 2001 From: Lukasz Lenart Date: Sat, 1 Oct 2022 16:48:18 +0200 Subject: [PATCH] WW-5233 Introduces Tiles base code into the Tiles plugin WW-5233 Copies a based set of Tiles classes used by Struts WW-5233 Copies Portlet related Tiles code base WW-5233 Copies Tiles API related tests WW-5233 Copies Tiles Core related tests WW-5233 Copies Tiles EL related tests WW-5233 Copies Tiles OGNL related tests WW-5233 Copies Tiles Template related tests WW-5233 Copies Tiles Servlet related tests WW-5233 Upgrades Easymock to version 4.3 to support Java 17 WW-5233 Copies Tiles Request related tests WW-5233 Copies Tiles Autotag related tests WW-5233 Drops useless @version tag and addresses some potential RegEx vulnerabilities WW-5233 Addresses bugs reported by Sonar WW-5233 Addresses a few code smells WW-5233 Copies Tiles Portal related tests WW-5233 Fixes broken test WW-5233 Adds Tiles DTD definition Add missing classes and tld definition. Add generating of Autotags and tests. Make plugin standalone with all generated resources. Make plugin standalone with all generated resources for velocity. Make plugin standalone with all generated resources for velocity. WW-5233 Marks Velocity dependencies as optional --- apps/showcase/pom.xml | 6 - bom/pom.xml | 4 +- plugins/portlet-tiles/pom.xml | 10 +- .../views/tiles/PortletTilesResult.java | 6 +- .../tiles/request/portlet/PortletRequest.java | 344 +++++ .../request/portlet/RenderPortletRequest.java | 47 + .../delegate/MimeResponseDelegate.java | 72 + .../delegate/PortletRequestDelegate.java | 79 ++ .../portlet/delegate/RequestDelegate.java | 43 + .../portlet/delegate/ResponseDelegate.java | 70 + .../portlet/delegate/package-info.java | 24 + .../extractor/ApplicationScopeExtractor.java | 66 + .../portlet/extractor/HeaderExtractor.java | 74 + .../extractor/InitParameterExtractor.java | 57 + .../portlet/extractor/ParameterExtractor.java | 56 + .../extractor/RequestScopeExtractor.java | 66 + .../extractor/SessionScopeExtractor.java | 88 ++ .../StateAwareParameterExtractor.java | 53 + .../portlet/extractor/package-info.java | 24 + .../tiles/request/portlet/package-info.java | 24 + .../request/portlet/PortletRequestTest.java | 424 ++++++ .../portlet/RenderPortletRequestTest.java | 69 + .../delegate/MimeResponseDelegateTest.java | 132 ++ .../delegate/PortletRequestDelegateTest.java | 83 ++ .../ApplicationScopeExtractorTest.java | 106 ++ .../extractor/HeaderExtractorTest.java | 117 ++ .../extractor/InitParameterExtractorTest.java | 83 ++ .../extractor/ParameterExtractorTest.java | 83 ++ .../extractor/RequestScopeExtractorTest.java | 107 ++ .../extractor/SessionScopeExtractorTest.java | 154 +++ .../StateAwareParameterExtractorTest.java | 50 + plugins/tiles/pom.xml | 106 +- .../apache/struts2/tiles/BuildAutotags.java | 229 ++++ .../struts2/tiles/I18NAttributeEvaluator.java | 2 +- .../tiles/StrutsAttributeEvaluator.java | 4 +- .../StrutsFreeMarkerAttributeRenderer.java | 6 +- .../struts2/tiles/StrutsPreparerFactory.java | 4 +- .../tiles/StrutsTilesAnnotationProcessor.java | 10 +- .../tiles/StrutsTilesContainerFactory.java | 44 +- .../struts2/tiles/StrutsTilesInitializer.java | 6 +- .../struts2/tiles/StrutsTilesListener.java | 4 +- .../tiles/StrutsTilesLocaleResolver.java | 4 +- ...rutsWildcardServletApplicationContext.java | 1 - .../struts2/views/tiles/TilesResult.java | 44 +- .../java/org/apache/tiles/api/Attribute.java | 366 +++++ .../apache/tiles/api/AttributeContext.java | 161 +++ .../tiles/api/BasicAttributeContext.java | 462 +++++++ .../java/org/apache/tiles/api/Definition.java | 165 +++ .../java/org/apache/tiles/api/Expression.java | 165 +++ .../org/apache/tiles/api/ListAttribute.java | 169 +++ .../tiles/api/NoSuchContainerException.java | 38 + .../org/apache/tiles/api/TilesContainer.java | 137 ++ .../tiles/api/TilesContainerWrapper.java | 107 ++ .../org/apache/tiles/api/TilesException.java | 66 + .../apache/tiles/api/access/TilesAccess.java | 158 +++ .../apache/tiles/api/access/package-info.java | 23 + .../tiles/api/mgmt/MutableTilesContainer.java | 39 + .../apache/tiles/api/mgmt/package-info.java | 24 + .../org/apache/tiles/api/package-info.java | 385 ++++++ .../tiles/api/preparer/PreparerException.java | 67 + .../tiles/api/preparer/ViewPreparer.java | 54 + .../tiles/api/preparer/package-info.java | 26 + .../autotag/core/AutotagRuntimeException.java | 60 + .../core/runtime/AbstractModelBody.java | 80 ++ .../autotag/core/runtime/AutotagRuntime.java | 49 + .../tiles/autotag/core/runtime/ModelBody.java | 58 + .../core/runtime/annotation/Parameter.java | 52 + .../core/runtime/annotation/package-info.java | 22 + .../autotag/core/runtime/package-info.java | 22 + .../autotag/core/runtime/util/NullWriter.java | 46 + .../core/runtime/util/package-info.java | 22 + .../autotag/freemarker/FMModelGenerator.java | 63 + .../FMModelRepositoryGenerator.java | 61 + .../FMTemplateGeneratorFactory.java | 69 + .../autotag/freemarker/package-info.java | 24 + .../AbstractTemplateClassGenerator.java | 143 ++ .../AbstractTemplateSuiteGenerator.java | 128 ++ .../generate/BasicTemplateGenerator.java | 187 +++ .../generate/TemplateClassGenerator.java | 45 + .../autotag/generate/TemplateGenerator.java | 56 + .../generate/TemplateGeneratorBuilder.java | 180 +++ .../generate/TemplateGeneratorFactory.java | 32 + .../generate/TemplateSuiteGenerator.java | 40 + .../tiles/autotag/generate/package-info.java | 22 + .../jsp/JspTemplateGeneratorFactory.java | 79 ++ .../tiles/autotag/jsp/TLDGenerator.java | 60 + .../tiles/autotag/jsp/TagClassGenerator.java | 63 + .../tiles/autotag/jsp/package-info.java | 22 + .../tiles/autotag/model/TemplateClass.java | 191 +++ .../tiles/autotag/model/TemplateMethod.java | 127 ++ .../autotag/model/TemplateParameter.java | 182 +++ .../tiles/autotag/model/TemplateSuite.java | 125 ++ .../tiles/autotag/model/package-info.java | 22 + .../apache/tiles/autotag/tool/StringTool.java | 138 ++ .../tiles/autotag/tool/package-info.java | 22 + .../velocity/VelocityDirectiveGenerator.java | 67 + .../velocity/VelocityPropertiesGenerator.java | 64 + .../VelocityTemplateGeneratorFactory.java | 87 ++ .../tiles/autotag/velocity/package-info.java | 24 + .../core/definition/DefinitionsFactory.java | 75 ++ .../DefinitionsFactoryException.java | 72 + .../core/definition/DefinitionsReader.java | 52 + .../definition/NoSuchDefinitionException.java | 35 + .../tiles/core/definition/RefreshMonitor.java | 36 + .../UnresolvingLocaleDefinitionsFactory.java | 86 ++ .../dao/BaseLocaleUrlDefinitionDAO.java | 163 +++ .../dao/CachingLocaleUrlDefinitionDAO.java | 272 ++++ .../core/definition/dao/DefinitionDAO.java | 54 + .../dao/ResolvingLocaleUrlDefinitionDAO.java | 172 +++ .../core/definition/dao/package-info.java | 23 + .../digester/DigesterDefinitionsReader.java | 464 +++++++ .../DigesterDefinitionsReaderException.java | 40 + .../definition/digester/package-info.java | 22 + .../tiles/core/definition/package-info.java | 23 + .../AbstractPatternDefinitionResolver.java | 106 ++ .../BasicPatternDefinitionResolver.java | 75 ++ .../pattern/DefinitionPatternMatcher.java | 40 + .../DefinitionPatternMatcherFactory.java | 41 + .../pattern/PatternDefinitionResolver.java | 63 + .../PatternDefinitionResolverAware.java | 36 + .../definition/pattern/PatternRecognizer.java | 37 + .../core/definition/pattern/PatternUtil.java | 240 ++++ .../PrefixedPatternDefinitionResolver.java | 103 ++ .../core/definition/pattern/package-info.java | 22 + .../RegexpDefinitionPatternMatcher.java | 72 + ...RegexpDefinitionPatternMatcherFactory.java | 36 + .../pattern/regexp/package-info.java | 22 + .../WildcardDefinitionPatternMatcher.java | 78 ++ ...ldcardDefinitionPatternMatcherFactory.java | 54 + .../pattern/wildcard/package-info.java | 22 + .../evaluator/AbstractAttributeEvaluator.java | 50 + .../core/evaluator/AttributeEvaluator.java | 50 + .../evaluator/AttributeEvaluatorFactory.java | 48 + .../AttributeEvaluatorFactoryAware.java | 35 + .../BasicAttributeEvaluatorFactory.java | 88 ++ .../core/evaluator/EvaluationException.java | 50 + .../impl/DirectAttributeEvaluator.java | 36 + .../core/evaluator/impl/package-info.java | 22 + .../tiles/core/evaluator/package-info.java | 22 + .../AbstractTilesContainerFactory.java | 41 + .../factory/BasicTilesContainerFactory.java | 406 ++++++ .../TilesContainerFactoryException.java | 41 + .../tiles/core/factory/package-info.java | 22 + .../tiles/core/impl/BasicTilesContainer.java | 398 ++++++ .../core/impl/InvalidTemplateException.java | 50 + .../core/impl/mgmt/CachingTilesContainer.java | 222 +++ .../tiles/core/impl/mgmt/package-info.java | 22 + .../apache/tiles/core/impl/package-info.java | 22 + .../tiles/core/locale/LocaleResolver.java | 38 + .../locale/impl/DefaultLocaleResolver.java | 55 + .../tiles/core/locale/impl/package-info.java | 22 + .../tiles/core/locale/package-info.java | 23 + .../prepare/factory/BasicPreparerFactory.java | 84 ++ .../factory/NoSuchPreparerException.java | 39 + .../core/prepare/factory/PreparerFactory.java | 49 + .../core/prepare/factory/package-info.java | 26 + .../core/renderer/DefinitionRenderer.java | 67 + .../tiles/core/renderer/package-info.java | 22 + .../startup/AbstractTilesInitializer.java | 110 ++ .../tiles/core/startup/TilesInitializer.java | 45 + .../tiles/core/startup/package-info.java | 24 + .../tiles/core/util/CombinedBeanInfo.java | 95 ++ .../tiles/core/util/WildcardHelper.java | 543 ++++++++ .../apache/tiles/core/util/package-info.java | 22 + .../apache/tiles/el/ELAttributeEvaluator.java | 92 ++ .../org/apache/tiles/el/ELContextImpl.java | 144 ++ .../tiles/el/ExpressionFactoryFactory.java | 37 + .../tiles/el/JspExpressionFactoryFactory.java | 63 + .../org/apache/tiles/el/ScopeELResolver.java | 143 ++ .../tiles/el/TilesContextBeanELResolver.java | 172 +++ .../tiles/el/TilesContextELResolver.java | 156 +++ .../org/apache/tiles/el/package-info.java | 22 + .../apache/tiles/freemarker/package-info.java | 22 + .../template/AddAttributeFMModel.java | 78 ++ .../template/AddListAttributeFMModel.java | 73 + .../template/DefinitionFMModel.java | 76 ++ .../template/GetAsStringFMModel.java | 81 ++ .../template/ImportAttributeFMModel.java | 74 + .../template/InsertAttributeFMModel.java | 94 ++ .../template/InsertDefinitionFMModel.java | 99 ++ .../template/InsertTemplateFMModel.java | 98 ++ .../template/PutAttributeFMModel.java | 101 ++ .../template/PutListAttributeFMModel.java | 76 ++ .../template/SetCurrentContainerFMModel.java | 64 + .../template/TilesFMModelRepository.java | 199 +++ .../tiles/ognl/AnyScopePropertyAccessor.java | 89 ++ .../tiles/ognl/DelegatePropertyAccessor.java | 84 ++ .../NestedObjectDelegatePropertyAccessor.java | 93 ++ .../tiles/ognl/NestedObjectExtractor.java | 37 + .../tiles/ognl/OGNLAttributeEvaluator.java | 45 + .../ognl/PropertyAccessorDelegateFactory.java | 43 + .../tiles/ognl/ScopePropertyAccessor.java | 68 + ...plicationContextNestedObjectExtractor.java | 35 + ...ontextPropertyAccessorDelegateFactory.java | 103 ++ .../org/apache/tiles/ognl/package-info.java | 22 + .../tiles/request/AbstractClientRequest.java | 91 ++ .../apache/tiles/request/AbstractRequest.java | 54 + .../tiles/request/AbstractViewRequest.java | 60 + .../tiles/request/ApplicationAccess.java | 47 + .../tiles/request/ApplicationContext.java | 79 ++ .../request/ApplicationContextAware.java | 34 + .../tiles/request/ApplicationResource.java | 80 ++ .../apache/tiles/request/DispatchRequest.java | 51 + .../tiles/request/DispatchRequestWrapper.java | 139 ++ .../request/NotAvailableFeatureException.java | 36 + .../org/apache/tiles/request/Request.java | 161 +++ .../tiles/request/RequestException.java | 45 + .../apache/tiles/request/RequestWrapper.java | 33 + .../tiles/request/attribute/Addable.java | 35 + .../request/attribute/AttributeExtractor.java | 25 + .../attribute/EnumeratedValuesExtractor.java | 35 + .../request/attribute/HasAddableKeys.java | 27 + .../tiles/request/attribute/HasKeys.java | 44 + .../request/attribute/HasRemovableKeys.java | 34 + .../tiles/request/attribute/package-info.java | 26 + .../collection/AddableParameterMap.java | 95 ++ .../request/collection/CollectionUtil.java | 66 + .../request/collection/HeaderValuesMap.java | 556 ++++++++ .../tiles/request/collection/KeySet.java | 167 +++ .../tiles/request/collection/MapEntry.java | 124 ++ .../collection/MapEntryArrayValues.java | 95 ++ .../collection/ReadOnlyEnumerationMap.java | 461 +++++++ .../request/collection/RemovableKeySet.java | 91 ++ .../tiles/request/collection/ScopeMap.java | 169 +++ .../request/collection/package-info.java | 34 + .../freemarker/EnvironmentScopeMap.java | 58 + .../request/freemarker/FreemarkerRequest.java | 143 ++ .../FreemarkerRequestException.java | 37 + .../freemarker/FreemarkerRequestUtil.java | 82 ++ ...otAvailableFreemarkerServletException.java | 37 + .../autotag/FreemarkerAutotagException.java | 36 + .../autotag/FreemarkerAutotagRuntime.java | 68 + .../autotag/FreemarkerModelBody.java | 62 + .../freemarker/autotag/FreemarkerUtil.java | 60 + .../freemarker/autotag/package-info.java | 22 + .../extractor/EnvironmentScopeExtractor.java | 87 ++ .../freemarker/extractor/package-info.java | 24 + .../request/freemarker/package-info.java | 24 + .../servlet/SharedVariableFactory.java | 34 + .../servlet/WebappClassTemplateLoader.java | 81 ++ .../freemarker/servlet/package-info.java | 24 + .../request/jsp/JspPrintWriterAdapter.java | 432 ++++++ .../apache/tiles/request/jsp/JspRequest.java | 199 +++ .../org/apache/tiles/request/jsp/JspUtil.java | 52 + .../jsp/autotag/JspAutotagRuntime.java | 69 + .../request/jsp/autotag/JspModelBody.java | 63 + .../request/jsp/autotag/package-info.java | 22 + .../request/jsp/extractor/ScopeExtractor.java | 71 + .../jsp/extractor/SessionScopeExtractor.java | 76 ++ .../request/jsp/extractor/package-info.java | 24 + .../tiles/request/jsp/package-info.java | 24 + .../tiles/request/locale/LocaleUtil.java | 58 + .../locale/PostfixedApplicationResource.java | 235 ++++ .../locale/URLApplicationResource.java | 213 +++ .../CannotInstantiateObjectException.java | 38 + .../tiles/request/reflect/ClassUtil.java | 123 ++ .../tiles/request/reflect/package-info.java | 22 + .../request/render/BasicRendererFactory.java | 79 ++ .../request/render/CannotRenderException.java | 46 + .../render/ChainedDelegateRenderer.java | 80 ++ .../request/render/DispatchRenderer.java | 61 + .../render/NoSuchRendererException.java | 35 + .../tiles/request/render/RenderException.java | 46 + .../apache/tiles/request/render/Renderer.java | 48 + .../tiles/request/render/RendererFactory.java | 41 + .../tiles/request/render/StringRenderer.java | 43 + .../ExternalWriterHttpServletResponse.java | 58 + .../NotAServletEnvironmentException.java | 36 + .../servlet/ServletApplicationContext.java | 127 ++ .../tiles/request/servlet/ServletRequest.java | 343 +++++ .../tiles/request/servlet/ServletUtil.java | 117 ++ .../extractor/ApplicationScopeExtractor.java | 64 + .../servlet/extractor/HeaderExtractor.java | 72 + .../extractor/InitParameterExtractor.java | 55 + .../servlet/extractor/ParameterExtractor.java | 54 + .../extractor/RequestScopeExtractor.java | 64 + .../extractor/SessionScopeExtractor.java | 77 ++ .../servlet/extractor/package-info.java | 24 + .../tiles/request/servlet/package-info.java | 24 + .../request/velocity/VelocityRequest.java | 169 +++ .../request/velocity/VelocityScopeMap.java | 87 ++ .../autotag/VelocityAutotagRuntime.java | 102 ++ .../velocity/autotag/VelocityModelBody.java | 61 + .../velocity/autotag/VelocityUtil.java | 67 + .../velocity/autotag/package-info.java | 22 + .../extractor/VelocityScopeExtractor.java | 99 ++ .../velocity/extractor/package-info.java | 22 + .../tiles/request/velocity/package-info.java | 22 + .../render/ApplicationContextJeeConfig.java | 77 ++ .../velocity/render/VelocityRenderer.java | 75 ++ .../render/VelocityRendererBuilder.java | 91 ++ .../request/velocity/render/package-info.java | 22 + .../tiles/template/AddAttributeModel.java | 124 ++ .../tiles/template/AddListAttributeModel.java | 60 + .../tiles/template/AttributeResolver.java | 58 + .../tiles/template/ComposeStackUtil.java | 83 ++ .../template/DefaultAttributeResolver.java | 85 ++ .../tiles/template/DefinitionModel.java | 139 ++ .../tiles/template/GetAsStringModel.java | 224 ++++ .../tiles/template/ImportAttributeModel.java | 194 +++ .../tiles/template/InsertAttributeModel.java | 204 +++ .../tiles/template/InsertDefinitionModel.java | 147 ++ .../tiles/template/InsertTemplateModel.java | 141 ++ .../template/NoSuchAttributeException.java | 40 + .../tiles/template/PutAttributeModel.java | 165 +++ .../tiles/template/PutListAttributeModel.java | 88 ++ .../template/SetCurrentContainerModel.java | 41 + .../apache/tiles/template/package-info.java | 24 + .../velocity/TilesVelocityException.java | 71 + .../apache/tiles/velocity/package-info.java | 22 + .../AbstractDefaultToStringRenderable.java | 119 ++ .../template/AddAttributeDirective.java | 78 ++ .../template/AddListAttributeDirective.java | 73 + .../velocity/template/ContextHolder.java | 154 +++ .../template/DefinitionDirective.java | 76 ++ .../template/GetAsStringDirective.java | 81 ++ .../template/ImportAttributeDirective.java | 74 + .../template/InsertAttributeDirective.java | 94 ++ .../template/InsertDefinitionDirective.java | 99 ++ .../template/InsertTemplateDirective.java | 98 ++ .../template/PutAttributeDirective.java | 101 ++ .../template/PutListAttributeDirective.java | 76 ++ .../SetCurrentContainerDirective.java | 64 + .../template/VelocityStyleTilesTool.java | 224 ++++ .../tiles/velocity/template/package-info.java | 22 + .../tiles/web/jsp/taglib/AddAttributeTag.java | 165 +++ .../web/jsp/taglib/AddListAttributeTag.java | 87 ++ .../tiles/web/jsp/taglib/DefinitionTag.java | 184 +++ .../tiles/web/jsp/taglib/GetAsStringTag.java | 264 ++++ .../web/jsp/taglib/ImportAttributeTag.java | 166 +++ .../web/jsp/taglib/InsertAttributeTag.java | 299 +++++ .../web/jsp/taglib/InsertDefinitionTag.java | 257 ++++ .../web/jsp/taglib/InsertTemplateTag.java | 230 ++++ .../tiles/web/jsp/taglib/PutAttributeTag.java | 233 ++++ .../web/jsp/taglib/PutListAttributeTag.java | 164 +++ .../jsp/taglib/SetCurrentContainerTag.java | 80 ++ .../tiles/web/jsp/taglib/UseAttributeTag.java | 214 +++ .../tiles/web/jsp/taglib/package-info.java | 23 + .../web/startup/AbstractTilesListener.java | 69 + .../tiles/web/startup/package-info.java | 24 + .../web/util/AttributeContextMutator.java | 42 + .../tiles/web/util/TilesDispatchServlet.java | 148 ++ .../apache/tiles/web/util/package-info.java | 24 + .../resources/META-INF/template-suite.xml | 1188 +++++++++++++++++ .../META-INF/tld/tiles-extras-jsp.tld | 105 ++ .../main/resources/META-INF/tld/tiles-jsp.tld | 922 +++++++++++++ .../resources/META-INF/velocity.properties | 30 + .../tiles/autotag/freemarker/fmModel.vm | 78 ++ .../tiles/autotag/freemarker/repository.vm | 57 + .../org/apache/tiles/autotag/jsp/bodyTag.vm | 102 ++ .../org/apache/tiles/autotag/jsp/tld.vm | 66 + .../apache/tiles/autotag/velocity.properties | 101 ++ .../autotag/velocity/velocityDirective.vm | 76 ++ .../autotag/velocity/velocityProperties.vm | 21 + .../tiles/resources/tiles-config_3_0.dtd | 245 ++++ plugins/tiles/src/main/resources/tools.xml | 24 + .../StrutsTilesAnnotationProcessorTest.java | 6 +- .../org/apache/tiles/api/AttributeTest.java | 275 ++++ .../tiles/api/BasicAttributeContextTest.java | 681 ++++++++++ .../org/apache/tiles/api/ExpressionTest.java | 108 ++ .../apache/tiles/api/ListAttributeTest.java | 109 ++ .../api/NoSuchContainerExceptionTest.java | 39 + .../org/apache/tiles/api/TestDefinition.java | 248 ++++ .../tiles/api/TilesContainerWrapperTest.java | 232 ++++ .../apache/tiles/api/TilesExceptionTest.java | 62 + .../tiles/api/access/TilesAccessTest.java | 206 +++ .../api/preparer/PreparerExceptionTest.java | 74 + .../freemarker/FMModelGeneratorTest.java | 139 ++ .../FMModelRepositoryGeneratorTest.java | 126 ++ .../FMTemplateGeneratorFactoryTest.java | 58 + .../jsp/JspTemplateGeneratorFactoryTest.java | 61 + .../tiles/autotag/jsp/TLDGeneratorTest.java | 129 ++ .../autotag/jsp/TagClassGeneratorTest.java | 139 ++ .../autotag/model/TemplateClassTest.java | 153 +++ .../autotag/model/TemplateMethodTest.java | 132 ++ .../autotag/model/TemplateParameterTest.java | 88 ++ .../autotag/model/TemplateSuiteTest.java | 112 ++ .../runtime/AbstractModelBodyTest.java | 157 +++ .../autotag/runtime/util/NullWriterTest.java | 71 + .../VelocityDirectiveGeneratorTest.java | 139 ++ .../VelocityPropertiesGeneratorTest.java | 125 ++ .../VelocityTemplateGeneratorFactoryTest.java | 60 + .../DefinitionsFactoryExceptionTest.java | 74 + .../definition/MockDefinitionsReader.java | 44 + .../NoSuchDefinitionExceptionTest.java | 42 + ...resolvingLocaleDefinitionsFactoryTest.java | 63 + .../dao/BaseLocaleUrlDefinitionDAOTest.java | 156 +++ .../CachingLocaleUrlDefinitionDAOTest.java | 371 +++++ .../ResolvingLocaleUrlDefinitionDAOTest.java | 391 ++++++ ...igesterDefinitionsReaderExceptionTest.java | 41 + .../TestDigesterDefinitionsReader.java | 279 ++++ ...AbstractPatternDefinitionResolverTest.java | 119 ++ .../BasicPatternDefinitionResolverTest.java | 78 ++ .../definition/pattern/PatternUtilTest.java | 316 +++++ ...PrefixedPatternDefinitionResolverTest.java | 77 ++ ...xpDefinitionPatternMatcherFactoryTest.java | 49 + .../RegexpDefinitionPatternMatcherTest.java | 47 + ...rdDefinitionPatternMatcherFactoryTest.java | 61 + .../WildcardDefinitionPatternMatcherTest.java | 53 + .../BasicAttributeEvaluatorFactoryTest.java | 85 ++ .../evaluator/EvaluatorExceptionTest.java | 53 + .../impl/DirectAttributeEvaluatorTest.java | 84 ++ .../factory/BasicPreparerFactoryTest.java | 72 + .../BasicTilesContainerFactoryTest.java | 252 ++++ .../factory/NoSuchPreparerExceptionTest.java | 43 + .../TilesContainerFactoryExceptionTest.java | 42 + .../core/impl/BasicTilesContainerTest.java | 126 ++ .../impl/BasicTilesContainerUnitTest.java | 836 ++++++++++++ .../core/impl/CannotRenderExceptionTest.java | 54 + .../core/impl/DefaultLocaleResolverTest.java | 58 + .../impl/InvalidTemplateExceptionTest.java | 53 + .../impl/mgmt/CachingTilesContainerTest.java | 305 +++++ .../core/renderer/DefinitionRendererTest.java | 106 ++ .../startup/AbstractTilesInitializerTest.java | 130 ++ .../tiles/core/util/CombinedBeanInfoTest.java | 93 ++ .../tiles/el/ELAttributeEvaluatorTest.java | 189 +++ .../apache/tiles/el/ELContextImplTest.java | 120 ++ .../el/JspExpressionFactoryFactoryTest.java | 84 ++ .../apache/tiles/el/ScopeELResolverTest.java | 175 +++ .../el/TilesContextBeanELResolverTest.java | 299 +++++ .../tiles/el/TilesContextELResolverTest.java | 189 +++ .../ognl/AnyScopePropertyAccessorTest.java | 152 +++ .../ognl/DelegatePropertyAccessorTest.java | 111 ++ ...tedObjectDelegatePropertyAccessorTest.java | 106 ++ .../ognl/OGNLAttributeEvaluatorTest.java | 229 ++++ .../tiles/ognl/ScopePropertyAccessorTest.java | 91 ++ ...ationContextNestedObjectExtractorTest.java | 51 + ...xtPropertyAccessorDelegateFactoryTest.java | 189 +++ .../request/AbstractClientRequestTest.java | 155 +++ .../tiles/request/AbstractRequestTest.java | 54 + .../request/AbstractViewRequestTest.java | 119 ++ .../tiles/request/ApplicationAccessTest.java | 51 + .../request/DispatchRequestWrapperTest.java | 90 ++ .../NotAvailableFeatureExceptionTest.java | 41 + .../tiles/request/RequestExceptionTest.java | 53 + .../collection/AddableParameterMapTest.java | 112 ++ .../collection/CollectionUtilTest.java | 59 + .../HeaderValuesCollectionTest.java | 398 ++++++ .../HeaderValuesMapEntrySetTest.java | 337 +++++ .../collection/HeaderValuesMapTest.java | 337 +++++ .../tiles/request/collection/KeySetTest.java | 283 ++++ .../collection/MapEntryArrayValuesTest.java | 76 ++ .../request/collection/MapEntryTest.java | 106 ++ .../ReadOnlyEnumerationMapEntrySetTest.java | 294 ++++ .../ReadOnlyEnumerationMapTest.java | 306 +++++ ...nlyEnumerationMapValuesCollectionTest.java | 312 +++++ .../collection/RemovableKeySetTest.java | 129 ++ .../collection/ScopeMapEntrySetTest.java | 234 ++++ .../request/collection/ScopeMapTest.java | 135 ++ .../tiles/request/locale/LocaleUtilTest.java | 42 + .../PostfixedApplicationResourceTest.java | 131 ++ .../locale/URLApplicationResourceTest.java | 201 +++ .../CannotInstantiateObjectExceptionTest.java | 41 + .../tiles/request/reflect/ClassUtilTest.java | 175 +++ .../render/BasicRendererFactoryTest.java | 100 ++ .../render/ChainedDelegateRendererTest.java | 178 +++ .../request/render/DispatchRendererTest.java | 74 + .../render/NoSuchRendererExceptionTest.java | 42 + .../request/render/StringRendererTest.java | 79 ++ .../tiles/template/AddAttributeModelTest.java | 111 ++ .../template/AddListAttributeModelTest.java | 86 ++ .../tiles/template/ComposeStackUtilTest.java | 123 ++ .../DefaultAttributeResolverTest.java | 155 +++ .../tiles/template/DefinitionModelTest.java | 98 ++ .../tiles/template/GetAsStringModelTest.java | 140 ++ .../template/ImportAttributeModelTest.java | 316 +++++ .../template/InsertAttributeModelTest.java | 131 ++ .../template/InsertDefinitionModelTest.java | 90 ++ .../template/InsertTemplateModelTest.java | 89 ++ .../tiles/template/PutAttributeModelTest.java | 93 ++ .../template/PutListAttributeModelTest.java | 93 ++ .../SetCurrentContainerModelTest.java | 84 ++ .../web/jsp/taglib/UseAttributeTagTest.java | 220 +++ .../startup/AbstractTilesListenerTest.java | 61 + .../freemarker/test/DoStuffFMModel.javat | 72 + .../test/DoStuffNoBodyFMModel.javat | 70 + .../test/TldtestFMModelRepository.javat | 64 + .../autotag/jsp/test/DoStuffNoBodyTag.java | 134 ++ .../tiles/autotag/jsp/test/DoStuffTag.java | 136 ++ .../velocity/test/DoStuffDirective.javat | 70 + .../test/DoStuffNoBodyDirective.javat | 68 + .../tiles/core/config/defs-tiles-513.xml | 48 + .../tiles/core/config/defs-wildcard.xml | 62 + .../org/apache/tiles/core/config/defs1.xml | 75 ++ .../apache/tiles/core/config/defs1_en_US.xml | 45 + .../org/apache/tiles/core/config/defs1_fr.xml | 58 + .../apache/tiles/core/config/defs1_fr_CA.xml | 45 + .../org/apache/tiles/core/config/defs2.xml | 44 + .../org/apache/tiles/core/config/defs3.xml | 44 + .../core/config/defs_regression_TILES-352.xml | 40 + .../apache/tiles/core/config/invalid-defs.xml | 44 + .../tiles/core/config/malformed-defs.xml | 42 + .../apache/tiles/core/config/temp-defs.xml | 45 + .../tiles/core/config/tiles-defs-2.1.xml | 88 ++ .../tiles/core/config/tiles-defs-2.1_it.xml | 33 + .../apache/tiles/core/config/tiles-defs.xml | 143 ++ .../tiles/core/factory/test-defs-key-one.xml | 37 + .../tiles/core/factory/test-defs-key-two.xml | 37 + .../apache/tiles/core/factory/test-defs.xml | 37 + .../request/locale/resource with space.txt | 17 + .../apache/tiles/request/locale/resource.txt | 17 + .../tiles/src/test/resources/tldtest-jsp.tld | 121 ++ .../test/resources/velocity.properties.test | 21 + pom.xml | 70 +- 504 files changed, 52311 insertions(+), 191 deletions(-) create mode 100644 plugins/portlet-tiles/src/main/java/org/apache/tiles/request/portlet/PortletRequest.java create mode 100644 plugins/portlet-tiles/src/main/java/org/apache/tiles/request/portlet/RenderPortletRequest.java create mode 100644 plugins/portlet-tiles/src/main/java/org/apache/tiles/request/portlet/delegate/MimeResponseDelegate.java create mode 100644 plugins/portlet-tiles/src/main/java/org/apache/tiles/request/portlet/delegate/PortletRequestDelegate.java create mode 100644 plugins/portlet-tiles/src/main/java/org/apache/tiles/request/portlet/delegate/RequestDelegate.java create mode 100644 plugins/portlet-tiles/src/main/java/org/apache/tiles/request/portlet/delegate/ResponseDelegate.java create mode 100644 plugins/portlet-tiles/src/main/java/org/apache/tiles/request/portlet/delegate/package-info.java create mode 100644 plugins/portlet-tiles/src/main/java/org/apache/tiles/request/portlet/extractor/ApplicationScopeExtractor.java create mode 100644 plugins/portlet-tiles/src/main/java/org/apache/tiles/request/portlet/extractor/HeaderExtractor.java create mode 100644 plugins/portlet-tiles/src/main/java/org/apache/tiles/request/portlet/extractor/InitParameterExtractor.java create mode 100644 plugins/portlet-tiles/src/main/java/org/apache/tiles/request/portlet/extractor/ParameterExtractor.java create mode 100644 plugins/portlet-tiles/src/main/java/org/apache/tiles/request/portlet/extractor/RequestScopeExtractor.java create mode 100644 plugins/portlet-tiles/src/main/java/org/apache/tiles/request/portlet/extractor/SessionScopeExtractor.java create mode 100644 plugins/portlet-tiles/src/main/java/org/apache/tiles/request/portlet/extractor/StateAwareParameterExtractor.java create mode 100644 plugins/portlet-tiles/src/main/java/org/apache/tiles/request/portlet/extractor/package-info.java create mode 100644 plugins/portlet-tiles/src/main/java/org/apache/tiles/request/portlet/package-info.java create mode 100644 plugins/portlet-tiles/src/test/java/org/apache/tiles/request/portlet/PortletRequestTest.java create mode 100644 plugins/portlet-tiles/src/test/java/org/apache/tiles/request/portlet/RenderPortletRequestTest.java create mode 100644 plugins/portlet-tiles/src/test/java/org/apache/tiles/request/portlet/delegate/MimeResponseDelegateTest.java create mode 100644 plugins/portlet-tiles/src/test/java/org/apache/tiles/request/portlet/delegate/PortletRequestDelegateTest.java create mode 100644 plugins/portlet-tiles/src/test/java/org/apache/tiles/request/portlet/extractor/ApplicationScopeExtractorTest.java create mode 100644 plugins/portlet-tiles/src/test/java/org/apache/tiles/request/portlet/extractor/HeaderExtractorTest.java create mode 100644 plugins/portlet-tiles/src/test/java/org/apache/tiles/request/portlet/extractor/InitParameterExtractorTest.java create mode 100644 plugins/portlet-tiles/src/test/java/org/apache/tiles/request/portlet/extractor/ParameterExtractorTest.java create mode 100644 plugins/portlet-tiles/src/test/java/org/apache/tiles/request/portlet/extractor/RequestScopeExtractorTest.java create mode 100644 plugins/portlet-tiles/src/test/java/org/apache/tiles/request/portlet/extractor/SessionScopeExtractorTest.java create mode 100644 plugins/portlet-tiles/src/test/java/org/apache/tiles/request/portlet/extractor/StateAwareParameterExtractorTest.java create mode 100644 plugins/tiles/src/main/java/org/apache/struts2/tiles/BuildAutotags.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/api/Attribute.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/api/AttributeContext.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/api/BasicAttributeContext.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/api/Definition.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/api/Expression.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/api/ListAttribute.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/api/NoSuchContainerException.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/api/TilesContainer.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/api/TilesContainerWrapper.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/api/TilesException.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/api/access/TilesAccess.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/api/access/package-info.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/api/mgmt/MutableTilesContainer.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/api/mgmt/package-info.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/api/package-info.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/api/preparer/PreparerException.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/api/preparer/ViewPreparer.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/api/preparer/package-info.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/autotag/core/AutotagRuntimeException.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/autotag/core/runtime/AbstractModelBody.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/autotag/core/runtime/AutotagRuntime.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/autotag/core/runtime/ModelBody.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/autotag/core/runtime/annotation/Parameter.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/autotag/core/runtime/annotation/package-info.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/autotag/core/runtime/package-info.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/autotag/core/runtime/util/NullWriter.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/autotag/core/runtime/util/package-info.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/autotag/freemarker/FMModelGenerator.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/autotag/freemarker/FMModelRepositoryGenerator.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/autotag/freemarker/FMTemplateGeneratorFactory.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/autotag/freemarker/package-info.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/autotag/generate/AbstractTemplateClassGenerator.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/autotag/generate/AbstractTemplateSuiteGenerator.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/autotag/generate/BasicTemplateGenerator.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/autotag/generate/TemplateClassGenerator.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/autotag/generate/TemplateGenerator.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/autotag/generate/TemplateGeneratorBuilder.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/autotag/generate/TemplateGeneratorFactory.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/autotag/generate/TemplateSuiteGenerator.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/autotag/generate/package-info.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/autotag/jsp/JspTemplateGeneratorFactory.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/autotag/jsp/TLDGenerator.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/autotag/jsp/TagClassGenerator.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/autotag/jsp/package-info.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/autotag/model/TemplateClass.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/autotag/model/TemplateMethod.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/autotag/model/TemplateParameter.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/autotag/model/TemplateSuite.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/autotag/model/package-info.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/autotag/tool/StringTool.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/autotag/tool/package-info.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/autotag/velocity/VelocityDirectiveGenerator.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/autotag/velocity/VelocityPropertiesGenerator.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/autotag/velocity/VelocityTemplateGeneratorFactory.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/autotag/velocity/package-info.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/core/definition/DefinitionsFactory.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/core/definition/DefinitionsFactoryException.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/core/definition/DefinitionsReader.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/core/definition/NoSuchDefinitionException.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/core/definition/RefreshMonitor.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/core/definition/UnresolvingLocaleDefinitionsFactory.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/core/definition/dao/BaseLocaleUrlDefinitionDAO.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/core/definition/dao/CachingLocaleUrlDefinitionDAO.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/core/definition/dao/DefinitionDAO.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/core/definition/dao/ResolvingLocaleUrlDefinitionDAO.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/core/definition/dao/package-info.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/core/definition/digester/DigesterDefinitionsReader.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/core/definition/digester/DigesterDefinitionsReaderException.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/core/definition/digester/package-info.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/core/definition/package-info.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/core/definition/pattern/AbstractPatternDefinitionResolver.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/core/definition/pattern/BasicPatternDefinitionResolver.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/core/definition/pattern/DefinitionPatternMatcher.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/core/definition/pattern/DefinitionPatternMatcherFactory.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/core/definition/pattern/PatternDefinitionResolver.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/core/definition/pattern/PatternDefinitionResolverAware.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/core/definition/pattern/PatternRecognizer.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/core/definition/pattern/PatternUtil.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/core/definition/pattern/PrefixedPatternDefinitionResolver.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/core/definition/pattern/package-info.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/core/definition/pattern/regexp/RegexpDefinitionPatternMatcher.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/core/definition/pattern/regexp/RegexpDefinitionPatternMatcherFactory.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/core/definition/pattern/regexp/package-info.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/core/definition/pattern/wildcard/WildcardDefinitionPatternMatcher.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/core/definition/pattern/wildcard/WildcardDefinitionPatternMatcherFactory.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/core/definition/pattern/wildcard/package-info.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/core/evaluator/AbstractAttributeEvaluator.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/core/evaluator/AttributeEvaluator.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/core/evaluator/AttributeEvaluatorFactory.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/core/evaluator/AttributeEvaluatorFactoryAware.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/core/evaluator/BasicAttributeEvaluatorFactory.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/core/evaluator/EvaluationException.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/core/evaluator/impl/DirectAttributeEvaluator.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/core/evaluator/impl/package-info.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/core/evaluator/package-info.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/core/factory/AbstractTilesContainerFactory.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/core/factory/BasicTilesContainerFactory.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/core/factory/TilesContainerFactoryException.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/core/factory/package-info.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/core/impl/BasicTilesContainer.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/core/impl/InvalidTemplateException.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/core/impl/mgmt/CachingTilesContainer.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/core/impl/mgmt/package-info.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/core/impl/package-info.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/core/locale/LocaleResolver.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/core/locale/impl/DefaultLocaleResolver.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/core/locale/impl/package-info.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/core/locale/package-info.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/core/prepare/factory/BasicPreparerFactory.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/core/prepare/factory/NoSuchPreparerException.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/core/prepare/factory/PreparerFactory.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/core/prepare/factory/package-info.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/core/renderer/DefinitionRenderer.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/core/renderer/package-info.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/core/startup/AbstractTilesInitializer.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/core/startup/TilesInitializer.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/core/startup/package-info.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/core/util/CombinedBeanInfo.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/core/util/WildcardHelper.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/core/util/package-info.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/el/ELAttributeEvaluator.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/el/ELContextImpl.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/el/ExpressionFactoryFactory.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/el/JspExpressionFactoryFactory.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/el/ScopeELResolver.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/el/TilesContextBeanELResolver.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/el/TilesContextELResolver.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/el/package-info.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/freemarker/package-info.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/freemarker/template/AddAttributeFMModel.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/freemarker/template/AddListAttributeFMModel.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/freemarker/template/DefinitionFMModel.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/freemarker/template/GetAsStringFMModel.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/freemarker/template/ImportAttributeFMModel.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/freemarker/template/InsertAttributeFMModel.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/freemarker/template/InsertDefinitionFMModel.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/freemarker/template/InsertTemplateFMModel.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/freemarker/template/PutAttributeFMModel.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/freemarker/template/PutListAttributeFMModel.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/freemarker/template/SetCurrentContainerFMModel.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/freemarker/template/TilesFMModelRepository.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/ognl/AnyScopePropertyAccessor.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/ognl/DelegatePropertyAccessor.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/ognl/NestedObjectDelegatePropertyAccessor.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/ognl/NestedObjectExtractor.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/ognl/OGNLAttributeEvaluator.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/ognl/PropertyAccessorDelegateFactory.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/ognl/ScopePropertyAccessor.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/ognl/TilesApplicationContextNestedObjectExtractor.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/ognl/TilesContextPropertyAccessorDelegateFactory.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/ognl/package-info.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/request/AbstractClientRequest.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/request/AbstractRequest.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/request/AbstractViewRequest.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/request/ApplicationAccess.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/request/ApplicationContext.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/request/ApplicationContextAware.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/request/ApplicationResource.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/request/DispatchRequest.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/request/DispatchRequestWrapper.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/request/NotAvailableFeatureException.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/request/Request.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/request/RequestException.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/request/RequestWrapper.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/request/attribute/Addable.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/request/attribute/AttributeExtractor.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/request/attribute/EnumeratedValuesExtractor.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/request/attribute/HasAddableKeys.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/request/attribute/HasKeys.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/request/attribute/HasRemovableKeys.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/request/attribute/package-info.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/request/collection/AddableParameterMap.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/request/collection/CollectionUtil.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/request/collection/HeaderValuesMap.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/request/collection/KeySet.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/request/collection/MapEntry.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/request/collection/MapEntryArrayValues.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/request/collection/ReadOnlyEnumerationMap.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/request/collection/RemovableKeySet.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/request/collection/ScopeMap.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/request/collection/package-info.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/request/freemarker/EnvironmentScopeMap.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/request/freemarker/FreemarkerRequest.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/request/freemarker/FreemarkerRequestException.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/request/freemarker/FreemarkerRequestUtil.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/request/freemarker/NotAvailableFreemarkerServletException.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/request/freemarker/autotag/FreemarkerAutotagException.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/request/freemarker/autotag/FreemarkerAutotagRuntime.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/request/freemarker/autotag/FreemarkerModelBody.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/request/freemarker/autotag/FreemarkerUtil.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/request/freemarker/autotag/package-info.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/request/freemarker/extractor/EnvironmentScopeExtractor.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/request/freemarker/extractor/package-info.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/request/freemarker/package-info.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/request/freemarker/servlet/SharedVariableFactory.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/request/freemarker/servlet/WebappClassTemplateLoader.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/request/freemarker/servlet/package-info.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/request/jsp/JspPrintWriterAdapter.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/request/jsp/JspRequest.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/request/jsp/JspUtil.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/request/jsp/autotag/JspAutotagRuntime.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/request/jsp/autotag/JspModelBody.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/request/jsp/autotag/package-info.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/request/jsp/extractor/ScopeExtractor.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/request/jsp/extractor/SessionScopeExtractor.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/request/jsp/extractor/package-info.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/request/jsp/package-info.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/request/locale/LocaleUtil.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/request/locale/PostfixedApplicationResource.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/request/locale/URLApplicationResource.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/request/reflect/CannotInstantiateObjectException.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/request/reflect/ClassUtil.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/request/reflect/package-info.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/request/render/BasicRendererFactory.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/request/render/CannotRenderException.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/request/render/ChainedDelegateRenderer.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/request/render/DispatchRenderer.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/request/render/NoSuchRendererException.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/request/render/RenderException.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/request/render/Renderer.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/request/render/RendererFactory.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/request/render/StringRenderer.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/request/servlet/ExternalWriterHttpServletResponse.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/request/servlet/NotAServletEnvironmentException.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/request/servlet/ServletApplicationContext.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/request/servlet/ServletRequest.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/request/servlet/ServletUtil.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/request/servlet/extractor/ApplicationScopeExtractor.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/request/servlet/extractor/HeaderExtractor.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/request/servlet/extractor/InitParameterExtractor.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/request/servlet/extractor/ParameterExtractor.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/request/servlet/extractor/RequestScopeExtractor.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/request/servlet/extractor/SessionScopeExtractor.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/request/servlet/extractor/package-info.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/request/servlet/package-info.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/request/velocity/VelocityRequest.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/request/velocity/VelocityScopeMap.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/request/velocity/autotag/VelocityAutotagRuntime.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/request/velocity/autotag/VelocityModelBody.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/request/velocity/autotag/VelocityUtil.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/request/velocity/autotag/package-info.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/request/velocity/extractor/VelocityScopeExtractor.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/request/velocity/extractor/package-info.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/request/velocity/package-info.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/request/velocity/render/ApplicationContextJeeConfig.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/request/velocity/render/VelocityRenderer.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/request/velocity/render/VelocityRendererBuilder.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/request/velocity/render/package-info.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/template/AddAttributeModel.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/template/AddListAttributeModel.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/template/AttributeResolver.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/template/ComposeStackUtil.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/template/DefaultAttributeResolver.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/template/DefinitionModel.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/template/GetAsStringModel.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/template/ImportAttributeModel.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/template/InsertAttributeModel.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/template/InsertDefinitionModel.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/template/InsertTemplateModel.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/template/NoSuchAttributeException.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/template/PutAttributeModel.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/template/PutListAttributeModel.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/template/SetCurrentContainerModel.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/template/package-info.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/velocity/TilesVelocityException.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/velocity/package-info.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/velocity/template/AbstractDefaultToStringRenderable.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/velocity/template/AddAttributeDirective.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/velocity/template/AddListAttributeDirective.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/velocity/template/ContextHolder.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/velocity/template/DefinitionDirective.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/velocity/template/GetAsStringDirective.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/velocity/template/ImportAttributeDirective.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/velocity/template/InsertAttributeDirective.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/velocity/template/InsertDefinitionDirective.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/velocity/template/InsertTemplateDirective.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/velocity/template/PutAttributeDirective.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/velocity/template/PutListAttributeDirective.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/velocity/template/SetCurrentContainerDirective.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/velocity/template/VelocityStyleTilesTool.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/velocity/template/package-info.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/web/jsp/taglib/AddAttributeTag.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/web/jsp/taglib/AddListAttributeTag.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/web/jsp/taglib/DefinitionTag.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/web/jsp/taglib/GetAsStringTag.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/web/jsp/taglib/ImportAttributeTag.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/web/jsp/taglib/InsertAttributeTag.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/web/jsp/taglib/InsertDefinitionTag.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/web/jsp/taglib/InsertTemplateTag.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/web/jsp/taglib/PutAttributeTag.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/web/jsp/taglib/PutListAttributeTag.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/web/jsp/taglib/SetCurrentContainerTag.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/web/jsp/taglib/UseAttributeTag.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/web/jsp/taglib/package-info.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/web/startup/AbstractTilesListener.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/web/startup/package-info.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/web/util/AttributeContextMutator.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/web/util/TilesDispatchServlet.java create mode 100644 plugins/tiles/src/main/java/org/apache/tiles/web/util/package-info.java create mode 100644 plugins/tiles/src/main/resources/META-INF/template-suite.xml create mode 100644 plugins/tiles/src/main/resources/META-INF/tld/tiles-extras-jsp.tld create mode 100644 plugins/tiles/src/main/resources/META-INF/tld/tiles-jsp.tld create mode 100644 plugins/tiles/src/main/resources/META-INF/velocity.properties create mode 100644 plugins/tiles/src/main/resources/org/apache/tiles/autotag/freemarker/fmModel.vm create mode 100644 plugins/tiles/src/main/resources/org/apache/tiles/autotag/freemarker/repository.vm create mode 100644 plugins/tiles/src/main/resources/org/apache/tiles/autotag/jsp/bodyTag.vm create mode 100644 plugins/tiles/src/main/resources/org/apache/tiles/autotag/jsp/tld.vm create mode 100644 plugins/tiles/src/main/resources/org/apache/tiles/autotag/velocity.properties create mode 100644 plugins/tiles/src/main/resources/org/apache/tiles/autotag/velocity/velocityDirective.vm create mode 100644 plugins/tiles/src/main/resources/org/apache/tiles/autotag/velocity/velocityProperties.vm create mode 100644 plugins/tiles/src/main/resources/org/apache/tiles/resources/tiles-config_3_0.dtd create mode 100644 plugins/tiles/src/main/resources/tools.xml create mode 100644 plugins/tiles/src/test/java/org/apache/tiles/api/AttributeTest.java create mode 100644 plugins/tiles/src/test/java/org/apache/tiles/api/BasicAttributeContextTest.java create mode 100644 plugins/tiles/src/test/java/org/apache/tiles/api/ExpressionTest.java create mode 100644 plugins/tiles/src/test/java/org/apache/tiles/api/ListAttributeTest.java create mode 100644 plugins/tiles/src/test/java/org/apache/tiles/api/NoSuchContainerExceptionTest.java create mode 100644 plugins/tiles/src/test/java/org/apache/tiles/api/TestDefinition.java create mode 100644 plugins/tiles/src/test/java/org/apache/tiles/api/TilesContainerWrapperTest.java create mode 100644 plugins/tiles/src/test/java/org/apache/tiles/api/TilesExceptionTest.java create mode 100644 plugins/tiles/src/test/java/org/apache/tiles/api/access/TilesAccessTest.java create mode 100644 plugins/tiles/src/test/java/org/apache/tiles/api/preparer/PreparerExceptionTest.java create mode 100644 plugins/tiles/src/test/java/org/apache/tiles/autotag/freemarker/FMModelGeneratorTest.java create mode 100644 plugins/tiles/src/test/java/org/apache/tiles/autotag/freemarker/FMModelRepositoryGeneratorTest.java create mode 100644 plugins/tiles/src/test/java/org/apache/tiles/autotag/freemarker/FMTemplateGeneratorFactoryTest.java create mode 100644 plugins/tiles/src/test/java/org/apache/tiles/autotag/jsp/JspTemplateGeneratorFactoryTest.java create mode 100644 plugins/tiles/src/test/java/org/apache/tiles/autotag/jsp/TLDGeneratorTest.java create mode 100644 plugins/tiles/src/test/java/org/apache/tiles/autotag/jsp/TagClassGeneratorTest.java create mode 100644 plugins/tiles/src/test/java/org/apache/tiles/autotag/model/TemplateClassTest.java create mode 100644 plugins/tiles/src/test/java/org/apache/tiles/autotag/model/TemplateMethodTest.java create mode 100644 plugins/tiles/src/test/java/org/apache/tiles/autotag/model/TemplateParameterTest.java create mode 100644 plugins/tiles/src/test/java/org/apache/tiles/autotag/model/TemplateSuiteTest.java create mode 100644 plugins/tiles/src/test/java/org/apache/tiles/autotag/runtime/AbstractModelBodyTest.java create mode 100644 plugins/tiles/src/test/java/org/apache/tiles/autotag/runtime/util/NullWriterTest.java create mode 100644 plugins/tiles/src/test/java/org/apache/tiles/autotag/velocity/VelocityDirectiveGeneratorTest.java create mode 100644 plugins/tiles/src/test/java/org/apache/tiles/autotag/velocity/VelocityPropertiesGeneratorTest.java create mode 100644 plugins/tiles/src/test/java/org/apache/tiles/autotag/velocity/VelocityTemplateGeneratorFactoryTest.java create mode 100644 plugins/tiles/src/test/java/org/apache/tiles/core/definition/DefinitionsFactoryExceptionTest.java create mode 100644 plugins/tiles/src/test/java/org/apache/tiles/core/definition/MockDefinitionsReader.java create mode 100644 plugins/tiles/src/test/java/org/apache/tiles/core/definition/NoSuchDefinitionExceptionTest.java create mode 100644 plugins/tiles/src/test/java/org/apache/tiles/core/definition/UnresolvingLocaleDefinitionsFactoryTest.java create mode 100644 plugins/tiles/src/test/java/org/apache/tiles/core/definition/dao/BaseLocaleUrlDefinitionDAOTest.java create mode 100644 plugins/tiles/src/test/java/org/apache/tiles/core/definition/dao/CachingLocaleUrlDefinitionDAOTest.java create mode 100644 plugins/tiles/src/test/java/org/apache/tiles/core/definition/dao/ResolvingLocaleUrlDefinitionDAOTest.java create mode 100644 plugins/tiles/src/test/java/org/apache/tiles/core/definition/digester/DigesterDefinitionsReaderExceptionTest.java create mode 100644 plugins/tiles/src/test/java/org/apache/tiles/core/definition/digester/TestDigesterDefinitionsReader.java create mode 100644 plugins/tiles/src/test/java/org/apache/tiles/core/definition/pattern/AbstractPatternDefinitionResolverTest.java create mode 100644 plugins/tiles/src/test/java/org/apache/tiles/core/definition/pattern/BasicPatternDefinitionResolverTest.java create mode 100644 plugins/tiles/src/test/java/org/apache/tiles/core/definition/pattern/PatternUtilTest.java create mode 100644 plugins/tiles/src/test/java/org/apache/tiles/core/definition/pattern/PrefixedPatternDefinitionResolverTest.java create mode 100644 plugins/tiles/src/test/java/org/apache/tiles/core/definition/pattern/regexp/RegexpDefinitionPatternMatcherFactoryTest.java create mode 100644 plugins/tiles/src/test/java/org/apache/tiles/core/definition/pattern/regexp/RegexpDefinitionPatternMatcherTest.java create mode 100644 plugins/tiles/src/test/java/org/apache/tiles/core/definition/pattern/wildcard/WildcardDefinitionPatternMatcherFactoryTest.java create mode 100644 plugins/tiles/src/test/java/org/apache/tiles/core/definition/pattern/wildcard/WildcardDefinitionPatternMatcherTest.java create mode 100644 plugins/tiles/src/test/java/org/apache/tiles/core/evaluator/BasicAttributeEvaluatorFactoryTest.java create mode 100644 plugins/tiles/src/test/java/org/apache/tiles/core/evaluator/EvaluatorExceptionTest.java create mode 100644 plugins/tiles/src/test/java/org/apache/tiles/core/evaluator/impl/DirectAttributeEvaluatorTest.java create mode 100644 plugins/tiles/src/test/java/org/apache/tiles/core/factory/BasicPreparerFactoryTest.java create mode 100644 plugins/tiles/src/test/java/org/apache/tiles/core/factory/BasicTilesContainerFactoryTest.java create mode 100644 plugins/tiles/src/test/java/org/apache/tiles/core/factory/NoSuchPreparerExceptionTest.java create mode 100644 plugins/tiles/src/test/java/org/apache/tiles/core/factory/TilesContainerFactoryExceptionTest.java create mode 100644 plugins/tiles/src/test/java/org/apache/tiles/core/impl/BasicTilesContainerTest.java create mode 100644 plugins/tiles/src/test/java/org/apache/tiles/core/impl/BasicTilesContainerUnitTest.java create mode 100644 plugins/tiles/src/test/java/org/apache/tiles/core/impl/CannotRenderExceptionTest.java create mode 100644 plugins/tiles/src/test/java/org/apache/tiles/core/impl/DefaultLocaleResolverTest.java create mode 100644 plugins/tiles/src/test/java/org/apache/tiles/core/impl/InvalidTemplateExceptionTest.java create mode 100644 plugins/tiles/src/test/java/org/apache/tiles/core/impl/mgmt/CachingTilesContainerTest.java create mode 100644 plugins/tiles/src/test/java/org/apache/tiles/core/renderer/DefinitionRendererTest.java create mode 100644 plugins/tiles/src/test/java/org/apache/tiles/core/startup/AbstractTilesInitializerTest.java create mode 100644 plugins/tiles/src/test/java/org/apache/tiles/core/util/CombinedBeanInfoTest.java create mode 100644 plugins/tiles/src/test/java/org/apache/tiles/el/ELAttributeEvaluatorTest.java create mode 100644 plugins/tiles/src/test/java/org/apache/tiles/el/ELContextImplTest.java create mode 100644 plugins/tiles/src/test/java/org/apache/tiles/el/JspExpressionFactoryFactoryTest.java create mode 100644 plugins/tiles/src/test/java/org/apache/tiles/el/ScopeELResolverTest.java create mode 100644 plugins/tiles/src/test/java/org/apache/tiles/el/TilesContextBeanELResolverTest.java create mode 100644 plugins/tiles/src/test/java/org/apache/tiles/el/TilesContextELResolverTest.java create mode 100644 plugins/tiles/src/test/java/org/apache/tiles/ognl/AnyScopePropertyAccessorTest.java create mode 100644 plugins/tiles/src/test/java/org/apache/tiles/ognl/DelegatePropertyAccessorTest.java create mode 100644 plugins/tiles/src/test/java/org/apache/tiles/ognl/NestedObjectDelegatePropertyAccessorTest.java create mode 100644 plugins/tiles/src/test/java/org/apache/tiles/ognl/OGNLAttributeEvaluatorTest.java create mode 100644 plugins/tiles/src/test/java/org/apache/tiles/ognl/ScopePropertyAccessorTest.java create mode 100644 plugins/tiles/src/test/java/org/apache/tiles/ognl/TilesApplicationContextNestedObjectExtractorTest.java create mode 100644 plugins/tiles/src/test/java/org/apache/tiles/ognl/TilesContextPropertyAccessorDelegateFactoryTest.java create mode 100644 plugins/tiles/src/test/java/org/apache/tiles/request/AbstractClientRequestTest.java create mode 100644 plugins/tiles/src/test/java/org/apache/tiles/request/AbstractRequestTest.java create mode 100644 plugins/tiles/src/test/java/org/apache/tiles/request/AbstractViewRequestTest.java create mode 100644 plugins/tiles/src/test/java/org/apache/tiles/request/ApplicationAccessTest.java create mode 100644 plugins/tiles/src/test/java/org/apache/tiles/request/DispatchRequestWrapperTest.java create mode 100644 plugins/tiles/src/test/java/org/apache/tiles/request/NotAvailableFeatureExceptionTest.java create mode 100644 plugins/tiles/src/test/java/org/apache/tiles/request/RequestExceptionTest.java create mode 100644 plugins/tiles/src/test/java/org/apache/tiles/request/collection/AddableParameterMapTest.java create mode 100644 plugins/tiles/src/test/java/org/apache/tiles/request/collection/CollectionUtilTest.java create mode 100644 plugins/tiles/src/test/java/org/apache/tiles/request/collection/HeaderValuesCollectionTest.java create mode 100644 plugins/tiles/src/test/java/org/apache/tiles/request/collection/HeaderValuesMapEntrySetTest.java create mode 100644 plugins/tiles/src/test/java/org/apache/tiles/request/collection/HeaderValuesMapTest.java create mode 100644 plugins/tiles/src/test/java/org/apache/tiles/request/collection/KeySetTest.java create mode 100644 plugins/tiles/src/test/java/org/apache/tiles/request/collection/MapEntryArrayValuesTest.java create mode 100644 plugins/tiles/src/test/java/org/apache/tiles/request/collection/MapEntryTest.java create mode 100644 plugins/tiles/src/test/java/org/apache/tiles/request/collection/ReadOnlyEnumerationMapEntrySetTest.java create mode 100644 plugins/tiles/src/test/java/org/apache/tiles/request/collection/ReadOnlyEnumerationMapTest.java create mode 100644 plugins/tiles/src/test/java/org/apache/tiles/request/collection/ReadOnlyEnumerationMapValuesCollectionTest.java create mode 100644 plugins/tiles/src/test/java/org/apache/tiles/request/collection/RemovableKeySetTest.java create mode 100644 plugins/tiles/src/test/java/org/apache/tiles/request/collection/ScopeMapEntrySetTest.java create mode 100644 plugins/tiles/src/test/java/org/apache/tiles/request/collection/ScopeMapTest.java create mode 100644 plugins/tiles/src/test/java/org/apache/tiles/request/locale/LocaleUtilTest.java create mode 100644 plugins/tiles/src/test/java/org/apache/tiles/request/locale/PostfixedApplicationResourceTest.java create mode 100644 plugins/tiles/src/test/java/org/apache/tiles/request/locale/URLApplicationResourceTest.java create mode 100644 plugins/tiles/src/test/java/org/apache/tiles/request/reflect/CannotInstantiateObjectExceptionTest.java create mode 100644 plugins/tiles/src/test/java/org/apache/tiles/request/reflect/ClassUtilTest.java create mode 100644 plugins/tiles/src/test/java/org/apache/tiles/request/render/BasicRendererFactoryTest.java create mode 100644 plugins/tiles/src/test/java/org/apache/tiles/request/render/ChainedDelegateRendererTest.java create mode 100644 plugins/tiles/src/test/java/org/apache/tiles/request/render/DispatchRendererTest.java create mode 100644 plugins/tiles/src/test/java/org/apache/tiles/request/render/NoSuchRendererExceptionTest.java create mode 100644 plugins/tiles/src/test/java/org/apache/tiles/request/render/StringRendererTest.java create mode 100644 plugins/tiles/src/test/java/org/apache/tiles/template/AddAttributeModelTest.java create mode 100644 plugins/tiles/src/test/java/org/apache/tiles/template/AddListAttributeModelTest.java create mode 100644 plugins/tiles/src/test/java/org/apache/tiles/template/ComposeStackUtilTest.java create mode 100644 plugins/tiles/src/test/java/org/apache/tiles/template/DefaultAttributeResolverTest.java create mode 100644 plugins/tiles/src/test/java/org/apache/tiles/template/DefinitionModelTest.java create mode 100644 plugins/tiles/src/test/java/org/apache/tiles/template/GetAsStringModelTest.java create mode 100644 plugins/tiles/src/test/java/org/apache/tiles/template/ImportAttributeModelTest.java create mode 100644 plugins/tiles/src/test/java/org/apache/tiles/template/InsertAttributeModelTest.java create mode 100644 plugins/tiles/src/test/java/org/apache/tiles/template/InsertDefinitionModelTest.java create mode 100644 plugins/tiles/src/test/java/org/apache/tiles/template/InsertTemplateModelTest.java create mode 100644 plugins/tiles/src/test/java/org/apache/tiles/template/PutAttributeModelTest.java create mode 100644 plugins/tiles/src/test/java/org/apache/tiles/template/PutListAttributeModelTest.java create mode 100644 plugins/tiles/src/test/java/org/apache/tiles/template/SetCurrentContainerModelTest.java create mode 100644 plugins/tiles/src/test/java/org/apache/tiles/web/jsp/taglib/UseAttributeTagTest.java create mode 100644 plugins/tiles/src/test/java/org/apache/tiles/web/startup/AbstractTilesListenerTest.java create mode 100644 plugins/tiles/src/test/resources/org/apache/tiles/autotag/freemarker/test/DoStuffFMModel.javat create mode 100644 plugins/tiles/src/test/resources/org/apache/tiles/autotag/freemarker/test/DoStuffNoBodyFMModel.javat create mode 100644 plugins/tiles/src/test/resources/org/apache/tiles/autotag/freemarker/test/TldtestFMModelRepository.javat create mode 100644 plugins/tiles/src/test/resources/org/apache/tiles/autotag/jsp/test/DoStuffNoBodyTag.java create mode 100644 plugins/tiles/src/test/resources/org/apache/tiles/autotag/jsp/test/DoStuffTag.java create mode 100644 plugins/tiles/src/test/resources/org/apache/tiles/autotag/velocity/test/DoStuffDirective.javat create mode 100644 plugins/tiles/src/test/resources/org/apache/tiles/autotag/velocity/test/DoStuffNoBodyDirective.javat create mode 100644 plugins/tiles/src/test/resources/org/apache/tiles/core/config/defs-tiles-513.xml create mode 100644 plugins/tiles/src/test/resources/org/apache/tiles/core/config/defs-wildcard.xml create mode 100644 plugins/tiles/src/test/resources/org/apache/tiles/core/config/defs1.xml create mode 100644 plugins/tiles/src/test/resources/org/apache/tiles/core/config/defs1_en_US.xml create mode 100644 plugins/tiles/src/test/resources/org/apache/tiles/core/config/defs1_fr.xml create mode 100644 plugins/tiles/src/test/resources/org/apache/tiles/core/config/defs1_fr_CA.xml create mode 100644 plugins/tiles/src/test/resources/org/apache/tiles/core/config/defs2.xml create mode 100644 plugins/tiles/src/test/resources/org/apache/tiles/core/config/defs3.xml create mode 100644 plugins/tiles/src/test/resources/org/apache/tiles/core/config/defs_regression_TILES-352.xml create mode 100644 plugins/tiles/src/test/resources/org/apache/tiles/core/config/invalid-defs.xml create mode 100644 plugins/tiles/src/test/resources/org/apache/tiles/core/config/malformed-defs.xml create mode 100644 plugins/tiles/src/test/resources/org/apache/tiles/core/config/temp-defs.xml create mode 100644 plugins/tiles/src/test/resources/org/apache/tiles/core/config/tiles-defs-2.1.xml create mode 100644 plugins/tiles/src/test/resources/org/apache/tiles/core/config/tiles-defs-2.1_it.xml create mode 100644 plugins/tiles/src/test/resources/org/apache/tiles/core/config/tiles-defs.xml create mode 100644 plugins/tiles/src/test/resources/org/apache/tiles/core/factory/test-defs-key-one.xml create mode 100644 plugins/tiles/src/test/resources/org/apache/tiles/core/factory/test-defs-key-two.xml create mode 100644 plugins/tiles/src/test/resources/org/apache/tiles/core/factory/test-defs.xml create mode 100644 plugins/tiles/src/test/resources/org/apache/tiles/request/locale/resource with space.txt create mode 100644 plugins/tiles/src/test/resources/org/apache/tiles/request/locale/resource.txt create mode 100644 plugins/tiles/src/test/resources/tldtest-jsp.tld create mode 100644 plugins/tiles/src/test/resources/velocity.properties.test diff --git a/apps/showcase/pom.xml b/apps/showcase/pom.xml index 1c8e079b0..1a04728ce 100644 --- a/apps/showcase/pom.xml +++ b/apps/showcase/pom.xml @@ -68,12 +68,6 @@ struts2-json-plugin - - org.apache.tiles - tiles-jsp - runtime - - org.apache.struts struts2-convention-plugin diff --git a/bom/pom.xml b/bom/pom.xml index c4ffbaf5e..6a9757382 100644 --- a/bom/pom.xml +++ b/bom/pom.xml @@ -24,8 +24,8 @@ org.apache.struts - struts-master - 14 + struts2-parent + 6.3.0-SNAPSHOT struts2-bom diff --git a/plugins/portlet-tiles/pom.xml b/plugins/portlet-tiles/pom.xml index 60631ebc6..7caba1442 100644 --- a/plugins/portlet-tiles/pom.xml +++ b/plugins/portlet-tiles/pom.xml @@ -40,10 +40,6 @@ org.apache.struts struts2-portlet-plugin - - org.apache.tiles - tiles-request-portlet - javax.servlet.jsp jsp-api @@ -55,9 +51,9 @@ provided - org.apache.tiles - tiles-jsp - runtime + org.easymock + easymock + test diff --git a/plugins/portlet-tiles/src/main/java/org/apache/struts2/views/tiles/PortletTilesResult.java b/plugins/portlet-tiles/src/main/java/org/apache/struts2/views/tiles/PortletTilesResult.java index 82249ccc9..ef1f82f76 100644 --- a/plugins/portlet-tiles/src/main/java/org/apache/struts2/views/tiles/PortletTilesResult.java +++ b/plugins/portlet-tiles/src/main/java/org/apache/struts2/views/tiles/PortletTilesResult.java @@ -22,9 +22,9 @@ import com.opensymphony.xwork2.ActionInvocation; import org.apache.struts2.portlet.PortletConstants; import org.apache.struts2.portlet.context.PortletActionContext; import org.apache.struts2.result.ServletDispatcherResult; -import org.apache.tiles.TilesContainer; -import org.apache.tiles.TilesException; -import org.apache.tiles.access.TilesAccess; +import org.apache.tiles.api.TilesContainer; +import org.apache.tiles.api.TilesException; +import org.apache.tiles.api.access.TilesAccess; import org.apache.tiles.request.ApplicationContext; import org.apache.tiles.request.Request; import org.apache.tiles.request.portlet.RenderPortletRequest; diff --git a/plugins/portlet-tiles/src/main/java/org/apache/tiles/request/portlet/PortletRequest.java b/plugins/portlet-tiles/src/main/java/org/apache/tiles/request/portlet/PortletRequest.java new file mode 100644 index 000000000..6946776e4 --- /dev/null +++ b/plugins/portlet-tiles/src/main/java/org/apache/tiles/request/portlet/PortletRequest.java @@ -0,0 +1,344 @@ +/* + * $Id$ + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.request.portlet; + +import org.apache.tiles.request.AbstractClientRequest; +import org.apache.tiles.request.ApplicationContext; +import org.apache.tiles.request.attribute.Addable; +import org.apache.tiles.request.collection.HeaderValuesMap; +import org.apache.tiles.request.collection.ReadOnlyEnumerationMap; +import org.apache.tiles.request.collection.ScopeMap; +import org.apache.tiles.request.portlet.delegate.RequestDelegate; +import org.apache.tiles.request.portlet.delegate.ResponseDelegate; +import org.apache.tiles.request.portlet.extractor.HeaderExtractor; +import org.apache.tiles.request.portlet.extractor.RequestScopeExtractor; +import org.apache.tiles.request.portlet.extractor.SessionScopeExtractor; + +import javax.portlet.PortletContext; +import javax.portlet.PortletException; +import javax.portlet.PortletRequestDispatcher; +import javax.portlet.PortletResponse; +import javax.portlet.PortletSession; +import java.io.IOException; +import java.io.OutputStream; +import java.io.PrintWriter; +import java.io.Writer; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Locale; +import java.util.Map; + +/** + * Portlet-based TilesApplicationContext implementation. + */ +public class PortletRequest extends AbstractClientRequest { + + /** + * The native available scopes. + */ + private static final List SCOPES = Collections.unmodifiableList(Arrays.asList(REQUEST_SCOPE, "portletSession", "session", APPLICATION_SCOPE)); + + /** + *

The lazily instantiated Map of header name-value + * combinations (immutable).

+ */ + private Map header = null; + + + /** + *

The lazily instantiated Map of header name-value + * combinations (write-only).

+ */ + private Addable responseHeaders = null; + + + /** + *

The lazily instantiated Map of header name-values + * combinations (immutable).

+ */ + private Map headerValues = null; + + /** + * The PortletContext for this application. + */ + protected PortletContext context; + + /** + *

The PortletRequest for this request.

+ */ + protected javax.portlet.PortletRequest request; + + /** + * The delegate to get information about parameters. + */ + protected RequestDelegate requestDelegate; + + + /** + *

The lazily instantiated Map of request scope + * attributes.

+ */ + private Map requestScope = null; + + + /** + *

The PortletResponse for this request.

+ */ + protected PortletResponse response; + + /** + * The delegate to get information from a response (output stream, writer, etc.). + */ + protected ResponseDelegate responseDelegate; + + + /** + *

The lazily instantiated Map of session scope + * attributes.

+ */ + private Map sessionScope = null; + + /** + *

The lazily instantiated Map of portlet session scope + * attributes.

+ */ + private Map portletSessionScope = null; + + + /** + * Creates a new instance of PortletTilesRequestContext. + * + * @param applicationContext The Tiles application context. + * @param context The portlet context to use. + * @param request The request object to use. + * @param response The response object to use. + * @param requestDelegate The request delegate. + * @param responseDelegate The response delegate. + */ + public PortletRequest(ApplicationContext applicationContext, + PortletContext context, javax.portlet.PortletRequest request, + PortletResponse response, RequestDelegate requestDelegate, ResponseDelegate responseDelegate) { + super(applicationContext); + + // Save the specified Portlet API object references + this.context = context; + this.request = request; + this.response = response; + this.requestDelegate = requestDelegate; + this.responseDelegate = responseDelegate; + } + + /** + *

Return the {@link PortletRequest} for this context.

+ * + * @return The used portlet request. + */ + public javax.portlet.PortletRequest getRequest() { + return (this.request); + } + + /** + * Returns the portlet context. + * + * @return The portlet context. + */ + public PortletContext getPortletContext() { + return context; + } + + /** + * {@inheritDoc} + */ + public Map getHeader() { + if ((header == null) && (request != null)) { + header = new ReadOnlyEnumerationMap<>(new HeaderExtractor(request, null)); + } + return (header); + } + + /** + * {@inheritDoc} + */ + public Addable getResponseHeaders() { + if ((responseHeaders == null) && (request != null)) { + responseHeaders = new HeaderExtractor(null, response); + } + return (responseHeaders); + } + + /** + * {@inheritDoc} + */ + public Map getHeaderValues() { + if ((headerValues == null) && (request != null)) { + headerValues = new HeaderValuesMap(new HeaderExtractor(request, response)); + } + return (headerValues); + } + + /** + * {@inheritDoc} + */ + public Map getRequestScope() { + if ((requestScope == null) && (request != null)) { + requestScope = new ScopeMap(new RequestScopeExtractor(request)); + } + return (requestScope); + } + + /** + * {@inheritDoc} + */ + public Map getSessionScope() { + if ((sessionScope == null) && (request != null)) { + sessionScope = new ScopeMap(new SessionScopeExtractor(request, + PortletSession.APPLICATION_SCOPE)); + } + return (sessionScope); + } + + /** + * {@inheritDoc} + */ + public Map getPortletSessionScope() { + if ((portletSessionScope == null) && (request != null)) { + portletSessionScope = new ScopeMap(new SessionScopeExtractor( + request, PortletSession.APPLICATION_SCOPE)); + } + return (portletSessionScope); + } + + @Override + public List getAvailableScopes() { + return SCOPES; + } + + /** + * {@inheritDoc} + */ + public Locale getRequestLocale() { + return request.getLocale(); + } + + @Override + public Map getParam() { + return requestDelegate.getParam(); + } + + @Override + public Map getParamValues() { + return requestDelegate.getParamValues(); + } + + /** + * {@inheritDoc} + */ + public boolean isUserInRole(String role) { + return request.isUserInRole(role); + } + + @Override + public OutputStream getOutputStream() throws IOException { + return responseDelegate.getOutputStream(); + } + + @Override + public PrintWriter getPrintWriter() throws IOException { + return responseDelegate.getPrintWriter(); + } + + @Override + public Writer getWriter() throws IOException { + return responseDelegate.getWriter(); + } + + @Override + public boolean isResponseCommitted() { + return responseDelegate.isResponseCommitted(); + } + + @Override + public void setContentType(String contentType) { + responseDelegate.setContentType(contentType); + } + + /** + * {@inheritDoc} + */ + public void doForward(String path) throws IOException { + if (responseDelegate.isResponseCommitted()) { + doInclude(path); + return; + } + + try { + PortletRequestDispatcher rd = getPortletContext() + .getRequestDispatcher(path); + + if (rd == null) { + throw new IOException( + "No portlet request dispatcher returned for path '" + + path + "'"); + } + + rd.forward(request, response); + } catch (PortletException e) { + throw new IOException("PortletException while including path '" + + path + "'.", e); + } + } + + /** + * {@inheritDoc} + */ + public void doInclude(String path) throws IOException { + try { + PortletRequestDispatcher rd = getPortletContext() + .getRequestDispatcher(path); + + if (rd == null) { + throw new IOException( + "No portlet request dispatcher returned for path '" + + path + "'"); + } + + rd.include(request, response); + } catch (PortletException e) { + throw new IOException("PortletException while including path '" + + path + "'.", e); + } + } + + @Override + public Map getContext(String scope) { + if (REQUEST_SCOPE.equals(scope)) { + return getRequestScope(); + } else if ("session".equals(scope)) { + return getSessionScope(); + } else if ("portletSession".equals(scope)) { + return getPortletSessionScope(); + } else if (APPLICATION_SCOPE.equals(scope)) { + return getApplicationScope(); + } + throw new IllegalArgumentException(scope + " does not exist. Call getAvailableScopes() first to check."); + } +} diff --git a/plugins/portlet-tiles/src/main/java/org/apache/tiles/request/portlet/RenderPortletRequest.java b/plugins/portlet-tiles/src/main/java/org/apache/tiles/request/portlet/RenderPortletRequest.java new file mode 100644 index 000000000..ea22c38a2 --- /dev/null +++ b/plugins/portlet-tiles/src/main/java/org/apache/tiles/request/portlet/RenderPortletRequest.java @@ -0,0 +1,47 @@ +/* + * $Id$ + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.request.portlet; + +import org.apache.tiles.request.ApplicationContext; +import org.apache.tiles.request.portlet.delegate.MimeResponseDelegate; +import org.apache.tiles.request.portlet.delegate.PortletRequestDelegate; + +import javax.portlet.PortletContext; +import javax.portlet.RenderRequest; +import javax.portlet.RenderResponse; + +/** + * Portlet request for a {@link RenderRequest}. + */ +public class RenderPortletRequest extends PortletRequest { + + /** + * Constructor. + * + * @param applicationContext The application context. + * @param context The portlet context. + * @param request The portlet request. + * @param response The portlet response. + */ + public RenderPortletRequest(ApplicationContext applicationContext, PortletContext context, RenderRequest request, RenderResponse response) { + super(applicationContext, context, request, response, new PortletRequestDelegate(request), new MimeResponseDelegate(response)); + } +} diff --git a/plugins/portlet-tiles/src/main/java/org/apache/tiles/request/portlet/delegate/MimeResponseDelegate.java b/plugins/portlet-tiles/src/main/java/org/apache/tiles/request/portlet/delegate/MimeResponseDelegate.java new file mode 100644 index 000000000..347873cf1 --- /dev/null +++ b/plugins/portlet-tiles/src/main/java/org/apache/tiles/request/portlet/delegate/MimeResponseDelegate.java @@ -0,0 +1,72 @@ +/* + * $Id$ + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.request.portlet.delegate; + +import javax.portlet.MimeResponse; +import java.io.IOException; +import java.io.OutputStream; +import java.io.PrintWriter; +import java.io.Writer; + +/** + * Response delegate in case of {@link MimeResponse}. + */ +public class MimeResponseDelegate implements ResponseDelegate { + + /** + * The response. + */ + private final MimeResponse response; + + /** + * Constructor. + * + * @param response The response. + */ + public MimeResponseDelegate(MimeResponse response) { + this.response = response; + } + + /** {@inheritDoc} */ + public OutputStream getOutputStream() throws IOException { + return response.getPortletOutputStream(); + } + + /** {@inheritDoc} */ + public PrintWriter getPrintWriter() throws IOException { + return response.getWriter(); + } + + /** {@inheritDoc} */ + public Writer getWriter() throws IOException { + return response.getWriter(); + } + + /** {@inheritDoc} */ + public boolean isResponseCommitted() { + return response.isCommitted(); + } + + /** {@inheritDoc} */ + public void setContentType(String contentType) { + response.setContentType(contentType); + } +} diff --git a/plugins/portlet-tiles/src/main/java/org/apache/tiles/request/portlet/delegate/PortletRequestDelegate.java b/plugins/portlet-tiles/src/main/java/org/apache/tiles/request/portlet/delegate/PortletRequestDelegate.java new file mode 100644 index 000000000..e5683d5a0 --- /dev/null +++ b/plugins/portlet-tiles/src/main/java/org/apache/tiles/request/portlet/delegate/PortletRequestDelegate.java @@ -0,0 +1,79 @@ +/* + * $Id$ + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.request.portlet.delegate; + +import org.apache.tiles.request.collection.ReadOnlyEnumerationMap; +import org.apache.tiles.request.portlet.extractor.ParameterExtractor; + +import javax.portlet.PortletRequest; +import java.util.Map; + +/** + * Request delegate in case of simple Portlet request. + */ +public class PortletRequestDelegate implements RequestDelegate { + + /** + * The request. + */ + private final PortletRequest request; + + /** + *

The lazily instantiated Map of request + * parameter name-value.

+ */ + private Map param = null; + + /** + *

The lazily instantiated Map of request + * parameter name-values.

+ */ + private Map paramValues = null; + + /** + * Constructor. + * + * @param request The request. + */ + public PortletRequestDelegate(PortletRequest request) { + this.request = request; + } + + /** + * {@inheritDoc} + */ + public Map getParam() { + if ((param == null) && (request != null)) { + param = new ReadOnlyEnumerationMap<>(new ParameterExtractor(request)); + } + return (param); + } + + /** + * {@inheritDoc} + */ + public Map getParamValues() { + if ((paramValues == null) && (request != null)) { + paramValues = request.getParameterMap(); + } + return (paramValues); + } +} diff --git a/plugins/portlet-tiles/src/main/java/org/apache/tiles/request/portlet/delegate/RequestDelegate.java b/plugins/portlet-tiles/src/main/java/org/apache/tiles/request/portlet/delegate/RequestDelegate.java new file mode 100644 index 000000000..03846cc72 --- /dev/null +++ b/plugins/portlet-tiles/src/main/java/org/apache/tiles/request/portlet/delegate/RequestDelegate.java @@ -0,0 +1,43 @@ +/* + * $Id$ + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.request.portlet.delegate; + +import java.util.Map; + +/** + * Exposes the parameters of a portlet request, if available. + */ +public interface RequestDelegate { + + /** + * The parameters, as single values. + * + * @return The parameters. + */ + Map getParam(); + + /** + * The parameters, with values as array of strings. + * + * @return The parameters. + */ + Map getParamValues(); +} diff --git a/plugins/portlet-tiles/src/main/java/org/apache/tiles/request/portlet/delegate/ResponseDelegate.java b/plugins/portlet-tiles/src/main/java/org/apache/tiles/request/portlet/delegate/ResponseDelegate.java new file mode 100644 index 000000000..92f46cef6 --- /dev/null +++ b/plugins/portlet-tiles/src/main/java/org/apache/tiles/request/portlet/delegate/ResponseDelegate.java @@ -0,0 +1,70 @@ +/* + * $Id$ + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.request.portlet.delegate; + +import java.io.IOException; +import java.io.OutputStream; +import java.io.PrintWriter; +import java.io.Writer; + +/** + * Exposes features of a response, if they are available. + */ +public interface ResponseDelegate { + + /** + * Returns the output stream. + * + * @return The output stream. + * @throws IOException If the underlying response causes a problem. + */ + OutputStream getOutputStream() throws IOException; + + /** + * Returns the print writer. + * + * @return The print writer. + * @throws IOException If the underlying response causes a problem. + */ + PrintWriter getPrintWriter() throws IOException; + + /** + * Returns the writer. + * + * @return The writer. + * @throws IOException If the underlying response causes a problem. + */ + Writer getWriter() throws IOException; + + /** + * Sets the content type of the response. + * + * @param contentType The content type. + */ + void setContentType(String contentType); + + /** + * Checks if the response is committed. + * + * @return true if the response is committed. + */ + boolean isResponseCommitted(); +} diff --git a/plugins/portlet-tiles/src/main/java/org/apache/tiles/request/portlet/delegate/package-info.java b/plugins/portlet-tiles/src/main/java/org/apache/tiles/request/portlet/delegate/package-info.java new file mode 100644 index 000000000..5080dc3e0 --- /dev/null +++ b/plugins/portlet-tiles/src/main/java/org/apache/tiles/request/portlet/delegate/package-info.java @@ -0,0 +1,24 @@ +/* + * $Id: package-info.java 1049711 2010-12-15 21:12:00Z apetrelli $ + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +/** + * Delegations to map all the different types of request and responses. + */ +package org.apache.tiles.request.portlet.delegate; diff --git a/plugins/portlet-tiles/src/main/java/org/apache/tiles/request/portlet/extractor/ApplicationScopeExtractor.java b/plugins/portlet-tiles/src/main/java/org/apache/tiles/request/portlet/extractor/ApplicationScopeExtractor.java new file mode 100644 index 000000000..590046cff --- /dev/null +++ b/plugins/portlet-tiles/src/main/java/org/apache/tiles/request/portlet/extractor/ApplicationScopeExtractor.java @@ -0,0 +1,66 @@ +/* + * $Id$ + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.request.portlet.extractor; + +import org.apache.tiles.request.attribute.AttributeExtractor; + +import javax.portlet.PortletContext; +import java.util.Enumeration; + +/** + * Extracts attributes from portlet application scope. + */ +public class ApplicationScopeExtractor implements AttributeExtractor { + + /** + * The portlet context. + */ + private final PortletContext context; + + /** + * Constructor. + * + * @param context The portlet context. + */ + public ApplicationScopeExtractor(PortletContext context) { + this.context = context; + } + + @Override + public void setValue(String name, Object value) { + context.setAttribute(name, value); + } + + @Override + public void removeValue(String name) { + context.removeAttribute(name); + } + + @Override + public Enumeration getKeys() { + return context.getAttributeNames(); + } + + @Override + public Object getValue(String key) { + return context.getAttribute(key); + } +} diff --git a/plugins/portlet-tiles/src/main/java/org/apache/tiles/request/portlet/extractor/HeaderExtractor.java b/plugins/portlet-tiles/src/main/java/org/apache/tiles/request/portlet/extractor/HeaderExtractor.java new file mode 100644 index 000000000..0c94fa90f --- /dev/null +++ b/plugins/portlet-tiles/src/main/java/org/apache/tiles/request/portlet/extractor/HeaderExtractor.java @@ -0,0 +1,74 @@ +/* + * $Id$ + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.request.portlet.extractor; + +import org.apache.tiles.request.attribute.EnumeratedValuesExtractor; + +import javax.portlet.PortletRequest; +import javax.portlet.PortletResponse; +import java.util.Enumeration; + +/** + * Extracts and puts headers in portlet requests and responses. + */ +public class HeaderExtractor implements EnumeratedValuesExtractor { + + /** + * The request. + */ + private final PortletRequest request; + + /** + * The response. + */ + private final PortletResponse response; + + /** + * Constructor. + * + * @param request The request. + * @param response The response. + */ + public HeaderExtractor(PortletRequest request, PortletResponse response) { + this.request = request; + this.response = response; + } + + @Override + public Enumeration getKeys() { + return request.getPropertyNames(); + } + + @Override + public String getValue(String key) { + return request.getProperty(key); + } + + @Override + public Enumeration getValues(String key) { + return request.getProperties(key); + } + + @Override + public void setValue(String key, String value) { + response.setProperty(key, value); + } +} diff --git a/plugins/portlet-tiles/src/main/java/org/apache/tiles/request/portlet/extractor/InitParameterExtractor.java b/plugins/portlet-tiles/src/main/java/org/apache/tiles/request/portlet/extractor/InitParameterExtractor.java new file mode 100644 index 000000000..f27fdf4f1 --- /dev/null +++ b/plugins/portlet-tiles/src/main/java/org/apache/tiles/request/portlet/extractor/InitParameterExtractor.java @@ -0,0 +1,57 @@ +/* + * $Id$ + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.request.portlet.extractor; + +import org.apache.tiles.request.attribute.HasKeys; + +import javax.portlet.PortletContext; +import java.util.Enumeration; + +/** + * Extracts init parameters from a portlet context. + */ +public class InitParameterExtractor implements HasKeys { + + /** + * The portlet context. + */ + private final PortletContext context; + + /** + * Constructor. + * + * @param context The portlet context. + */ + public InitParameterExtractor(PortletContext context) { + this.context = context; + } + + @Override + public Enumeration getKeys() { + return context.getInitParameterNames(); + } + + @Override + public String getValue(String key) { + return context.getInitParameter(key); + } + +} diff --git a/plugins/portlet-tiles/src/main/java/org/apache/tiles/request/portlet/extractor/ParameterExtractor.java b/plugins/portlet-tiles/src/main/java/org/apache/tiles/request/portlet/extractor/ParameterExtractor.java new file mode 100644 index 000000000..e412a84c6 --- /dev/null +++ b/plugins/portlet-tiles/src/main/java/org/apache/tiles/request/portlet/extractor/ParameterExtractor.java @@ -0,0 +1,56 @@ +/* + * $Id$ + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.request.portlet.extractor; + +import org.apache.tiles.request.attribute.HasKeys; + +import javax.portlet.PortletRequest; +import java.util.Enumeration; + +/** + * Extracts parameters from a portlet request. + */ +public class ParameterExtractor implements HasKeys { + + /** + * The portlet request. + */ + private final PortletRequest request; + + /** + * Constructor. + * + * @param request The portlet request. + */ + public ParameterExtractor(PortletRequest request) { + this.request = request; + } + + @Override + public Enumeration getKeys() { + return request.getParameterNames(); + } + + @Override + public String getValue(String key) { + return request.getParameter(key); + } +} diff --git a/plugins/portlet-tiles/src/main/java/org/apache/tiles/request/portlet/extractor/RequestScopeExtractor.java b/plugins/portlet-tiles/src/main/java/org/apache/tiles/request/portlet/extractor/RequestScopeExtractor.java new file mode 100644 index 000000000..edc72bc9e --- /dev/null +++ b/plugins/portlet-tiles/src/main/java/org/apache/tiles/request/portlet/extractor/RequestScopeExtractor.java @@ -0,0 +1,66 @@ +/* + * $Id$ + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.request.portlet.extractor; + +import org.apache.tiles.request.attribute.AttributeExtractor; + +import javax.portlet.PortletRequest; +import java.util.Enumeration; + +/** + * Extracts attributes from request scope of a portlet request. + */ +public class RequestScopeExtractor implements AttributeExtractor { + + /** + * The portlet request. + */ + private final PortletRequest request; + + /** + * Constructor. + * + * @param request The portlet request. + */ + public RequestScopeExtractor(PortletRequest request) { + this.request = request; + } + + @Override + public void setValue(String name, Object value) { + request.setAttribute(name, value); + } + + @Override + public void removeValue(String name) { + request.removeAttribute(name); + } + + @Override + public Enumeration getKeys() { + return request.getAttributeNames(); + } + + @Override + public Object getValue(String key) { + return request.getAttribute(key); + } +} diff --git a/plugins/portlet-tiles/src/main/java/org/apache/tiles/request/portlet/extractor/SessionScopeExtractor.java b/plugins/portlet-tiles/src/main/java/org/apache/tiles/request/portlet/extractor/SessionScopeExtractor.java new file mode 100644 index 000000000..9801454fa --- /dev/null +++ b/plugins/portlet-tiles/src/main/java/org/apache/tiles/request/portlet/extractor/SessionScopeExtractor.java @@ -0,0 +1,88 @@ +/* + * $Id$ + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.request.portlet.extractor; + +import org.apache.tiles.request.attribute.AttributeExtractor; + +import javax.portlet.PortletRequest; +import javax.portlet.PortletSession; +import java.util.Enumeration; + +/** + * Extracts attributes from the session scope of a portlet request. + */ +public class SessionScopeExtractor implements AttributeExtractor { + + /** + * The portlet request. + */ + private final PortletRequest request; + + /** + * The subscope (application or portlet). + */ + private final int scope; + + /** + * Constructor. + * + * @param request The request. + * @param scope The subscope (application or portlet). + */ + public SessionScopeExtractor(PortletRequest request, int scope) { + this.request = request; + if (scope != PortletSession.APPLICATION_SCOPE && scope != PortletSession.PORTLET_SCOPE) { + throw new IllegalArgumentException("The scope must be either APPLICATION_SCOPE or PORTLET_SCOPE"); + } + this.scope = scope; + } + + @Override + public void setValue(String name, Object value) { + request.getPortletSession().setAttribute(name, value, scope); + } + + @Override + public void removeValue(String name) { + PortletSession session = request.getPortletSession(false); + if (session != null) { + session.removeAttribute(name, scope); + } + } + + @Override + public Enumeration getKeys() { + PortletSession session = request.getPortletSession(false); + if (session != null) { + return session.getAttributeNames(scope); + } + return null; + } + + @Override + public Object getValue(String key) { + PortletSession session = request.getPortletSession(false); + if (session != null) { + return session.getAttribute(key, scope); + } + return null; + } +} diff --git a/plugins/portlet-tiles/src/main/java/org/apache/tiles/request/portlet/extractor/StateAwareParameterExtractor.java b/plugins/portlet-tiles/src/main/java/org/apache/tiles/request/portlet/extractor/StateAwareParameterExtractor.java new file mode 100644 index 000000000..a14f53a7b --- /dev/null +++ b/plugins/portlet-tiles/src/main/java/org/apache/tiles/request/portlet/extractor/StateAwareParameterExtractor.java @@ -0,0 +1,53 @@ +/* + * $Id$ + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.request.portlet.extractor; + +import org.apache.tiles.request.attribute.HasAddableKeys; + +import javax.portlet.PortletRequest; +import javax.portlet.StateAwareResponse; + +/** + * Extracts parameters from a request and allows putting render parameters in a state aware response. + */ +public class StateAwareParameterExtractor extends ParameterExtractor implements HasAddableKeys { + + /** + * The portlet response. + */ + private final StateAwareResponse response; + + /** + * Constructor. + * + * @param request The portlet request. + * @param response The portlet response. + */ + public StateAwareParameterExtractor(PortletRequest request, StateAwareResponse response) { + super(request); + this.response = response; + } + + @Override + public void setValue(String key, String value) { + response.setRenderParameter(key, value); + } +} diff --git a/plugins/portlet-tiles/src/main/java/org/apache/tiles/request/portlet/extractor/package-info.java b/plugins/portlet-tiles/src/main/java/org/apache/tiles/request/portlet/extractor/package-info.java new file mode 100644 index 000000000..a37ccbb9e --- /dev/null +++ b/plugins/portlet-tiles/src/main/java/org/apache/tiles/request/portlet/extractor/package-info.java @@ -0,0 +1,24 @@ +/* + * $Id: package-info.java 1049711 2010-12-15 21:12:00Z apetrelli $ + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +/** + * Extractors to get scopes from Portlet requests. + */ +package org.apache.tiles.request.portlet.extractor; diff --git a/plugins/portlet-tiles/src/main/java/org/apache/tiles/request/portlet/package-info.java b/plugins/portlet-tiles/src/main/java/org/apache/tiles/request/portlet/package-info.java new file mode 100644 index 000000000..b9eb0d168 --- /dev/null +++ b/plugins/portlet-tiles/src/main/java/org/apache/tiles/request/portlet/package-info.java @@ -0,0 +1,24 @@ +/* + * $Id: package-info.java 1049711 2010-12-15 21:12:00Z apetrelli $ + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +/** + * Support of Tiles requests to portlets. + */ +package org.apache.tiles.request.portlet; diff --git a/plugins/portlet-tiles/src/test/java/org/apache/tiles/request/portlet/PortletRequestTest.java b/plugins/portlet-tiles/src/test/java/org/apache/tiles/request/portlet/PortletRequestTest.java new file mode 100644 index 000000000..53a6bf856 --- /dev/null +++ b/plugins/portlet-tiles/src/test/java/org/apache/tiles/request/portlet/PortletRequestTest.java @@ -0,0 +1,424 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.request.portlet; + +import org.apache.tiles.request.ApplicationContext; +import org.apache.tiles.request.collection.HeaderValuesMap; +import org.apache.tiles.request.collection.ReadOnlyEnumerationMap; +import org.apache.tiles.request.collection.ScopeMap; +import org.apache.tiles.request.portlet.delegate.RequestDelegate; +import org.apache.tiles.request.portlet.delegate.ResponseDelegate; +import org.apache.tiles.request.portlet.extractor.HeaderExtractor; +import org.junit.Before; +import org.junit.Test; + +import javax.portlet.PortletContext; +import javax.portlet.PortletException; +import javax.portlet.PortletRequestDispatcher; +import javax.portlet.PortletResponse; +import javax.servlet.ServletOutputStream; +import java.io.IOException; +import java.io.PrintWriter; +import java.util.Locale; +import java.util.Map; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.expectLastCall; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +/** + * Tests {@link PortletRequest}. + */ +public class PortletRequestTest { + + /** + * The application context. + */ + private ApplicationContext applicationContext; + + /** + * The portlet context. + */ + private PortletContext portletContext; + + /** + * The request. + */ + private javax.portlet.PortletRequest request; + + /** + * The response. + */ + private PortletResponse response; + + /** + * The request to test. + */ + private PortletRequest req; + + /** + * The request delegate. + */ + private RequestDelegate requestDelegate; + + /** + * The response delegate. + */ + private ResponseDelegate responseDelegate; + + /** + * Sets up the test. + */ + @Before + public void setUp() { + applicationContext = createMock(ApplicationContext.class); + portletContext = createMock(PortletContext.class); + request = createMock(javax.portlet.PortletRequest.class); + response = createMock(PortletResponse.class); + requestDelegate = createMock(RequestDelegate.class); + responseDelegate = createMock(ResponseDelegate.class); + req = new PortletRequest(applicationContext, portletContext, request, + response, requestDelegate, responseDelegate); + } + + /** + * Test method for {@link PortletRequest#doForward(String)}. + * + * @throws IOException If something goes wrong. + * @throws PortletException If something goes wrong. + */ + @Test + public void testDoForward() throws PortletException, IOException { + PortletRequestDispatcher rd = createMock(PortletRequestDispatcher.class); + + expect(responseDelegate.isResponseCommitted()).andReturn(false); + expect(portletContext.getRequestDispatcher("/my/path")).andReturn(rd); + rd.forward(request, response); + + replay(applicationContext, portletContext, request, response, rd); + req.doForward("/my/path"); + verify(applicationContext, portletContext, request, response, rd); + } + + /** + * Test method for {@link PortletRequest#doForward(String)}. + * + * @throws IOException If something goes wrong. + */ + @Test(expected = IOException.class) + public void testDoForwardNoDispatcher() throws IOException { + expect(responseDelegate.isResponseCommitted()).andReturn(false); + expect(portletContext.getRequestDispatcher("/my/path")).andReturn(null); + + replay(applicationContext, request, response, portletContext, requestDelegate, responseDelegate); + try { + req.doForward("/my/path"); + } finally { + verify(applicationContext, request, response, portletContext, requestDelegate, responseDelegate); + } + } + + /** + * Test method for {@link PortletRequest#doForward(String)}. + * + * @throws IOException If something goes wrong. + * @throws PortletException If something goes wrong. + */ + @Test(expected = IOException.class) + public void testDoForwardPortletException() throws PortletException, IOException { + PortletRequestDispatcher rd = createMock(PortletRequestDispatcher.class); + + expect(responseDelegate.isResponseCommitted()).andReturn(false); + expect(portletContext.getRequestDispatcher("/my/path")).andReturn(rd); + rd.forward(request, response); + expectLastCall().andThrow(new PortletException()); + + replay(applicationContext, request, response, rd, portletContext, requestDelegate, responseDelegate); + try { + req.doForward("/my/path"); + } finally { + verify(applicationContext, request, response, rd, portletContext, requestDelegate, responseDelegate); + } + } + + /** + * Test method for {@link PortletRequest#doForward(String)}. + * + * @throws IOException If something goes wrong. + * @throws PortletException If something goes wrong. + */ + @Test + public void testDoForwardInclude() throws PortletException, IOException { + PortletRequestDispatcher rd = createMock(PortletRequestDispatcher.class); + + expect(responseDelegate.isResponseCommitted()).andReturn(true); + expect(portletContext.getRequestDispatcher("/my/path")).andReturn(rd); + rd.include(request, response); + + replay(applicationContext, request, response, rd, portletContext, requestDelegate, responseDelegate); + req.doForward("/my/path"); + verify(applicationContext, request, response, rd, portletContext, requestDelegate, responseDelegate); + } + + /** + * Test method for {@link PortletRequest#doInclude(String)}. + * + * @throws IOException If something goes wrong. + * @throws PortletException If something goes wrong. + */ + @Test + public void testDoInclude() throws IOException, PortletException { + PortletRequestDispatcher rd = createMock(PortletRequestDispatcher.class); + + expect(portletContext.getRequestDispatcher("/my/path")).andReturn(rd); + rd.include(request, response); + + replay(applicationContext, request, response, rd, portletContext, requestDelegate, responseDelegate); + req.doInclude("/my/path"); + verify(applicationContext, request, response, rd, portletContext, requestDelegate, responseDelegate); + } + + /** + * Test method for {@link PortletRequest#doInclude(String)}. + * + * @throws IOException If something goes wrong. + */ + @Test(expected = IOException.class) + public void testDoIncludeNoDispatcher() throws IOException { + expect(portletContext.getRequestDispatcher("/my/path")).andReturn(null); + + replay(applicationContext, request, response, portletContext, requestDelegate, responseDelegate); + try { + req.doInclude("/my/path"); + } finally { + verify(applicationContext, request, response, portletContext, requestDelegate, responseDelegate); + } + } + + /** + * Test method for {@link PortletRequest#doInclude(String)}. + * + * @throws IOException If something goes wrong. + * @throws PortletException If something goes wrong. + */ + @Test(expected = IOException.class) + public void testDoIncludePortletException() throws IOException, PortletException { + PortletRequestDispatcher rd = createMock(PortletRequestDispatcher.class); + + expect(portletContext.getRequestDispatcher("/my/path")).andReturn(rd); + rd.include(request, response); + expectLastCall().andThrow(new PortletException()); + + replay(applicationContext, request, response, rd, portletContext, requestDelegate, responseDelegate); + try { + req.doInclude("/my/path"); + } finally { + verify(applicationContext, request, response, rd, portletContext, requestDelegate, responseDelegate); + } + } + + /** + * Test method for {@link PortletRequest#getHeader()}. + */ + @Test + public void testGetHeader() { + assertTrue(req.getHeader() instanceof ReadOnlyEnumerationMap); + } + + /** + * Test method for {@link PortletRequest#getResponseHeaders()}. + */ + @Test + public void testGetResponseHeaders() { + assertTrue(req.getResponseHeaders() instanceof HeaderExtractor); + } + + /** + * Test method for {@link PortletRequest#getHeaderValues()}. + */ + @Test + public void testGetHeaderValues() { + assertTrue(req.getHeaderValues() instanceof HeaderValuesMap); + } + + /** + * Test method for {@link PortletRequest#getParam()}. + */ + @Test + public void testGetParam() { + Map map = createMock(Map.class); + + expect(requestDelegate.getParam()).andReturn(map); + + replay(applicationContext, request, response, portletContext, requestDelegate, responseDelegate); + assertEquals(map, req.getParam()); + verify(applicationContext, request, response, portletContext, requestDelegate, responseDelegate); + } + + /** + * Test method for {@link PortletRequest#getParamValues()}. + */ + @Test + public void testGetParamValues() { + Map paramMap = createMock(Map.class); + + expect(requestDelegate.getParamValues()).andReturn(paramMap); + + replay(applicationContext, request, response, paramMap, portletContext, requestDelegate, responseDelegate); + assertEquals(paramMap, req.getParamValues()); + verify(applicationContext, request, response, paramMap, portletContext, requestDelegate, responseDelegate); + } + + /** + * Test method for {@link PortletRequest#getRequestScope()}. + */ + @Test + public void testGetRequestScope() { + assertTrue(req.getRequestScope() instanceof ScopeMap); + } + + /** + * Test method for {@link PortletRequest#getSessionScope()}. + */ + @Test + public void testGetSessionScope() { + assertTrue(req.getSessionScope() instanceof ScopeMap); + } + + /** + * Test method for {@link PortletRequest#getPortletSessionScope()}. + */ + @Test + public void testGetPortletSessionScope() { + assertTrue(req.getPortletSessionScope() instanceof ScopeMap); + } + + /** + * Test method for {@link PortletRequest#getOutputStream()}. + * + * @throws IOException If something goes wrong. + */ + @Test + public void testGetOutputStream() throws IOException { + ServletOutputStream os = createMock(ServletOutputStream.class); + + expect(responseDelegate.getOutputStream()).andReturn(os); + + replay(applicationContext, request, response, os, portletContext, requestDelegate, responseDelegate); + assertEquals(req.getOutputStream(), os); + verify(applicationContext, request, response, os, portletContext, requestDelegate, responseDelegate); + } + + /** + * Test method for {@link PortletRequest#getWriter()}. + * + * @throws IOException If something goes wrong. + */ + @Test + public void testGetWriter() throws IOException { + PrintWriter os = createMock(PrintWriter.class); + + expect(responseDelegate.getWriter()).andReturn(os); + + replay(applicationContext, request, response, os, portletContext, requestDelegate, responseDelegate); + assertEquals(req.getWriter(), os); + verify(applicationContext, request, response, os, portletContext, requestDelegate, responseDelegate); + } + + /** + * Test method for {@link PortletRequest#getPrintWriter()}. + * + * @throws IOException If something goes wrong. + */ + @Test + public void testGetPrintWriter() throws IOException { + PrintWriter os = createMock(PrintWriter.class); + + expect(responseDelegate.getPrintWriter()).andReturn(os); + + replay(applicationContext, request, response, os, portletContext, requestDelegate, responseDelegate); + assertEquals(req.getPrintWriter(), os); + verify(applicationContext, request, response, os, portletContext, requestDelegate, responseDelegate); + } + + /** + * Test method for {@link PortletRequest#isResponseCommitted()}. + */ + @Test + public void testIsResponseCommitted() { + expect(responseDelegate.isResponseCommitted()).andReturn(true); + + replay(applicationContext, request, response, portletContext, requestDelegate, responseDelegate); + assertTrue(req.isResponseCommitted()); + verify(applicationContext, request, response, portletContext, requestDelegate, responseDelegate); + } + + /** + * Test method for {@link PortletRequest#setContentType(String)}. + */ + @Test + public void testSetContentType() { + responseDelegate.setContentType("text/html"); + + replay(applicationContext, request, response, portletContext, requestDelegate, responseDelegate); + req.setContentType("text/html"); + verify(applicationContext, request, response, portletContext, requestDelegate, responseDelegate); + } + + /** + * Test method for {@link PortletRequest#getRequestLocale()}. + */ + @Test + public void testGetRequestLocale() { + Locale locale = Locale.ITALY; + + expect(request.getLocale()).andReturn(locale); + + replay(applicationContext, request, response, portletContext, requestDelegate, responseDelegate); + assertEquals(locale, req.getRequestLocale()); + verify(applicationContext, request, response, portletContext, requestDelegate, responseDelegate); + } + + /** + * Test method for {@link PortletRequest#getRequest()}. + */ + @Test + public void testGetRequest() { + replay(applicationContext, request, response, portletContext, requestDelegate, responseDelegate); + assertEquals(request, req.getRequest()); + verify(applicationContext, request, response, portletContext, requestDelegate, responseDelegate); + } + + /** + * Test method for {@link PortletRequest#isUserInRole(String)}. + */ + @Test + public void testIsUserInRole() { + expect(request.isUserInRole("myrole")).andReturn(true); + + replay(applicationContext, request, response, portletContext, requestDelegate, responseDelegate); + assertTrue(req.isUserInRole("myrole")); + verify(applicationContext, request, response, portletContext, requestDelegate, responseDelegate); + } + +} diff --git a/plugins/portlet-tiles/src/test/java/org/apache/tiles/request/portlet/RenderPortletRequestTest.java b/plugins/portlet-tiles/src/test/java/org/apache/tiles/request/portlet/RenderPortletRequestTest.java new file mode 100644 index 000000000..5bba700fb --- /dev/null +++ b/plugins/portlet-tiles/src/test/java/org/apache/tiles/request/portlet/RenderPortletRequestTest.java @@ -0,0 +1,69 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.request.portlet; + +import org.apache.tiles.request.ApplicationContext; +import org.apache.tiles.request.portlet.delegate.MimeResponseDelegate; +import org.apache.tiles.request.portlet.delegate.PortletRequestDelegate; +import org.junit.Test; + +import javax.portlet.PortletContext; +import javax.portlet.RenderRequest; +import javax.portlet.RenderResponse; +import java.lang.reflect.Field; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import static org.junit.Assert.assertTrue; + +/** + * Tests {@link RenderPortletRequest}. + */ +public class RenderPortletRequestTest { + + /** + * Test method for + * {@link RenderPortletRequest#RenderPortletRequest(ApplicationContext, PortletContext, + * RenderRequest, RenderResponse)}. + * + * @throws NoSuchFieldException If something goes wrong. + * @throws SecurityException If something goes wrong. + * @throws IllegalAccessException If something goes wrong. + * @throws IllegalArgumentException If something goes wrong. + */ + @Test + public void testRenderPortletRequest() throws NoSuchFieldException, IllegalAccessException { + ApplicationContext applicationContext = createMock(ApplicationContext.class); + PortletContext portletContext = createMock(PortletContext.class); + RenderRequest request = createMock(RenderRequest.class); + RenderResponse response = createMock(RenderResponse.class); + + replay(applicationContext, portletContext, request, response); + RenderPortletRequest req = new RenderPortletRequest(applicationContext, + portletContext, request, response); + Class clazz = req.getClass(); + Field field = clazz.getSuperclass().getDeclaredField("requestDelegate"); + assertTrue(field.get(req) instanceof PortletRequestDelegate); + field = clazz.getSuperclass().getDeclaredField("responseDelegate"); + assertTrue(field.get(req) instanceof MimeResponseDelegate); + verify(applicationContext, portletContext, request, response); + } + +} diff --git a/plugins/portlet-tiles/src/test/java/org/apache/tiles/request/portlet/delegate/MimeResponseDelegateTest.java b/plugins/portlet-tiles/src/test/java/org/apache/tiles/request/portlet/delegate/MimeResponseDelegateTest.java new file mode 100644 index 000000000..25d653456 --- /dev/null +++ b/plugins/portlet-tiles/src/test/java/org/apache/tiles/request/portlet/delegate/MimeResponseDelegateTest.java @@ -0,0 +1,132 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.request.portlet.delegate; + +import org.junit.Before; +import org.junit.Test; + +import javax.portlet.MimeResponse; +import java.io.IOException; +import java.io.OutputStream; +import java.io.PrintWriter; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +/** + * Tests {@link MimeResponseDelegate}. + */ +public class MimeResponseDelegateTest { + + /** + * The response. + */ + private MimeResponse response; + + /** + * The delegate to test. + */ + private MimeResponseDelegate delegate; + + /** + * Sets up the test. + */ + @Before + public void setUp() { + response = createMock(MimeResponse.class); + delegate = new MimeResponseDelegate(response); + } + + /** + * Test method for {@link MimeResponseDelegate#getOutputStream()}. + * + * @throws IOException If something goes wrong. + */ + @Test + public void testGetOutputStream() throws IOException { + OutputStream os = createMock(OutputStream.class); + + expect(response.getPortletOutputStream()).andReturn(os); + + replay(response, os); + assertEquals(os, delegate.getOutputStream()); + verify(response, os); + } + + /** + * Test method for {@link MimeResponseDelegate#getPrintWriter()}. + * + * @throws IOException If something goes wrong. + */ + @Test + public void testGetPrintWriter() throws IOException { + PrintWriter os = createMock(PrintWriter.class); + + expect(response.getWriter()).andReturn(os); + + replay(response, os); + assertEquals(os, delegate.getPrintWriter()); + verify(response, os); + } + + /** + * Test method for {@link MimeResponseDelegate#getWriter()}. + * + * @throws IOException If something goes wrong. + */ + @Test + public void testGetWriter() throws IOException { + PrintWriter os = createMock(PrintWriter.class); + + expect(response.getWriter()).andReturn(os); + + replay(response, os); + assertEquals(os, delegate.getWriter()); + verify(response, os); + } + + /** + * Test method for {@link MimeResponseDelegate#isResponseCommitted()}. + */ + @Test + public void testIsResponseCommitted() { + expect(response.isCommitted()).andReturn(true); + + replay(response); + assertTrue(delegate.isResponseCommitted()); + verify(response); + } + + /** + * Test method for {@link MimeResponseDelegate#setContentType(String)}. + */ + @Test + public void testSetContentType() { + response.setContentType("text/html"); + + replay(response); + delegate.setContentType("text/html"); + verify(response); + } + +} diff --git a/plugins/portlet-tiles/src/test/java/org/apache/tiles/request/portlet/delegate/PortletRequestDelegateTest.java b/plugins/portlet-tiles/src/test/java/org/apache/tiles/request/portlet/delegate/PortletRequestDelegateTest.java new file mode 100644 index 000000000..ce6d4e849 --- /dev/null +++ b/plugins/portlet-tiles/src/test/java/org/apache/tiles/request/portlet/delegate/PortletRequestDelegateTest.java @@ -0,0 +1,83 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.request.portlet.delegate; + +import org.apache.tiles.request.collection.ReadOnlyEnumerationMap; +import org.junit.Before; +import org.junit.Test; + +import javax.portlet.PortletRequest; +import java.util.Map; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +/** + * Tests {@link PortletRequestDelegate}. + */ +public class PortletRequestDelegateTest { + + /** + * The request. + */ + private PortletRequest request; + + /** + * The delegate to test. + */ + private PortletRequestDelegate delegate; + + /** + * Sets up the test. + */ + @Before + public void setUp() { + request = createMock(PortletRequest.class); + delegate = new PortletRequestDelegate(request); + } + + /** + * Test method for {@link PortletRequestDelegate#getParam()}. + */ + @Test + public void testGetParam() { + replay(request); + assertTrue(delegate.getParam() instanceof ReadOnlyEnumerationMap); + verify(request); + } + + /** + * Test method for {@link PortletRequestDelegate#getParamValues()}. + */ + @Test + public void testGetParamValues() { + Map params = createMock(Map.class); + + expect(request.getParameterMap()).andReturn(params); + + replay(request, params); + assertEquals(params, delegate.getParamValues()); + verify(request, params); + } + +} diff --git a/plugins/portlet-tiles/src/test/java/org/apache/tiles/request/portlet/extractor/ApplicationScopeExtractorTest.java b/plugins/portlet-tiles/src/test/java/org/apache/tiles/request/portlet/extractor/ApplicationScopeExtractorTest.java new file mode 100644 index 000000000..5ede84f69 --- /dev/null +++ b/plugins/portlet-tiles/src/test/java/org/apache/tiles/request/portlet/extractor/ApplicationScopeExtractorTest.java @@ -0,0 +1,106 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.request.portlet.extractor; + +import org.apache.tiles.request.portlet.extractor.ApplicationScopeExtractor; +import org.junit.Before; +import org.junit.Test; + +import javax.portlet.PortletContext; +import java.util.Enumeration; + +import static org.easymock.EasyMock.*; +import static org.easymock.EasyMock.*; +import static org.junit.Assert.assertEquals; + +/** + * Tests {@link ApplicationScopeExtractor}. + */ +public class ApplicationScopeExtractorTest { + + /** + * The portlet context. + */ + private PortletContext context; + + /** + * The extractot to test. + */ + private ApplicationScopeExtractor extractor; + + /** + * Sets up the test. + */ + @Before + public void setUp() { + context = createMock(PortletContext.class); + extractor = new ApplicationScopeExtractor(context); + } + + /** + * Test method for {@link ApplicationScopeExtractor#setValue(String, Object)}. + */ + @Test + public void testSetValue() { + context.setAttribute("attribute", "value"); + + replay(context); + extractor.setValue("attribute", "value"); + verify(context); + } + + /** + * Test method for {@link ApplicationScopeExtractor#removeValue(String)}. + */ + @Test + public void testRemoveValue() { + context.removeAttribute("attribute"); + + replay(context); + extractor.removeValue("attribute"); + verify(context); + } + + /** + * Test method for {@link ApplicationScopeExtractor#getKeys()}. + */ + @SuppressWarnings("unchecked") + @Test + public void testGetKeys() { + Enumeration keys = createMock(Enumeration.class); + expect(context.getAttributeNames()).andReturn(keys); + + replay(context, keys); + assertEquals(keys, extractor.getKeys()); + verify(context, keys); + } + + /** + * Test method for {@link ApplicationScopeExtractor#getValue(String)}. + */ + @Test + public void testGetValue() { + expect(context.getAttribute("attribute")).andReturn("value"); + + replay(context); + assertEquals("value", extractor.getValue("attribute")); + verify(context); + } + +} diff --git a/plugins/portlet-tiles/src/test/java/org/apache/tiles/request/portlet/extractor/HeaderExtractorTest.java b/plugins/portlet-tiles/src/test/java/org/apache/tiles/request/portlet/extractor/HeaderExtractorTest.java new file mode 100644 index 000000000..7f5054c02 --- /dev/null +++ b/plugins/portlet-tiles/src/test/java/org/apache/tiles/request/portlet/extractor/HeaderExtractorTest.java @@ -0,0 +1,117 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.request.portlet.extractor; + +import org.apache.tiles.request.portlet.extractor.HeaderExtractor; +import org.junit.Before; +import org.junit.Test; + +import javax.portlet.PortletRequest; +import javax.portlet.PortletResponse; +import java.util.Enumeration; + +import static org.easymock.EasyMock.*; +import static org.easymock.EasyMock.*; +import static org.junit.Assert.assertEquals; + +/** + * Tests {@link HeaderExtractor}. + */ +public class HeaderExtractorTest { + + /** + * The request. + */ + private PortletRequest request; + + /** + * The response. + */ + private PortletResponse response; + + /** + * The extractor to test. + */ + private HeaderExtractor extractor; + + /** + * Sets up the test. + */ + @Before + public void setUp() { + request = createMock(PortletRequest.class); + response = createMock(PortletResponse.class); + extractor = new HeaderExtractor(request, response); + } + + /** + * Test method for {@link HeaderExtractor#getKeys()}. + */ + @SuppressWarnings("unchecked") + @Test + public void testGetKeys() { + Enumeration keys = createMock(Enumeration.class); + + expect(request.getPropertyNames()).andReturn(keys); + + replay(request, response, keys); + assertEquals(keys, extractor.getKeys()); + verify(request, response, keys); + } + + /** + * Test method for {@link HeaderExtractor#getValue(String)}. + */ + @Test + public void testGetValue() { + expect(request.getProperty("name")).andReturn("value"); + + replay(request, response); + assertEquals("value", extractor.getValue("name")); + verify(request, response); + } + + /** + * Test method for {@link HeaderExtractor#getValues(String)}. + */ + @SuppressWarnings("unchecked") + @Test + public void testGetValues() { + Enumeration keys = createMock(Enumeration.class); + + expect(request.getProperties("name")).andReturn(keys); + + replay(request, response, keys); + assertEquals(keys, extractor.getValues("name")); + verify(request, response, keys); + } + + /** + * Test method for {@link HeaderExtractor#setValue(String, String)}. + */ + @Test + public void testSetValue() { + response.setProperty("name", "value"); + + replay(request, response); + extractor.setValue("name", "value"); + verify(request, response); + } + +} diff --git a/plugins/portlet-tiles/src/test/java/org/apache/tiles/request/portlet/extractor/InitParameterExtractorTest.java b/plugins/portlet-tiles/src/test/java/org/apache/tiles/request/portlet/extractor/InitParameterExtractorTest.java new file mode 100644 index 000000000..66a1f9ea7 --- /dev/null +++ b/plugins/portlet-tiles/src/test/java/org/apache/tiles/request/portlet/extractor/InitParameterExtractorTest.java @@ -0,0 +1,83 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.request.portlet.extractor; + +import org.apache.tiles.request.portlet.extractor.InitParameterExtractor; +import org.junit.Before; +import org.junit.Test; + +import javax.portlet.PortletContext; +import java.util.Enumeration; + +import static org.easymock.EasyMock.*; +import static org.easymock.EasyMock.*; +import static org.junit.Assert.assertEquals; + +/** + * Tests {@link InitParameterExtractor}. + */ +public class InitParameterExtractorTest { + + /** + * The portlet context. + */ + private PortletContext context; + + /** + * The extractor to test. + */ + private InitParameterExtractor extractor; + + /** + * Sets up the test. + */ + @Before + public void setUp() { + context = createMock(PortletContext.class); + extractor = new InitParameterExtractor(context); + } + + /** + * Test method for {@link InitParameterExtractor#getKeys()}. + */ + @SuppressWarnings("unchecked") + @Test + public void testGetKeys() { + Enumeration keys = createMock(Enumeration.class); + + expect(context.getInitParameterNames()).andReturn(keys); + + replay(context, keys); + assertEquals(keys, extractor.getKeys()); + verify(context, keys); + } + + /** + * Test method for {@link InitParameterExtractor#getValue(String)}. + */ + @Test + public void testGetValue() { + expect(context.getInitParameter("name")).andReturn("value"); + + replay(context); + assertEquals("value", extractor.getValue("name")); + verify(context); + } + +} diff --git a/plugins/portlet-tiles/src/test/java/org/apache/tiles/request/portlet/extractor/ParameterExtractorTest.java b/plugins/portlet-tiles/src/test/java/org/apache/tiles/request/portlet/extractor/ParameterExtractorTest.java new file mode 100644 index 000000000..0e8005325 --- /dev/null +++ b/plugins/portlet-tiles/src/test/java/org/apache/tiles/request/portlet/extractor/ParameterExtractorTest.java @@ -0,0 +1,83 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.request.portlet.extractor; + +import org.apache.tiles.request.portlet.extractor.ParameterExtractor; +import org.junit.Before; +import org.junit.Test; + +import javax.portlet.PortletRequest; +import java.util.Enumeration; + +import static org.easymock.EasyMock.*; +import static org.easymock.EasyMock.*; +import static org.junit.Assert.assertEquals; + +/** + * Tests {@link ParameterExtractor}. + */ +public class ParameterExtractorTest { + + /** + * The request. + */ + private PortletRequest request; + + /** + * The extractor to test. + */ + private ParameterExtractor extractor; + + /** + * Sets up the test. + */ + @Before + public void setUp() { + request = createMock(PortletRequest.class); + extractor = new ParameterExtractor(request); + } + + /** + * Test method for {@link ParameterExtractor#getKeys()}. + */ + @SuppressWarnings("unchecked") + @Test + public void testGetKeys() { + Enumeration keys = createMock(Enumeration.class); + + expect(request.getParameterNames()).andReturn(keys); + + replay(request, keys); + assertEquals(keys, extractor.getKeys()); + verify(request, keys); + } + + /** + * Test method for {@link ParameterExtractor#getValue(String)}. + */ + @Test + public void testGetValue() { + expect(request.getParameter("name")).andReturn("value"); + + replay(request); + assertEquals("value", extractor.getValue("name")); + verify(request); + } + +} diff --git a/plugins/portlet-tiles/src/test/java/org/apache/tiles/request/portlet/extractor/RequestScopeExtractorTest.java b/plugins/portlet-tiles/src/test/java/org/apache/tiles/request/portlet/extractor/RequestScopeExtractorTest.java new file mode 100644 index 000000000..df76a515e --- /dev/null +++ b/plugins/portlet-tiles/src/test/java/org/apache/tiles/request/portlet/extractor/RequestScopeExtractorTest.java @@ -0,0 +1,107 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.request.portlet.extractor; + +import org.apache.tiles.request.portlet.extractor.RequestScopeExtractor; +import org.junit.Before; +import org.junit.Test; + +import javax.portlet.PortletRequest; +import java.util.Enumeration; + +import static org.easymock.EasyMock.*; +import static org.easymock.EasyMock.*; +import static org.junit.Assert.assertEquals; + +/** + * Tests {@link RequestScopeExtractor}. + */ +public class RequestScopeExtractorTest { + + /** + * The request to test. + */ + private PortletRequest request; + + /** + * The extractor to test. + */ + private RequestScopeExtractor extractor; + + /** + * Sets up the test. + */ + @Before + public void setUp() { + request = createMock(PortletRequest.class); + extractor = new RequestScopeExtractor(request); + } + + /** + * Test method for {@link RequestScopeExtractor#setValue(String, Object)}. + */ + @Test + public void testSetValue() { + request.setAttribute("name", "value"); + + replay(request); + extractor.setValue("name", "value"); + verify(request); + } + + /** + * Test method for {@link RequestScopeExtractor#removeValue(String)}. + */ + @Test + public void testRemoveValue() { + request.removeAttribute("name"); + + replay(request); + extractor.removeValue("name"); + verify(request); + } + + /** + * Test method for {@link RequestScopeExtractor#getKeys()}. + */ + @SuppressWarnings("unchecked") + @Test + public void testGetKeys() { + Enumeration keys = createMock(Enumeration.class); + + expect(request.getAttributeNames()).andReturn(keys); + + replay(request, keys); + assertEquals(keys, extractor.getKeys()); + verify(request, keys); + } + + /** + * Test method for {@link RequestScopeExtractor#getValue(String)}. + */ + @Test + public void testGetValue() { + expect(request.getAttribute("name")).andReturn("value"); + + replay(request); + assertEquals("value", extractor.getValue("name")); + verify(request); + } + +} diff --git a/plugins/portlet-tiles/src/test/java/org/apache/tiles/request/portlet/extractor/SessionScopeExtractorTest.java b/plugins/portlet-tiles/src/test/java/org/apache/tiles/request/portlet/extractor/SessionScopeExtractorTest.java new file mode 100644 index 000000000..09010ff0c --- /dev/null +++ b/plugins/portlet-tiles/src/test/java/org/apache/tiles/request/portlet/extractor/SessionScopeExtractorTest.java @@ -0,0 +1,154 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.request.portlet.extractor; + +import org.apache.tiles.request.portlet.extractor.SessionScopeExtractor; +import org.junit.Before; +import org.junit.Test; + +import javax.portlet.PortletRequest; +import javax.portlet.PortletSession; +import java.util.Enumeration; + +import static org.easymock.EasyMock.*; +import static org.easymock.EasyMock.*; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; + +/** + * Tests {@link SessionScopeExtractor}. + */ +public class SessionScopeExtractorTest { + + /** + * The request. + */ + private PortletRequest request; + + /** + * The session. + */ + private PortletSession session; + + /** + * The scope to test. + */ + private SessionScopeExtractor extractor; + + /** + * Sets up the test. + */ + @Before + public void setUp() { + request = createMock(PortletRequest.class); + session = createMock(PortletSession.class); + extractor = new SessionScopeExtractor(request, PortletSession.PORTLET_SCOPE); + } + + + /** + * Tests {@link SessionScopeExtractor#SessionScopeExtractor(PortletRequest, int)}. + */ + @Test(expected = IllegalArgumentException.class) + public void testIllegalScope() { + replay(request, session); + new SessionScopeExtractor(request, 0); + verify(request, session); + } + + /** + * Test method for {@link SessionScopeExtractor#setValue(String, Object)}. + */ + @Test + public void testSetValue() { + expect(request.getPortletSession()).andReturn(session); + session.setAttribute("name", "value", PortletSession.PORTLET_SCOPE); + + replay(request, session); + extractor.setValue("name", "value"); + verify(request, session); + } + + /** + * Test method for {@link SessionScopeExtractor#removeValue(String)}. + */ + @Test + public void testRemoveValue() { + expect(request.getPortletSession(false)).andReturn(session); + session.removeAttribute("name", PortletSession.PORTLET_SCOPE); + + replay(request, session); + extractor.removeValue("name"); + verify(request, session); + } + + /** + * Test method for {@link SessionScopeExtractor#getKeys()}. + */ + @SuppressWarnings("unchecked") + @Test + public void testGetKeys() { + Enumeration keys = createMock(Enumeration.class); + + expect(request.getPortletSession(false)).andReturn(session); + expect(session.getAttributeNames(PortletSession.PORTLET_SCOPE)).andReturn(keys); + + replay(request, session, keys); + assertEquals(keys, extractor.getKeys()); + verify(request, session, keys); + } + + /** + * Test method for {@link SessionScopeExtractor#getKeys()}. + */ + @Test + public void testGetKeysNoSession() { + expect(request.getPortletSession(false)).andReturn(null); + + replay(request, session); + assertNull(extractor.getKeys()); + verify(request, session); + } + + /** + * Test method for {@link SessionScopeExtractor#getValue(String)}. + */ + @Test + public void testGetValue() { + expect(request.getPortletSession(false)).andReturn(session); + expect(session.getAttribute("name", PortletSession.PORTLET_SCOPE)).andReturn("value"); + + replay(request, session); + assertEquals("value", extractor.getValue("name")); + verify(request, session); + } + + /** + * Test method for {@link SessionScopeExtractor#getValue(String)}. + */ + @Test + public void testGetValueNoSession() { + expect(request.getPortletSession(false)).andReturn(null); + + replay(request, session); + assertNull(extractor.getValue("name")); + verify(request, session); + } + +} diff --git a/plugins/portlet-tiles/src/test/java/org/apache/tiles/request/portlet/extractor/StateAwareParameterExtractorTest.java b/plugins/portlet-tiles/src/test/java/org/apache/tiles/request/portlet/extractor/StateAwareParameterExtractorTest.java new file mode 100644 index 000000000..5157b6fe6 --- /dev/null +++ b/plugins/portlet-tiles/src/test/java/org/apache/tiles/request/portlet/extractor/StateAwareParameterExtractorTest.java @@ -0,0 +1,50 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.request.portlet.extractor; + +import org.apache.tiles.request.portlet.extractor.StateAwareParameterExtractor; +import org.junit.Test; + +import javax.portlet.PortletRequest; +import javax.portlet.StateAwareResponse; + +import static org.easymock.EasyMock.*; + +/** + * Tests {@link StateAwareParameterExtractor}. + */ +public class StateAwareParameterExtractorTest { + + /** + * Test method for {@link StateAwareParameterExtractor#setValue(String, String)}. + */ + @Test + public void testSetValue() { + PortletRequest request = createMock(PortletRequest.class); + StateAwareResponse response = createMock(StateAwareResponse.class); + + response.setRenderParameter("name", "value"); + + replay(request, response); + StateAwareParameterExtractor extractor = new StateAwareParameterExtractor(request, response); + extractor.setValue("name", "value"); + verify(request, response); + } + +} diff --git a/plugins/tiles/pom.xml b/plugins/tiles/pom.xml index 0c0488dc0..9716e7198 100644 --- a/plugins/tiles/pom.xml +++ b/plugins/tiles/pom.xml @@ -31,46 +31,44 @@ jar Struts 2 Tiles Plugin + + + + build-autotags + + true + + + + + org.codehaus.mojo + exec-maven-plugin + 3.1.0 + + + compile + + java + + + + + org.apache.struts2.tiles.BuildAutotags + + + ${project.build.directory} + + + + + + + + - org.apache.tiles - tiles-api - - - org.apache.tiles - tiles-core - - - org.apache.tiles - tiles-servlet - - - org.apache.tiles - tiles-request-api - - - org.apache.tiles - tiles-request-jsp - - - org.apache.tiles - tiles-request-servlet - - - org.apache.tiles - tiles-jsp - - - org.apache.tiles - tiles-freemarker - - - org.apache.tiles - tiles-ognl - - - org.apache.tiles - tiles-el + commons-digester + commons-digester org.glassfish @@ -82,8 +80,38 @@ jsp-api provided + + org.apache.velocity + velocity-engine-core + true + + + org.apache.velocity.tools + velocity-tools-view + true + + + org.apache.velocity.tools + velocity-tools-view-jsp + true + + + com.thoughtworks.xstream + xstream + true + + + org.easymock + easymock + test + + + org.apache.logging.log4j + log4j-jcl + test + - UTF-8 + UTF-8 diff --git a/plugins/tiles/src/main/java/org/apache/struts2/tiles/BuildAutotags.java b/plugins/tiles/src/main/java/org/apache/struts2/tiles/BuildAutotags.java new file mode 100644 index 000000000..4e90bb7ba --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/struts2/tiles/BuildAutotags.java @@ -0,0 +1,229 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.struts2.tiles; + +import java.io.File; +import java.io.InputStream; +import java.util.HashMap; +import java.util.Map; +import java.util.Properties; + +import org.apache.tiles.autotag.freemarker.FMTemplateGeneratorFactory; +import org.apache.tiles.autotag.generate.TemplateGenerator; +import org.apache.tiles.autotag.generate.TemplateGeneratorBuilder; +import org.apache.tiles.autotag.jsp.JspTemplateGeneratorFactory; +import org.apache.tiles.autotag.model.TemplateSuite; +import org.apache.tiles.autotag.velocity.VelocityTemplateGeneratorFactory; +import org.apache.velocity.app.VelocityEngine; + +import com.thoughtworks.xstream.XStream; +import com.thoughtworks.xstream.io.xml.DomDriver; + +/** + * Helper class for building/generating the classes and resources used in the + * plugin. + */ +public class BuildAutotags { + + public BuildAutotags() { + } + + /** + * The main method. + * + * @param args the arguments + */ + public static void main(String[] args) { + + BuildAutotags me = new BuildAutotags(); + + // Jsp classes + me.buildJsp(args[0]); + + // Freemarker classes + me.buildFreemarker(args[0]); + + // Velocity classes + me.buildVelocity(args[0]); + + } + + /** + * Build JSP tag classes and .tld file. + * + * To build, change template-suite.xml as required and then run this program. + * Copy the classes and .tld from the target autotag folder into the packageName + * location, .tld to src/main/resources/META-INF/tld/tiles-jsp.tld + * + * @param outputDir the output dir + */ + public void buildJsp(String outputDir) { + + // Default values + String taglibURI = "http://tiles.apache.org/tags-tiles"; + String packageName = "org.apache.tiles.web.jsp.taglib"; + String requestClass = "org.apache.tiles.request.Request"; + String runtime = "org.apache.tiles.request.jsp.autotag.JspAutotagRuntime"; + // outputDir = "/target" + + Map parameters = new HashMap(); + parameters.put("taglibURI", taglibURI); + + try { + + TemplateSuite suite; + + InputStream stream = getClass().getResourceAsStream("/META-INF/template-suite.xml"); + + try { + XStream xstream = new XStream(new DomDriver()); + xstream.allowTypes(new Class[] { org.apache.tiles.autotag.model.TemplateClass.class, + org.apache.tiles.autotag.model.TemplateSuite.class, + org.apache.tiles.autotag.model.TemplateParameter.class }); + suite = (TemplateSuite) xstream.fromXML(stream); + } finally { + stream.close(); + } + + Properties props = new Properties(); + InputStream propsStream = getClass().getResourceAsStream("/org/apache/tiles/autotag/velocity.properties"); + props.load(propsStream); + propsStream.close(); + + File classesOutputDirectory = new File(outputDir + "/generated-sources/autotag/classes"); + File resourcesOutputDirectory = new File(outputDir + "/generated-sources/autotag"); + + TemplateGenerator generator = new JspTemplateGeneratorFactory(classesOutputDirectory, + resourcesOutputDirectory, new VelocityEngine(props), TemplateGeneratorBuilder.createNewInstance()) + .createTemplateGenerator(); + + generator.generate(packageName, suite, parameters, runtime, requestClass); + + } catch (Exception e) { + // ignored + } + + } + + /** + * Builds the Freemarker classes. + * + * To build, change template-suite.xml as required and then run this program. + * Copy the classes from the target autotag folder into the packageName + * location. + * + * @param outputDir the output dir + */ + public void buildFreemarker(String outputDir) { + + // Default values + String packageName = "org.apache.tiles.freemarker.template"; + String requestClass = "org.apache.tiles.request.Request"; + String runtime = "org.apache.tiles.request.freemarker.autotag.FreemarkerAutotagRuntime"; + // outputDir = "/target" + + try { + + TemplateSuite suite; + + InputStream stream = getClass().getResourceAsStream("/META-INF/template-suite.xml"); + + try { + XStream xstream = new XStream(new DomDriver()); + xstream.allowTypes(new Class[] { org.apache.tiles.autotag.model.TemplateClass.class, + org.apache.tiles.autotag.model.TemplateSuite.class, + org.apache.tiles.autotag.model.TemplateParameter.class }); + suite = (TemplateSuite) xstream.fromXML(stream); + } finally { + stream.close(); + } + + Properties props = new Properties(); + InputStream propsStream = getClass().getResourceAsStream("/org/apache/tiles/autotag/velocity.properties"); + props.load(propsStream); + propsStream.close(); + + File classesOutputDirectory = new File(outputDir + "/generated-sources/autotag/classes"); + + TemplateGenerator generator = new FMTemplateGeneratorFactory(classesOutputDirectory, + new VelocityEngine(props), TemplateGeneratorBuilder.createNewInstance()).createTemplateGenerator(); + + generator.generate(packageName, suite, null, runtime, requestClass); + + } catch (Exception e) { + // ignored + } + + } + + /** + * Builds the velocity classes and velocity.properties. + * + * To build, change template-suite.xml as required and then run this program. + * Copy the classes from the target autotag folder into the packageName + * location, and velocity.properties to + * src/main/resources/META-INF/velocity.properties + * + * @param outputDir the output dir + */ + public void buildVelocity(String outputDir) { + + // Default values + String packageName = "org.apache.tiles.velocity.template"; + String requestClass = "org.apache.tiles.request.Request"; + String runtime = "org.apache.tiles.request.velocity.autotag.VelocityAutotagRuntime"; + // outputDir = "/target" + + try { + + TemplateSuite suite; + + InputStream stream = getClass().getResourceAsStream("/META-INF/template-suite.xml"); + + try { + XStream xstream = new XStream(new DomDriver()); + xstream.allowTypes(new Class[] { org.apache.tiles.autotag.model.TemplateClass.class, + org.apache.tiles.autotag.model.TemplateSuite.class, + org.apache.tiles.autotag.model.TemplateParameter.class }); + suite = (TemplateSuite) xstream.fromXML(stream); + } finally { + stream.close(); + } + + Properties props = new Properties(); + InputStream propsStream = getClass().getResourceAsStream("/org/apache/tiles/autotag/velocity.properties"); + props.load(propsStream); + propsStream.close(); + + File classesOutputDirectory = new File(outputDir + "/generated-sources/autotag/classes"); + File resourcesOutputDirectory = new File(outputDir + "/generated-sources/autotag"); + + TemplateGenerator generator = new VelocityTemplateGeneratorFactory(classesOutputDirectory, + resourcesOutputDirectory, new VelocityEngine(props), TemplateGeneratorBuilder.createNewInstance()) + .createTemplateGenerator(); + + generator.generate(packageName, suite, null, runtime, requestClass); + + } catch (Exception e) { + // ignored + } + + } + +} diff --git a/plugins/tiles/src/main/java/org/apache/struts2/tiles/I18NAttributeEvaluator.java b/plugins/tiles/src/main/java/org/apache/struts2/tiles/I18NAttributeEvaluator.java index 04673f294..e566f5747 100644 --- a/plugins/tiles/src/main/java/org/apache/struts2/tiles/I18NAttributeEvaluator.java +++ b/plugins/tiles/src/main/java/org/apache/struts2/tiles/I18NAttributeEvaluator.java @@ -25,7 +25,7 @@ import com.opensymphony.xwork2.config.ConfigurationException; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.apache.struts2.ServletActionContext; -import org.apache.tiles.evaluator.AbstractAttributeEvaluator; +import org.apache.tiles.core.evaluator.AbstractAttributeEvaluator; import org.apache.tiles.request.Request; import org.apache.tiles.request.servlet.ServletUtil; diff --git a/plugins/tiles/src/main/java/org/apache/struts2/tiles/StrutsAttributeEvaluator.java b/plugins/tiles/src/main/java/org/apache/struts2/tiles/StrutsAttributeEvaluator.java index b0cdb95ba..7b3e7624f 100644 --- a/plugins/tiles/src/main/java/org/apache/struts2/tiles/StrutsAttributeEvaluator.java +++ b/plugins/tiles/src/main/java/org/apache/struts2/tiles/StrutsAttributeEvaluator.java @@ -25,8 +25,8 @@ import ognl.OgnlException; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.apache.struts2.ServletActionContext; -import org.apache.tiles.evaluator.AbstractAttributeEvaluator; -import org.apache.tiles.evaluator.EvaluationException; +import org.apache.tiles.core.evaluator.AbstractAttributeEvaluator; +import org.apache.tiles.core.evaluator.EvaluationException; import org.apache.tiles.request.Request; import org.apache.tiles.request.servlet.ServletUtil; diff --git a/plugins/tiles/src/main/java/org/apache/struts2/tiles/StrutsFreeMarkerAttributeRenderer.java b/plugins/tiles/src/main/java/org/apache/struts2/tiles/StrutsFreeMarkerAttributeRenderer.java index cb6e0d403..e39fed4c6 100644 --- a/plugins/tiles/src/main/java/org/apache/struts2/tiles/StrutsFreeMarkerAttributeRenderer.java +++ b/plugins/tiles/src/main/java/org/apache/struts2/tiles/StrutsFreeMarkerAttributeRenderer.java @@ -33,9 +33,9 @@ import org.apache.struts2.views.freemarker.FreemarkerManager; import org.apache.struts2.views.freemarker.FreemarkerResult; import org.apache.struts2.views.freemarker.StrutsBeanWrapper; import org.apache.tiles.freemarker.template.TilesFMModelRepository; -import org.apache.tiles.impl.InvalidTemplateException; import org.apache.tiles.request.Request; import org.apache.tiles.request.render.Renderer; +import org.apache.tiles.core.impl.InvalidTemplateException; import org.apache.tiles.request.servlet.ServletUtil; import javax.servlet.ServletContext; @@ -44,7 +44,7 @@ import java.io.IOException; public class StrutsFreeMarkerAttributeRenderer implements Renderer { - private static Logger LOG = LogManager.getLogger(StrutsFreeMarkerAttributeRenderer.class); + private static final Logger LOG = LogManager.getLogger(StrutsFreeMarkerAttributeRenderer.class); @Override public void render(String path, Request request) throws IOException { @@ -75,7 +75,7 @@ public class StrutsFreeMarkerAttributeRenderer implements Renderer { } /** - * Depending how Tiles definition was defined, request can an instance of JspRequest (for JSPs) + * Depending on how Tiles definition was defined, request can an instance of JspRequest (for JSPs) * or a ServletRequest (FreeMarker) */ protected ActionContext readActionContext(Request request) { diff --git a/plugins/tiles/src/main/java/org/apache/struts2/tiles/StrutsPreparerFactory.java b/plugins/tiles/src/main/java/org/apache/struts2/tiles/StrutsPreparerFactory.java index e279adcb4..8630a061f 100644 --- a/plugins/tiles/src/main/java/org/apache/struts2/tiles/StrutsPreparerFactory.java +++ b/plugins/tiles/src/main/java/org/apache/struts2/tiles/StrutsPreparerFactory.java @@ -23,8 +23,8 @@ import com.opensymphony.xwork2.ObjectFactory; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.message.ParameterizedMessage; -import org.apache.tiles.preparer.ViewPreparer; -import org.apache.tiles.preparer.factory.BasicPreparerFactory; +import org.apache.tiles.api.preparer.ViewPreparer; +import org.apache.tiles.core.prepare.factory.BasicPreparerFactory; /** * This is a basic ViewPreparer factory that uses {@link ObjectFactory} to create the ViewPreparer diff --git a/plugins/tiles/src/main/java/org/apache/struts2/tiles/StrutsTilesAnnotationProcessor.java b/plugins/tiles/src/main/java/org/apache/struts2/tiles/StrutsTilesAnnotationProcessor.java index e36b75d16..8842578af 100644 --- a/plugins/tiles/src/main/java/org/apache/struts2/tiles/StrutsTilesAnnotationProcessor.java +++ b/plugins/tiles/src/main/java/org/apache/struts2/tiles/StrutsTilesAnnotationProcessor.java @@ -25,10 +25,10 @@ import org.apache.struts2.tiles.annotation.TilesDefinition; import org.apache.struts2.tiles.annotation.TilesDefinitions; import org.apache.struts2.tiles.annotation.TilesPutAttribute; import org.apache.struts2.tiles.annotation.TilesPutListAttribute; -import org.apache.tiles.Attribute; -import org.apache.tiles.Definition; -import org.apache.tiles.Expression; -import org.apache.tiles.ListAttribute; +import org.apache.tiles.api.Attribute; +import org.apache.tiles.api.Definition; +import org.apache.tiles.api.Expression; +import org.apache.tiles.api.ListAttribute; /** * Processes tiles annotations to create {@link Definition}s and @@ -123,7 +123,7 @@ public class StrutsTilesAnnotationProcessor { String templateType = getValueOrNull(tilesDef.templateType()); if (templateType != null) { attribute.setRenderer(templateType); - } else if (getValueOrNull(tilesDef.extend()) != null && templateType == null) { + } else if (getValueOrNull(tilesDef.extend()) != null) { attribute.setRenderer(null); } return attribute; diff --git a/plugins/tiles/src/main/java/org/apache/struts2/tiles/StrutsTilesContainerFactory.java b/plugins/tiles/src/main/java/org/apache/struts2/tiles/StrutsTilesContainerFactory.java index 41b93a38f..205476467 100644 --- a/plugins/tiles/src/main/java/org/apache/struts2/tiles/StrutsTilesContainerFactory.java +++ b/plugins/tiles/src/main/java/org/apache/struts2/tiles/StrutsTilesContainerFactory.java @@ -24,25 +24,31 @@ import ognl.OgnlRuntime; import ognl.PropertyAccessor; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import org.apache.tiles.TilesContainer; -import org.apache.tiles.definition.DefinitionsFactory; -import org.apache.tiles.definition.pattern.DefinitionPatternMatcherFactory; -import org.apache.tiles.definition.pattern.PatternDefinitionResolver; -import org.apache.tiles.definition.pattern.PrefixedPatternDefinitionResolver; -import org.apache.tiles.definition.pattern.regexp.RegexpDefinitionPatternMatcherFactory; -import org.apache.tiles.definition.pattern.wildcard.WildcardDefinitionPatternMatcherFactory; +import org.apache.tiles.api.TilesContainer; +import org.apache.tiles.request.ApplicationContext; +import org.apache.tiles.request.ApplicationResource; +import org.apache.tiles.request.Request; +import org.apache.tiles.request.render.BasicRendererFactory; +import org.apache.tiles.request.render.ChainedDelegateRenderer; +import org.apache.tiles.core.definition.DefinitionsFactory; +import org.apache.tiles.core.definition.pattern.DefinitionPatternMatcherFactory; +import org.apache.tiles.core.definition.pattern.PatternDefinitionResolver; +import org.apache.tiles.core.definition.pattern.PrefixedPatternDefinitionResolver; +import org.apache.tiles.core.definition.pattern.regexp.RegexpDefinitionPatternMatcherFactory; +import org.apache.tiles.core.definition.pattern.wildcard.WildcardDefinitionPatternMatcherFactory; +import org.apache.tiles.core.evaluator.AttributeEvaluatorFactory; +import org.apache.tiles.core.evaluator.BasicAttributeEvaluatorFactory; +import org.apache.tiles.core.evaluator.impl.DirectAttributeEvaluator; +import org.apache.tiles.core.factory.BasicTilesContainerFactory; +import org.apache.tiles.core.factory.TilesContainerFactoryException; +import org.apache.tiles.core.impl.mgmt.CachingTilesContainer; +import org.apache.tiles.core.locale.LocaleResolver; +import org.apache.tiles.core.prepare.factory.PreparerFactory; import org.apache.tiles.el.ELAttributeEvaluator; import org.apache.tiles.el.JspExpressionFactoryFactory; import org.apache.tiles.el.ScopeELResolver; import org.apache.tiles.el.TilesContextBeanELResolver; import org.apache.tiles.el.TilesContextELResolver; -import org.apache.tiles.evaluator.AttributeEvaluatorFactory; -import org.apache.tiles.evaluator.BasicAttributeEvaluatorFactory; -import org.apache.tiles.evaluator.impl.DirectAttributeEvaluator; -import org.apache.tiles.factory.BasicTilesContainerFactory; -import org.apache.tiles.factory.TilesContainerFactoryException; -import org.apache.tiles.impl.mgmt.CachingTilesContainer; -import org.apache.tiles.locale.LocaleResolver; import org.apache.tiles.ognl.AnyScopePropertyAccessor; import org.apache.tiles.ognl.DelegatePropertyAccessor; import org.apache.tiles.ognl.NestedObjectDelegatePropertyAccessor; @@ -51,12 +57,6 @@ import org.apache.tiles.ognl.PropertyAccessorDelegateFactory; import org.apache.tiles.ognl.ScopePropertyAccessor; import org.apache.tiles.ognl.TilesApplicationContextNestedObjectExtractor; import org.apache.tiles.ognl.TilesContextPropertyAccessorDelegateFactory; -import org.apache.tiles.preparer.factory.PreparerFactory; -import org.apache.tiles.request.ApplicationContext; -import org.apache.tiles.request.ApplicationResource; -import org.apache.tiles.request.Request; -import org.apache.tiles.request.render.BasicRendererFactory; -import org.apache.tiles.request.render.ChainedDelegateRenderer; import org.apache.tiles.request.render.Renderer; import javax.el.ArrayELResolver; @@ -81,7 +81,7 @@ import java.util.Set; * - S2 ro access Struts' ValueStack * - OGNL * - EL - * + *

* If you need additional features create your own listener and factory, * you can base on code from Tiles' CompleteAutoloadTilesContainerFactory */ @@ -270,4 +270,4 @@ public class StrutsTilesContainerFactory extends BasicTilesContainerFactory { } } -} \ No newline at end of file +} diff --git a/plugins/tiles/src/main/java/org/apache/struts2/tiles/StrutsTilesInitializer.java b/plugins/tiles/src/main/java/org/apache/struts2/tiles/StrutsTilesInitializer.java index 5170003a4..cb471a1ab 100644 --- a/plugins/tiles/src/main/java/org/apache/struts2/tiles/StrutsTilesInitializer.java +++ b/plugins/tiles/src/main/java/org/apache/struts2/tiles/StrutsTilesInitializer.java @@ -20,11 +20,11 @@ package org.apache.struts2.tiles; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import org.apache.tiles.definition.DefinitionsFactory; -import org.apache.tiles.factory.AbstractTilesContainerFactory; +import org.apache.tiles.core.definition.DefinitionsFactory; +import org.apache.tiles.core.factory.AbstractTilesContainerFactory; +import org.apache.tiles.core.startup.AbstractTilesInitializer; import org.apache.tiles.request.ApplicationContext; import org.apache.tiles.request.servlet.ServletApplicationContext; -import org.apache.tiles.startup.AbstractTilesInitializer; import javax.servlet.ServletContext; diff --git a/plugins/tiles/src/main/java/org/apache/struts2/tiles/StrutsTilesListener.java b/plugins/tiles/src/main/java/org/apache/struts2/tiles/StrutsTilesListener.java index 38e506552..5ebe36237 100644 --- a/plugins/tiles/src/main/java/org/apache/struts2/tiles/StrutsTilesListener.java +++ b/plugins/tiles/src/main/java/org/apache/struts2/tiles/StrutsTilesListener.java @@ -20,7 +20,7 @@ package org.apache.struts2.tiles; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import org.apache.tiles.startup.TilesInitializer; +import org.apache.tiles.core.startup.TilesInitializer; import org.apache.tiles.web.startup.AbstractTilesListener; /** @@ -37,4 +37,4 @@ public class StrutsTilesListener extends AbstractTilesListener { LOG.info("Starting Struts Tiles 3 integration ..."); return new StrutsTilesInitializer(); } -} \ No newline at end of file +} diff --git a/plugins/tiles/src/main/java/org/apache/struts2/tiles/StrutsTilesLocaleResolver.java b/plugins/tiles/src/main/java/org/apache/struts2/tiles/StrutsTilesLocaleResolver.java index 3e6524fa4..0d3d3ec33 100644 --- a/plugins/tiles/src/main/java/org/apache/struts2/tiles/StrutsTilesLocaleResolver.java +++ b/plugins/tiles/src/main/java/org/apache/struts2/tiles/StrutsTilesLocaleResolver.java @@ -24,7 +24,7 @@ import com.opensymphony.xwork2.config.ConfigurationException; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.apache.struts2.ServletActionContext; -import org.apache.tiles.locale.LocaleResolver; +import org.apache.tiles.core.locale.LocaleResolver; import org.apache.tiles.request.Request; import org.apache.tiles.request.servlet.ServletUtil; @@ -33,7 +33,7 @@ import java.util.Locale; public class StrutsTilesLocaleResolver implements LocaleResolver { - private static Logger LOG = LogManager.getLogger(StrutsTilesLocaleResolver.class); + private static final Logger LOG = LogManager.getLogger(StrutsTilesLocaleResolver.class); @Override public Locale resolveLocale(Request request) { diff --git a/plugins/tiles/src/main/java/org/apache/struts2/tiles/StrutsWildcardServletApplicationContext.java b/plugins/tiles/src/main/java/org/apache/struts2/tiles/StrutsWildcardServletApplicationContext.java index 6a890d4a9..7af6069bb 100644 --- a/plugins/tiles/src/main/java/org/apache/struts2/tiles/StrutsWildcardServletApplicationContext.java +++ b/plugins/tiles/src/main/java/org/apache/struts2/tiles/StrutsWildcardServletApplicationContext.java @@ -24,7 +24,6 @@ import com.opensymphony.xwork2.util.finder.ResourceFinder; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.apache.tiles.request.ApplicationResource; -import org.apache.tiles.request.locale.URLApplicationResource; import org.apache.tiles.request.servlet.ServletApplicationContext; import javax.servlet.ServletContext; diff --git a/plugins/tiles/src/main/java/org/apache/struts2/views/tiles/TilesResult.java b/plugins/tiles/src/main/java/org/apache/struts2/views/tiles/TilesResult.java index a1e1c69d7..3ca20e4c1 100644 --- a/plugins/tiles/src/main/java/org/apache/struts2/views/tiles/TilesResult.java +++ b/plugins/tiles/src/main/java/org/apache/struts2/views/tiles/TilesResult.java @@ -29,58 +29,41 @@ import org.apache.struts2.ServletActionContext; import org.apache.struts2.result.ServletDispatcherResult; import org.apache.struts2.tiles.StrutsTilesAnnotationProcessor; import org.apache.struts2.tiles.annotation.TilesDefinition; -import org.apache.tiles.Definition; -import org.apache.tiles.TilesContainer; -import org.apache.tiles.TilesException; +import org.apache.tiles.api.Definition; +import org.apache.tiles.api.TilesContainer; +import org.apache.tiles.api.TilesException; import com.opensymphony.xwork2.ActionInvocation; -import org.apache.tiles.access.TilesAccess; -import org.apache.tiles.mgmt.MutableTilesContainer; +import org.apache.tiles.api.access.TilesAccess; +import org.apache.tiles.api.mgmt.MutableTilesContainer; import org.apache.tiles.request.ApplicationContext; import org.apache.tiles.request.Request; import org.apache.tiles.request.servlet.ServletRequest; import org.apache.tiles.request.servlet.ServletUtil; /** - * - * Renders a view using struts-tiles. - * - * - * - * In your web.xml file, you need to add a TilesListener. - * + * Renders a view using struts-tiles. In your web.xml file, you need to add a TilesListener. + *

* <listener> * <listener-class>org.apache.struts2.tiles.StrutsTilesListener</listener-class> * </listener> - * - * - * + *

* In struts.xml, use type="tiles" on your <result>. - * + *

* <action name="editUser" class="userAction" method="edit"> * <result name="success" type="tiles">userForm</result> * <result name="input" type="tiles">userList</result> * </action> - * - * - * - * - * + *

* Making this result type the default for the current package. - * + *

* <result-types> * <result-type name="tiles" * class="org.apache.struts2.views.tiles.TilesResult" default="true" /> * </result-types> - * - * - * - * + *

* You have to configure tiles itself. Therefore you can add tiles.xml either * to resources or WEB-INF. You may also use annotations like {@link TilesDefinition}. - * - * - * */ public class TilesResult extends ServletDispatcherResult { @@ -114,8 +97,7 @@ public class TilesResult extends ServletDispatcherResult { if (StringUtils.isEmpty(location)) { LOG.trace("location not set -> action must have one @TilesDefinition"); tilesDefinition = annotationProcessor.findAnnotation(action, null); - String tileName = StringUtils.isNotEmpty(tilesDefinition.name()) ? tilesDefinition.name() : actionName; - location = tileName; + location = StringUtils.isNotEmpty(tilesDefinition.name()) ? tilesDefinition.name() : actionName; LOG.debug("using new location name '{}' and @TilesDefinition '{}'", location, tilesDefinition); } setLocation(location); diff --git a/plugins/tiles/src/main/java/org/apache/tiles/api/Attribute.java b/plugins/tiles/src/main/java/org/apache/tiles/api/Attribute.java new file mode 100644 index 000000000..65be6537a --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/api/Attribute.java @@ -0,0 +1,366 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tiles.api; + +import com.opensymphony.xwork2.util.TextParseUtil; +import org.apache.tiles.request.Request; + +import java.util.Iterator; +import java.util.Objects; +import java.util.Set; + +/** + * Common implementation of attribute definition. + */ +public class Attribute { + + /** + * The name of the template renderer. + */ + private static final String TEMPLATE_RENDERER = "template"; + + /** + * The roles that can render this attribute. + * + * @since 2.0.6 + */ + private Set roles = null; + + /** + * The value of the attribute. + */ + private Object value = null; + + /** + * The expression to evaluate. Ignored if {@link #value} is not null. + * + * @since 2.2.0 + */ + private Expression expressionObject = null; + + /** + * The renderer name of the attribute. Default names are string, + * template, definition, object. + */ + private String renderer = null; + + /** + * Constructor. + */ + public Attribute() { + } + + /** + * Constructor. + * + * @param value Object to store. + */ + public Attribute(Object value) { + this.value = value; + } + + /** + * Copy constructor. + * + * @param attribute The attribute to copy from. + */ + public Attribute(Attribute attribute) { + this.roles = attribute.roles; + this.value = attribute.getValue(); + if (attribute.expressionObject != null) { + this.expressionObject = new Expression(attribute.expressionObject); + } else { + this.expressionObject = null; + } + this.renderer = attribute.renderer; + } + + /** + * Constructor. + * + * @param value Object to store. + * @param role Asociated role. + */ + public Attribute(Object value, String role) { + this.value = value; + setRole(role); + } + + /** + * Constructor. + * + * @param value Object to store. If specified, the expression + * parameter will be ignored. + * @param expression The expression to be evaluated. Ignored if the + * value is not null. + * @param role Associated role. + * @param rendererName The renderer name. + * @since 2.2.0 + */ + public Attribute(Object value, Expression expression, String role, String rendererName) { + this.value = value; + this.expressionObject = expression; + this.renderer = rendererName; + setRole(role); + } + + /** + * Creates a template attribute, starting from the name of the template. + * + * @param template The template that will be rendered. + * @return The template attribute. + * @since 2.1.2 + */ + public static Attribute createTemplateAttribute(String template) { + Attribute attribute = new Attribute(); + attribute.setValue(template); + attribute.setRenderer(TEMPLATE_RENDERER); + return attribute; + } + + /** + * Creates a template attribute, starting from the name of the template. + * + * @param template The template that will be rendered. + * @param templateExpression The template expression that will be evaluated + * to a template. + * @param templateType The type, or renderer, of the template. If null, the + * default template will be used. + * @param role The comma-separated roles for which the template is + * authorized to be rendered. + * @return The template attribute. + * @since 2.2.2 + */ + public static Attribute createTemplateAttribute(String template, + String templateExpression, String templateType, String role) { + Attribute templateAttribute = createTemplateAttribute(template); + templateAttribute.setRole(role); + if (templateType != null) { + templateAttribute.setRenderer(templateType); + } + templateAttribute + .setExpressionObject(Expression + .createExpressionFromDescribedExpression(templateExpression)); + return templateAttribute; + } + + /** + * Get role. + * + * @return the name of the required role(s) + */ + public String getRole() { + String retValue = null; + + if (roles != null && !roles.isEmpty()) { + StringBuilder builder = new StringBuilder(); + Iterator roleIt = roles.iterator(); + if (roleIt.hasNext()) { + builder.append(roleIt.next()); + while (roleIt.hasNext()) { + builder.append(","); + builder.append(roleIt.next()); + } + retValue = builder.toString(); + } + } + + return retValue; + } + + /** + * Returns the roles that can render this attribute. + * + * @return The enabled roles. + * @since 2.0.6 + */ + public Set getRoles() { + return roles; + } + + /** + * Set role. + * + * @param role Associated role. + */ + public void setRole(String role) { + if (role != null && role.trim().length() > 0) { + roles = TextParseUtil.commaDelimitedStringToSet(role); + } else { + roles = null; + } + } + + /** + * Sets the roles that can render this attribute. + * + * @param roles The enabled roles. + * @since 2.0.6 + */ + public void setRoles(Set roles) { + this.roles = roles; + } + + /** + * Get value. + * + * @return the value + */ + public Object getValue() { + return value; + } + + /** + * Set value. + * + * @param value New value. + */ + public void setValue(Object value) { + this.value = value; + } + + /** + * Returns The expression to evaluate. Ignored if {@link #value} is not + * null. + * + * @return The expression to be evaluated. + * @since 2.2.0 + */ + public Expression getExpressionObject() { + return expressionObject; + } + + /** + * Sets The expression to evaluate. Ignored if {@link #value} is not + * null. + * + * @param expressionObject The expression to be evaluated. + * @since 2.2.0 + */ + public void setExpressionObject(Expression expressionObject) { + this.expressionObject = expressionObject; + } + + /** + * {@inheritDoc} + */ + @Override + public String toString() { + return Objects.toString(value); + } + + /** + * Returns the renderer name to use. + * + * @return The renderer name. + * @since 2.1.0 + */ + public String getRenderer() { + return renderer; + } + + /** + * Sets the renderer name to use. + * + * @param rendererName The renderer. + * @since 2.1.0 + */ + public void setRenderer(String rendererName) { + this.renderer = rendererName; + } + + /** + * Inherits an attribute, i.e. overwrites null properties with the ones + * provided by the attribute. + * + * @param attribute The attribute to inherit. + * @since 2.1.2 + */ + public void inherit(Attribute attribute) { + if (value == null) { + value = attribute.getValue(); + } + Expression targetExpressionObject = attribute.getExpressionObject(); + if (targetExpressionObject != null + && (expressionObject == null || expressionObject + .getExpression() == null)) { + expressionObject = new Expression(targetExpressionObject); + } + if (roles == null || roles.isEmpty()) { + roles = attribute.getRoles(); + } + if (renderer == null) { + renderer = attribute.getRenderer(); + } + } + + /** + * {@inheritDoc} + */ + @Override + public boolean equals(Object obj) { + if (obj == null && value == null) { + return true; + } + if (!(obj instanceof Attribute)) { + return false; + } + Attribute attribute = (Attribute) obj; + return Objects.equals(value, attribute.value) + && Objects.equals(renderer, attribute.renderer) + && Objects.equals(roles, attribute.roles) + && Objects.equals(expressionObject, attribute.expressionObject); + } + + /** + * Checks if the current user can use this attribute. + * + * @param request The request context. + * @return true if the current user can see this attribute. + * @since 3.0.0 + */ + public boolean isPermitted(Request request) { + if (roles == null || roles.isEmpty()) { + return true; + } + + boolean retValue = false; + + for (Iterator roleIt = roles.iterator(); roleIt.hasNext() + && !retValue; ) { + retValue = request.isUserInRole(roleIt.next()); + } + + return retValue; + } + + /** + * {@inheritDoc} + */ + @Override + public int hashCode() { + return Objects.hashCode(value) + Objects.hashCode(renderer) + + Objects.hashCode(roles) + Objects.hashCode(expressionObject); + } + + public Attribute copy() { + return new Attribute(this); + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/api/AttributeContext.java b/plugins/tiles/src/main/java/org/apache/tiles/api/AttributeContext.java new file mode 100644 index 000000000..554bd9ec0 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/api/AttributeContext.java @@ -0,0 +1,161 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.api; + +import java.util.Map; +import java.util.Set; + +/** + * Encapsulation of the current state of execution. + * + * @since Tiles 2.0 + */ +public interface AttributeContext { + + /** + * Returns the attribute that will be used to render a template. + * + * @return The template attribute. + * @since 2.1.2 + */ + Attribute getTemplateAttribute(); + + /** + * Sets the template attribute, that will be used to render the template + * page. + * + * @param templateAttribute The template attribute. + * @since 2.1.2 + */ + void setTemplateAttribute(Attribute templateAttribute); + + /** + * Get associated preparer instance. + * + * @return The preparer name. + * @since 2.1.0 + */ + String getPreparer(); + + /** + * Set associated preparer instance. + * + * @param url The preparer name. + * @since 2.1.0 + */ + void setPreparer(String url); + + /** + * Add all attributes to the context. + * + * @param newAttributes the attributes to be added. + */ + void addAll(Map newAttributes); + + /** + * Copies the cascaded attributes to this attribute context. + * + * @param parent The parent context to be used. + * @since 2.1.0 + */ + void inheritCascadedAttributes(AttributeContext parent); + + /** + * Copies all missing attributes from the parent attribute + * context to this one. + * + * @param parent The attribute context to copy attributes from. + * @since 2.1.0 + */ + void inherit(AttributeContext parent); + + /** + * Retrieve the named attribute, either cascaded or not. + * + * @param name key name for the attribute. + * @return Attribute associated with the given name. + */ + Attribute getAttribute(String name); + + /** + * Retrieve the attribute that has been defined in this context (i.e. not + * cascaded). + * + * @param name key name for the attribute. + * @return Attribute The local attribute associated with the given name, if + * present, or null otherwise. + * @since 2.1.0 + */ + Attribute getLocalAttribute(String name); + + /** + * Retrieve the attribute that has been cascaded at upper levels. + * + * @param name key name for the attribute. + * @return Attribute The cascaded attribute associated with the given name, + * if present, or null otherwise. + * @since 2.1.0 + */ + Attribute getCascadedAttribute(String name); + + /** + * Returns the names of the local attributes, i.e. the one that have not + * been cascaded. + * + * @return The local attribute names. + * @since 2.1.0 + */ + Set getLocalAttributeNames(); + + /** + * Returns the names of the cascaded attributes. + * + * @return The cascaded attribute names. + * @since 2.1.0 + */ + Set getCascadedAttributeNames(); + + /** + * Add the specified attribute. The attribute value will be available only + * in the current context, i.e. it is like calling + * {@link AttributeContext#putAttribute(String, Attribute, boolean)} with + * cascade = false. + * + * @param name name of the attribute + * @param value value of the attribute + */ + void putAttribute(String name, Attribute value); + + /** + * Add the specified attribute. + * + * @param name name of the attribute + * @param value value of the attribute + * @param cascade If true, the attribute value will be + * available in all nested contexts. If false, it will be + * available only in the current context. + * @since 2.1.0 + */ + void putAttribute(String name, Attribute value, boolean cascade); + + /** + * Clear the attributes. + */ + void clear(); +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/api/BasicAttributeContext.java b/plugins/tiles/src/main/java/org/apache/tiles/api/BasicAttributeContext.java new file mode 100644 index 000000000..cd12ea860 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/api/BasicAttributeContext.java @@ -0,0 +1,462 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.api; + +import java.io.Serializable; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; +import java.util.Set; + +/** + * Basic implementation for AttributeContext. + * + * @since 2.1.0 + */ +public class BasicAttributeContext implements AttributeContext, Serializable { + + /** + * The template attribute, to render a template. + * + * @since 2.1.2 + */ + protected Attribute templateAttribute; + + /** + * Associated ViewPreparer URL or classname, if defined. + * + * @since 2.1.0 + */ + protected String preparer = null; + + /** + * Template attributes. + * + * @since 2.1.0 + */ + protected Map attributes = null; + + /** + * Cascaded template attributes. + * + * @since 2.1.0 + */ + protected Map cascadedAttributes = null; + + /** + * Constructor. + * + * @since 2.1.0 + */ + public BasicAttributeContext() { + } + + /** + * Constructor. + * Create a context and set specified attributes. + * + * @param attributes Attributes to initialize context. + * @since 2.1.0 + */ + public BasicAttributeContext(Map attributes) { + if (attributes != null) { + this.attributes = deepCopyAttributeMap(attributes); + } + } + + /** + * Copy constructor. + * + * @param context The constructor to copy. + * @since 2.1.0 + */ + public BasicAttributeContext(AttributeContext context) { + if (context instanceof BasicAttributeContext) { + copyBasicAttributeContext((BasicAttributeContext) context); + } else { + Attribute parentTemplateAttribute = context.getTemplateAttribute(); + if (parentTemplateAttribute != null) { + this.templateAttribute = new Attribute(parentTemplateAttribute); + } + this.preparer = context.getPreparer(); + this.attributes = new HashMap<>(); + Set parentAttributeNames = context.getLocalAttributeNames(); + if (parentAttributeNames != null) { + for (String name : parentAttributeNames) { + attributes.put(name, new Attribute(context.getLocalAttribute(name))); + } + } + inheritCascadedAttributes(context); + } + } + + /** + * Copy constructor. + * + * @param context The constructor to copy. + * @since 2.1.0 + */ + public BasicAttributeContext(BasicAttributeContext context) { + copyBasicAttributeContext(context); + } + + /** + * {@inheritDoc} + */ + public Attribute getTemplateAttribute() { + return templateAttribute; + } + + /** + * {@inheritDoc} + */ + public void setTemplateAttribute(Attribute templateAttribute) { + this.templateAttribute = templateAttribute; + } + + /** + * {@inheritDoc} + */ + public String getPreparer() { + return preparer; + } + + /** + * {@inheritDoc} + */ + public void setPreparer(String url) { + this.preparer = url; + } + + /** + * {@inheritDoc} + */ + public void inheritCascadedAttributes(AttributeContext context) { + if (context instanceof BasicAttributeContext) { + if (((BasicAttributeContext) context).cascadedAttributes != null && !((BasicAttributeContext) context).cascadedAttributes.isEmpty()) { + cascadedAttributes = deepCopyAttributeMap(((BasicAttributeContext) context).cascadedAttributes); + } + } else { + this.cascadedAttributes = new HashMap<>(); + Set parentAttributeNames = context.getCascadedAttributeNames(); + if (parentAttributeNames != null) { + for (String name : parentAttributeNames) { + cascadedAttributes.put(name, new Attribute(context + .getCascadedAttribute(name))); + } + } + } + } + + /** + * {@inheritDoc} + */ + public void inherit(AttributeContext parent) { + if (parent instanceof BasicAttributeContext) { + inherit((BasicAttributeContext) parent); + } else { + // Inheriting template, roles and preparer. + Attribute parentTemplateAttribute = parent.getTemplateAttribute(); + inheritParentTemplateAttribute(parentTemplateAttribute); + if (preparer == null) { + preparer = parent.getPreparer(); + } + + // Inheriting attributes. + Set names = parent.getCascadedAttributeNames(); + if (names != null && !names.isEmpty()) { + for (String name : names) { + Attribute attribute = parent.getCascadedAttribute(name); + Attribute destAttribute = getCascadedAttribute(name); + if (destAttribute == null) { + putAttribute(name, attribute, true); + } else if (attribute instanceof ListAttribute + && destAttribute instanceof ListAttribute + && ((ListAttribute) destAttribute).isInherit()) { + ((ListAttribute) destAttribute).inherit((ListAttribute) attribute); + } + } + } + names = parent.getLocalAttributeNames(); + if (names != null && !names.isEmpty()) { + for (String name : names) { + Attribute attribute = parent.getLocalAttribute(name); + Attribute destAttribute = getLocalAttribute(name); + if (destAttribute == null) { + putAttribute(name, attribute, false); + } else if (attribute instanceof ListAttribute + && destAttribute instanceof ListAttribute + && ((ListAttribute) destAttribute).isInherit()) { + ((ListAttribute) destAttribute).inherit((ListAttribute) attribute); + } + } + } + } + } + + /** + * Inherits the attribute context, inheriting, i.e. copying if not present, + * the attributes. + * + * @param parent The attribute context to inherit. + * @since 2.1.0 + */ + public void inherit(BasicAttributeContext parent) { + // Set template, roles and preparer if not set. + inheritParentTemplateAttribute(parent.getTemplateAttribute()); + if (preparer == null) { + preparer = parent.preparer; + } + + // Sets attributes. + cascadedAttributes = addMissingAttributes(parent.cascadedAttributes, + cascadedAttributes); + attributes = addMissingAttributes(parent.attributes, attributes); + } + + /** + * Add all attributes to this context. + * Copies all the mappings from the specified attribute map to this context. + * New attribute mappings will replace any mappings that this context had for any of the keys + * currently in the specified attribute map. + * + * @param newAttributes Attributes to add. + * @since 2.1.0 + */ + public void addAll(Map newAttributes) { + if (newAttributes == null) { + return; + } + + if (attributes == null) { + attributes = new HashMap<>(newAttributes); + return; + } + + attributes.putAll(newAttributes); + } + + /** + * {@inheritDoc} + */ + public Attribute getAttribute(String name) { + Attribute retValue = null; + if (attributes != null) { + retValue = attributes.get(name); + } + + if (retValue == null && cascadedAttributes != null) { + retValue = cascadedAttributes.get(name); + } + + return retValue; + } + + /** + * {@inheritDoc} + */ + public Attribute getLocalAttribute(String name) { + if (attributes == null) { + return null; + } + + return attributes.get(name); + } + + /** + * {@inheritDoc} + */ + public Attribute getCascadedAttribute(String name) { + if (cascadedAttributes == null) { + return null; + } + + return cascadedAttributes.get(name); + } + + /** + * {@inheritDoc} + */ + public Set getLocalAttributeNames() { + if (attributes != null && !attributes.isEmpty()) { + return attributes.keySet(); + } + return null; + } + + /** + * {@inheritDoc} + */ + public Set getCascadedAttributeNames() { + if (cascadedAttributes != null && !cascadedAttributes.isEmpty()) { + return cascadedAttributes.keySet(); + } + return null; + } + + /** + * {@inheritDoc} + */ + public void putAttribute(String name, Attribute value) { + if (attributes == null) { + attributes = new HashMap<>(); + } + + attributes.put(name, value); + } + + /** + * {@inheritDoc} + */ + public void putAttribute(String name, Attribute value, boolean cascade) { + Map mapToUse; + if (cascade) { + if (cascadedAttributes == null) { + cascadedAttributes = new HashMap<>(); + } + mapToUse = cascadedAttributes; + } else { + if (attributes == null) { + attributes = new HashMap<>(); + } + mapToUse = attributes; + } + mapToUse.put(name, value); + } + + /** + * {@inheritDoc} + */ + public void clear() { + templateAttribute = null; + preparer = null; + attributes.clear(); + cascadedAttributes.clear(); + } + + /** + * {@inheritDoc} + */ + @Override + public boolean equals(Object obj) { + if (obj == null) { + return false; + } + if (!(obj instanceof BasicAttributeContext)) { + return false; + } + BasicAttributeContext bac = (BasicAttributeContext) obj; + return Objects.equals(templateAttribute, bac.templateAttribute) + && Objects.equals(preparer, bac.preparer) + && Objects.equals(attributes, bac.attributes) + && Objects.equals(cascadedAttributes, bac.cascadedAttributes); + } + + /** + * {@inheritDoc} + */ + @Override + public int hashCode() { + return Objects.hashCode(templateAttribute) + Objects.hashCode(preparer) + + Objects.hashCode(attributes) + + Objects.hashCode(cascadedAttributes); + } + + /** + * Inherits the parent template attribute. + * + * @param parentTemplateAttribute The parent template attribute. + */ + private void inheritParentTemplateAttribute( + Attribute parentTemplateAttribute) { + if (parentTemplateAttribute != null) { + if (templateAttribute == null) { + templateAttribute = new Attribute(parentTemplateAttribute); + } else { + templateAttribute.inherit(parentTemplateAttribute); + } + } + } + + /** + * Copies a BasicAttributeContext in an easier way. + * + * @param context The context to copy. + */ + private void copyBasicAttributeContext(BasicAttributeContext context) { + Attribute parentTemplateAttribute = context.getTemplateAttribute(); + if (parentTemplateAttribute != null) { + this.templateAttribute = new Attribute(parentTemplateAttribute); + } + preparer = context.preparer; + if (context.attributes != null && !context.attributes.isEmpty()) { + attributes = deepCopyAttributeMap(context.attributes); + } + if (context.cascadedAttributes != null && !context.cascadedAttributes.isEmpty()) { + cascadedAttributes = deepCopyAttributeMap(context.cascadedAttributes); + } + } + + /** + * Adds missing attributes to the destination map. + * + * @param source The source attribute map. + * @param destination The destination attribute map. + * @return The destination attribute map if not null, a new one otherwise. + */ + private Map addMissingAttributes(Map source, Map destination) { + if (source != null && !source.isEmpty()) { + if (destination == null) { + destination = new HashMap<>(); + } + for (Map.Entry entry : source.entrySet()) { + String key = entry.getKey(); + Attribute destAttribute = destination.get(key); + if (destAttribute == null) { + destination.put(key, entry.getValue()); + } else if (destAttribute instanceof ListAttribute + && entry.getValue() instanceof ListAttribute + && ((ListAttribute) destAttribute).isInherit()) { + ((ListAttribute) destAttribute) + .inherit((ListAttribute) entry.getValue()); + } + } + } + + return destination; + } + + /** + * Deep copies the attribute map, by creating clones (using copy + * constructors) of the attributes. + * + * @param attributes The attribute map to copy. + * @return The copied map. + */ + private Map deepCopyAttributeMap(Map attributes) { + Map retValue = new HashMap<>(attributes.size()); + for (Map.Entry entry : attributes.entrySet()) { + Attribute toCopy = entry.getValue(); + if (toCopy != null) { + retValue.put(entry.getKey(), toCopy.copy()); + } + } + return retValue; + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/api/Definition.java b/plugins/tiles/src/main/java/org/apache/tiles/api/Definition.java new file mode 100644 index 000000000..54ac5e035 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/api/Definition.java @@ -0,0 +1,165 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.api; + +import java.util.Map; +import java.util.Objects; + +/** + * A definition, i.e. a template with (completely or not) filled attributes. + * Attributes of a template can be defined with the help of this class.
+ * It can be used as a data transfer object used for registering new + * definitions with the Container. + * + * @since Tiles 2.0 + */ +public class Definition extends BasicAttributeContext { + /** + * Extends attribute value. + */ + protected String inherit; + /** + * Definition name. + */ + protected String name = null; + + /** + * Constructor. + */ + public Definition() { + } + + /** + * Copy Constructor. + * Create a new definition initialized with parent definition. + * Do a shallow copy : attributes are shared between copies, but not the Map + * containing attributes. + * + * @param definition The definition to copy. + */ + public Definition(Definition definition) { + super(definition); + this.name = definition.name; + this.inherit = definition.inherit; + } + + /** + * Constructor. + * + * @param name The name of the definition. + * @param templateAttribute The template attribute of the definition. + * @param attributes The attribute map of the definition. + * @since 2.1.2 + */ + public Definition(String name, Attribute templateAttribute, + Map attributes) { + super(attributes); + this.name = name; + this.templateAttribute = templateAttribute; + } + + /** + * Access method for the name property. + * + * @return the current value of the name property + */ + public String getName() { + return name; + } + + /** + * Sets the value of the name property. + * + * @param aName the new value of the name property + */ + public void setName(String aName) { + name = aName; + } + + /** + * Set extends. + * + * @param name Name of the extended definition. + */ + public void setExtends(String name) { + inherit = name; + } + + /** + * Get extends. + * + * @return Name of the extended definition. + */ + public String getExtends() { + return inherit; + } + + + /** + * {@inheritDoc} + */ + @Override + public boolean equals(Object obj) { + if (obj == null) { + return false; + } + if (!(obj instanceof Definition)) { + return false; + } + Definition def = (Definition) obj; + return Objects.equals(name, def.name) && Objects.equals(inherit, def.inherit) && super.equals(def); + } + + /** + * {@inheritDoc} + */ + @Override + public int hashCode() { + return Objects.hashCode(name) + Objects.hashCode(inherit) + super.hashCode(); + } + + /** + * Get extends flag. + * + * @return true if this definition extends another. + */ + public boolean isExtending() { + return inherit != null; + } + + /** + * Returns a description of the attributes. + * + * @return A string representation of the content of this definition. + */ + @Override + public String toString() { + return "{name=" + + name + + ", template=" + + (templateAttribute != null ? templateAttribute.getValue() : "") + + ", role=" + + (templateAttribute != null ? templateAttribute.getRoles() : "") + + ", preparerInstance=" + + preparer + + ", attributes=" + + attributes + + "}"; + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/api/Expression.java b/plugins/tiles/src/main/java/org/apache/tiles/api/Expression.java new file mode 100644 index 000000000..38d152ccb --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/api/Expression.java @@ -0,0 +1,165 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tiles.api; + +import java.util.Objects; + +/** + * It is an expression, along with the expression language (e.g. EL, MVEL, OGNL) + * it is expressed with. + * + * @since 2.2.0 + */ +public class Expression { + + /** + * The expression itself. + */ + private final String expression; + + /** + * The language of the expression. + */ + private final String language; + + /** + * Constructor. + * + * @param expression The expression itself. + * @param language The language of the expression. + * @since 2.2.0 + */ + public Expression(String expression, String language) { + this.expression = expression; + this.language = language; + } + + /** + * Constructor, using the default (i.e. null) language. + * + * @param expression The expression itself. + * @since 2.2.0 + */ + public Expression(String expression) { + this(expression, null); + } + + /** + * Copy constructor. + * + * @param toCopy The expression to copy. + * @since 2.2.0 + */ + public Expression(Expression toCopy) { + this.expression = toCopy.expression; + this.language = toCopy.language; + } + + /** + * Creates an Expression object from a string in the form + * LANGUAGE:EXPRESSION. + * + * @param describedExpression The expression in the form + * LANGUAGE:EXPRESSION. The LANGUAGE part should be expressed + * only with letters and numbers. + * @return The created object, or null if the expression is null. + * @since 2.2.0 + */ + public static Expression createExpressionFromDescribedExpression(String describedExpression) { + if (describedExpression != null) { + String language = null; + String expression = describedExpression; + if (describedExpression.matches("[a-zA-Z0-9]+:.+")) { + language = describedExpression.substring(0, describedExpression.indexOf(':')); + expression = describedExpression.substring(describedExpression.indexOf(':') + 1); + } + return new Expression(expression, language); + } + + return null; + } + + /** + * Creates an Expression object from the expression and its language. + * + * @param expression The expression itself. + * @param language The language of the expression. + * @return The created object, or null if the expression is null. + * @since 2.2.0 + */ + public static Expression createExpression(String expression, String language) { + if (expression != null) { + return new Expression(expression, language); + } + + return null; + } + + /** + * Returns the expression string. + * + * @return The expression itself. + * @since 2.2.0 + */ + public String getExpression() { + return expression; + } + + /** + * Returns the language in which the expression is expressed. + * + * @return The expression language. + * @since 2.2.0 + */ + public String getLanguage() { + return language; + } + + /** + * {@inheritDoc} + */ + @Override + public boolean equals(Object obj) { + if (obj == null) { + return false; + } + if (!(obj instanceof Expression)) { + return false; + } + Expression exp = (Expression) obj; + return Objects.equals(expression, exp.expression) && Objects.equals(language, exp.language); + } + + /** + * {@inheritDoc} + */ + @Override + public int hashCode() { + return Objects.hashCode(expression) + Objects.hashCode(language); + } + + /** + * {@inheritDoc} + */ + @Override + public String toString() { + return (language == null ? "DEFAULT" : language) + ":" + expression; + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/api/ListAttribute.java b/plugins/tiles/src/main/java/org/apache/tiles/api/ListAttribute.java new file mode 100644 index 000000000..67b329443 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/api/ListAttribute.java @@ -0,0 +1,169 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.api; + +import java.util.ArrayList; +import java.util.List; + +/** + * An attribute as a List. + * This attribute associates a name with a list. The list can be found by the + * property name. + * Elements in list are retrieved using List methods. + * This class is used to read configuration files. + * + * @since 2.1.0 + */ +public class ListAttribute extends Attribute { + + /** + * If true, the attribute will put the elements of the attribute with the + * same name of the parent definition before the ones specified here. By + * default, it is 'false'. + */ + private boolean inherit = false; + + /** + * Constructor. + * + * @since 2.1.0 + */ + public ListAttribute() { + setValue(new ArrayList()); + } + + /** + * Copy constructor. + * + * @param toCopy The list attribute to copy. + * @since 2.1.3 + */ + public ListAttribute(ListAttribute toCopy) { + super(toCopy); + List attributesToCopy = toCopy.getValue(); + if (attributesToCopy != null) { + List attributes = new ArrayList<>(attributesToCopy.size()); + for (Attribute attribute : attributesToCopy) { + if (attribute != null) { + attributes.add(attribute.copy()); + } else { + attributes.add(null); + } + } + setValue(attributes); + } + this.inherit = toCopy.inherit; + } + + /** + * Sets the list of the attributes that are elements of this attribute. + * + * @param attributes The attributes. + * @since 3.0.0 + */ + public void setValue(List attributes) { + super.setValue(attributes); + } + + /** + * Returns the list of the attributes that are elements of this attribute. + * + * @return The attributes. + * @since 3.0.0 + */ + @SuppressWarnings("unchecked") + @Override + public List getValue() { + return (List) super.getValue(); + } + + /** + * Add an element in list. + * We use a property to avoid rewriting a new class. + * + * @param element XmlAttribute to add. + * @since 2.1.0 + */ + public void add(Attribute element) { + getValue().add(element); + } + + /** + * If true, the attribute will put the elements of the attribute with the + * same name of the parent definition before the ones specified here. By + * default, it is 'false' + * + * @param inherit The "inherit" value. + * @since 2.1.0 + */ + public void setInherit(boolean inherit) { + this.inherit = inherit; + } + + /** + * If true, the attribute will put the elements of the attribute with the + * same name of the parent definition before the ones specified here. By + * default, it is 'false' + * + * @return inherit The "inherit" value. + * @since 2.1.0 + */ + public boolean isInherit() { + return inherit; + } + + /** + * Inherits elements present in a "parent" list attribute. The elements will + * be put before the ones already present. + * + * @param parent The parent list attribute. + * @since 2.1.0 + */ + public void inherit(ListAttribute parent) { + List tempList = new ArrayList<>(); + tempList.addAll(parent.getValue()); + tempList.addAll(getValue()); + setValue(tempList); + } + + /** {@inheritDoc} */ + @Override + public boolean equals(Object obj) { + if (obj == null) { + return false; + } + if (!(obj instanceof ListAttribute)) { + return false; + } + ListAttribute attribute = (ListAttribute) obj; + return super.equals(attribute) && this.inherit == attribute.inherit; + } + + /** {@inheritDoc} */ + @Override + public int hashCode() { + return super.hashCode() + Boolean.valueOf(inherit).hashCode(); + } + + /** {@inheritDoc} */ + @Override + public ListAttribute copy() { + return new ListAttribute(this); + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/api/NoSuchContainerException.java b/plugins/tiles/src/main/java/org/apache/tiles/api/NoSuchContainerException.java new file mode 100644 index 000000000..6d6d19307 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/api/NoSuchContainerException.java @@ -0,0 +1,38 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.api; + +/** + * Indicates that a keyed container has not been found. + * + * @since 2.1.0 + */ +public class NoSuchContainerException extends TilesException { + + /** + * Constructor. + * + * @param message The detail message. + * @since 2.1.0 + */ + public NoSuchContainerException(String message) { + super(message); + } + +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/api/TilesContainer.java b/plugins/tiles/src/main/java/org/apache/tiles/api/TilesContainer.java new file mode 100644 index 000000000..00afe9dac --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/api/TilesContainer.java @@ -0,0 +1,137 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.api; + +import org.apache.tiles.request.ApplicationContext; +import org.apache.tiles.request.Request; + +import java.io.IOException; + +/** + * An encapsulation of the Tiles framework. This interface is + * used to expose tiles features to frameworks which leverage + * it as a plugin. It can alternately be used by web applications + * which would like a programmatic interface. + * + * @since 2.0 + */ +public interface TilesContainer { + + /** + * Retrieve the container's context. + * + * @return current application context + */ + ApplicationContext getApplicationContext(); + + /** + * Retrieve the attribute context of the current request. + * @param request The request. + * @return map of the attributes in the current attribute context. + */ + AttributeContext getAttributeContext(Request request); + + /** + * Starts a new context, where attribute values are stored independently of others.
+ * When the use of the contexts is finished, call{@link TilesContainer#endContext(Request)} + * + * @param request The request. + * @return The newly created context. + */ + AttributeContext startContext(Request request); + + /** + * Ends a context, where attribute values are stored independently of others.
+ * It must be called after a {@link TilesContainer#startContext(Request)} call. + * + * @param request The request. + */ + void endContext(Request request); + + /** + * Renders the current context, as it is. + * @param request The request. + * + * @since 2.1.0 + */ + void renderContext(Request request); + + /** + * Executes a preparer. + * + * @param preparer The name of the preparer to execute. + * @param request The request. + */ + void prepare(String preparer, Request request); + + /** + * Render the given tiles request. + * + * @param definition the current definition. + * @param request The request. + */ + void render(String definition, Request request); + + /** + * Renders the specified definition. + * @param definition The definition to render. + * @param request The request context. + */ + void render(Definition definition, Request request); + + /** + * Render the given Attribute. + * + * @param attribute The attribute to render. + * @param request The request. + * @throws IOException If something goes wrong during writing to the output. + * @since 2.1.2 + */ + void render(Attribute attribute, Request request) + throws IOException; + + /** + * Evaluates the given attribute. + * + * @param attribute The attribute to evaluate. + * @param request The request. + * @return The evaluated object. + * @since 2.1.0 + */ + Object evaluate(Attribute attribute, Request request); + + /** + * Returns a definition specifying its name. + * + * @param definitionName The name of the definition to find. + * @param request The request context. + * @return The definition, if found. + */ + Definition getDefinition(String definitionName, + Request request); + + /** + * Determine whether the definition exists. + * + * @param definition the name of the definition. + * @param request The request. + * @return true if the definition is found. + */ + boolean isValidDefinition(String definition, Request request); +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/api/TilesContainerWrapper.java b/plugins/tiles/src/main/java/org/apache/tiles/api/TilesContainerWrapper.java new file mode 100644 index 000000000..e8707e34f --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/api/TilesContainerWrapper.java @@ -0,0 +1,107 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.api; + +import org.apache.tiles.request.ApplicationContext; +import org.apache.tiles.request.Request; + +import java.io.IOException; + +/** + * Wraps a Tiles container to allow easy decoration. + */ +public class TilesContainerWrapper implements TilesContainer { + + /** + * The container to wrap. + */ + protected TilesContainer container; + + /** + * Constructor. + * + * @param container The container to wrap. + */ + public TilesContainerWrapper(TilesContainer container) { + this.container = container; + if (container == null) { + throw new NullPointerException("The wrapped container must be not null"); + } + } + + @Override + public void endContext(Request request) { + container.endContext(request); + } + + @Override + public Object evaluate(Attribute attribute, Request request) { + return container.evaluate(attribute, request); + } + + @Override + public ApplicationContext getApplicationContext() { + return container.getApplicationContext(); + } + + @Override + public AttributeContext getAttributeContext(Request request) { + return container.getAttributeContext(request); + } + + @Override + public Definition getDefinition(String definitionName, Request request) { + return container.getDefinition(definitionName, request); + } + + @Override + public boolean isValidDefinition(String definition, Request request) { + return container.isValidDefinition(definition, request); + } + + @Override + public void prepare(String preparer, Request request) { + container.prepare(preparer, request); + } + + @Override + public void render(String definition, Request request) { + container.render(definition, request); + } + + @Override + public void render(Definition definition, Request request) { + container.render(definition, request); + } + + @Override + public void render(Attribute attribute, Request request) throws IOException { + container.render(attribute, request); + } + + @Override + public void renderContext(Request request) { + container.renderContext(request); + } + + @Override + public AttributeContext startContext(Request request) { + return container.startContext(request); + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/api/TilesException.java b/plugins/tiles/src/main/java/org/apache/tiles/api/TilesException.java new file mode 100644 index 000000000..520c24419 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/api/TilesException.java @@ -0,0 +1,66 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.api; + +/** + * Root class for all Tiles-exceptions. + */ +public class TilesException extends RuntimeException { + + /** + * Constructor. + */ + public TilesException() { + } + + /** + * Constructor. + * + * @param message The error or warning message. + */ + public TilesException(String message) { + super(message); + } + + /** + * Create a new TilesException wrapping an existing exception. + *

+ *

The existing exception will be embedded in the new + * one, and its message will become the default message for + * the TilesException.

+ * + * @param e The cause to be wrapped. + */ + public TilesException(Throwable e) { + super(e); + } + + /** + * Create a new TilesException from an existing exception. + *

+ *

The existing exception will be embedded in the new + * one, but the new exception will have its own message.

+ * + * @param message The detail message. + * @param e The cause to be wrapped. + */ + public TilesException(String message, Throwable e) { + super(message, e); + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/api/access/TilesAccess.java b/plugins/tiles/src/main/java/org/apache/tiles/api/access/TilesAccess.java new file mode 100644 index 000000000..81cf48864 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/api/access/TilesAccess.java @@ -0,0 +1,158 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.api.access; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.apache.tiles.api.NoSuchContainerException; +import org.apache.tiles.api.TilesContainer; +import org.apache.tiles.request.ApplicationContext; +import org.apache.tiles.request.Request; + +import java.util.Map; + +/** + * Provides static access to the Tiles container. + */ +public final class TilesAccess { + + private static final Logger LOG = LogManager.getLogger(TilesAccess.class); + + /** + * Name of the attribute used to store the current used container. + */ + public static final String CURRENT_CONTAINER_ATTRIBUTE_NAME = + "org.apache.tiles.servlet.context.ServletTilesRequestContext.CURRENT_CONTAINER_KEY"; + + /** + * Constructor, private to avoid instantiation. + */ + private TilesAccess() { + } + + /** + * The name of the attribute to use when getting and setting the container + * object in a context. + */ + public static final String CONTAINER_ATTRIBUTE = + "org.apache.tiles.CONTAINER"; + + /** + * Configures the container to be used in the application. + * + * @param context The Tiles application context object to use. + * @param container The container object to set. + * @param key The key under which the container will be stored. + * @since 2.1.2 + */ + public static void setContainer(ApplicationContext context, TilesContainer container, String key) { + if (key == null) { + key = CONTAINER_ATTRIBUTE; + } + + if (container == null) { + LOG.info("Removing TilesContext for context: {}", context.getClass().getName()); + context.getApplicationScope().remove(key); + } else { + LOG.info("Publishing TilesContext for context: {}", context.getClass().getName()); + context.getApplicationScope().put(key, container); + } + } + + /** + * Returns default the container to be used in the application. + * + * @param context The Tiles application context object to use. + * @return The default container object. + * @since 3.0.0 + */ + public static TilesContainer getContainer(ApplicationContext context) { + return getContainer(context, CONTAINER_ATTRIBUTE); + } + + /** + * Returns the container to be used in the application registered under a specific key. + * + * @param context The Tiles application context object to use. + * @param key The key under which the container will be stored. + * @return The container object. + * @since 3.0.0 + */ + public static TilesContainer getContainer(ApplicationContext context, + String key) { + if (key == null) { + key = CONTAINER_ATTRIBUTE; + } + + return (TilesContainer) context.getApplicationScope().get(key); + } + + /** + * Sets the current container to use in web pages. + * + * @param request The request to use. + * @param key The key under which the container is stored. + * @since 2.1.0 + */ + public static void setCurrentContainer(Request request, + String key) { + ApplicationContext applicationContext = request.getApplicationContext(); + TilesContainer container = getContainer(applicationContext, key); + if (container != null) { + request.getContext("request").put(CURRENT_CONTAINER_ATTRIBUTE_NAME, container); + } else { + throw new NoSuchContainerException("The container with the key '" + + key + "' cannot be found"); + } + } + + /** + * Sets the current container to use in web pages. + * + * @param request The request to use. + * @param container The container to use as the current container. + * @since 2.1.0 + */ + public static void setCurrentContainer(Request request, TilesContainer container) { + if (container != null) { + request.getContext("request").put(CURRENT_CONTAINER_ATTRIBUTE_NAME, container); + } else { + throw new NullPointerException("The container cannot be null"); + } + } + + /** + * Returns the current container that has been set, or the default one. + * + * @param request The request to use. + * @return The current Tiles container to use in web pages. + * @since 2.1.0 + */ + public static TilesContainer getCurrentContainer(Request request) { + ApplicationContext context = request.getApplicationContext(); + Map requestScope = request.getContext("request"); + TilesContainer container = (TilesContainer) requestScope.get(CURRENT_CONTAINER_ATTRIBUTE_NAME); + if (container == null) { + container = getContainer(context); + requestScope.put(CURRENT_CONTAINER_ATTRIBUTE_NAME, container); + } + + return container; + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/api/access/package-info.java b/plugins/tiles/src/main/java/org/apache/tiles/api/access/package-info.java new file mode 100644 index 000000000..f6090a574 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/api/access/package-info.java @@ -0,0 +1,23 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +/** + * Tiles access package. Utility classes to access Tiles funcionality from an application. + */ +package org.apache.tiles.api.access; + diff --git a/plugins/tiles/src/main/java/org/apache/tiles/api/mgmt/MutableTilesContainer.java b/plugins/tiles/src/main/java/org/apache/tiles/api/mgmt/MutableTilesContainer.java new file mode 100644 index 000000000..5348f239c --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/api/mgmt/MutableTilesContainer.java @@ -0,0 +1,39 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.api.mgmt; + +import org.apache.tiles.api.Definition; +import org.apache.tiles.api.TilesContainer; +import org.apache.tiles.request.Request; + +/** + * Defines a mutable version of the TilesContainer. + * + * @since Tiles 2.0 + */ +public interface MutableTilesContainer extends TilesContainer { + + /** + * Register a new definition with the container. + * + * @param definition The definition to register. + * @param request TODO + */ + void register(Definition definition, Request request); +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/api/mgmt/package-info.java b/plugins/tiles/src/main/java/org/apache/tiles/api/mgmt/package-info.java new file mode 100644 index 000000000..8a22e1cb5 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/api/mgmt/package-info.java @@ -0,0 +1,24 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +/** + * Classes and interfaces to be used when it is needed to create Tiles definitions + * during the execution of the application. + */ +package org.apache.tiles.api.mgmt; + diff --git a/plugins/tiles/src/main/java/org/apache/tiles/api/package-info.java b/plugins/tiles/src/main/java/org/apache/tiles/api/package-info.java new file mode 100644 index 000000000..f19af6def --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/api/package-info.java @@ -0,0 +1,385 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +/** + * The Tiles taglib and framework allows building web pages by assembling reusable + pieces of pages, called Tiles. A Tiles is usually a simple JSP page. + +
+

Introduction

+ +

The Tiles framework allows building pages by assembling reusable Tiles. + As an example, the page in the next figure can be build by assembling a + header, a footer, a menu and a body.

+ +

doc-files/image001

+ +

Each Tiles (header, menu, body, ...) is a JSP page and can itself be build + by assembling other Tiles.

+ +

Using Tiles can be compared as using Java methods: You need to define the Tiles (the method body), and then you + can "call" this body anywhere you want, passing it some parameters. In Tiles, parameters are called + "attributes" in order to avoid confusion with the request parameters.

+ +

The Tiles body can be a simple JSP page, a Struts action or any URI pointing + to a resource inside the current web site.

+ +

Inserting the body, or calling it, is done with the tag <tiles:insert + ...> anywhere in a JSP page. Insertion can also be done by specifying + a definition name as the path of a Struts forward or as input, + forward or include attributes of a Struts action.

+ +

Tiles bodies are used to create layouts, reusable parts, ... Tiles insertions + are used to insert Tiles. The same Tiles can be reused several times in + the same site, or even in the same page.

+ +

Insertion of a Tiles body can be associated to a logical name in what Tiles calls a "definition". A + definition contains a logical name, a page used as body and some attribute values. The definition declaration + doesn't insert the associated Tiles body. It just associates it with the name. A definition name can be used + anywhere insertion of a Tiles body can occur. The associated Tiles body is then inserted with associated + attributes.

+ +

The definition declarations can be done in JSP pages or in one or more + centralized files. A definition can extend another one, overload some attributes, + add new attributes ... This allows the declaration of a "master" definition + declaring the common layout, header, menu and footer. All other definitions + extend this master layout thereby making it possible to change the entire + site look & feel simply by changing the master definition.

+
+
+

Simple Examples

+ +
+

Insert a JSP page

+
<tiles:insert page="/layouts/commonLayout.jsp" flush="true" />
+ 
+

This example inserts the specified page in place of the tag. The page attribute is any valid URL pointing to + a resource inside the current site.

+
+
+ + +

Insert a Tiles passing some attributes

+
+ <tiles:insert page="/layouts/classicLayout.jsp" flush=&quot;true">
+ <tiles:put name="title"  value="Page Title" />
+ <tiles:put name="header" value="/common/header.jsp" />
+ <tiles:put name="footer" value="/common/footer.jsp" />
+ <tiles:put name="menu"   value="/common/menu.jsp" />
+ <tiles:put name="body"   value="/tiles/mainBody.jsp" />
+ </tiles:insert>
+ 
+

This example inserts the specified page, passing it the attributes. Attributes + are stored in a Tiles context which is passed to the inserted pag and + can then be accesssed by their names.

+
+
+

Retrieve an attribute value as String

+
+ <tiles:getAsString name="title" />
+ 
+

This example retrieves the value of the attribute "title" and prints it as a String in the current + output stream. The method toString() is applied on the attribute value, allowing to pass any kind of object + as value.

+
+
+

Insert Tiles referenced by an attribute

+
+ <tiles:insert attribute='menu' />
+ 
+

This inserts the Tiles referenced by the attribute "menu" value. The + specified attribute value is first retrieved from current Tiles's context, + and then the value is used as a page target to insert.

+
+
+

Classic Layout

+ +

This example is a layout assembling a page in the classic header-footer-menu-body + fashion.

+
+ <%@ taglib uri="http://tiles.apache.org/tags-tiles" prefix="tiles" %>
+ <HTML>
+ <HEAD>
+ <link rel="stylesheet" href="<%=request.getContextPath()%>/layouts/stylesheet.css"
+ type="text/css"/>
+ <title><tiles:getAsString name="title"/></title>
+ </HEAD>
+ <body>
+ <table border="0" width="100%" cellspacing="5">
+ <tr>
+ <td colspan="2"><tiles:insert attribute="header" /></td>
+ </tr>
+ <tr>
+ <td width="140" valign="top">
+ <tiles:insert attribute='menu' />
+ </td>
+ <td valign="top"  align="left">
+ <tiles:insert attribute='body' />
+ </td>
+ </tr>
+ <tr>
+ <td colspan="2">
+ <tiles:insert attribute="footer" />
+ </td>
+ </tr>
+ </table>
+ </body>
+ </html>
+ 
+

The layout is declared in a JSP page (ex: /layouts/classicLayout.jsp). + It can be used in conjunction with the tag described in "Insert + a page passing some attributes".

+
+
+
+

Definitions

+ +

A definition associates a logical name with the URL of a Tiles to be inserted + and some attribute values. A definition doesn't insert the Tiles. This is + done later using the definition name. A definition name can be inserted + as often as you want in your site, making it easy to reuse a Tiles.

+ +

A definition can extend another definition and overload some attributes + or add new ones. This makes easy factorization of definitions differing + by some attributes. For example, you can define a master definition declaring + the main header, menu, footer, and a default title. Then let each of your + page definitions extend this master definition and overload the title and + the body.

+ +

Definitions can be declared in a JSP page, or in one or more centralized + files. To enable the definitions from centralized files, you need to initialize + the "definitions factory&&quot; which will parse the definitions from the files + and provide them to the Tiles framework.

+ +
+

Enabling Definition Factory

+ +

To enable Tiles definitions described in one or more files, you need to write these files and to initialize the + definition factory.

+ +

Initialization is different depending on the Struts version you use, + or if you do not use Struts at all.

+ +
+

Struts1.1

+ +

Use the Tiles plug-in to enable Tiles definitions. This plug-in creates + the definition factory and passese it a configuration object populated + with parameters. Parameters can be specified in the web.xml file or + as plug-in parameters. The plug-in first reads parameters from web.xml, + and then overloads them with the ones found in the plug-in. All parameters + are optional and can be omitted. The plug-in should be declared in each + struts-config file:

+
+ <plug-in className=&&quot;org.apache.struts.tiles.TilesPlugin&&quot; >
+ <set-property property=&&quot;definitions-config&&quot;
+ value=&&quot;/WEB-INF/tiles-defs.xml,
+ /WEB-INF/tiles-tests-defs.xml,/WEB-INF/tiles-tutorial-defs.xml,
+ /WEB-INF/tiles-examples-defs.xml&&quot; />
+ <set-property property=&&quot;moduleAware&&quot; value=&&quot;true&&quot; />
+ <set-property
+ property=&&quot;org.apache.tiles.definition.digester.DigesterDefinitionsReader.PARSER_VALIDATE&&quot;
+ value=&&quot;true&&quot; />
+ </plug-in>
+ 
+
    +
  • definitions-config: (optional) +
      +
    • Specify configuration file names. There can be several comma separated file names (default: ?? ) +
    • +
    +
  • +
  • org.apache.tiles.definition.digester.DigesterDefinitionsReader.PARSER_VALIDATE: (optional) +
      +
    • Specify if XML parser should validate the Tiles configuration + file +
        +
      • true : validate. DTD should be specified in file header (default)
      • +
      • false : no validation
      • + +
      +
    • +
    +
  • + +
  • moduleAware: (optional) +
      +
    • Specify if the Tiles definition factory is module aware. If true (default), + there will be one factory for each Struts module. + If false, there will be one common factory for all module. In this later case, + it is still needed to declare one plugin per module. The factory will be + initialized with parameters found in the first initialized plugin (generally the + one associated with the default module). +
        +
      • true : Tiles framework is module aware
      • +
      • false :Tiles framework has one single factoy shared among modules (default)
      • +
      +
    • +
    +
  • + +
  • tilesUtilImplClassname: (optional - for advanced user) +
      +
    • Specify The classname of the TilesUtil implementation to use. The specified class should + be a subclass of TilesUtilStrutsImpl. This option disable the moduleAware option. +
      Specifying &&"TilesUtilStrutsImpl&&" is equivalent to moduleAware = + false. +
      Specifying &&"TilesUtilStrutsModuleImpl&&" is equivalent to moduleAware + = true. + This option is taken into account only once, when it is first encountered. To avoid problems, + it is advice to specify the same values in all TilesPlugin declaration. +
    • +
    +
  • + +
+

The TilesPlugin class creates one definition factory for each struts module. +

+ +

+ If the flag moduleAware is false, only one shared factory is created for all modules. + In this later case, the factory is initialized with parameters found in the first plugin. + The plugins should be declared in all modules, and the moduleAware flag should be + the same for the entire application.

+ +

+ Paths found in Tiles definitions are relative to the main context.

+ +

You don't need to specify a TilesRequestProcessor, this is automatically + done by the plug-in. If, however, you want to specify your own RequestProcessor, + it should extend the TilesRequestProcessor. The plug-in checks this + constraint.

+
+
+

Struts1.0.x

+ +

You need to use a special servlet extending the Struts servlet. This is specified in the web.xml file of your + application:

+
+ <servlet>
+ <servlet-name>action</servlet-name>
+ <servlet-class>org.apache.tiles.web.startup.TilesServlet</servlet-class>
+ <!-- Tiles Servlet parameter
+ Specify configuration file names. There can be several comma
+ separated file names
+ -->
+ <init-param>
+ <param-name>definitions-config</param-name>
+ <param-value>/WEB-INF/tiles-defs.xml</param-value>
+ </init-param>
+ <!-- Tiles Servlet parameter
+ Specify if XML parser should validate the Tiles configuration file(s).
+ true : validate. DTD should be specified in file header.
+ false : no validation
+ -->
+ <init-param>
+ <param-name>org.apache.tiles.definition.digester.DigesterDefinitionsReader.PARSER_VALIDATE</param-name>
+ <param-value>true</param-value>
+ </init-param>
+ ...
+ </servlet>
+ 
+
+
+

Without Struts

+ +

Tiles can be used without Struts. To initialize the definition factory, you can use the provided servlet. Declare + it in the web.xml file of your application:

+
+ <servlet>
+ <servlet-name>action</servlet-name>
+ <servlet-class>org.apache.struts.tiles.TilesServlet</servlet-class>
+
+
+ <init-param>
+ <param-name>definitions-config</param-name>
+ <param-value>/WEB-INF/tiles-defs.xml</param-value>
+ </init-param>
+ <init-param>
+ <param-name>org.apache.tiles.definition.digester.DigesterDefinitionsReader.PARSER_VALIDATE</param-name>
+ <param-value>true</param-value>
+ </init-param>
+ ...
+ 
+

The parameters are the same as for Struts1.1 or 1.0.

+
+
+
+

Definition File Syntax

+ +

The definition file syntax can be found in the + tiles-config_2_0.dtd file. +

+ +

Following is a simple example:

+
+ <!DOCTYPE tiles-definitions PUBLIC
+ &&quot;-//Apache Software Foundation//DTD Tiles Configuration//EN&&quot;
+ &&quot;http://tiles.apache.org/dtds/tiles-config_2_0.dtd&&quot;>
+
+ <!-- Definitions for Tiles documentation   -->
+ <tiles-definitions>
+
+ <!-- ========================================================== -->
+ <!-- Master definition                                          -->
+ <!-- ========================================================== -->
+ <!-- Main page layout used as a root for other page definitions -->
+
+ <definition name=&&quot;site.mainLayout&&quot;
+   template=&&quot;/layouts/classicLayout.jsp&&quot;>
+ <put name=&&quot;title&&quot;  value=&&quot;Tiles Blank Site&&quot; />
+ <put name=&&quot;header&&quot; value=&&quot;/tiles/common/header.jsp&&quot; />
+ <put name=&&quot;menu&&quot;   value=&&quot;site.menu.bar&&quot; />
+ <put name=&&quot;footer&&quot; value=&&quot;/tiles/common/footer.jsp&&quot; />
+ <put name=&&quot;body&&quot;   value=&&quot;/tiles/body.jsp&&quot; />
+ </definition>
+
+ <!-- ========================================================== -->
+ <!-- Index page definition                                      -->
+ <!-- ========================================================== -->
+ <!-- This definition inherits from the main definition.
+ It overloads the page title and the body used.
+ Use the same mechanism to define new pages sharing common
+ properties (here header, menu, footer, layout)
+ -->
+
+ <definition name=&&quot;site.index.page&&quot;
+   extends=&&quot;site.mainLayout&&quot; >
+ <put name=&&quot;title&&quot;  value=&&quot;Tiles Blank Site Index&&quot; />
+ <put name=&&quot;body&&quot;   value=&&quot;/tiles/body.jsp&&quot; />
+ </definition>
+
+ </tiles-definition>
+ 
+
+
+

Debugging

+ +

To debug a page made of Tiles, you can use following advices:

+
    +
  • Check each Tiles separatly. Try to access nested Tiles directly to test + if thes work properly. +
  • +
  • Enable Tiles logging. See the commons-logging package help.
  • +
+
+
+ + */ +package org.apache.tiles.api; + diff --git a/plugins/tiles/src/main/java/org/apache/tiles/api/preparer/PreparerException.java b/plugins/tiles/src/main/java/org/apache/tiles/api/preparer/PreparerException.java new file mode 100644 index 000000000..87ba1f1f3 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/api/preparer/PreparerException.java @@ -0,0 +1,67 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.api.preparer; + +import org.apache.tiles.api.TilesException; + +/** + *

+ * Thrown when an exception occurs while processing + * a prepare request. + *

+ * + * @since Tiles 2.0 + */ +public class PreparerException extends TilesException { + + /** + * Constructor. + */ + public PreparerException() { + super(); + } + + /** + * Constructor. + * + * @param e The cause exception. + */ + public PreparerException(Throwable e) { + super(e); + } + + /** + * Constructor. + * + * @param message The message to include. + */ + public PreparerException(String message) { + super(message); + } + + /** + * Constructor. + * + * @param message The message to include. + * @param e The cause exception. + */ + public PreparerException(String message, Throwable e) { + super(message, e); + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/api/preparer/ViewPreparer.java b/plugins/tiles/src/main/java/org/apache/tiles/api/preparer/ViewPreparer.java new file mode 100644 index 000000000..9abf720a6 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/api/preparer/ViewPreparer.java @@ -0,0 +1,54 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.api.preparer; + +import org.apache.tiles.api.AttributeContext; +import org.apache.tiles.request.Request; + +/** + *

+ * Executed prior to rendering a view. + *

+ * + *

+ * A view preparer is typically used to provide last minute + * translations of the data within the attribute context. + * A preparer is not intended to replace the controller within an + * MVC architecture. + *

+ * + * See + *
    + *
  • <insert>
  • + *
  • <definition>
  • + *
> + */ +public interface ViewPreparer { + + /** + * Method associated to a tile and called immediately before the tile + * is included. + * + * @param tilesContext Current tiles application context. + * @param attributeContext Current tile context. + * @throws PreparerException If something goes wrong during execution. + */ + void execute(Request tilesContext, + AttributeContext attributeContext); +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/api/preparer/package-info.java b/plugins/tiles/src/main/java/org/apache/tiles/api/preparer/package-info.java new file mode 100644 index 000000000..a8fcab1fd --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/api/preparer/package-info.java @@ -0,0 +1,26 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +/** + * "View preparers" are objects that allows the "preparation" of a Tiles artifact + * (definition, template or attribute) before it is rendered.
+ * It is useful, for example, when a view item should be built and stored in a + * particular context (e.g. a menu) and then rendered. + */ +package org.apache.tiles.api.preparer; + diff --git a/plugins/tiles/src/main/java/org/apache/tiles/autotag/core/AutotagRuntimeException.java b/plugins/tiles/src/main/java/org/apache/tiles/autotag/core/AutotagRuntimeException.java new file mode 100644 index 000000000..188dae269 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/autotag/core/AutotagRuntimeException.java @@ -0,0 +1,60 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.autotag.core; + +/** + * Generic exception for Autotag. + */ +public class AutotagRuntimeException extends RuntimeException { + + /** + * Constructor. + */ + public AutotagRuntimeException() { + } + + /** + * Constructor. + * + * @param message The message of the exception. + */ + public AutotagRuntimeException(String message) { + super(message); + } + + /** + * Constructor. + * + * @param cause The cause. + */ + public AutotagRuntimeException(Throwable cause) { + super(cause); + } + + /** + * Constructor. + * + * @param message The message of the exception. + * @param cause The cause. + */ + public AutotagRuntimeException(String message, Throwable cause) { + super(message, cause); + } + +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/autotag/core/runtime/AbstractModelBody.java b/plugins/tiles/src/main/java/org/apache/tiles/autotag/core/runtime/AbstractModelBody.java new file mode 100644 index 000000000..b1a937e73 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/autotag/core/runtime/AbstractModelBody.java @@ -0,0 +1,80 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.autotag.core.runtime; + +import org.apache.tiles.autotag.core.runtime.util.NullWriter; + +import java.io.IOException; +import java.io.StringWriter; +import java.io.Writer; +import java.util.regex.Pattern; + +/** + * Base class for the abstraction of the body. + */ +public abstract class AbstractModelBody implements ModelBody { + + // precompiled the pattern to avoid compiling on every method call + private static final Pattern PATTERN = Pattern.compile("^\\s*$"); + + /** + * The default writer to use. + */ + private final Writer defaultWriter; + + /** + * Constructor. + * + * @param defaultWriter The default writer to use. + */ + public AbstractModelBody(Writer defaultWriter) { + this.defaultWriter = defaultWriter; + } + + @Override + public void evaluate() throws IOException { + evaluate(defaultWriter); + } + + @Override + public String evaluateAsString() throws IOException { + StringWriter writer = new StringWriter(); + try { + evaluate(writer); + } finally { + writer.close(); + } + String body = writer.toString(); + if (body != null) { + body = PATTERN.matcher(body).replaceAll(""); + if (body.length() == 0) { + body = null; + } + } + return body; + } + + @Override + public void evaluateWithoutWriting() throws IOException { + try (NullWriter writer = new NullWriter()) { + evaluate(writer); + } + } + +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/autotag/core/runtime/AutotagRuntime.java b/plugins/tiles/src/main/java/org/apache/tiles/autotag/core/runtime/AutotagRuntime.java new file mode 100644 index 000000000..f95e39d77 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/autotag/core/runtime/AutotagRuntime.java @@ -0,0 +1,49 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.autotag.core.runtime; + +/** + * Builder interface for creating requests. + * The implementations are expected to provide a default constructor, + * and to implement another interface that can be used to provide the + * parameters needed to build the actual request object. + */ +public interface AutotagRuntime { + /** + * Creates a new Request instance. + * + * @return The Request. + */ + R createRequest(); + + /** + * Creates a new ModelBody instance to match the request. + * + * @return The ModelBody. + */ + ModelBody createModelBody(); + + /** + * Extracts a parameter from the tag. + * @param name The name of the parameter. + * @param defaultValue The default value if none is specified. + * @return The value of the parameter. + */ + T getParameter(String name, Class type, T defaultValue); +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/autotag/core/runtime/ModelBody.java b/plugins/tiles/src/main/java/org/apache/tiles/autotag/core/runtime/ModelBody.java new file mode 100644 index 000000000..0f97ec0d0 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/autotag/core/runtime/ModelBody.java @@ -0,0 +1,58 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.autotag.core.runtime; + +import java.io.IOException; +import java.io.Writer; + +/** + * Abstracts a tag/directive body. + */ +public interface ModelBody { + + /** + * Evaluates a body and returns it as a string. + * + * @return The body, as a string. + * @throws IOException If something goes wrong. + */ + String evaluateAsString() throws IOException; + + /** + * Evaluates a body, but discards result. + * + * @throws IOException If something goes wrong. + */ + void evaluateWithoutWriting() throws IOException; + + /** + * Evaluates the body and writes in the default writer. + * + * @throws IOException If something goes wrong. + */ + void evaluate() throws IOException; + + /** + * Evaluates the body and writes the result in the writer. + * + * @param writer The writer to write the result into. + * @throws IOException If something goes wrong. + */ + void evaluate(Writer writer) throws IOException; +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/autotag/core/runtime/annotation/Parameter.java b/plugins/tiles/src/main/java/org/apache/tiles/autotag/core/runtime/annotation/Parameter.java new file mode 100644 index 000000000..8833eddeb --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/autotag/core/runtime/annotation/Parameter.java @@ -0,0 +1,52 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.autotag.core.runtime.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Specifies behaviour for a parameter of the "execute" method of a template class. + */ +@Retention(RetentionPolicy.SOURCE) +@Target(ElementType.PARAMETER) +public @interface Parameter { + + /** + * Indicates to use the parameter name itself for the exported name. + */ + String SAME_NAME = "USE THE SAME NAME"; + + /** + * Returns the name of the exported property name. + */ + String name() default SAME_NAME; + + /** + * Indicates that this parameter is required. + */ + boolean required() default false; + + /** + * Indicates the default value, as it will be written in Java code. + */ + String defaultValue() default "null"; +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/autotag/core/runtime/annotation/package-info.java b/plugins/tiles/src/main/java/org/apache/tiles/autotag/core/runtime/annotation/package-info.java new file mode 100644 index 000000000..2b68de79d --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/autotag/core/runtime/annotation/package-info.java @@ -0,0 +1,22 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +/** + * Annotations to be used in template classes. + */ +package org.apache.tiles.autotag.core.runtime.annotation; diff --git a/plugins/tiles/src/main/java/org/apache/tiles/autotag/core/runtime/package-info.java b/plugins/tiles/src/main/java/org/apache/tiles/autotag/core/runtime/package-info.java new file mode 100644 index 000000000..8d7b72483 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/autotag/core/runtime/package-info.java @@ -0,0 +1,22 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +/** + * Runtime part for all Autotag generated code. + */ +package org.apache.tiles.autotag.core.runtime; diff --git a/plugins/tiles/src/main/java/org/apache/tiles/autotag/core/runtime/util/NullWriter.java b/plugins/tiles/src/main/java/org/apache/tiles/autotag/core/runtime/util/NullWriter.java new file mode 100644 index 000000000..4905e6c63 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/autotag/core/runtime/util/NullWriter.java @@ -0,0 +1,46 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tiles.autotag.core.runtime.util; + +import java.io.Writer; + +/** + * A writer that does not write anything. + */ +public class NullWriter extends Writer { + + /** {@inheritDoc} */ + @Override + public void close() { + // Does nothing + } + + /** {@inheritDoc} */ + @Override + public void flush() { + // Does nothing + } + + /** {@inheritDoc} */ + @Override + public void write(char[] cbuf, int off, int len) { + // Does nothing + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/autotag/core/runtime/util/package-info.java b/plugins/tiles/src/main/java/org/apache/tiles/autotag/core/runtime/util/package-info.java new file mode 100644 index 000000000..76efc98f1 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/autotag/core/runtime/util/package-info.java @@ -0,0 +1,22 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +/** + * Utilities for Autotag core runtime. + */ +package org.apache.tiles.autotag.core.runtime.util; diff --git a/plugins/tiles/src/main/java/org/apache/tiles/autotag/freemarker/FMModelGenerator.java b/plugins/tiles/src/main/java/org/apache/tiles/autotag/freemarker/FMModelGenerator.java new file mode 100644 index 000000000..8c3520e91 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/autotag/freemarker/FMModelGenerator.java @@ -0,0 +1,63 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.autotag.freemarker; + +import java.io.File; +import java.util.Map; + +import org.apache.tiles.autotag.generate.AbstractTemplateClassGenerator; +import org.apache.tiles.autotag.model.TemplateClass; +import org.apache.tiles.autotag.model.TemplateSuite; +import org.apache.velocity.app.VelocityEngine; + +/** + * Generates a single Freemarker directive model, given a template class. + */ +public class FMModelGenerator extends AbstractTemplateClassGenerator { + + /** + * Constructor. + * + * @param velocityEngine The Velocity engine. + */ + public FMModelGenerator(VelocityEngine velocityEngine) { + super(velocityEngine); + } + + @Override + protected String getDirectoryName(File directory, String packageName, + TemplateSuite suite, TemplateClass clazz, Map parameters, + String runtimeClass, String requestClass) { + return packageName.replaceAll("\\.", "/"); + } + + @Override + protected String getFilename(File directory, String packageName, + TemplateSuite suite, TemplateClass clazz, Map parameters, + String runtimeClass, String requestClass) { + return clazz.getTagClassPrefix() + "FMModel.java"; + } + + @Override + protected String getTemplatePath(File directory, String packageName, + TemplateSuite suite, TemplateClass clazz, Map parameters, + String runtimeClass, String requestClass) { + return "/org/apache/tiles/autotag/freemarker/fmModel.vm"; + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/autotag/freemarker/FMModelRepositoryGenerator.java b/plugins/tiles/src/main/java/org/apache/tiles/autotag/freemarker/FMModelRepositoryGenerator.java new file mode 100644 index 000000000..6c045a535 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/autotag/freemarker/FMModelRepositoryGenerator.java @@ -0,0 +1,61 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.autotag.freemarker; + +import java.io.File; +import java.util.Map; + +import org.apache.tiles.autotag.generate.AbstractTemplateSuiteGenerator; +import org.apache.tiles.autotag.model.TemplateSuite; +import org.apache.velocity.app.VelocityEngine; + +/** + * Generates the model repository, given the template suite. + */ +public class FMModelRepositoryGenerator extends AbstractTemplateSuiteGenerator { + + /** + * Constructor. + * + * @param velocityEngine The Velocity engine. + */ + public FMModelRepositoryGenerator(VelocityEngine velocityEngine) { + super(velocityEngine); + } + + @Override + protected String getTemplatePath(File directory, String packageName, + TemplateSuite suite, Map parameters) { + return "/org/apache/tiles/autotag/freemarker/repository.vm"; + } + + @Override + protected String getFilename(File directory, String packageName, + TemplateSuite suite, Map parameters) { + String name = suite.getName(); + return name.substring(0, 1).toUpperCase() + name.substring(1) + "FMModelRepository.java"; + } + + @Override + protected String getDirectoryName(File directory, String packageName, + TemplateSuite suite, Map parameters) { + return packageName.replaceAll("\\.", "/"); + } + +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/autotag/freemarker/FMTemplateGeneratorFactory.java b/plugins/tiles/src/main/java/org/apache/tiles/autotag/freemarker/FMTemplateGeneratorFactory.java new file mode 100644 index 000000000..b13b7a37c --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/autotag/freemarker/FMTemplateGeneratorFactory.java @@ -0,0 +1,69 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.autotag.freemarker; + +import java.io.File; + +import org.apache.tiles.autotag.generate.TemplateGenerator; +import org.apache.tiles.autotag.generate.TemplateGeneratorBuilder; +import org.apache.tiles.autotag.generate.TemplateGeneratorFactory; +import org.apache.velocity.app.VelocityEngine; + +/** + * Creates a template generator that generates code for Freemarker. + */ +public class FMTemplateGeneratorFactory implements TemplateGeneratorFactory { + + /** + * Location of the file. + */ + private File classesOutputDirectory; + + /** + * The Velocity engine. + */ + private VelocityEngine velocityEngine; + + /** + * The template generator builder. + */ + private TemplateGeneratorBuilder templateGeneratorBuilder; + + /** + * Constructor. + * + * @param classesOutputDirectory Directory where code will be placed. + * @param velocityEngine The Velocity engine. + * @param templateGeneratorBuilder The template generator builder. + */ + public FMTemplateGeneratorFactory(File classesOutputDirectory, VelocityEngine velocityEngine, + TemplateGeneratorBuilder templateGeneratorBuilder) { + this.classesOutputDirectory = classesOutputDirectory; + this.velocityEngine = velocityEngine; + this.templateGeneratorBuilder = templateGeneratorBuilder; + } + + @Override + public TemplateGenerator createTemplateGenerator() { + return templateGeneratorBuilder.setClassesOutputDirectory(classesOutputDirectory) + .addClassesTemplateSuiteGenerator(new FMModelRepositoryGenerator(velocityEngine)) + .addClassesTemplateClassGenerator(new FMModelGenerator(velocityEngine)).build(); + } + +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/autotag/freemarker/package-info.java b/plugins/tiles/src/main/java/org/apache/tiles/autotag/freemarker/package-info.java new file mode 100644 index 000000000..f891ee347 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/autotag/freemarker/package-info.java @@ -0,0 +1,24 @@ +/* + * $Id: package-info.java 1044819 2010-12-12 13:29:34Z apetrelli $ + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +/** + * Autotag support for Freemarker. + */ +package org.apache.tiles.autotag.freemarker; diff --git a/plugins/tiles/src/main/java/org/apache/tiles/autotag/generate/AbstractTemplateClassGenerator.java b/plugins/tiles/src/main/java/org/apache/tiles/autotag/generate/AbstractTemplateClassGenerator.java new file mode 100644 index 000000000..009d6d1a5 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/autotag/generate/AbstractTemplateClassGenerator.java @@ -0,0 +1,143 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.autotag.generate; + +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.io.Writer; +import java.util.Map; + +import org.apache.tiles.autotag.core.AutotagRuntimeException; +import org.apache.tiles.autotag.model.TemplateClass; +import org.apache.tiles.autotag.model.TemplateSuite; +import org.apache.tiles.autotag.tool.StringTool; +import org.apache.velocity.Template; +import org.apache.velocity.VelocityContext; +import org.apache.velocity.app.VelocityEngine; +import org.apache.velocity.exception.ParseErrorException; +import org.apache.velocity.exception.ResourceNotFoundException; + +/** + * A base template class generator. + */ +public abstract class AbstractTemplateClassGenerator implements + TemplateClassGenerator { + + /** + * The Velocity engine to use. + */ + private VelocityEngine velocityEngine; + + /** + * Constructor. + * + * @param velocityEngine The Velocity engine. + */ + public AbstractTemplateClassGenerator(VelocityEngine velocityEngine) { + this.velocityEngine = velocityEngine; + } + + @Override + public void generate(File directory, String packageName, + TemplateSuite suite, TemplateClass clazz, Map parameters, + String runtimeClass, String requestClass) { + File dir = new File(directory, getDirectoryName(directory, packageName, + suite, clazz, parameters, runtimeClass, requestClass)); + dir.mkdirs(); + File file = new File(dir, getFilename(dir, packageName, suite, clazz, parameters, runtimeClass, requestClass)); + VelocityContext context = new VelocityContext(); + context.put("packageName", packageName); + context.put("suite", suite); + context.put("clazz", clazz); + context.put("stringTool", new StringTool()); + context.put("parameters", parameters); + context.put("runtimeClass", runtimeClass); + context.put("requestClass", requestClass); + try { + file.createNewFile(); + Template template = velocityEngine.getTemplate(getTemplatePath(dir, + packageName, suite, clazz, parameters, runtimeClass, requestClass)); + Writer writer = new FileWriter(file); + try { + template.merge(context, writer); + } finally { + writer.close(); + } + } catch (ResourceNotFoundException e) { + throw new AutotagRuntimeException("Cannot find template resource", + e); + } catch (ParseErrorException e) { + throw new AutotagRuntimeException( + "The template resource is not parseable", e); + } catch (IOException e) { + throw new AutotagRuntimeException( + "I/O Exception when generating file", e); + } catch (RuntimeException e) { + throw e; + } catch (Exception e) { + throw new AutotagRuntimeException( + "Another generic exception while parsing the template resource", + e); + } + } + + /** + * Calculates and returns the template path. + * + * @param directory The directory where the file will be written. + * @param packageName The name of the package. + * @param suite The template suite. + * @param clazz The template class. + * @param parameters The map of parameters. + * @return The template path. + */ + protected abstract String getTemplatePath(File directory, + String packageName, TemplateSuite suite, TemplateClass clazz, Map parameters, + String runtimeClass, String requestClass); + + /** + * Calculates and returns the filename of the generated file. + * + * @param directory The directory where the file will be written. + * @param packageName The name of the package. + * @param suite The template suite. + * @param clazz The template class. + * @param parameters The map of parameters. + * @return The template path. + */ + protected abstract String getFilename(File directory, String packageName, + TemplateSuite suite, TemplateClass clazz, Map parameters, String runtimeClass, + String requestClass); + + /** + * Calculates and returns the directory where the file will be written.. + * + * @param directory The directory where the file will be written. + * @param packageName The name of the package. + * @param suite The template suite. + * @param clazz The template class. + * @param parameters The map of parameters. + * @return The template path. + */ + protected abstract String getDirectoryName(File directory, + String packageName, TemplateSuite suite, TemplateClass clazz, Map parameters, + String runtimeClass, String requestClass); + +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/autotag/generate/AbstractTemplateSuiteGenerator.java b/plugins/tiles/src/main/java/org/apache/tiles/autotag/generate/AbstractTemplateSuiteGenerator.java new file mode 100644 index 000000000..16e3234b6 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/autotag/generate/AbstractTemplateSuiteGenerator.java @@ -0,0 +1,128 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.autotag.generate; + +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.io.Writer; +import java.util.Map; + +import org.apache.tiles.autotag.core.AutotagRuntimeException; +import org.apache.tiles.autotag.model.TemplateSuite; +import org.apache.tiles.autotag.tool.StringTool; +import org.apache.velocity.Template; +import org.apache.velocity.VelocityContext; +import org.apache.velocity.app.VelocityEngine; +import org.apache.velocity.exception.ParseErrorException; +import org.apache.velocity.exception.ResourceNotFoundException; + +/** + * A base template suite generator. + */ +public abstract class AbstractTemplateSuiteGenerator implements TemplateSuiteGenerator { + + /** + * The velocity engine. + */ + private VelocityEngine velocityEngine; + + /** + * Constructor. + * + * @param velocityEngine The Velocity engine. + */ + public AbstractTemplateSuiteGenerator(VelocityEngine velocityEngine) { + this.velocityEngine = velocityEngine; + } + + @Override + public void generate(File directory, String packageName, TemplateSuite suite, Map parameters) { + File dir = new File(directory, getDirectoryName(directory, packageName, suite, parameters)); + dir.mkdirs(); + File file = new File(dir, getFilename(dir, packageName, suite, parameters)); + VelocityContext context = new VelocityContext(); + context.put("packageName", packageName); + context.put("suite", suite); + context.put("stringTool", new StringTool()); + context.put("parameters", parameters); + try { + file.createNewFile(); + Template template = velocityEngine.getTemplate(getTemplatePath(dir, + packageName, suite, parameters)); + Writer writer = new FileWriter(file); + try { + template.merge(context, writer); + } finally { + writer.close(); + } + } catch (ResourceNotFoundException e) { + throw new AutotagRuntimeException("Cannot find template resource", e); + } catch (ParseErrorException e) { + throw new AutotagRuntimeException("The template resource is not parseable", e); + } catch (IOException e) { + throw new AutotagRuntimeException( + "I/O Exception when generating file", e); + } catch (RuntimeException e) { + throw e; + } catch (Exception e) { + throw new AutotagRuntimeException( + "Another generic exception while parsing the template resource", + e); + } + } + + /** + * Calculates and returns the template path. + * + * @param directory The directory where the file will be written. + * @param packageName The name of the package. + * @param suite The template suite. + * @param parameters The map of parameters. + * @return The template path. + */ + protected abstract String getTemplatePath(File directory, + String packageName, TemplateSuite suite, + Map parameters); + + /** + * Calculates and returns the filename of the generated file. + * + * @param directory The directory where the file will be written. + * @param packageName The name of the package. + * @param suite The template suite. + * @param parameters The map of parameters. + * @return The template path. + */ + protected abstract String getFilename(File directory, String packageName, + TemplateSuite suite, Map parameters); + + /** + * Calculates and returns the directory where the file will be written.. + * + * @param directory The directory where the file will be written. + * @param packageName The name of the package. + * @param suite The template suite. + * @param parameters The map of parameters. + * @return The template path. + */ + protected abstract String getDirectoryName(File directory, + String packageName, TemplateSuite suite, + Map parameters); +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/autotag/generate/BasicTemplateGenerator.java b/plugins/tiles/src/main/java/org/apache/tiles/autotag/generate/BasicTemplateGenerator.java new file mode 100644 index 000000000..e9b27b060 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/autotag/generate/BasicTemplateGenerator.java @@ -0,0 +1,187 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.autotag.generate; + +import java.io.File; +import java.util.List; +import java.util.Map; + +import org.apache.tiles.autotag.model.TemplateClass; +import org.apache.tiles.autotag.model.TemplateSuite; + +/** + * The basic template generator. Use {@link TemplateGeneratorBuilder} to + * create instances of this class. + */ +class BasicTemplateGenerator implements TemplateGenerator { + + /** + * The template suite generators. + */ + private List templateSuiteGenerators; + + /** + * The template class generators. + */ + private List templateClassGenerators; + + /** + * Indicates that this generator generates resources. + */ + private boolean generatingResources = false; + + /** + * Indicates that this generator generates classes. + */ + private boolean generatingClasses = false; + + /** + * Constructor. + * + * @param templateSuiteGenerators The template suite generators. + * @param templateClassGenerators The template class generators. + * @param generatingClasses Indicates that this generator generates classes. + * @param generatingResources Indicates that this generator generates resources. + */ + BasicTemplateGenerator( + List templateSuiteGenerators, + List templateClassGenerators, + boolean generatingClasses, boolean generatingResources) { + this.templateSuiteGenerators = templateSuiteGenerators; + this.templateClassGenerators = templateClassGenerators; + this.generatingClasses = generatingClasses; + this.generatingResources = generatingResources; + } + + + + @Override + public void generate(String packageName, TemplateSuite suite, Map parameters, + String runtimeClass, String requestClass) { + for (TSGeneratorDirectoryPair pair : templateSuiteGenerators) { + pair.getGenerator().generate(pair.getDirectory(), packageName, suite, parameters); + } + for (TemplateClass templateClass : suite.getTemplateClasses()) { + for (TCGeneratorDirectoryPair pair : templateClassGenerators) { + pair.getGenerator().generate(pair.getDirectory(), packageName, + suite, templateClass, parameters, runtimeClass, requestClass); + } + } + } + + /** + * A pair of a template suite generator and a directory. + */ + static class TSGeneratorDirectoryPair { + /** + * The directory where files are generated. + */ + private File directory; + + /** + * The generator. + */ + private TemplateSuiteGenerator generator; + + /** + * Constructor. + * + * @param directory The directory where files are generated. + * @param generator The generator. + */ + public TSGeneratorDirectoryPair(File directory, + TemplateSuiteGenerator generator) { + this.directory = directory; + this.generator = generator; + } + + /** + * Returns the directory where files are generated. + * + * @return The directory where files are generated. + */ + public File getDirectory() { + return directory; + } + + /** + * Returns the generator. + * + * @return The generator. + */ + public TemplateSuiteGenerator getGenerator() { + return generator; + } + } + + /** + * A pair of a template class generator and a directory. + */ + static class TCGeneratorDirectoryPair { + /** + * The directory where files are generated. + */ + private File directory; + + /** + * The generator. + */ + private TemplateClassGenerator generator; + + /** + * Constructor. + * + * @param directory The directory where files are generated. + * @param generator The generator. + */ + public TCGeneratorDirectoryPair(File directory, + TemplateClassGenerator generator) { + this.directory = directory; + this.generator = generator; + } + + /** + * Returns the directory where files are generated. + * + * @return The directory where files are generated. + */ + public File getDirectory() { + return directory; + } + + /** + * Returns the generator. + * + * @return The generator. + */ + public TemplateClassGenerator getGenerator() { + return generator; + } + } + + @Override + public boolean isGeneratingResources() { + return generatingResources; + } + + @Override + public boolean isGeneratingClasses() { + return generatingClasses; + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/autotag/generate/TemplateClassGenerator.java b/plugins/tiles/src/main/java/org/apache/tiles/autotag/generate/TemplateClassGenerator.java new file mode 100644 index 000000000..3d958beef --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/autotag/generate/TemplateClassGenerator.java @@ -0,0 +1,45 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.autotag.generate; + +import java.io.File; +import java.util.Map; + +import org.apache.tiles.autotag.model.TemplateClass; +import org.apache.tiles.autotag.model.TemplateSuite; + +/** + * Generates code from a parsed class. + */ +public interface TemplateClassGenerator { + + /** + * Generates the code. + * + * @param directory The base directory where the code will be put. + * @param packageName The package name. + * @param suite The template suite. + * @param clazz The template class. + * @param parameters Configuration parameters. + * @param runtimeClass The RequestBuilder implementation. + */ + void generate(File directory, String packageName, TemplateSuite suite, + TemplateClass clazz, Map parameters, + String runtimeClass, String requestClass); +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/autotag/generate/TemplateGenerator.java b/plugins/tiles/src/main/java/org/apache/tiles/autotag/generate/TemplateGenerator.java new file mode 100644 index 000000000..9e462ff2d --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/autotag/generate/TemplateGenerator.java @@ -0,0 +1,56 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.autotag.generate; + + +import java.util.Map; + +import org.apache.tiles.autotag.model.TemplateSuite; + +/** + * Generates all the code for a template suite. + */ +public interface TemplateGenerator { + + /** + * Generates the code. + * + * @param packageName The package name. + * @param suite The template suite. + * @param parameters Configuration parameters. + * @param runtimeClass The RequestBuilder implementation. + * @param requestClass The request class to use. + */ + void generate(String packageName, TemplateSuite suite, Map parameters, + String runtimeClass, String requestClass); + + /** + * Indicates that this generator generates resources. + * + * @return true if the generator generates resources. + */ + boolean isGeneratingResources(); + + /** + * Indicates that this generator generates classes. + * + * @return true if the generator generates classes. + */ + boolean isGeneratingClasses(); +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/autotag/generate/TemplateGeneratorBuilder.java b/plugins/tiles/src/main/java/org/apache/tiles/autotag/generate/TemplateGeneratorBuilder.java new file mode 100644 index 000000000..943175da6 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/autotag/generate/TemplateGeneratorBuilder.java @@ -0,0 +1,180 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.autotag.generate; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; + +import org.apache.tiles.autotag.generate.BasicTemplateGenerator.TCGeneratorDirectoryPair; +import org.apache.tiles.autotag.generate.BasicTemplateGenerator.TSGeneratorDirectoryPair; + +/** + * Builds a TemplateGenerator. + */ +public class TemplateGeneratorBuilder { + + /** + * The template suite generators. + */ + private List templateSuiteGenerators; + + /** + * The template class generators. + */ + private List templateClassGenerators; + + /** + * Indicates that this generator generates resources. + */ + private boolean generatingResources = false; + + /** + * Indicates that this generator generates classes. + */ + private boolean generatingClasses = false; + + /** + * The classes output directory. + */ + private File classesOutputDirectory; + + /** + * The resources output directory. + */ + private File resourcesOutputDirectory; + + /** + * Constructor. + */ + private TemplateGeneratorBuilder() { + templateSuiteGenerators = new ArrayList(); + templateClassGenerators = new ArrayList(); + } + + /** + * Creates a new instance of the builder. + * + * @return A new instance of the builder. + */ + public static TemplateGeneratorBuilder createNewInstance() { + return new TemplateGeneratorBuilder(); + } + + /** + * Sets the classes output directory. + * + * @param classesOutputDirectory The classes output directory. + * @return This instance. + */ + public TemplateGeneratorBuilder setClassesOutputDirectory(File classesOutputDirectory) { + this.classesOutputDirectory = classesOutputDirectory; + return this; + } + + /** + * Sets the resources output directory. + * + * @param resourcesOutputDirectory The resources output directory. + * @return This instance. + */ + public TemplateGeneratorBuilder setResourcesOutputDirectory(File resourcesOutputDirectory) { + this.resourcesOutputDirectory = resourcesOutputDirectory; + return this; + } + + /** + * Adds a new template suite generator to generate classes. + * + * @param generator The generator to add. + * @return This instance. + */ + public TemplateGeneratorBuilder addClassesTemplateSuiteGenerator(TemplateSuiteGenerator generator) { + if (classesOutputDirectory == null) { + throw new NullPointerException( + "Classes output directory not specified, call 'setClassesOutputDirectory' first"); + } + templateSuiteGenerators.add(new TSGeneratorDirectoryPair( + classesOutputDirectory, generator)); + generatingClasses = true; + return this; + } + + /** + * Adds a new template class generator to generate classes. + * + * @param generator The generator to add. + * @return This instance. + */ + public TemplateGeneratorBuilder addClassesTemplateClassGenerator(TemplateClassGenerator generator) { + if (classesOutputDirectory == null) { + throw new NullPointerException( + "Classes output directory not specified, call 'setClassesOutputDirectory' first"); + } + templateClassGenerators.add(new TCGeneratorDirectoryPair( + classesOutputDirectory, generator)); + generatingClasses = true; + return this; + } + + /** + * Adds a new template suite generator to generate resources. + * + * @param generator The generator to add. + * @return This instance. + */ + public TemplateGeneratorBuilder addResourcesTemplateSuiteGenerator(TemplateSuiteGenerator generator) { + if (resourcesOutputDirectory == null) { + throw new NullPointerException( + "Resources output directory not specified, call 'setClassesOutputDirectory' first"); + } + templateSuiteGenerators.add(new TSGeneratorDirectoryPair( + resourcesOutputDirectory, generator)); + generatingResources = true; + return this; + } + + /** + * Adds a new template class generator to generate resources. + * + * @param generator The generator to add. + * @return This instance. + */ + public TemplateGeneratorBuilder addResourcesTemplateClassGenerator(TemplateClassGenerator generator) { + if (resourcesOutputDirectory == null) { + throw new NullPointerException( + "Resources output directory not specified, call 'setClassesOutputDirectory' first"); + } + templateClassGenerators.add(new TCGeneratorDirectoryPair( + resourcesOutputDirectory, generator)); + generatingResources = true; + return this; + } + + /** + * Builds and returns a new template generator. + * + * @return The new template generator. + */ + public TemplateGenerator build() { + return new BasicTemplateGenerator(templateSuiteGenerators, + templateClassGenerators, generatingClasses, generatingResources); + } + +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/autotag/generate/TemplateGeneratorFactory.java b/plugins/tiles/src/main/java/org/apache/tiles/autotag/generate/TemplateGeneratorFactory.java new file mode 100644 index 000000000..11fbf693f --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/autotag/generate/TemplateGeneratorFactory.java @@ -0,0 +1,32 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.autotag.generate; + +/** + * Creates a new template generator. + */ +public interface TemplateGeneratorFactory { + + /** + * Creates a template generator. + * + * @return The newly created template generator. + */ + TemplateGenerator createTemplateGenerator(); +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/autotag/generate/TemplateSuiteGenerator.java b/plugins/tiles/src/main/java/org/apache/tiles/autotag/generate/TemplateSuiteGenerator.java new file mode 100644 index 000000000..f8986779d --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/autotag/generate/TemplateSuiteGenerator.java @@ -0,0 +1,40 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.autotag.generate; + +import java.io.File; +import java.util.Map; + +import org.apache.tiles.autotag.model.TemplateSuite; + +/** + * Generates code from a template suite. + */ +public interface TemplateSuiteGenerator { + + /** + * Generates the code. + * + * @param directory The base directory where the code will be put. + * @param packageName The package name. + * @param suite The template suite. + * @param parameters Configuration parameters. + */ + void generate(File directory, String packageName, TemplateSuite suite, Map parameters); +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/autotag/generate/package-info.java b/plugins/tiles/src/main/java/org/apache/tiles/autotag/generate/package-info.java new file mode 100644 index 000000000..2fbdf2ae0 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/autotag/generate/package-info.java @@ -0,0 +1,22 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +/** + * The Autotag generation classes. + */ +package org.apache.tiles.autotag.generate; diff --git a/plugins/tiles/src/main/java/org/apache/tiles/autotag/jsp/JspTemplateGeneratorFactory.java b/plugins/tiles/src/main/java/org/apache/tiles/autotag/jsp/JspTemplateGeneratorFactory.java new file mode 100644 index 000000000..90c7ce32e --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/autotag/jsp/JspTemplateGeneratorFactory.java @@ -0,0 +1,79 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.autotag.jsp; + +import java.io.File; + +import org.apache.tiles.autotag.generate.TemplateGenerator; +import org.apache.tiles.autotag.generate.TemplateGeneratorBuilder; +import org.apache.tiles.autotag.generate.TemplateGeneratorFactory; +import org.apache.velocity.app.VelocityEngine; + +/** + * Creates a template generator to build JSP code around template models. + */ +public class JspTemplateGeneratorFactory implements TemplateGeneratorFactory { + + /** + * Location of the file. + */ + private File classesOutputDirectory; + + /** + * Location of the file. + */ + private File resourcesOutputDirectory; + + /** + * The Velocity engine. + */ + private VelocityEngine velocityEngine; + + /** + * The template generator builder. + */ + private TemplateGeneratorBuilder templateGeneratorBuilder; + + /** + * Constructor. + * + * @param classesOutputDirectory The directory where classes will be + * generated. + * @param resourcesOutputDirectory The directory where the TLD file will be + * generated. + * @param velocityEngine The Velocity engine. + * @param templateGeneratorBuilder The template generator builder. + */ + public JspTemplateGeneratorFactory(File classesOutputDirectory, File resourcesOutputDirectory, + VelocityEngine velocityEngine, TemplateGeneratorBuilder templateGeneratorBuilder) { + this.classesOutputDirectory = classesOutputDirectory; + this.resourcesOutputDirectory = resourcesOutputDirectory; + this.velocityEngine = velocityEngine; + this.templateGeneratorBuilder = templateGeneratorBuilder; + } + + @Override + public TemplateGenerator createTemplateGenerator() { + return templateGeneratorBuilder.setClassesOutputDirectory(classesOutputDirectory) + .setResourcesOutputDirectory(resourcesOutputDirectory) + .addResourcesTemplateSuiteGenerator(new TLDGenerator(velocityEngine)) + .addClassesTemplateClassGenerator(new TagClassGenerator(velocityEngine)).build(); + } + +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/autotag/jsp/TLDGenerator.java b/plugins/tiles/src/main/java/org/apache/tiles/autotag/jsp/TLDGenerator.java new file mode 100644 index 000000000..28d947d6e --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/autotag/jsp/TLDGenerator.java @@ -0,0 +1,60 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.autotag.jsp; + +import java.io.File; +import java.util.Map; + +import org.apache.tiles.autotag.generate.AbstractTemplateSuiteGenerator; +import org.apache.tiles.autotag.model.TemplateSuite; +import org.apache.velocity.app.VelocityEngine; + +/** + * Generates the TLD file, using a template suite. + */ +public class TLDGenerator extends AbstractTemplateSuiteGenerator { + + /** + * Constructor. + * + * @param velocityEngine The Velocity engine. + */ + public TLDGenerator(VelocityEngine velocityEngine) { + super(velocityEngine); + } + + @Override + protected String getTemplatePath(File directory, String packageName, + TemplateSuite suite, Map parameters) { + return "/org/apache/tiles/autotag/jsp/tld.vm"; + } + + @Override + protected String getFilename(File directory, String packageName, + TemplateSuite suite, Map parameters) { + return suite.getName() + "-jsp.tld"; + } + + @Override + protected String getDirectoryName(File directory, String packageName, + TemplateSuite suite, Map parameters) { + return "META-INF/tld/"; + } + +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/autotag/jsp/TagClassGenerator.java b/plugins/tiles/src/main/java/org/apache/tiles/autotag/jsp/TagClassGenerator.java new file mode 100644 index 000000000..c0ee919de --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/autotag/jsp/TagClassGenerator.java @@ -0,0 +1,63 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.autotag.jsp; + +import java.io.File; +import java.util.Map; + +import org.apache.tiles.autotag.generate.AbstractTemplateClassGenerator; +import org.apache.tiles.autotag.model.TemplateClass; +import org.apache.tiles.autotag.model.TemplateSuite; +import org.apache.velocity.app.VelocityEngine; + +/** + * Generates a tag class using a template class. + */ +public class TagClassGenerator extends AbstractTemplateClassGenerator { + + /** + * Constructor. + * + * @param velocityEngine The Velocity engine. + */ + public TagClassGenerator(VelocityEngine velocityEngine) { + super(velocityEngine); + } + + @Override + protected String getDirectoryName(File directory, String packageName, + TemplateSuite suite, TemplateClass clazz, Map parameters, + String runtimeClass, String requestClass) { + return packageName.replaceAll("\\.", "/"); + } + + @Override + protected String getFilename(File directory, String packageName, + TemplateSuite suite, TemplateClass clazz, Map parameters, + String runtimeClass, String requestClass) { + return clazz.getTagClassPrefix() + "Tag.java"; + } + + @Override + protected String getTemplatePath(File directory, String packageName, + TemplateSuite suite, TemplateClass clazz, Map parameters, + String runtimeClass, String requestClass) { + return "/org/apache/tiles/autotag/jsp/bodyTag.vm"; + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/autotag/jsp/package-info.java b/plugins/tiles/src/main/java/org/apache/tiles/autotag/jsp/package-info.java new file mode 100644 index 000000000..f142dabfa --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/autotag/jsp/package-info.java @@ -0,0 +1,22 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +/** + * Autotag support for JavaServer Pages. + */ +package org.apache.tiles.autotag.jsp; diff --git a/plugins/tiles/src/main/java/org/apache/tiles/autotag/model/TemplateClass.java b/plugins/tiles/src/main/java/org/apache/tiles/autotag/model/TemplateClass.java new file mode 100644 index 000000000..0aeb990ce --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/autotag/model/TemplateClass.java @@ -0,0 +1,191 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.autotag.model; + +import java.util.Collection; +import java.util.LinkedHashMap; +import java.util.Map; + +/** + * It represents a parsed template class. + */ +public class TemplateClass { + + /** + * The class name. + */ + private String name; + + /** + * The name of the tag. + */ + private String tagName; + + /** + * The prefix of the tag class. + */ + private String tagClassPrefix; + + /** + * Documentation about this tag. + */ + private String documentation; + + /** + * The method that executes the template class. + */ + private TemplateMethod executeMethod; + + /** + * Constructor. + * + * @param name The name of the template class. + */ + public TemplateClass(String name) { + this(name, null, null, null); + } + + /** + * Constructor. + * + * @param name The name of the template class. + * @param tagName The name of the tag. + * @param tagClassPrefix The tag class prefix. + * @param executeMethod The method that executes the template class. + */ + public TemplateClass(String name, String tagName, String tagClassPrefix, + TemplateMethod executeMethod) { + this.name = name; + this.tagName = tagName; + this.tagClassPrefix = tagClassPrefix; + this.executeMethod = executeMethod; + } + + /** + * The name of the parsed class. + * + * @return The name of the class. + */ + public String getName() { + return name; + } + + /** + * Returns the name of the class, without the package part. + * + * @return The simple class name. + */ + public String getSimpleName() { + int pos = name.lastIndexOf('.'); + if (pos >= 0) { + return name.substring(pos + 1); + } + return name; + } + + /** + * Returns the tag name. + * + * @return The tag name. + */ + public String getTagName() { + return tagName; + } + + /** + * Returns the tag class prefix. + * + * @return The tag class prefix. + */ + public String getTagClassPrefix() { + return tagClassPrefix; + } + + /** + * Returns the documentation for this class. + * + * @return The documentation. + */ + public String getDocumentation() { + return documentation; + } + + /** + * Sets the documentation for this class. + * + * @param documentation The documentation. + */ + public void setDocumentation(String documentation) { + this.documentation = documentation; + } + + /** + * Returns the method that execute this class. + * + * @return The execute method. + */ + public TemplateMethod getExecuteMethod() { + return executeMethod; + } + + /** + * Returns the collection of regular parameters (no request, no body) + * of the execute method. + * + * @return The regular parameters. + */ + public Collection getParameters() { + Map params = new LinkedHashMap(); + fillRegularParameters(params, executeMethod); + return params.values(); + } + + /** + * Indicates that this class needs a tag body. + * + * @return true if tag body is needed. + */ + public boolean hasBody() { + return executeMethod.hasBody(); + } + + @Override + public String toString() { + return "TemplateClass [name=" + name + ", tagName=" + tagName + + ", tagClassPrefix=" + tagClassPrefix + ", documentation=" + + documentation + ", executeMethod=" + executeMethod + "]"; + } + + /** + * Creates regular parameters map. + * + * @param params The map to fill. + * @param method The method to analyze. + */ + private void fillRegularParameters(Map params, + TemplateMethod method) { + if (method != null) { + for (TemplateParameter param : method.getParameters()) { + if (!param.isRequest() && !param.isBody()) { + params.put(param.getName(), param); + } + } + } + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/autotag/model/TemplateMethod.java b/plugins/tiles/src/main/java/org/apache/tiles/autotag/model/TemplateMethod.java new file mode 100644 index 000000000..2bccf2ddd --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/autotag/model/TemplateMethod.java @@ -0,0 +1,127 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.autotag.model; + +import java.util.Collection; +import java.util.LinkedHashMap; +import java.util.Map; + +/** + * It represents a parsed method in a parsed template class. + */ +public class TemplateMethod { + + /** + * The name of the method. + */ + private String name; + + /** + * Documentation about the method. + */ + private String documentation; + + /** + * The map of parameters. + */ + private Map parameters; + + /** + * Constructor. + * + * @param name The name of the method. + * @param parameters The map of parameters. + */ + public TemplateMethod(String name, + Iterable parameters) { + this.name = name; + this.parameters = new LinkedHashMap(); + for (TemplateParameter parameter : parameters) { + this.parameters.put(parameter.getName(), parameter); + } + } + + /** + * Returns the name of the method. + * + * @return The name of the method. + */ + public String getName() { + return name; + } + + /** + * Returns the documentation for this method. + * + * @return The documentation. + */ + public String getDocumentation() { + return documentation; + } + + /** + * Sets the documentation for this method. + * + * @param documentation The documentation. + */ + public void setDocumentation(String documentation) { + this.documentation = documentation; + } + + /** + * Returns the parameters of this method. + * + * @return The parameters. + */ + public Collection getParameters() { + return parameters.values(); + } + + /** + * Returns a parameter given its name. + * + * @param name The name of the parameter. + * @return The parameter. + */ + public TemplateParameter getParameterByName(String name) { + return parameters.get(name); + } + + /** + * Indicates that this method needs a tag body. + * + * @return true if tag body is needed. + */ + public boolean hasBody() { + if (parameters.size() >= 2) { + for (TemplateParameter param : parameters.values()) { + if (param.isBody()) { + return true; + } + } + } + return false; + } + + @Override + public String toString() { + return "TemplateMethod [name=" + name + ", documentation=" + + documentation + ", parameters=" + parameters + "]"; + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/autotag/model/TemplateParameter.java b/plugins/tiles/src/main/java/org/apache/tiles/autotag/model/TemplateParameter.java new file mode 100644 index 000000000..0540954c1 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/autotag/model/TemplateParameter.java @@ -0,0 +1,182 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.autotag.model; + +import org.apache.tiles.autotag.core.runtime.ModelBody; + +/** + * It represents a parameter in a method in a parsed template class. + */ +public class TemplateParameter { + + /** + * The name of the parameter. + */ + private String name; + + /** + * The exported name, i.e. the name of the parameter in created code. Usually + * helpful if this exported name is a reserved word. + */ + private String exportedName; + + /** + * The parameter documentation. + */ + private String documentation; + + /** + * The type of the parameter. + */ + private String type; + + /** + * The default value, as it will be written in Java code. + */ + private String defaultValue; + + /** + * Indicates that this parameter is required. + */ + private boolean required; + + /** + * Indicates that this parameter is the request. + */ + private boolean request; + + /** + * Constructor. + * + * @param name The name of the parameter. + * @param exportedName The exported name, i.e. the name of the parameter in created code. Usually + * helpful if this exported name is a reserved word. + * @param type The type of the parameter. + * @param defaultValue The default value, as it will be written in Java code. + * @param required Indicates that this parameter is required. + */ + public TemplateParameter(String name, String exportedName, String type, String defaultValue, boolean required, boolean request) { + this.name = name; + this.exportedName = exportedName; + this.type = type; + this.defaultValue = defaultValue; + this.required = required; + this.request = request; + } + + /** + * Returns the documentation for this parameter. + * + * @return The documentation. + */ + public String getDocumentation() { + return documentation; + } + + /** + * Sets the documentation for this parameter. + * + * @param documentation The documentation. + */ + public void setDocumentation(String documentation) { + this.documentation = documentation; + } + + /** + * Returns the name of the parameter. + * + * @return The name of the parameter. + */ + public String getName() { + return name; + } + + /** + * Returns the exported name, i.e. the name of the parameter in created code. Usually + * helpful if this exported name is a reserved word. + * + * @return The exported name. + */ + public String getExportedName() { + return exportedName; + } + + /** + * Returns the type of the parameter. + * + * @return The type. + */ + public String getType() { + return type; + } + + /** + * Returns the default value, as it will be written in Java code. + * + * @return The default value. + */ + public String getDefaultValue() { + return defaultValue; + } + + /** + * Indicates that this parameter is required. + * + * @return true if the parameter is required. + */ + public boolean isRequired() { + return required; + } + + /** + * Indicates that this parameter implements {@link ModelBody}. + * + * @return true if the parameter is a body. + */ + public boolean isBody() { + return ModelBody.class.getName().equals(type); + } + + /** + * Indicates that this parameter implements {@link Request}. + * + * @return true if the parameter is a request. + */ + public boolean isRequest() { + return request; + } + + /** + * Returns the suffix for getter and setter of the property generated by + * this parameter. + * + * @return The getter and setter suffix. + */ + public String getGetterSetterSuffix() { + return exportedName.substring(0, 1).toUpperCase() + exportedName.substring(1); + } + + @Override + public String toString() { + return "TemplateParameter [name=" + name + ", exportedName=" + + exportedName + ", documentation=" + documentation + ", type=" + + type + ", defaultValue=" + defaultValue + ", required=" + + required + ", request=" + request + "]"; + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/autotag/model/TemplateSuite.java b/plugins/tiles/src/main/java/org/apache/tiles/autotag/model/TemplateSuite.java new file mode 100644 index 000000000..de14b466f --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/autotag/model/TemplateSuite.java @@ -0,0 +1,125 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.autotag.model; + +import java.util.Collection; +import java.util.LinkedHashMap; +import java.util.Map; + +/** + * It represents a suite of template classes. + */ +public class TemplateSuite { + + /** + * The name of the suite. + */ + private String name; + + /** + * The documentation of this suite. + */ + private String documentation; + + /** + * The map of template classes. + */ + private Map templateClasses; + + /** + * Constructor. + * + * @param name The name of the suite. + * @param documentation The documentation. + */ + public TemplateSuite(String name, String documentation) { + this(name, documentation, null); + } + + /** + * Constructor. + * + * @param name The name of the suite. + * @param documentation The documentation. + * @param classes The template classes. + */ + public TemplateSuite(String name, String documentation, + Iterable classes) { + this.name = name; + this.documentation = documentation; + templateClasses = new LinkedHashMap(); + if (classes != null) { + for (TemplateClass templateClass : classes) { + templateClasses.put(templateClass.getName(), templateClass); + } + } + } + + /** + * Returns the template suite name. + * + * @return The name. + */ + public String getName() { + return name; + } + + /** + * Returns the documentation. + * + * @return The documentation. + */ + public String getDocumentation() { + return documentation; + } + + /** + * Adds a new template class. + * + * @param clazz The template class. + */ + public void addTemplateClass(TemplateClass clazz) { + templateClasses.put(clazz.getName(), clazz); + } + + /** + * Returns the template classes. + * + * @return The template classes. + */ + public Collection getTemplateClasses() { + return templateClasses.values(); + } + + /** + * Returns a template class given its name. + * + * @param name The name of the class. + * @return The template class instance. + */ + public TemplateClass getTemplateClassByName(String name) { + return templateClasses.get(name); + } + + @Override + public String toString() { + return "TemplateSuite [name=" + name + ", documentation=" + + documentation + ", templateClasses=" + templateClasses + "]"; + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/autotag/model/package-info.java b/plugins/tiles/src/main/java/org/apache/tiles/autotag/model/package-info.java new file mode 100644 index 000000000..7eddcd1f5 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/autotag/model/package-info.java @@ -0,0 +1,22 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +/** + * Domain model classes representing a parsed template suite. + */ +package org.apache.tiles.autotag.model; diff --git a/plugins/tiles/src/main/java/org/apache/tiles/autotag/tool/StringTool.java b/plugins/tiles/src/main/java/org/apache/tiles/autotag/tool/StringTool.java new file mode 100644 index 000000000..247529835 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/autotag/tool/StringTool.java @@ -0,0 +1,138 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.autotag.tool; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.Reader; +import java.io.StringReader; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.tiles.autotag.core.AutotagRuntimeException; + +/** + * A Velocity tools to manipulate strings. + */ +public class StringTool { + + /** + * Maps a primitive type to its default value as a string. + */ + private Map type2default; + + /** + * Maps a primitive type to its boxed version. + */ + private Map primitive2wrapped; + + /** + * Constructor. + */ + public StringTool() { + type2default = new HashMap(); + type2default.put("byte", "0"); + type2default.put("short", "0"); + type2default.put("int", "0"); + type2default.put("long", "0L"); + type2default.put("float", "0.0f"); + type2default.put("double", "0.0d"); + type2default.put("char", "'\\u0000'"); + type2default.put("boolean", "false"); + + primitive2wrapped = new HashMap(); + primitive2wrapped.put("byte", Byte.class.getName()); + primitive2wrapped.put("short", Short.class.getName()); + primitive2wrapped.put("int", Integer.class.getName()); + primitive2wrapped.put("long", Long.class.getName()); + primitive2wrapped.put("float", Float.class.getName()); + primitive2wrapped.put("double", Double.class.getName()); + primitive2wrapped.put("char", Character.class.getName()); + primitive2wrapped.put("boolean", Boolean.class.getName()); + } + + /** + * Creates a list of strings, separating a string when a newline is encountered. + * + * @param toSplit The string to split. + * @return The list of splitted strings. + */ + public List splitOnNewlines(String toSplit) { + List retValue = new ArrayList(); + if (toSplit == null) { + return retValue; + } + Reader reader = new StringReader(toSplit); + BufferedReader bufReader = new BufferedReader(reader); + try { + String line; + while ((line = bufReader.readLine()) != null) { + retValue.add(line); + } + } catch (IOException e) { + throw new AutotagRuntimeException("Cannot read the string completely", e); + } + return retValue; + } + + /** + * Creates a string in which the first character is capitalized. + * + * @param string The string to use. + * @return The same string with the first character capitalized. + */ + public String capitalizeFirstLetter(String string) { + return string.substring(0, 1).toUpperCase() + string.substring(1); + } + + /** + * Returns the default value for a type. + * + * @param type The type. + * @param overriddenDefaultValue The default value, as specified by developers. + * @return The default value to use. + */ + public String getDefaultValue(String type, String overriddenDefaultValue) { + if (overriddenDefaultValue != null) { + return overriddenDefaultValue; + } + + String retValue = type2default.get(type); + if (retValue == null) { + retValue = "null"; + } + return retValue; + } + + /** + * Returns the class to be used to cast an Object. + * + * @param type The type to use, even a primitive type. + * @return The class to be used in casts. + */ + public String getClassToCast(String type) { + String retValue = primitive2wrapped.get(type); + if (retValue == null) { + retValue = type; + } + return retValue; + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/autotag/tool/package-info.java b/plugins/tiles/src/main/java/org/apache/tiles/autotag/tool/package-info.java new file mode 100644 index 000000000..b58748ab0 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/autotag/tool/package-info.java @@ -0,0 +1,22 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +/** + * Velocity tools to be used in Velocity templates. + */ +package org.apache.tiles.autotag.tool; diff --git a/plugins/tiles/src/main/java/org/apache/tiles/autotag/velocity/VelocityDirectiveGenerator.java b/plugins/tiles/src/main/java/org/apache/tiles/autotag/velocity/VelocityDirectiveGenerator.java new file mode 100644 index 000000000..b59b70843 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/autotag/velocity/VelocityDirectiveGenerator.java @@ -0,0 +1,67 @@ +/* + * $Id: VelocityDirectiveGenerator.java 1349964 2012-06-13 17:18:51Z nlebas $ + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.autotag.velocity; + +import java.io.File; +import java.util.Map; + +import org.apache.tiles.autotag.generate.AbstractTemplateClassGenerator; +import org.apache.tiles.autotag.model.TemplateClass; +import org.apache.tiles.autotag.model.TemplateSuite; +import org.apache.velocity.app.VelocityEngine; + +/** + * Generates a Velocity directive using a template class. + * + * @version $Rev: 1349964 $ $Date: 2012-06-13 13:18:51 -0400 (Wed, 13 Jun 2012) $ + */ +public class VelocityDirectiveGenerator extends AbstractTemplateClassGenerator { + + /** + * Constructor. + * + * @param velocityEngine The Velocity engine. + */ + public VelocityDirectiveGenerator(VelocityEngine velocityEngine) { + super(velocityEngine); + } + + @Override + protected String getDirectoryName(File directory, String packageName, + TemplateSuite suite, TemplateClass clazz, Map parameters, + String runtimeClass, String requestClass) { + return packageName.replaceAll("\\.", "/"); + } + + @Override + protected String getFilename(File directory, String packageName, + TemplateSuite suite, TemplateClass clazz, Map parameters, + String runtimeClass, String requestClass) { + return clazz.getTagClassPrefix() + "Directive.java"; + } + + @Override + protected String getTemplatePath(File directory, String packageName, + TemplateSuite suite, TemplateClass clazz, Map parameters, + String runtimeClass, String requestClass) { + return "/org/apache/tiles/autotag/velocity/velocityDirective.vm"; + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/autotag/velocity/VelocityPropertiesGenerator.java b/plugins/tiles/src/main/java/org/apache/tiles/autotag/velocity/VelocityPropertiesGenerator.java new file mode 100644 index 000000000..bf340c41f --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/autotag/velocity/VelocityPropertiesGenerator.java @@ -0,0 +1,64 @@ +/* + * $Id: VelocityPropertiesGenerator.java 1045345 2010-12-13 19:58:23Z apetrelli $ + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.autotag.velocity; + +import java.io.File; +import java.util.Map; + +import org.apache.tiles.autotag.generate.AbstractTemplateSuiteGenerator; +import org.apache.tiles.autotag.model.TemplateSuite; +import org.apache.velocity.app.VelocityEngine; + +/** + * Generates a Velocity properties containing the list of generated user directives for future use. + * + * @version $Rev: 1045345 $ $Date: 2010-12-13 14:58:23 -0500 (Mon, 13 Dec 2010) $ + */ +public class VelocityPropertiesGenerator extends AbstractTemplateSuiteGenerator { + + /** + * Constructor. + * + * @param velocityEngine The Velocity engine. + */ + public VelocityPropertiesGenerator(VelocityEngine velocityEngine) { + super(velocityEngine); + } + + @Override + protected String getTemplatePath(File directory, String packageName, + TemplateSuite suite, Map parameters) { + return "/org/apache/tiles/autotag/velocity/velocityProperties.vm"; + } + + @Override + protected String getFilename(File directory, String packageName, + TemplateSuite suite, Map parameters) { + return "velocity.properties"; + } + + @Override + protected String getDirectoryName(File directory, String packageName, + TemplateSuite suite, Map parameters) { + return "META-INF/"; + } + +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/autotag/velocity/VelocityTemplateGeneratorFactory.java b/plugins/tiles/src/main/java/org/apache/tiles/autotag/velocity/VelocityTemplateGeneratorFactory.java new file mode 100644 index 000000000..6ed64cf47 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/autotag/velocity/VelocityTemplateGeneratorFactory.java @@ -0,0 +1,87 @@ +/* + * $Id: VelocityTemplateGeneratorFactory.java 1045345 2010-12-13 19:58:23Z apetrelli $ + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.autotag.velocity; + +import java.io.File; + +import org.apache.tiles.autotag.generate.TemplateGenerator; +import org.apache.tiles.autotag.generate.TemplateGeneratorBuilder; +import org.apache.tiles.autotag.generate.TemplateGeneratorFactory; +import org.apache.velocity.app.VelocityEngine; + +/** + * Creates a template generator that generates code to build Velocity code + * around template classes. + * + * @version $Rev: 1045345 $ $Date: 2010-12-13 14:58:23 -0500 (Mon, 13 Dec 2010) $ + */ +public class VelocityTemplateGeneratorFactory implements + TemplateGeneratorFactory { + + /** + * Location of the file. + */ + private File classesOutputDirectory; + + /** + * Location of the file. + */ + private File resourcesOutputDirectory; + + /** + * The Velocity engine. + */ + private VelocityEngine velocityEngine; + + /** + * The template generator builder. + */ + private TemplateGeneratorBuilder templateGeneratorBuilder; + + /** + * Constructor. + * + * @param classesOutputDirectory The directory where classes will be generated. + * @param resourcesOutputDirectory The directory where velocity.properties will be written. + * @param velocityEngine The Velocity engine. + * @param templateGeneratorBuilder The template generator builder. + */ + public VelocityTemplateGeneratorFactory(File classesOutputDirectory, + File resourcesOutputDirectory, VelocityEngine velocityEngine, + TemplateGeneratorBuilder templateGeneratorBuilder) { + this.classesOutputDirectory = classesOutputDirectory; + this.resourcesOutputDirectory = resourcesOutputDirectory; + this.velocityEngine = velocityEngine; + this.templateGeneratorBuilder = templateGeneratorBuilder; + } + + @Override + public TemplateGenerator createTemplateGenerator() { + return templateGeneratorBuilder + .setClassesOutputDirectory(classesOutputDirectory) + .setResourcesOutputDirectory(resourcesOutputDirectory) + .addResourcesTemplateSuiteGenerator( + new VelocityPropertiesGenerator(velocityEngine)) + .addClassesTemplateClassGenerator( + new VelocityDirectiveGenerator(velocityEngine)).build(); + } + +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/autotag/velocity/package-info.java b/plugins/tiles/src/main/java/org/apache/tiles/autotag/velocity/package-info.java new file mode 100644 index 000000000..15e00360f --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/autotag/velocity/package-info.java @@ -0,0 +1,24 @@ +/* + * $Id: package-info.java 1045345 2010-12-13 19:58:23Z apetrelli $ + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +/** + * Autotag support for Velocity. + */ +package org.apache.tiles.autotag.velocity; diff --git a/plugins/tiles/src/main/java/org/apache/tiles/core/definition/DefinitionsFactory.java b/plugins/tiles/src/main/java/org/apache/tiles/core/definition/DefinitionsFactory.java new file mode 100644 index 000000000..8f0dcc7aa --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/core/definition/DefinitionsFactory.java @@ -0,0 +1,75 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tiles.core.definition; + +import org.apache.tiles.api.Definition; +import org.apache.tiles.request.Request; + +/** + * Interface for creating a {@link Definition}s and managing their contents. + *

+ *

+ * DefinitionsFactory implementations are responsible for maintaining the data + * sources of Tiles configuration data and using the data to create Definitions + * sets. Implementations also know how to append locale-specific configuration + * data to an existing Definitions set. + *

+ */ +public interface DefinitionsFactory { + + /** + * Property name that specifies the implementation of the DefinitionsReader. + */ + String READER_IMPL_PROPERTY = + "org.apache.tiles.definition.DefinitionsReader"; + + /** + * Property name that specifies the implementation of + * {@link org.apache.tiles.core.locale.LocaleResolver}. + */ + String LOCALE_RESOLVER_IMPL_PROPERTY = + "org.apache.tiles.locale.LocaleResolver"; + + /** + * Constant representing the configuration parameter + * used to define the tiles definition resources. + * + * @since 2.1.0 + */ + String DEFINITIONS_CONFIG = "org.apache.tiles.definition.DefinitionsFactory.DEFINITIONS_CONFIG"; + + /** + * Constant representing the configuration parameter used to define the + * definition DAO to use. + */ + String DEFINITION_DAO_INIT_PARAM = + "org.apache.tiles.definition.DefinitionsFactory.DefinitionDAO"; + + /** + * Returns a Definition object that matches the given name and + * Tiles context. + * + * @param name The name of the Definition to return. + * @param tilesContext The Tiles context to use to resolve the definition. + * @return the Definition matching the given name or null if none + * is found. + */ + Definition getDefinition(String name, Request tilesContext); +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/core/definition/DefinitionsFactoryException.java b/plugins/tiles/src/main/java/org/apache/tiles/core/definition/DefinitionsFactoryException.java new file mode 100644 index 000000000..3d07b20bb --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/core/definition/DefinitionsFactoryException.java @@ -0,0 +1,72 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.core.definition; + +import org.apache.tiles.api.TilesException; + +/** + * Exception thrown when an error occurs while the impl tries to + * create a new instance mapper. + */ +public class DefinitionsFactoryException extends TilesException { + + /** + * Constructor. + */ + public DefinitionsFactoryException() { + super(); + } + + /** + * Constructor. + * + * @param message The error or warning message. + */ + public DefinitionsFactoryException(String message) { + super(message); + } + + + /** + * Create a new DefinitionsFactoryException wrapping an existing exception. + *

+ *

The existing exception will be embedded in the new + * one and its message will become the default message for + * the DefinitionsFactoryException.

+ * + * @param e The exception to be wrapped. + */ + public DefinitionsFactoryException(Throwable e) { + super(e); + } + + + /** + * Create a new DefinitionsFactoryException from an existing exception. + *

+ *

The existing exception will be embedded in the new + * one, but the new exception will have its own message.

+ * + * @param message The detail message. + * @param e The exception to be wrapped. + */ + public DefinitionsFactoryException(String message, Throwable e) { + super(message, e); + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/core/definition/DefinitionsReader.java b/plugins/tiles/src/main/java/org/apache/tiles/core/definition/DefinitionsReader.java new file mode 100644 index 000000000..39d61a52b --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/core/definition/DefinitionsReader.java @@ -0,0 +1,52 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tiles.core.definition; + +import org.apache.tiles.api.Definition; + +import java.util.Map; + +/** + * Interface for reading {@link Definition} from a source. + *

+ *

This interface provides a standard way to read + * {@link Definition} objects from a source. Implementations + * should define what the source is, whether it be a persistent store such as a + * configuration file or database, or something like a web service. The + * DefinitionsReader is responsible for reading from a single location. It does + * not perform any internationalization duties or inheritance of Definitions. + * It only reads from the source and returns a Map of objects read.

+ */ +public interface DefinitionsReader { + + /** + * Reads {@link Definition} objects from a source. + *

+ * Implementations should publish what type of source object is expected. + * + * @param source The source from which definitions will be read. + * @return a Map of Definition objects read from + * the source. + * @throws DefinitionsFactoryException if the source is invalid or + * an error occurs when reading definitions. + */ + Map read(Object source); + +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/core/definition/NoSuchDefinitionException.java b/plugins/tiles/src/main/java/org/apache/tiles/core/definition/NoSuchDefinitionException.java new file mode 100644 index 000000000..6815f2db9 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/core/definition/NoSuchDefinitionException.java @@ -0,0 +1,35 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.core.definition; + +/** + * Exception thrown when a definition is not found. + */ +public class NoSuchDefinitionException extends DefinitionsFactoryException { + + /** + * Constructor. + * + * @param msg Message. + */ + public NoSuchDefinitionException(String msg) { + super(msg); + } + +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/core/definition/RefreshMonitor.java b/plugins/tiles/src/main/java/org/apache/tiles/core/definition/RefreshMonitor.java new file mode 100644 index 000000000..d5f62d8d2 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/core/definition/RefreshMonitor.java @@ -0,0 +1,36 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.core.definition; + +/** + * Implementing this interface means that the object monitors the sources it + * uses to check when they change. + * + * @since 2.1.0 + */ +public interface RefreshMonitor { + + /** + * Indicates whether the sources are out of date and need to be reloaded. + * + * @return true if the sources need to be refreshed. + * @since 2.1.0 + */ + boolean refreshRequired(); +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/core/definition/UnresolvingLocaleDefinitionsFactory.java b/plugins/tiles/src/main/java/org/apache/tiles/core/definition/UnresolvingLocaleDefinitionsFactory.java new file mode 100644 index 000000000..5a35e4825 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/core/definition/UnresolvingLocaleDefinitionsFactory.java @@ -0,0 +1,86 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tiles.core.definition; + +import org.apache.tiles.api.Definition; +import org.apache.tiles.request.Request; +import org.apache.tiles.core.definition.dao.DefinitionDAO; +import org.apache.tiles.core.locale.LocaleResolver; + +import java.util.Locale; + +/** + * {@link DefinitionsFactory DefinitionsFactory} implementation that manages + * Definitions configuration data from URLs, without resolving definition + * inheritance when a definition is returned.

+ *

+ * The Definition objects are read from the + * {@link org.apache.tiles.core.definition.digester.DigesterDefinitionsReader} + * class unless another implementation is specified. + *

+ * @since 2.2.1 + */ +public class UnresolvingLocaleDefinitionsFactory implements DefinitionsFactory { + + /** + * The definition DAO that extracts the definitions from the sources. + * + * @since 2.2.1 + */ + protected DefinitionDAO definitionDao; + + /** + * The locale resolver object. + * + * @since 2.2.1 + */ + protected LocaleResolver localeResolver; + + /** + * Sets the locale resolver to use. + * + * @param localeResolver The locale resolver. + * @since 2.2.1 + */ + public void setLocaleResolver(LocaleResolver localeResolver) { + this.localeResolver = localeResolver; + } + + /** + * Sets the definition DAO to use. It must be locale-based. + * + * @param definitionDao The definition DAO. + * @since 2.2.1 + */ + public void setDefinitionDAO(DefinitionDAO definitionDao) { + this.definitionDao = definitionDao; + } + + /** {@inheritDoc} */ + public Definition getDefinition(String name, Request tilesContext) { + Locale locale = null; + + if (tilesContext != null) { + locale = localeResolver.resolveLocale(tilesContext); + } + + return definitionDao.getDefinition(name, locale); + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/core/definition/dao/BaseLocaleUrlDefinitionDAO.java b/plugins/tiles/src/main/java/org/apache/tiles/core/definition/dao/BaseLocaleUrlDefinitionDAO.java new file mode 100644 index 000000000..cb01af434 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/core/definition/dao/BaseLocaleUrlDefinitionDAO.java @@ -0,0 +1,163 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.core.definition.dao; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.apache.tiles.api.Definition; +import org.apache.tiles.core.definition.DefinitionsFactoryException; +import org.apache.tiles.core.definition.DefinitionsReader; +import org.apache.tiles.core.definition.RefreshMonitor; +import org.apache.tiles.request.ApplicationContext; +import org.apache.tiles.request.ApplicationResource; + +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Set; + +/** + * Base abstract class for a DAO that is based on URLs and locale as a + * customization key. + * + * @since 2.1.0 + */ +public abstract class BaseLocaleUrlDefinitionDAO implements DefinitionDAO, RefreshMonitor { + + /** + * The logging object. + */ + private static final Logger LOG = LogManager.getLogger(BaseLocaleUrlDefinitionDAO.class); + + /** + * Contains the URL objects identifying where configuration data is found. + * + * @since 2.1.0 + */ + protected List sources; + + /** + * Contains the dates that the URL sources were last modified. + * + * @since 2.1.0 + */ + protected Map lastModifiedDates; + + /** + * Reader used to get definitions from the sources. + * + * @since 2.1.0 + */ + protected DefinitionsReader reader; + + /** + * ApplicationContext to locate the source files. + * + * @since 3.0.0 + */ + protected ApplicationContext applicationContext; + + /** + * Constructor. + */ + public BaseLocaleUrlDefinitionDAO(ApplicationContext applicationContext) { + this.applicationContext = applicationContext; + lastModifiedDates = new HashMap<>(); + } + + public void setSources(List sources) { + // filter out any sources that are already localized + ArrayList defaultSources = new ArrayList<>(); + for (ApplicationResource source : sources) { + if (Locale.ROOT.equals(source.getLocale())) { + defaultSources.add(source); + } + } + this.sources = defaultSources; + } + + public void setReader(DefinitionsReader reader) { + this.reader = reader; + } + + /** + * {@inheritDoc} + */ + public boolean refreshRequired() { + boolean status = false; + + Set paths = lastModifiedDates.keySet(); + + try { + for (String path : paths) { + Long lastModifiedDate = lastModifiedDates.get(path); + ApplicationResource resource = applicationContext.getResource(path); + long newModDate = resource.getLastModified(); + if (newModDate != lastModifiedDate) { + status = true; + break; + } + } + } catch (IOException e) { + LOG.warn("Exception while monitoring update times.", e); + return true; + } + return status; + } + + /** + * Loads definitions from an URL without loading from "parent" URLs. + * + * @param resource The URL to read. + * @return The definition map that has been read. + */ + protected Map loadDefinitionsFromResource(ApplicationResource resource) { + Map defsMap = null; + + InputStream stream = null; + try { + lastModifiedDates.put(resource.getLocalePath(), resource + .getLastModified()); + + // Definition must be collected, starting from the base + // source up to the last localized file. + stream = resource.getInputStream(); + defsMap = reader.read(stream); + } catch (FileNotFoundException e) { + // File not found. continue. + LOG.debug("File {} not found, continue", resource); + } catch (IOException e) { + throw new DefinitionsFactoryException("I/O error processing configuration.", e); + } finally { + try { + if (stream != null) { + stream.close(); + } + } catch (IOException ignore) { + } + } + + return defsMap; + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/core/definition/dao/CachingLocaleUrlDefinitionDAO.java b/plugins/tiles/src/main/java/org/apache/tiles/core/definition/dao/CachingLocaleUrlDefinitionDAO.java new file mode 100644 index 000000000..b280fc97b --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/core/definition/dao/CachingLocaleUrlDefinitionDAO.java @@ -0,0 +1,272 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tiles.core.definition.dao; + +import org.apache.tiles.api.Definition; +import org.apache.tiles.core.definition.pattern.PatternDefinitionResolver; +import org.apache.tiles.core.definition.pattern.PatternDefinitionResolverAware; +import org.apache.tiles.request.ApplicationContext; +import org.apache.tiles.request.ApplicationResource; +import org.apache.tiles.request.locale.LocaleUtil; + +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.Locale; +import java.util.Map; + +/** + *

+ * A definitions DAO (loading URLs and using Locale as a customization key) that + * caches definitions that have been loaded in a raw way (i.e. with inheritance + * that is not resolved). + *

+ *

+ * It can check if the URLs change, but by default this feature is turned off. + *

+ * + * @since 2.1.0 + */ +public class CachingLocaleUrlDefinitionDAO extends BaseLocaleUrlDefinitionDAO implements PatternDefinitionResolverAware { + + /** + * Initialization parameter to set whether we want to refresh URLs when they + * change. + * + * @since 2.1.0 + */ + public static final String CHECK_REFRESH_INIT_PARAMETER = "org.apache.tiles.definition.dao.LocaleUrlDefinitionDAO.CHECK_REFRESH"; + + /** + * The locale-specific set of definitions objects. + * + * @since 2.1.0 + */ + protected Map> locale2definitionMap; + + /** + * Flag that, when true, enables automatic checking of URLs + * changing. + * + * @since 2.1.0 + */ + protected boolean checkRefresh = false; + + /** + * Resolves definitions using patterns. + * + * @since 2.2.0 + */ + protected PatternDefinitionResolver definitionResolver; + + /** + * Constructor. + * + * @since 2.1.0 + */ + public CachingLocaleUrlDefinitionDAO(ApplicationContext applicationContext) { + super(applicationContext); + locale2definitionMap = new HashMap<>(); + } + + /** + * {@inheritDoc} + */ + public void setPatternDefinitionResolver( + PatternDefinitionResolver definitionResolver) { + this.definitionResolver = definitionResolver; + } + + /** + * {@inheritDoc} + */ + public Definition getDefinition(String name, Locale customizationKey) { + Definition retValue = null; + if (customizationKey == null) { + customizationKey = Locale.ROOT; + } + Map definitions = getDefinitions(customizationKey); + if (definitions != null) { + retValue = definitions.get(name); + + if (retValue == null) { + retValue = getDefinitionFromResolver(name, customizationKey); + + if (retValue != null) { + synchronized (definitions) { + definitions.put(name, retValue); + } + } + } + } + + return retValue; + } + + /** + * {@inheritDoc} + */ + public Map getDefinitions(Locale customizationKey) { + if (customizationKey == null) { + customizationKey = Locale.ROOT; + } + Map retValue = locale2definitionMap + .get(customizationKey); + if (retValue == null || (checkRefresh && refreshRequired())) { + retValue = checkAndloadDefinitions(customizationKey); + } + return retValue; + } + + /** + * Sets the flag to check source refresh. If not called, the default is + * false. + * + * @param checkRefresh When true, enables automatic checking + * of sources changing. + * @since 2.1.0 + */ + public void setCheckRefresh(boolean checkRefresh) { + this.checkRefresh = checkRefresh; + } + + /** + * Returns a definition from the definition resolver. + * + * @param name The name of the definition. + * @param customizationKey The customization key to use. + * @return The resolved definition. + */ + protected Definition getDefinitionFromResolver(String name, + Locale customizationKey) { + return definitionResolver.resolveDefinition(name, + customizationKey); + } + + /** + * Checks if sources have changed. If yes, it clears the cache. Then continues + * loading definitions. + * + * @param customizationKey The locale to use when loading sources. + * @return The loaded definitions. + * @since 2.1.0 + */ + protected synchronized Map checkAndloadDefinitions(Locale customizationKey) { + Map existingDefinitions = locale2definitionMap.get(customizationKey); + boolean definitionsAlreadyLoaded = existingDefinitions != null; + if (definitionsAlreadyLoaded) { + return existingDefinitions; + } + if (checkRefresh && refreshRequired()) { + locale2definitionMap.clear(); + definitionResolver.clearPatternPaths(customizationKey); + } + loadDefinitions(customizationKey); + return locale2definitionMap.get(customizationKey); + } + + /** + * Tries to load definitions if necessary. + * + * @param customizationKey The locale to use when loading sources. + * @return The loaded definitions. + * @since 2.1.0 + */ + protected Map loadDefinitions(Locale customizationKey) { + Map localeDefsMap = locale2definitionMap + .get(customizationKey); + if (localeDefsMap != null) { + return localeDefsMap; + } + + return loadDefinitionsFromResources(customizationKey); + } + + /** + * Loads definitions from the sources. + * + * @param customizationKey The locale to use when loading Resources. + * @return The loaded definitions. + * @since 2.1.0 + */ + protected Map loadDefinitionsFromResources(Locale customizationKey) { + Map localeDefsMap = loadRawDefinitionsFromResources(customizationKey); + Map defsMap = definitionResolver + .storeDefinitionPatterns(copyDefinitionMap(localeDefsMap), + customizationKey); + locale2definitionMap.put(customizationKey, defsMap); + return localeDefsMap; + } + + /** + * Loads the raw definitions from the sources associated with a locale. + * + * @param customizationKey The locale to use when loading Resources. + * @return The loaded definitions. + * @since 2.1.3 + */ + protected Map loadRawDefinitionsFromResources(Locale customizationKey) { + Map localeDefsMap; + + Locale parentLocale = LocaleUtil.getParentLocale(customizationKey); + localeDefsMap = new LinkedHashMap<>(); + if (parentLocale != null) { + Map parentDefs = loadRawDefinitionsFromResources(parentLocale); + if (parentDefs != null) { + localeDefsMap.putAll(parentDefs); + } + } + // For each source, the resource must be loaded. + for (ApplicationResource resource : sources) { + ApplicationResource newResource = applicationContext.getResource(resource, customizationKey); + if (newResource != null) { + Map defsMap = loadDefinitionsFromResource(newResource); + if (defsMap != null) { + localeDefsMap.putAll(defsMap); + } + } + } + return localeDefsMap; + } + + /** + * Loads parent definitions, i.e. definitions mapped to a parent locale. + * + * @param parentLocale The locale to use when loading URLs. + * @return The loaded parent definitions. + * @since 2.1.0 + */ + protected Map loadParentDefinitions(Locale parentLocale) { + return loadDefinitions(parentLocale); + } + + /** + * Copies the definition map to be passed to a higher level of customization + * key. + * + * @param localeDefsMap The map of definition to be copied. + * @return The copy of the definition map. This particular implementation + * return the localeDefsMap itself. + * @since 2.1.4 + */ + protected Map copyDefinitionMap( + Map localeDefsMap) { + return localeDefsMap; + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/core/definition/dao/DefinitionDAO.java b/plugins/tiles/src/main/java/org/apache/tiles/core/definition/dao/DefinitionDAO.java new file mode 100644 index 000000000..ce0b1ef4a --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/core/definition/dao/DefinitionDAO.java @@ -0,0 +1,54 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.core.definition.dao; + +import org.apache.tiles.api.Definition; + +import java.util.Map; + +/** + * It represents an object that provides definitions, depending on a + * customization key. + * + * @param The customization key class. + * @since 2.1.0 + */ +public interface DefinitionDAO { + + /** + * Returns a definition, given its name and the customization key. + * + * @param name The name of the definition. + * @param customizationKey The customization key. + * @return The requested definition, if found, otherwise null. + * The inheritance of the definition must not be resolved. + * @since 2.1.0 + */ + Definition getDefinition(String name, K customizationKey); + + /** + * Returns all the definitions used of a customization key. + * + * @param customizationKey The customization key. + * @return All the definitions that are connected to the customization key. + * The inheritance of the definitions must not be resolved. + * @since 2.1.0 + */ + Map getDefinitions(K customizationKey); +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/core/definition/dao/ResolvingLocaleUrlDefinitionDAO.java b/plugins/tiles/src/main/java/org/apache/tiles/core/definition/dao/ResolvingLocaleUrlDefinitionDAO.java new file mode 100644 index 000000000..d6af2f87b --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/core/definition/dao/ResolvingLocaleUrlDefinitionDAO.java @@ -0,0 +1,172 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tiles.core.definition.dao; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.apache.tiles.api.Definition; +import org.apache.tiles.core.definition.NoSuchDefinitionException; +import org.apache.tiles.request.ApplicationContext; + +import java.util.HashSet; +import java.util.LinkedHashMap; +import java.util.Locale; +import java.util.Map; +import java.util.Set; + +/** + *

+ * A definitions DAO (loading URLs and using Locale as a customization key) that + * caches definitions that have been loaded and resolves inheritances. + *

+ *

+ * It can check if the URLs change, but by default this feature is turned off. + *

+ * + * @since 2.1.0 + */ +public class ResolvingLocaleUrlDefinitionDAO extends CachingLocaleUrlDefinitionDAO { + + /** + * The logging object. + */ + private static final Logger LOG = LogManager.getLogger(ResolvingLocaleUrlDefinitionDAO.class); + + public ResolvingLocaleUrlDefinitionDAO(ApplicationContext applicationContext) { + super(applicationContext); + } + + /** {@inheritDoc} */ + @Override + protected Map loadParentDefinitions(Locale parentLocale) { + return loadRawDefinitionsFromResources(parentLocale); + } + + @Override + protected Map loadDefinitions(Locale customizationKey) { + Map localeDefsMap = super.loadDefinitions(customizationKey); + Map defsMap = definitionResolver + .storeDefinitionPatterns(copyDefinitionMap(localeDefsMap), + customizationKey); + resolveInheritances(defsMap, customizationKey); + locale2definitionMap.put(customizationKey, defsMap); + return defsMap; + } + + /** {@inheritDoc} */ + @Override + protected Definition getDefinitionFromResolver(String name, + Locale customizationKey) { + Definition retValue = super.getDefinitionFromResolver(name, customizationKey); + if (retValue != null && retValue.getExtends() != null) { + Definition parent = getDefinition(retValue.getExtends(), customizationKey); + retValue.inherit(parent); + } + + return retValue; + } + + /** + * Resolve locale-specific extended instances. + * + * @param map The definition map containing the definitions to resolve. + * @param locale The locale to use. + * @throws NoSuchDefinitionException If a parent definition is not found. + * @since 2.1.0 + */ + protected void resolveInheritances(Map map, Locale locale) { + if (map != null) { + Set alreadyResolvedDefinitions = new HashSet<>(); + for (Definition definition : map.values()) { + resolveInheritance(definition, map, locale, + alreadyResolvedDefinitions); + } // end loop + } + } + + /** + * Resolve locale-specific inheritance. First, resolve parent's inheritance, + * then set template to the parent's template. Also copy attributes setted + * in parent, and not set in child If instance doesn't extend anything, do + * nothing. + * + * @param definition The definition to resolve + * @param definitions The definitions to take when obtaining a parent + * definition. + * @param locale The locale to use. + * @param alreadyResolvedDefinitions The set of the definitions that have + * been already resolved. + * @throws NoSuchDefinitionException If an inheritance can not be solved. + * @since 2.1.0 + */ + protected void resolveInheritance(Definition definition, + Map definitions, Locale locale, + Set alreadyResolvedDefinitions) { + // Already done, or not needed ? + if (!definition.isExtending() || alreadyResolvedDefinitions.contains(definition.getName())) { + return; + } + + LOG.debug("Resolve definition for child name='{}' extends='{}.", definition.getName(), definition.getExtends()); + + // Set as visited to avoid endless recursivity. + alreadyResolvedDefinitions.add(definition.getName()); + + // Resolve parent before itself. + Definition parent = definitions.get(definition.getExtends()); + if (parent == null) { // error + String msg = "Error while resolving definition inheritance: child '" + + definition.getName() + + "' can't find its ancestor '" + + definition.getExtends() + + "'. Please check your description file."; + // to do : find better exception + throw new NoSuchDefinitionException(msg); + } + + resolveInheritance(parent, definitions, locale, + alreadyResolvedDefinitions); + + definition.inherit(parent); + } + + /** + * Copies the definition map to be passed to a higher level of customization + * key. + * + * @param localeDefsMap The map of definition to be copied. + * @return The copy of the definition map. This particular implementation + * deep-copies the localeDefsMap into a {@link LinkedHashMap}. + * @since 2.1.4 + */ + @Override + protected Map copyDefinitionMap( + Map localeDefsMap) { + Map retValue = new LinkedHashMap<>( + localeDefsMap.size()); + + for (Map.Entry entry : localeDefsMap.entrySet()) { + Definition definition = new Definition(entry.getValue()); + retValue.put(entry.getKey(), definition); + } + + return retValue; + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/core/definition/dao/package-info.java b/plugins/tiles/src/main/java/org/apache/tiles/core/definition/dao/package-info.java new file mode 100644 index 000000000..93cee8617 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/core/definition/dao/package-info.java @@ -0,0 +1,23 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +/** + * Classes to simply load definitions depending on a customization key. + * The package contains also basic implementations. + */ +package org.apache.tiles.core.definition.dao; diff --git a/plugins/tiles/src/main/java/org/apache/tiles/core/definition/digester/DigesterDefinitionsReader.java b/plugins/tiles/src/main/java/org/apache/tiles/core/definition/digester/DigesterDefinitionsReader.java new file mode 100644 index 000000000..4d756bbb2 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/core/definition/digester/DigesterDefinitionsReader.java @@ -0,0 +1,464 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tiles.core.definition.digester; + +import org.apache.commons.digester.Digester; +import org.apache.commons.digester.Rule; +import org.apache.tiles.api.Attribute; +import org.apache.tiles.api.Definition; +import org.apache.tiles.api.Expression; +import org.apache.tiles.api.ListAttribute; +import org.apache.tiles.core.definition.DefinitionsFactoryException; +import org.apache.tiles.core.definition.DefinitionsReader; +import org.xml.sax.Attributes; +import org.xml.sax.ErrorHandler; +import org.xml.sax.SAXException; +import org.xml.sax.SAXParseException; + +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; +import java.util.LinkedHashMap; +import java.util.Map; + +/** + * Reads {@link Definition} objects from + * an XML InputStream using Digester.

+ *

+ * This DefinitionsReader implementation expects the source to be + * passed as an InputStream. It parses XML data from the source + * and builds a Map of Definition objects. + *

+ *

+ *

+ * The Digester object can be configured by passing in initialization + * parameters. Currently the only parameter that is supported is the + * validating parameter. This value is set to false + * by default. To enable DTD validation for XML Definition files, give the init + * method a parameter with a key of + * org.apache.tiles.definition.digester.DigesterDefinitionsReader.PARSER_VALIDATE + * and a value of "true".

+ *

+ * The Definition objects are stored internally in a Map. The Map is stored as + * an instance variable rather than a local variable in the read + * method. This means that instances of this class are not + * thread-safe and access by multiple threads must be synchronized. + *

+ */ +public class DigesterDefinitionsReader implements DefinitionsReader { + + /** + * Digester validation parameter name. + */ + public static final String PARSER_VALIDATE_PARAMETER_NAME = "org.apache.tiles.definition.digester.DigesterDefinitionsReader.PARSER_VALIDATE"; + + // Digester rules constants for tag interception. + + /** + * Intercepts a <definition> tag. + */ + private static final String DEFINITION_TAG = "tiles-definitions/definition"; + + /** + * Intercepts a <put-attribute> tag. + */ + private static final String PUT_TAG = "*/definition/put-attribute"; + + /** + * Intercepts a <definition> inside a <put-attribute> tag. + */ + private static final String PUT_DEFINITION_TAG = "*/put-attribute/definition"; + + /** + * Intercepts a <definition> inside an <add-attribute> tag. + */ + private static final String ADD_DEFINITION_TAG = "*/add-attribute/definition"; + + /** + * Intercepts a <put-list-attribute> tag inside a %lt;definition> + * tag. + */ + private static final String DEF_LIST_TAG = "*/definition/put-list-attribute"; + + /** + * Intercepts a <add-attribute> tag. + */ + private static final String ADD_LIST_ELE_TAG = "*/add-attribute"; + + /** + * Intercepts a <add-list-attribute> tag. + */ + private static final String NESTED_LIST = "*/add-list-attribute"; + + // Handler class names. + + /** + * The handler to create definitions. + * + * @since 2.1.0 + */ + protected static final String DEFINITION_HANDLER_CLASS = + Definition.class.getName(); + + /** + * The handler to create attributes. + * + * @since 2.1.0 + */ + protected static final String PUT_ATTRIBUTE_HANDLER_CLASS = + Attribute.class.getName(); + + /** + * The handler to create list attributes. + * + * @since 2.1.0 + */ + protected static final String LIST_HANDLER_CLASS = + ListAttribute.class.getName(); + + /** + * Digester rule to manage definition filling. + * + * @since 2.1.2 + */ + public static class FillDefinitionRule extends Rule { + + /** {@inheritDoc} */ + @Override + public void begin(String namespace, String name, Attributes attributes) { + Definition definition = (Definition) digester.peek(); + definition.setName(attributes.getValue("name")); + definition.setPreparer(attributes.getValue("preparer")); + String extendsAttribute = attributes.getValue("extends"); + definition.setExtends(extendsAttribute); + + String template = attributes.getValue("template"); + Attribute attribute = Attribute.createTemplateAttribute(template); + attribute.setExpressionObject(Expression + .createExpressionFromDescribedExpression(attributes + .getValue("templateExpression"))); + attribute.setRole(attributes.getValue("role")); + String templateType = attributes.getValue("templateType"); + if (templateType != null) { + attribute.setRenderer(templateType); + } else if (extendsAttribute != null) { + attribute.setRenderer(null); + } + definition.setTemplateAttribute(attribute); + } + } + + /** + * Digester rule to manage attribute filling. + * + * @since 2.1.0 + */ + public static class FillAttributeRule extends Rule { + + /** {@inheritDoc} */ + @Override + public void begin(String namespace, String name, Attributes attributes) { + Attribute attribute = (Attribute) digester.peek(); + attribute.setValue(attributes.getValue("value")); + String expression = attributes.getValue("expression"); + attribute.setExpressionObject(Expression + .createExpressionFromDescribedExpression(expression)); + attribute.setRole(attributes.getValue("role")); + attribute.setRenderer(attributes.getValue("type")); + } + } + + /** + * Digester rule to manage assignment of the attribute to the parent + * element. + * + * @since 2.1.0 + */ + public static class PutAttributeRule extends Rule { + + /** {@inheritDoc} */ + @Override + public void begin(String namespace, String name, Attributes attributes) { + Attribute attribute = (Attribute) digester.peek(0); + Definition definition = (Definition) digester.peek(1); + definition.putAttribute(attributes.getValue("name"), attribute, + "true".equals(attributes.getValue("cascade"))); + } + } + + /** + * Digester rule to manage assignment of a nested definition in an attribute + * value. + * + * @since 2.1.0 + */ + public class AddNestedDefinitionRule extends Rule { + + /** {@inheritDoc} */ + @Override + public void begin(String namespace, String name, Attributes attributes) { + Definition definition = (Definition) digester.peek(0); + if (definition.getName() == null) { + definition.setName(getNextUniqueDefinitionName(definitions)); + } + Attribute attribute = (Attribute) digester.peek(1); + attribute.setValue(definition.getName()); + attribute.setRenderer("definition"); + } + } + + /** + * Digester object used to read Definition data + * from the source. + */ + protected Digester digester; + + /** + * The set of public identifiers, and corresponding resource names for + * the versions of the configuration file DTDs we know about. There + * MUST be an even number of Strings in this list! + */ + protected String[] registrations; + + /** + * Stores Definition objects. + */ + private Map definitions; + + /** + * Index to be used to create unique definition names for anonymous + * (nested) definitions. + */ + private int anonymousDefinitionIndex = 1; + + /** + * Creates a new instance of DigesterDefinitionsReader. + */ + public DigesterDefinitionsReader() { + digester = new Digester(); + digester.setNamespaceAware(true); + digester.setUseContextClassLoader(true); + digester.setErrorHandler(new ThrowingErrorHandler()); + + // Register our local copy of the DTDs that we can find + String[] registrations = getRegistrations(); + for (int i = 0; i < registrations.length; i += 2) { + URL url = this.getClass().getResource( + registrations[i + 1]); + if (url != null) { + digester.register(registrations[i], url.toString()); + } + } + + initSyntax(digester); + } + + /** + * Sets the validation of XML files. + * + * @param validating true means that XML validation is turned + * on. false otherwise. + * @since 3.3.0 + */ + public void setValidating(boolean validating) { + digester.setValidating(validating); + } + + /** + * Reads {@link Definition} objects from a source. + *

+ * Implementations should publish what type of source object is expected. + * + * @param source The InputStream source from which definitions + * will be read. + * @return a Map of Definition objects read from + * the source. + * @throws DefinitionsFactoryException If the source is invalid or + * an error occurs when reading definitions. + */ + public Map read(Object source) { + // This is an instance variable instead of a local variable because + // we want to be able to call the addDefinition method to populate it. + // But we reset the Map here, which, of course, has threading implications. + definitions = new LinkedHashMap<>(); + + if (source == null) { + // Perhaps we should throw an exception here. + return null; + } + + InputStream input; + try { + input = (InputStream) source; + } catch (ClassCastException e) { + throw new DefinitionsFactoryException( + "Invalid source type. Requires java.io.InputStream.", e); + } + + try { + // set first object in stack + //digester.clear(); + digester.push(this); + // parse + digester.parse(input); + + } catch (SAXException e) { + throw new DefinitionsFactoryException( + "XML error reading definitions.", e); + } catch (IOException e) { + throw new DefinitionsFactoryException( + "I/O Error reading definitions.", e); + } finally { + digester.clear(); + } + + return definitions; + } + + /** + * Initialised the syntax for reading XML files containing Tiles + * definitions. + * + * @param digester The digester to initialize. + */ + protected void initSyntax(Digester digester) { + initDigesterForTilesDefinitionsSyntax(digester); + } + + + /** + * Init digester for Tiles syntax with first element = tiles-definitions. + * + * @param digester Digester instance to use. + */ + private void initDigesterForTilesDefinitionsSyntax(Digester digester) { + // syntax rules + digester.addObjectCreate(DEFINITION_TAG, DEFINITION_HANDLER_CLASS); + digester.addRule(DEFINITION_TAG, new FillDefinitionRule()); + digester.addSetNext(DEFINITION_TAG, "addDefinition", DEFINITION_HANDLER_CLASS); + + // nested definition rules + digester.addObjectCreate(PUT_DEFINITION_TAG, DEFINITION_HANDLER_CLASS); + digester.addRule(PUT_DEFINITION_TAG, new FillDefinitionRule()); + digester.addSetRoot(PUT_DEFINITION_TAG, "addDefinition"); + digester.addRule(PUT_DEFINITION_TAG, new AddNestedDefinitionRule()); + digester.addObjectCreate(ADD_DEFINITION_TAG, DEFINITION_HANDLER_CLASS); + digester.addRule(ADD_DEFINITION_TAG, new FillDefinitionRule()); + digester.addSetRoot(ADD_DEFINITION_TAG, "addDefinition"); + digester.addRule(ADD_DEFINITION_TAG, new AddNestedDefinitionRule()); + + // put / putAttribute rules + // Rules for a same pattern are called in order, but rule.end() are called + // in reverse order. + // SetNext and CallMethod use rule.end() method. So, placing SetNext in + // first position ensure it will be called last (sic). + digester.addObjectCreate(PUT_TAG, PUT_ATTRIBUTE_HANDLER_CLASS); + digester.addRule(PUT_TAG, new FillAttributeRule()); + digester.addRule(PUT_TAG, new PutAttributeRule()); + // Definition level list rules + // This is rules for lists nested in a definition + digester.addObjectCreate(DEF_LIST_TAG, LIST_HANDLER_CLASS); + digester.addSetProperties(DEF_LIST_TAG); + digester.addRule(DEF_LIST_TAG, new PutAttributeRule()); + // list elements rules + // We use Attribute class to avoid rewriting a new class. + // Name part can't be used in listElement attribute. + digester.addObjectCreate(ADD_LIST_ELE_TAG, PUT_ATTRIBUTE_HANDLER_CLASS); + digester.addRule(ADD_LIST_ELE_TAG, new FillAttributeRule()); + digester.addSetNext(ADD_LIST_ELE_TAG, "add", PUT_ATTRIBUTE_HANDLER_CLASS); + + // nested list elements rules + // Create a list handler, and add it to parent list + digester.addObjectCreate(NESTED_LIST, LIST_HANDLER_CLASS); + digester.addSetProperties(NESTED_LIST); + digester.addSetNext(NESTED_LIST, "add", PUT_ATTRIBUTE_HANDLER_CLASS); + } + + /** + * Adds a new Definition to the internal Map or replaces + * an existing one. + * + * @param definition The Definition object to be added. + */ + public void addDefinition(Definition definition) { + String name = definition.getName(); + if (name == null) { + throw new DigesterDefinitionsReaderException("A root definition has been defined with no name"); + } + + definitions.put(name, definition); + } + + /** + * Error Handler that throws every exception it receives. + */ + private static class ThrowingErrorHandler implements ErrorHandler { + + /** {@inheritDoc} */ + public void warning(SAXParseException exception) throws SAXException { + throw exception; + } + + /** {@inheritDoc} */ + public void error(SAXParseException exception) throws SAXException { + throw exception; + } + + /** {@inheritDoc} */ + public void fatalError(SAXParseException exception) throws SAXException { + throw exception; + } + } + + /** + * Returns the registrations for local DTDs. + * + * @return An array containing the locations for registrations of local + * DTDs. + * @since 2.1.0 + */ + protected String[] getRegistrations() { + if (registrations == null) { + registrations = new String[] { + "-//Apache Software Foundation//DTD Tiles Configuration 3.0//EN", + "/org/apache/tiles/resources/tiles-config_3_0.dtd"}; + } + return registrations; + } + + /** + * Create a unique definition name usable to store anonymous definitions. + * + * @param definitions The already created definitions. + * @return The unique definition name to be used to store the definition. + * @since 2.1.0 + */ + protected String getNextUniqueDefinitionName( + Map definitions) { + String candidate; + + do { + candidate = "$anonymousDefinition" + anonymousDefinitionIndex; + anonymousDefinitionIndex++; + } while (definitions.containsKey(candidate)); + + return candidate; + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/core/definition/digester/DigesterDefinitionsReaderException.java b/plugins/tiles/src/main/java/org/apache/tiles/core/definition/digester/DigesterDefinitionsReaderException.java new file mode 100644 index 000000000..ca501e089 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/core/definition/digester/DigesterDefinitionsReaderException.java @@ -0,0 +1,40 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.core.definition.digester; + +import org.apache.tiles.api.TilesException; + +/** + * Indicates that something went wrong during the use of + * {@link DigesterDefinitionsReader}. + * @since 2.1.0 + */ +public class DigesterDefinitionsReaderException extends TilesException { + + /** + * Constructor. + * + * @param message The detail message. + * @since 2.1.0 + */ + public DigesterDefinitionsReaderException(String message) { + super(message); + } + +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/core/definition/digester/package-info.java b/plugins/tiles/src/main/java/org/apache/tiles/core/definition/digester/package-info.java new file mode 100644 index 000000000..49764f7cc --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/core/definition/digester/package-info.java @@ -0,0 +1,22 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +/** + * Allows reading definitions with the use of Jakarta Commons Digester. + */ +package org.apache.tiles.core.definition.digester; diff --git a/plugins/tiles/src/main/java/org/apache/tiles/core/definition/package-info.java b/plugins/tiles/src/main/java/org/apache/tiles/core/definition/package-info.java new file mode 100644 index 000000000..1dc51fc77 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/core/definition/package-info.java @@ -0,0 +1,23 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +/** + * It contains classes and interfaces to allow manipulations of "definitions", i.e. + * objects made of a template page and a number of filled attributes. + */ +package org.apache.tiles.core.definition; diff --git a/plugins/tiles/src/main/java/org/apache/tiles/core/definition/pattern/AbstractPatternDefinitionResolver.java b/plugins/tiles/src/main/java/org/apache/tiles/core/definition/pattern/AbstractPatternDefinitionResolver.java new file mode 100644 index 000000000..a960ec9bf --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/core/definition/pattern/AbstractPatternDefinitionResolver.java @@ -0,0 +1,106 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.core.definition.pattern; + +import org.apache.tiles.api.Definition; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * A pattern definition resolver that stores {@link DefinitionPatternMatcher} + * separated by customization key.
+ * Implementations should provide a way to translate a definition to a + * {@link DefinitionPatternMatcher}. + * + * @param The type of the customization key. + * @since 2.2.0 + */ +public abstract class AbstractPatternDefinitionResolver implements PatternDefinitionResolver { + + /** + * Stores patterns depending on the locale they refer to. + */ + private final Map> localePatternPaths = new HashMap<>(); + + /** {@inheritDoc} */ + public Definition resolveDefinition(String name, T customizationKey) { + Definition retValue = null; + if (localePatternPaths.containsKey(customizationKey)) { + retValue = searchAndResolveDefinition(localePatternPaths + .get(customizationKey), name); + } + return retValue; + } + + /** {@inheritDoc} */ + public Map storeDefinitionPatterns(Map localeDefsMap, T customizationKey) { + List lpaths = localePatternPaths.computeIfAbsent(customizationKey, k -> new ArrayList<>()); + return addDefinitionsAsPatternMatchers(lpaths, localeDefsMap); + } + + /** + * Adds definitions, filtering and adding them to the list of definition + * pattern matchers. Only a subset of definitions will be transformed into + * definition pattern matchers. + * + * @param matchers The list containing the currently stored definition pattern + * matchers. + * @param defsMap The definition map to parse. + * @return The map of the definitions not recognized as containing + * definition patterns. + * @since 2.2.1 + */ + protected abstract Map addDefinitionsAsPatternMatchers(List matchers, Map defsMap); + + /** + * Try to resolve a definition by iterating all pattern matchers. + * + * @param paths The list containing the currently stored paths. + * @param name The name of the definition to resolve. + * @return A definition, if found, or null if not. + */ + private Definition searchAndResolveDefinition(List paths, String name) { + Definition d = null; + + for (DefinitionPatternMatcher wm : paths) { + d = wm.createDefinition(name); + if (d != null) { + break; + } + } + + return d; + } + + + /** + * Used to clear all entries in the localePatternPaths for a specific locale. Necessary when reloading definition + * files to ensure that the list is cleared first + * + * @param customizationKey customization key + */ + @Override + public void clearPatternPaths(T customizationKey) { + if (localePatternPaths.get(customizationKey) != null) + localePatternPaths.get(customizationKey).clear(); + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/core/definition/pattern/BasicPatternDefinitionResolver.java b/plugins/tiles/src/main/java/org/apache/tiles/core/definition/pattern/BasicPatternDefinitionResolver.java new file mode 100644 index 000000000..541805c23 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/core/definition/pattern/BasicPatternDefinitionResolver.java @@ -0,0 +1,75 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.core.definition.pattern; + +import org.apache.tiles.api.Definition; + +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * A pattern definition resolver that stores {@link org.apache.tiles.core.definition.pattern.DefinitionPatternMatcher} + * separated by customization key.
+ * It delegates creation of definition pattern matchers to a + * {@link DefinitionPatternMatcherFactory} and recgnizes patterns through the + * use of a {@link PatternRecognizer}. + * + * @param The type of the customization key. + * @since 2.2.0 + */ +public class BasicPatternDefinitionResolver extends AbstractPatternDefinitionResolver { + + /** + * The factory of pattern matchers. + */ + private final DefinitionPatternMatcherFactory definitionPatternMatcherFactory; + + /** + * The pattern recognizer. + */ + private final PatternRecognizer patternRecognizer; + + /** + * Constructor. + * + * @param definitionPatternMatcherFactory The definition pattern matcher factory. + * @param patternRecognizer The pattern recognizer. + */ + public BasicPatternDefinitionResolver(DefinitionPatternMatcherFactory definitionPatternMatcherFactory, PatternRecognizer patternRecognizer) { + this.definitionPatternMatcherFactory = definitionPatternMatcherFactory; + this.patternRecognizer = patternRecognizer; + } + + /** {@inheritDoc} */ + @Override + protected Map addDefinitionsAsPatternMatchers(List matchers, Map defsMap) { + Set excludedKeys = new LinkedHashSet<>(); + for (Map.Entry de : defsMap.entrySet()) { + String key = de.getKey(); + if (patternRecognizer.isPatternRecognized(key)) { + matchers.add(definitionPatternMatcherFactory.createDefinitionPatternMatcher(key, de.getValue())); + } else { + excludedKeys.add(key); + } + } + return PatternUtil.createExtractedMap(defsMap, excludedKeys); + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/core/definition/pattern/DefinitionPatternMatcher.java b/plugins/tiles/src/main/java/org/apache/tiles/core/definition/pattern/DefinitionPatternMatcher.java new file mode 100644 index 000000000..657780650 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/core/definition/pattern/DefinitionPatternMatcher.java @@ -0,0 +1,40 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.core.definition.pattern; + +import org.apache.tiles.api.Definition; + +/** + * Matches a definition name to a definition, through pattern-matching. The + * matched pattern should be a single one. + * @since 2.2.0 + */ +public interface DefinitionPatternMatcher { + + /** + * Creates a definition, given the definition name, through the use of + * pattern matching. + * + * @param definitionName The definition name to match. + * @return The created definition, if matched, or null if not + * matched. + * @since 2.2.0 + */ + Definition createDefinition(String definitionName); +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/core/definition/pattern/DefinitionPatternMatcherFactory.java b/plugins/tiles/src/main/java/org/apache/tiles/core/definition/pattern/DefinitionPatternMatcherFactory.java new file mode 100644 index 000000000..df5890744 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/core/definition/pattern/DefinitionPatternMatcherFactory.java @@ -0,0 +1,41 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.core.definition.pattern; + +import org.apache.tiles.api.Definition; + +/** + * Creates a new definition pattern matcher for the given pattern and the given + * base definition with pattern expressions. + * @since 2.2.0 + */ +public interface DefinitionPatternMatcherFactory { + + /** + * Creates a new definition pattern matcher. + * + * @param pattern The pattern to be matched. + * @param definition The base definition. Created definitions by + * {@link DefinitionPatternMatcher#createDefinition(String)} will created + * with this one as a basis. + * @return The definition pattern matcher. + * @since 2.2.0 + */ + DefinitionPatternMatcher createDefinitionPatternMatcher(String pattern, Definition definition); +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/core/definition/pattern/PatternDefinitionResolver.java b/plugins/tiles/src/main/java/org/apache/tiles/core/definition/pattern/PatternDefinitionResolver.java new file mode 100644 index 000000000..959f082b9 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/core/definition/pattern/PatternDefinitionResolver.java @@ -0,0 +1,63 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.core.definition.pattern; + +import org.apache.tiles.api.Definition; + +import java.util.Map; + +/** + * Resolves a definition starting from patterns stored in definition maps. + * + * @param The type of the customization key. + * @since 2.2.0 + */ +public interface PatternDefinitionResolver { + + /** + * Stores definition patterns. + * + * @param localeDefsMap The map of definitions that may contain also + * patterns. + * @param customizationKey The customization key. + * @return The map of the definitions not recognized as containing + * definition patterns. + * @since 2.2.1 + */ + Map storeDefinitionPatterns(Map localeDefsMap, T customizationKey); + + /** + * Resolves a definition searching in all patterns for the requested + * customization key. + * + * @param name The name of the definition. + * @param customizationKey The customization key. + * @return The resolved definition. + * @since 2.2.0 + */ + Definition resolveDefinition(String name, T customizationKey); + + /** + * Used to clear all entries in the localePatternPaths for a specific locale. Necessary when reloading definition + * files to ensure that the list is cleared first + * + * @param customizationKey customization key + */ + void clearPatternPaths(T customizationKey); +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/core/definition/pattern/PatternDefinitionResolverAware.java b/plugins/tiles/src/main/java/org/apache/tiles/core/definition/pattern/PatternDefinitionResolverAware.java new file mode 100644 index 000000000..e91945973 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/core/definition/pattern/PatternDefinitionResolverAware.java @@ -0,0 +1,36 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.core.definition.pattern; + +/** + * It indicates an object that uses a {@link org.apache.tiles.core.definition.pattern.PatternDefinitionResolver}. + * + * @param The type of the customization key. + * @since 2.2.0 + */ +public interface PatternDefinitionResolverAware { + + /** + * Sets the pattern definition resolver to use. + * + * @param definitionResolver The pattern definition resolver. + * @since 2.2.0 + */ + void setPatternDefinitionResolver(PatternDefinitionResolver definitionResolver); +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/core/definition/pattern/PatternRecognizer.java b/plugins/tiles/src/main/java/org/apache/tiles/core/definition/pattern/PatternRecognizer.java new file mode 100644 index 000000000..0f3b23e66 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/core/definition/pattern/PatternRecognizer.java @@ -0,0 +1,37 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tiles.core.definition.pattern; + +/** + * Checks if a pattern (or a candidate one) is recognized as a pattern. + * + * @since 2.2.0 + */ +public interface PatternRecognizer { + + /** + * Checks if a pattern is recognized as a pattern. + * + * @param candidatePattern The pattern to check. + * @return true if the pattern has been recognized. + * @since 2.2.0 + */ + boolean isPatternRecognized(String candidatePattern); +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/core/definition/pattern/PatternUtil.java b/plugins/tiles/src/main/java/org/apache/tiles/core/definition/pattern/PatternUtil.java new file mode 100644 index 000000000..6d3dc39bc --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/core/definition/pattern/PatternUtil.java @@ -0,0 +1,240 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tiles.core.definition.pattern; + +import org.apache.tiles.api.Attribute; +import org.apache.tiles.api.Definition; +import org.apache.tiles.api.Expression; +import org.apache.tiles.api.ListAttribute; + +import java.text.MessageFormat; +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Set; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Utilities for pattern matching and substitution. + * + * @since 2.2.0 + */ +public final class PatternUtil { + + /** + * The root locale. Notice that this is a replacement for {@link Locale#ROOT} for + * Java 1.6. + */ + private static final Locale ROOT_LOCALE = new Locale("", ""); + + /** Pattern to find {.*} occurrences that do not match {[0-9]+} so to prevent MessageFormat from crashing. + */ + private static final Pattern INVALID_FORMAT_ELEMENT = Pattern.compile("\\{[^}0-9]+}"); + + /** + * Private constructor to avoid instantiation. + */ + private PatternUtil() { + } + + /** + * Creates a definition given its representation with wildcards and + * attribute values with placeholders, replacing real values into + * placeholders. + * + * @param d The definition to replace. + * @param name The name of the definition to be created. + * @param varsOrig The variables to be substituted. + * @return The definition that can be rendered. + * @since 2.2.0 + */ + public static Definition replacePlaceholders(Definition d, String name, + Object... varsOrig) { + + Object[] vars = replaceNullsWithBlank(varsOrig); + + Definition nudef = new Definition(); + + nudef.setExtends(replace(d.getExtends(), vars)); + nudef.setName(name); + nudef.setPreparer(replace(d.getPreparer(), vars)); + Attribute templateAttribute = d.getTemplateAttribute(); + if (templateAttribute != null) { + nudef.setTemplateAttribute(replaceVarsInAttribute( + templateAttribute, vars)); + } + + Set attributeNames = d.getLocalAttributeNames(); + if (attributeNames != null && !attributeNames.isEmpty()) { + for (String attributeName : attributeNames) { + Attribute attr = d.getLocalAttribute(attributeName); + Attribute nuattr = replaceVarsInAttribute(attr, vars); + + nudef.putAttribute(replace(attributeName, vars), nuattr); + } + } + + attributeNames = d.getCascadedAttributeNames(); + if (attributeNames != null && !attributeNames.isEmpty()) { + for (String attributeName : attributeNames) { + Attribute attr = d.getCascadedAttribute(attributeName); + Attribute nuattr = replaceVarsInAttribute(attr, vars); + + nudef.putAttribute(replace(attributeName, vars), nuattr, true); + } + } + + return nudef; + } + + /** + * Creates a new map that contains all the entries of the + * defsMap whose keys are contained in keys. + * + * @param map The map to read. + * @param keys The keys to extract. + * @param The key of the map. + * @param The value of the map. + * @return The extracted map. + * @since 2.2.1 + */ + public static Map createExtractedMap(Map map, Set keys) { + Map retValue = new LinkedHashMap<>(); + for (K key : keys) { + retValue.put(key, map.get(key)); + } + return retValue; + } + + /** + * Replaces variables into an attribute. + * + * @param attr The attribute to be used as a basis, containing placeholders + * for variables. + * @param vars The variables to replace. + * @return A new instance of an attribute, whose properties have been + * replaced with variables' values. + */ + private static Attribute replaceVarsInAttribute(Attribute attr, + Object... vars) { + Attribute nuattr; + if (attr instanceof ListAttribute) { + nuattr = replaceVarsInListAttribute((ListAttribute) attr, vars); + } else { + nuattr = replaceVarsInSimpleAttribute(attr, vars); + } + return nuattr; + } + + /** + * Replaces variables into a simple (not list) attribute. + * + * @param attr The attribute to be used as a basis, containing placeholders + * for variables. + * @param vars The variables to replace. + * @return A new instance of an attribute, whose properties have been + * replaced with variables' values. + */ + private static Attribute replaceVarsInSimpleAttribute(Attribute attr, + Object... vars) { + Attribute nuattr; + nuattr = new Attribute(); + + nuattr.setRole(replace(attr.getRole(), vars)); + nuattr.setRenderer(attr.getRenderer()); + Expression expressionObject = attr.getExpressionObject(); + if (expressionObject != null) { + Expression newExpressionObject = Expression + .createExpression(replace(expressionObject.getExpression(), vars), expressionObject.getLanguage()); + nuattr.setExpressionObject(newExpressionObject); + } + + Object value = attr.getValue(); + if (value instanceof String) { + value = replace((String) value, vars); + } + nuattr.setValue(value); + return nuattr; + } + + /** + * Replaces variables into a list attribute. + * + * @param listAttr The attribute to be used as a basis, containing attributes + * that may contain placeholders for variables. + * @param vars The variables to replace. + * @return A new instance of an attribute, whose properties have been + * replaced with variables' values. + */ + private static Attribute replaceVarsInListAttribute(ListAttribute listAttr, + Object... vars) { + Attribute nuattr; + ListAttribute nuListAttr = new ListAttribute(); + nuListAttr.setInherit(listAttr.isInherit()); + List nuItems = nuListAttr.getValue(); + for (Attribute item : listAttr.getValue()) { + Attribute child = item; + child = replaceVarsInAttribute(child, vars); + nuItems.add(child); + } + nuattr = nuListAttr; + return nuattr; + } + + /** + * Replaces a string with placeholders using values of a variable map. + * + * @param st The string to replace. + * @param vars The variables. + * @return The replaced string. + */ + private static String replace(String st, Object... vars) { + if (st != null && st.indexOf('{') >= 0) { + + // replace them with markers + List originals = new ArrayList<>(); + for(Matcher m = INVALID_FORMAT_ELEMENT.matcher(st); m.find() ; m = INVALID_FORMAT_ELEMENT.matcher(st)) { + originals.add(m.group()); + st = m.replaceFirst("INVALID_FORMAT_ELEMENT"); + } + + // do the MessageFormat replacement (escaping quote characters) + st = new MessageFormat(st.replaceAll("'", "'''"), ROOT_LOCALE) + .format(vars, new StringBuffer(), null).toString(); + + // return the markers to their original invalid occurrences + for (String original : originals) { + st = st.replaceFirst("INVALID_FORMAT_ELEMENT", original); + } + } + return st; + } + + private static Object[] replaceNullsWithBlank(Object[] varsOrig) { + Object[] vars = new Object[varsOrig.length]; + for(int i = 0; i < varsOrig.length; ++i) { + vars[i] = null != varsOrig[i] ? varsOrig[i] : ""; + } + return vars; + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/core/definition/pattern/PrefixedPatternDefinitionResolver.java b/plugins/tiles/src/main/java/org/apache/tiles/core/definition/pattern/PrefixedPatternDefinitionResolver.java new file mode 100644 index 000000000..a2148f1d8 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/core/definition/pattern/PrefixedPatternDefinitionResolver.java @@ -0,0 +1,103 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.core.definition.pattern; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.apache.tiles.api.Definition; +import org.apache.tiles.api.Expression; + +import java.util.HashMap; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * This resolver allows the use of multiple pattern matching languages. The + * syntax of definition names must be LANGUAGENAME:expression.
+ * The different languages must be registered through the use of + * {@link #registerDefinitionPatternMatcherFactory(String, DefinitionPatternMatcherFactory)} + * method before using this resolver. + * + * @param The type of the customization key. + * @since 2.2.0 + */ +public class PrefixedPatternDefinitionResolver extends AbstractPatternDefinitionResolver { + + /** + * The logging object. + */ + private static final Logger LOG = LogManager.getLogger(PrefixedPatternDefinitionResolver.class); + + /** + * Matches languages names to the corresponding + * {@link DefinitionPatternMatcherFactory}. + */ + private final Map language2matcherFactory; + + /** + * Constructor. + * + * @since 2.2.0 + */ + public PrefixedPatternDefinitionResolver() { + language2matcherFactory = new HashMap<>(); + } + + /** + * Registers a {@link DefinitionPatternMatcherFactory} connected to a + * particular language. + * + * @param language The name of the language. + * @param factory The pattern matcher factory to register. + * @since 2.2.0 + */ + public void registerDefinitionPatternMatcherFactory(String language, + DefinitionPatternMatcherFactory factory) { + language2matcherFactory.put(language, factory); + } + + /** {@inheritDoc} */ + @Override + protected Map addDefinitionsAsPatternMatchers(List matchers, Map defsMap) { + Set excludedKeys = new LinkedHashSet(); + for (Map.Entry entry : defsMap.entrySet()) { + String key = entry.getKey(); + Expression expression = Expression + .createExpressionFromDescribedExpression(key); + if (expression.getLanguage() != null) { + DefinitionPatternMatcherFactory factory = language2matcherFactory + .get(expression.getLanguage()); + if (factory != null) { + DefinitionPatternMatcher matcher = factory + .createDefinitionPatternMatcher(expression + .getExpression(), new Definition(entry + .getValue())); + matchers.add(matcher); + } else { + LOG.warn("Cannot find a DefinitionPatternMatcherFactory for expression '{}'", key); + } + } else { + excludedKeys.add(key); + } + } + return PatternUtil.createExtractedMap(defsMap, excludedKeys); + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/core/definition/pattern/package-info.java b/plugins/tiles/src/main/java/org/apache/tiles/core/definition/pattern/package-info.java new file mode 100644 index 000000000..d23eb0cad --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/core/definition/pattern/package-info.java @@ -0,0 +1,22 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +/** + * Classes to manage pattern matching in definition names, and substitution in attributes. + */ +package org.apache.tiles.core.definition.pattern; diff --git a/plugins/tiles/src/main/java/org/apache/tiles/core/definition/pattern/regexp/RegexpDefinitionPatternMatcher.java b/plugins/tiles/src/main/java/org/apache/tiles/core/definition/pattern/regexp/RegexpDefinitionPatternMatcher.java new file mode 100644 index 000000000..f060d69a5 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/core/definition/pattern/regexp/RegexpDefinitionPatternMatcher.java @@ -0,0 +1,72 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tiles.core.definition.pattern.regexp; + +import org.apache.tiles.api.Definition; +import org.apache.tiles.core.definition.pattern.DefinitionPatternMatcher; +import org.apache.tiles.core.definition.pattern.PatternUtil; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Matches regular expression patterns in definitions. + * + * @since 2.2.0 + */ +public class RegexpDefinitionPatternMatcher implements DefinitionPatternMatcher { + + /** + * The pattern to match. + */ + private final Pattern pattern; + + /** + * The definition to use as a basis. + */ + private final Definition definition; + + /** + * Constructor. + * + * @param pattern The pattern to use, in string form. + * @param definition The definition to use as a basis. + * @since 2.2.0 + */ + public RegexpDefinitionPatternMatcher(String pattern, Definition definition) { + this.pattern = Pattern.compile(pattern); + this.definition = definition; + } + + /** {@inheritDoc} */ + public Definition createDefinition(String definitionName) { + Definition retValue = null; + Matcher matcher = pattern.matcher(definitionName); + if (matcher.matches()) { + int groupCount = matcher.groupCount() + 1; + Object[] vars = new Object[groupCount]; + for (int i = 0; i < groupCount; i++) { + vars[i] = matcher.group(i); + } + retValue = PatternUtil.replacePlaceholders(definition, definitionName, vars); + } + return retValue; + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/core/definition/pattern/regexp/RegexpDefinitionPatternMatcherFactory.java b/plugins/tiles/src/main/java/org/apache/tiles/core/definition/pattern/regexp/RegexpDefinitionPatternMatcherFactory.java new file mode 100644 index 000000000..77ae96c16 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/core/definition/pattern/regexp/RegexpDefinitionPatternMatcherFactory.java @@ -0,0 +1,36 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.core.definition.pattern.regexp; + +import org.apache.tiles.api.Definition; +import org.apache.tiles.core.definition.pattern.DefinitionPatternMatcher; +import org.apache.tiles.core.definition.pattern.DefinitionPatternMatcherFactory; + +/** + * Creates instances of {@link RegexpDefinitionPatternMatcher}. + */ +public class RegexpDefinitionPatternMatcherFactory implements DefinitionPatternMatcherFactory { + + /** + * {@inheritDoc} + */ + public DefinitionPatternMatcher createDefinitionPatternMatcher(String pattern, Definition definition) { + return new RegexpDefinitionPatternMatcher(pattern, definition); + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/core/definition/pattern/regexp/package-info.java b/plugins/tiles/src/main/java/org/apache/tiles/core/definition/pattern/regexp/package-info.java new file mode 100644 index 000000000..dd679897a --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/core/definition/pattern/regexp/package-info.java @@ -0,0 +1,22 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +/** + * In Tiles it is possible to use regular expression patterns thanks to this package. + */ +package org.apache.tiles.core.definition.pattern.regexp; diff --git a/plugins/tiles/src/main/java/org/apache/tiles/core/definition/pattern/wildcard/WildcardDefinitionPatternMatcher.java b/plugins/tiles/src/main/java/org/apache/tiles/core/definition/pattern/wildcard/WildcardDefinitionPatternMatcher.java new file mode 100644 index 000000000..265047159 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/core/definition/pattern/wildcard/WildcardDefinitionPatternMatcher.java @@ -0,0 +1,78 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.core.definition.pattern.wildcard; + +import org.apache.tiles.api.Definition; +import org.apache.tiles.core.definition.pattern.DefinitionPatternMatcher; +import org.apache.tiles.core.definition.pattern.PatternUtil; +import org.apache.tiles.core.util.WildcardHelper; + +import java.util.List; + +/** + * Matches wildcard patterns in definitions. + * + * @since 2.2.0 + */ +public class WildcardDefinitionPatternMatcher implements DefinitionPatternMatcher { + + /** + * Allows to parse wildcard expressions and to recognize substitution + * variables. + */ + private final WildcardHelper wildcardHelper; + + /** + * The definition to use as a basis. + */ + private final Definition definition; + + /** + * The pattern to use. + */ + private final int[] pattern; + + /** + * Constructor. + * + * @param pattern The pattern to use, in string form. + * @param definition The definition to use as a basis. + * @param wildcardHelper The object that parses wildcard expressions and + * recognized substitution variables. + * @since 2.2.0 + */ + public WildcardDefinitionPatternMatcher(String pattern, + Definition definition, WildcardHelper wildcardHelper) { + this.wildcardHelper = wildcardHelper; + this.definition = definition; + this.pattern = wildcardHelper.compilePattern(pattern); + } + + /** {@inheritDoc} */ + public Definition createDefinition(String definitionName) { + List vars = wildcardHelper.match(definitionName, pattern); + Definition d = null; + + if (vars != null) { + d = PatternUtil.replacePlaceholders(definition, definitionName, vars.toArray()); + } + + return d; + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/core/definition/pattern/wildcard/WildcardDefinitionPatternMatcherFactory.java b/plugins/tiles/src/main/java/org/apache/tiles/core/definition/pattern/wildcard/WildcardDefinitionPatternMatcherFactory.java new file mode 100644 index 000000000..34c1c793c --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/core/definition/pattern/wildcard/WildcardDefinitionPatternMatcherFactory.java @@ -0,0 +1,54 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.core.definition.pattern.wildcard; + +import org.apache.tiles.api.Definition; +import org.apache.tiles.core.definition.pattern.DefinitionPatternMatcher; +import org.apache.tiles.core.definition.pattern.DefinitionPatternMatcherFactory; +import org.apache.tiles.core.definition.pattern.PatternRecognizer; +import org.apache.tiles.core.util.WildcardHelper; + +/** + * Creates instances of {@link WildcardDefinitionPatternMatcher}. + * + * @since 2.2.0 + */ +public class WildcardDefinitionPatternMatcherFactory implements DefinitionPatternMatcherFactory, PatternRecognizer { + + /** + * Allows to parse wildcard expressions and to recognize substitution + * variables. + */ + private final WildcardHelper wildcardHelper = new WildcardHelper(); + + /** + * {@inheritDoc} + */ + public DefinitionPatternMatcher createDefinitionPatternMatcher( + String pattern, Definition definition) { + return new WildcardDefinitionPatternMatcher(pattern, definition, wildcardHelper); + } + + /** + * {@inheritDoc} + */ + public boolean isPatternRecognized(String candidatePattern) { + return candidatePattern.indexOf('*') >= 0; + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/core/definition/pattern/wildcard/package-info.java b/plugins/tiles/src/main/java/org/apache/tiles/core/definition/pattern/wildcard/package-info.java new file mode 100644 index 000000000..2b7f1231e --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/core/definition/pattern/wildcard/package-info.java @@ -0,0 +1,22 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +/** + * In Tiles it is possible to use wildcard patterns thanks to this package. + */ +package org.apache.tiles.core.definition.pattern.wildcard; diff --git a/plugins/tiles/src/main/java/org/apache/tiles/core/evaluator/AbstractAttributeEvaluator.java b/plugins/tiles/src/main/java/org/apache/tiles/core/evaluator/AbstractAttributeEvaluator.java new file mode 100644 index 000000000..b035a0bbc --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/core/evaluator/AbstractAttributeEvaluator.java @@ -0,0 +1,50 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.core.evaluator; + +import org.apache.tiles.api.Attribute; +import org.apache.tiles.api.Expression; +import org.apache.tiles.request.Request; + +/** + * Abstract class to link a correct evaluation of an attribute, by evaluating + * {@link Attribute#getValue()} and then {@link Attribute#getExpressionObject()}. + * + * @since 2.1.2 + */ +public abstract class AbstractAttributeEvaluator implements AttributeEvaluator { + + /** {@inheritDoc} */ + public Object evaluate(Attribute attribute, Request request) { + if (attribute == null) { + throw new IllegalArgumentException("The attribute cannot be null"); + } + + Object retValue = attribute.getValue(); + + if (retValue == null) { + Expression expression = attribute.getExpressionObject(); + if (expression != null) { + retValue = evaluate(attribute.getExpressionObject().getExpression(), request); + } + } + + return retValue; + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/core/evaluator/AttributeEvaluator.java b/plugins/tiles/src/main/java/org/apache/tiles/core/evaluator/AttributeEvaluator.java new file mode 100644 index 000000000..487c306c4 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/core/evaluator/AttributeEvaluator.java @@ -0,0 +1,50 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.core.evaluator; + +import org.apache.tiles.api.Attribute; +import org.apache.tiles.request.Request; + +/** + * It represents an object that resolves a string to return an object. + * + * @since 2.1.0 + */ +public interface AttributeEvaluator { + + /** + * Evaluates an expression. + * + * @param expression The expression to evaluate. + * @param request The request object. + * @return The evaluated object. + * @since 2.1.0 + */ + Object evaluate(String expression, Request request); + + /** + * Evaluates an attribute value. + * + * @param attribute The attribute to evaluate. + * @param request The request object. + * @return The evaluated object. + * @since 2.1.0 + */ + Object evaluate(Attribute attribute, Request request); +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/core/evaluator/AttributeEvaluatorFactory.java b/plugins/tiles/src/main/java/org/apache/tiles/core/evaluator/AttributeEvaluatorFactory.java new file mode 100644 index 000000000..56725d065 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/core/evaluator/AttributeEvaluatorFactory.java @@ -0,0 +1,48 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tiles.core.evaluator; + +import org.apache.tiles.api.Attribute; + +/** + * Creates an attribute evaluator using the language or an attribute. + * + * @since 2.2.0 + */ +public interface AttributeEvaluatorFactory { + + /** + * Creates and attribute evaluator using an attribute. + * + * @param attribute The attribute used to obtain the evaluator. + * @return The attribute evaluator. It must not be null. + * @since 2.2.0 + */ + AttributeEvaluator getAttributeEvaluator(Attribute attribute); + + /** + * Creates and attribute evaluator for the given expression language. + * + * @param language The name of the expression language. + * @return The attribute evaluator. It must not be null. + * @since 2.2.0 + */ + AttributeEvaluator getAttributeEvaluator(String language); +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/core/evaluator/AttributeEvaluatorFactoryAware.java b/plugins/tiles/src/main/java/org/apache/tiles/core/evaluator/AttributeEvaluatorFactoryAware.java new file mode 100644 index 000000000..f7dee1eec --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/core/evaluator/AttributeEvaluatorFactoryAware.java @@ -0,0 +1,35 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.core.evaluator; + +/** + * It represents an object that can use an {@link AttributeEvaluatorFactory}. + * + * @since 2.2.0 + */ +public interface AttributeEvaluatorFactoryAware { + + /** + * Sets the attribute evaluator factory. + * + * @param attributeEvaluatorFactory The attribute evaluator factory to use. + * @since 2.2.0 + */ + void setAttributeEvaluatorFactory(AttributeEvaluatorFactory attributeEvaluatorFactory); +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/core/evaluator/BasicAttributeEvaluatorFactory.java b/plugins/tiles/src/main/java/org/apache/tiles/core/evaluator/BasicAttributeEvaluatorFactory.java new file mode 100644 index 000000000..7f87dc38d --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/core/evaluator/BasicAttributeEvaluatorFactory.java @@ -0,0 +1,88 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.core.evaluator; + +import org.apache.tiles.api.Attribute; +import org.apache.tiles.api.Expression; + +import java.util.HashMap; +import java.util.Map; + +/** + * Basic implementation of {@link AttributeEvaluatorFactory}. It supports a + * default attribute evaluator, in case the language is not recognized. + * + * @since 2.2.0 + */ +public class BasicAttributeEvaluatorFactory implements AttributeEvaluatorFactory { + + /** + * The default evaluator to return if it is not found in the map of known + * languages. + */ + private final AttributeEvaluator defaultEvaluator; + + /** + * Maps names of expression languages to their attribute evaluator. + * + * @since 2.2.0 + */ + private final Map language2evaluator; + + /** + * Constructor. + * + * @param defaultEvaluator The default evaluator to return if it is not + * found in the map of known languages. + * @since 2.2.0 + */ + public BasicAttributeEvaluatorFactory(AttributeEvaluator defaultEvaluator) { + this.defaultEvaluator = defaultEvaluator; + language2evaluator = new HashMap<>(); + } + + /** + * Registers a known expression language with its attribute evaluator. + * + * @param language The name of the expression language. + * @param evaluator The associated attribute evaluator. + * @since 2.2.0 + */ + public void registerAttributeEvaluator(String language, AttributeEvaluator evaluator) { + language2evaluator.put(language, evaluator); + } + + /** {@inheritDoc} */ + public AttributeEvaluator getAttributeEvaluator(String language) { + AttributeEvaluator retValue = language2evaluator.get(language); + if (retValue == null) { + retValue = defaultEvaluator; + } + return retValue; + } + + /** {@inheritDoc} */ + public AttributeEvaluator getAttributeEvaluator(Attribute attribute) { + Expression expression = attribute.getExpressionObject(); + if (expression != null) { + return getAttributeEvaluator(expression.getLanguage()); + } + return defaultEvaluator; + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/core/evaluator/EvaluationException.java b/plugins/tiles/src/main/java/org/apache/tiles/core/evaluator/EvaluationException.java new file mode 100644 index 000000000..f5073706f --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/core/evaluator/EvaluationException.java @@ -0,0 +1,50 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.core.evaluator; + +import org.apache.tiles.api.TilesException; + +/** + * Exception raised when an expression language evaluation fails. + * + * @since 2.2.0 + */ +public class EvaluationException extends TilesException { + + /** + * Constructor. + * + * @param e The cause. + * @since 2.2.0 + */ + public EvaluationException(Throwable e) { + super(e); + } + + /** + * Constructor. + * + * @param message The message- + * @param e The cause. + * @since 2.2.0 + */ + public EvaluationException(String message, Throwable e) { + super(message, e); + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/core/evaluator/impl/DirectAttributeEvaluator.java b/plugins/tiles/src/main/java/org/apache/tiles/core/evaluator/impl/DirectAttributeEvaluator.java new file mode 100644 index 000000000..7900872ac --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/core/evaluator/impl/DirectAttributeEvaluator.java @@ -0,0 +1,36 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.core.evaluator.impl; + +import org.apache.tiles.core.evaluator.AbstractAttributeEvaluator; +import org.apache.tiles.request.Request; + +/** + * Resolves a string and returns the string itself. It is useful for backward + * compatibility. + * + * @since 2.1.0 + */ +public class DirectAttributeEvaluator extends AbstractAttributeEvaluator { + + /** {@inheritDoc} */ + public Object evaluate(String expression, Request request) { + return expression; + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/core/evaluator/impl/package-info.java b/plugins/tiles/src/main/java/org/apache/tiles/core/evaluator/impl/package-info.java new file mode 100644 index 000000000..c8b19297c --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/core/evaluator/impl/package-info.java @@ -0,0 +1,22 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +/** + * Classes to manage attribute value evaluation. + */ +package org.apache.tiles.core.evaluator.impl; diff --git a/plugins/tiles/src/main/java/org/apache/tiles/core/evaluator/package-info.java b/plugins/tiles/src/main/java/org/apache/tiles/core/evaluator/package-info.java new file mode 100644 index 000000000..2285788b6 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/core/evaluator/package-info.java @@ -0,0 +1,22 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +/** + * Interfaces to manage attribute value evaluation. + */ +package org.apache.tiles.core.evaluator; diff --git a/plugins/tiles/src/main/java/org/apache/tiles/core/factory/AbstractTilesContainerFactory.java b/plugins/tiles/src/main/java/org/apache/tiles/core/factory/AbstractTilesContainerFactory.java new file mode 100644 index 000000000..c64a30931 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/core/factory/AbstractTilesContainerFactory.java @@ -0,0 +1,41 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.core.factory; + +import org.apache.tiles.api.TilesContainer; +import org.apache.tiles.request.ApplicationContext; + +/** + * Abstract Factory that creates instances of {@link TilesContainer}. + * + * @since 2.1.0 + */ +public abstract class AbstractTilesContainerFactory { + + /** + * Creates a Tiles container. + * + * @param applicationContext The Tiles application context object. + * @return The created container. + * @throws TilesContainerFactoryException If something goes wrong during + * instantiation. + * @since 2.1.1 + */ + public abstract TilesContainer createContainer(ApplicationContext applicationContext); +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/core/factory/BasicTilesContainerFactory.java b/plugins/tiles/src/main/java/org/apache/tiles/core/factory/BasicTilesContainerFactory.java new file mode 100644 index 000000000..7a424d31c --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/core/factory/BasicTilesContainerFactory.java @@ -0,0 +1,406 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.core.factory; + +import org.apache.tiles.api.TilesContainer; +import org.apache.tiles.core.definition.DefinitionsFactory; +import org.apache.tiles.core.definition.DefinitionsReader; +import org.apache.tiles.core.definition.UnresolvingLocaleDefinitionsFactory; +import org.apache.tiles.core.definition.dao.BaseLocaleUrlDefinitionDAO; +import org.apache.tiles.core.definition.dao.DefinitionDAO; +import org.apache.tiles.core.definition.dao.ResolvingLocaleUrlDefinitionDAO; +import org.apache.tiles.core.definition.digester.DigesterDefinitionsReader; +import org.apache.tiles.core.definition.pattern.BasicPatternDefinitionResolver; +import org.apache.tiles.core.definition.pattern.PatternDefinitionResolver; +import org.apache.tiles.core.definition.pattern.PatternDefinitionResolverAware; +import org.apache.tiles.core.definition.pattern.wildcard.WildcardDefinitionPatternMatcherFactory; +import org.apache.tiles.core.evaluator.AttributeEvaluatorFactory; +import org.apache.tiles.core.evaluator.BasicAttributeEvaluatorFactory; +import org.apache.tiles.core.evaluator.impl.DirectAttributeEvaluator; +import org.apache.tiles.core.impl.BasicTilesContainer; +import org.apache.tiles.core.locale.LocaleResolver; +import org.apache.tiles.core.locale.impl.DefaultLocaleResolver; +import org.apache.tiles.core.prepare.factory.BasicPreparerFactory; +import org.apache.tiles.core.prepare.factory.PreparerFactory; +import org.apache.tiles.core.renderer.DefinitionRenderer; +import org.apache.tiles.request.ApplicationContext; +import org.apache.tiles.request.ApplicationResource; +import org.apache.tiles.request.render.BasicRendererFactory; +import org.apache.tiles.request.render.ChainedDelegateRenderer; +import org.apache.tiles.request.render.DispatchRenderer; +import org.apache.tiles.request.render.Renderer; +import org.apache.tiles.request.render.RendererFactory; +import org.apache.tiles.request.render.StringRenderer; + +import java.util.ArrayList; +import java.util.List; +import java.util.Locale; + +/** + * Factory that builds a standard Tiles container using only Java code. + * + * @since 2.1.0 + */ +public class BasicTilesContainerFactory extends AbstractTilesContainerFactory { + + /** + * The string renderer name. + */ + protected static final String STRING_RENDERER_NAME = "string"; + + /** + * The template renderer name. + */ + protected static final String TEMPLATE_RENDERER_NAME = "template"; + + /** + * The definition renderer name. + */ + protected static final String DEFINITION_RENDERER_NAME = "definition"; + + /** + * {@inheritDoc} + */ + @Override + public TilesContainer createContainer(ApplicationContext applicationContext) { + BasicTilesContainer container = instantiateContainer(applicationContext); + container.setApplicationContext(applicationContext); + LocaleResolver resolver = createLocaleResolver(applicationContext); + container.setDefinitionsFactory(createDefinitionsFactory(applicationContext, resolver)); + AttributeEvaluatorFactory attributeEvaluatorFactory = createAttributeEvaluatorFactory(applicationContext, resolver); + container.setAttributeEvaluatorFactory(attributeEvaluatorFactory); + container.setPreparerFactory(createPreparerFactory(applicationContext)); + TilesContainer injectedContainer = createDecoratedContainer(container, applicationContext); + container.setRendererFactory(createRendererFactory(applicationContext, injectedContainer, attributeEvaluatorFactory)); + return injectedContainer; + } + + /** + * Instantiate the container, without initialization. + * + * @param context The Tiles application context object. + * @return The instantiated container. + * @since 2.1.1 + */ + protected BasicTilesContainer instantiateContainer(ApplicationContext context) { + return new BasicTilesContainer(); + } + + /** + * Instantiate the container that will be injected to child objects. + * + * @param originalContainer The original instantiated container. + * @param context The Tiles application context object. + * @return The instantiated container. + * @since 3.0.0 + */ + protected TilesContainer createDecoratedContainer( + TilesContainer originalContainer, + ApplicationContext context + ) { + return originalContainer; + } + + /** + * Creates the definitions factory. By default it creates a + * {@link UnresolvingLocaleDefinitionsFactory} with default dependencies. + * + * @param applicationContext The Tiles application context. + * @param resolver The locale resolver. + * @return The definitions factory. + * @since 2.1.1 + */ + protected DefinitionsFactory createDefinitionsFactory( + ApplicationContext applicationContext, + LocaleResolver resolver + ) { + UnresolvingLocaleDefinitionsFactory factory = instantiateDefinitionsFactory(applicationContext, resolver); + factory.setLocaleResolver(resolver); + factory.setDefinitionDAO(createLocaleDefinitionDao(applicationContext, resolver)); + return factory; + } + + /** + * Instantiate a new definitions factory based on Locale. + * + * @param applicationContext The Tiles application context. + * @param resolver The locale resolver. + * @return The definitions factory. + * @since 2.2.1 + */ + protected UnresolvingLocaleDefinitionsFactory instantiateDefinitionsFactory( + ApplicationContext applicationContext, + LocaleResolver resolver + ) { + return new UnresolvingLocaleDefinitionsFactory(); + } + + + /** + * Instantiate (and does not initialize) a Locale-based definition DAO. + * + * @param applicationContext The Tiles application context. + * @param resolver The locale resolver. + * @return The definition DAO. + * @since 2.1.1 + */ + protected BaseLocaleUrlDefinitionDAO instantiateLocaleDefinitionDao( + ApplicationContext applicationContext, + LocaleResolver resolver + ) { + return new ResolvingLocaleUrlDefinitionDAO(applicationContext); + } + + /** + * Creates a Locale-based definition DAO. + * + * @param applicationContext The Tiles application context. + * @param resolver The locale resolver. + * @return The definition DAO. + * @since 2.1.1 + */ + @SuppressWarnings("unchecked") + protected DefinitionDAO createLocaleDefinitionDao(ApplicationContext applicationContext, LocaleResolver resolver) { + BaseLocaleUrlDefinitionDAO definitionDao = instantiateLocaleDefinitionDao(applicationContext, resolver); + definitionDao.setReader(createDefinitionsReader(applicationContext)); + definitionDao.setSources(getSources(applicationContext)); + if (definitionDao instanceof PatternDefinitionResolverAware) { + ((PatternDefinitionResolverAware) definitionDao) + .setPatternDefinitionResolver(createPatternDefinitionResolver(Locale.class)); + } + return definitionDao; + } + + /** + * Creates the locale resolver. By default it creates a + * {@link DefaultLocaleResolver}. + * + * @param applicationContext The Tiles application context. + * @return The locale resolver. + * @since 2.1.1 + */ + protected LocaleResolver createLocaleResolver(ApplicationContext applicationContext) { + return new DefaultLocaleResolver(); + } + + /** + * Creates the definitions reader. By default it creates a + * {@link DigesterDefinitionsReader}. + * + * @param applicationContext The Tiles application context. + * @return The definitions reader. + * @since 2.1.1 + */ + protected DefinitionsReader createDefinitionsReader(ApplicationContext applicationContext) { + return new DigesterDefinitionsReader(); + } + + /** + * Returns a list containing the resources to be parsed. By default, it returns a + * list containing the resource at "/WEB-INF/tiles.xml". + * + * @param applicationContext The Tiles application context. + * @return The resources. + * @since 2.1.1 + */ + protected List getSources(ApplicationContext applicationContext) { + List retValue = new ArrayList<>(1); + retValue.add(applicationContext.getResource("/WEB-INF/tiles.xml")); + return retValue; + } + + /** + * Creates the attribute evaluator factory to use. By default it returns a + * {@link BasicAttributeEvaluatorFactory} containing the + * {@link DirectAttributeEvaluator} as the default evaluator. + * + * @param applicationContext The Tiles application context. + * @param resolver The locale resolver. + * @return The evaluator factory. + * @since 2.2.0 + */ + protected AttributeEvaluatorFactory createAttributeEvaluatorFactory( + ApplicationContext applicationContext, + LocaleResolver resolver) { + return new BasicAttributeEvaluatorFactory(new DirectAttributeEvaluator()); + } + + /** + * Creates the preparer factory to use. By default it returns a + * {@link BasicPreparerFactory}. + * + * @param applicationContext The Tiles application context. + * @return The preparer factory. + * @since 2.1.1 + */ + protected PreparerFactory createPreparerFactory(ApplicationContext applicationContext) { + return new BasicPreparerFactory(); + } + + /** + * Creates a renderer factory. By default, it returns a + * {@link BasicRendererFactory}, composed of an + * {@link ChainedDelegateRenderer} as default, and delegates of + * {@link StringRenderer}, {@link DispatchRenderer}, + * {@link DefinitionRenderer}. + * + * @param applicationContext The Tiles application context. + * @param container The container. + * @param attributeEvaluatorFactory The attribute evaluator factory. + * @return The renderer factory. + * @since 2.2.0 + */ + protected RendererFactory createRendererFactory(ApplicationContext applicationContext, + TilesContainer container, + AttributeEvaluatorFactory attributeEvaluatorFactory) { + BasicRendererFactory retValue = new BasicRendererFactory(); + registerAttributeRenderers(retValue, applicationContext, container, + attributeEvaluatorFactory); + retValue.setDefaultRenderer(createDefaultAttributeRenderer(retValue, + applicationContext, container, attributeEvaluatorFactory)); + return retValue; + } + + /** + * Creates the default attribute renderer. By default it is an + * {@link ChainedDelegateRenderer}. + * + * @param rendererFactory The renderer factory to configure. + * @param applicationContext The Tiles application context. + * @param container The container. + * @param attributeEvaluatorFactory The attribute evaluator factory. + * @return The default attribute renderer. + * @since 3.0.0 + */ + protected Renderer createDefaultAttributeRenderer( + BasicRendererFactory rendererFactory, + ApplicationContext applicationContext, + TilesContainer container, + AttributeEvaluatorFactory attributeEvaluatorFactory) { + ChainedDelegateRenderer retValue = new ChainedDelegateRenderer(); + retValue.addAttributeRenderer(rendererFactory.getRenderer(DEFINITION_RENDERER_NAME)); + retValue.addAttributeRenderer(rendererFactory.getRenderer(TEMPLATE_RENDERER_NAME)); + retValue.addAttributeRenderer(rendererFactory.getRenderer(STRING_RENDERER_NAME)); + return retValue; + } + + /** + * Creates a new pattern definition resolver. By default, it instantiate a + * {@link BasicPatternDefinitionResolver} with + * {@link WildcardDefinitionPatternMatcherFactory} to manage wildcard + * substitution. + * + * @param The type of the customization key. + * @param customizationKeyClass The customization key class. + * @return The pattern definition resolver. + * @since 2.2.0 + */ + protected PatternDefinitionResolver createPatternDefinitionResolver(Class customizationKeyClass) { + WildcardDefinitionPatternMatcherFactory definitionPatternMatcherFactory = new WildcardDefinitionPatternMatcherFactory(); + return new BasicPatternDefinitionResolver<>(definitionPatternMatcherFactory, definitionPatternMatcherFactory); + } + + /** + * Registers attribute renderers in a {@link BasicRendererFactory}. By + * default, it registers delegates to {@link StringRenderer}, + * {@link DispatchRenderer} and {@link DefinitionRenderer}. + * + * @param rendererFactory The renderer factory to configure. + * @param applicationContext The Tiles application context. + * @param container The container. + * @param attributeEvaluatorFactory The attribute evaluator factory. + * @since 2.2.0 + */ + protected void registerAttributeRenderers( + BasicRendererFactory rendererFactory, + ApplicationContext applicationContext, + TilesContainer container, + AttributeEvaluatorFactory attributeEvaluatorFactory + ) { + rendererFactory.registerRenderer( + STRING_RENDERER_NAME, + createStringAttributeRenderer(rendererFactory, applicationContext, container, attributeEvaluatorFactory) + ); + rendererFactory.registerRenderer( + TEMPLATE_RENDERER_NAME, + createTemplateAttributeRenderer(rendererFactory, applicationContext, container, attributeEvaluatorFactory) + ); + rendererFactory.registerRenderer( + DEFINITION_RENDERER_NAME, + createDefinitionAttributeRenderer(rendererFactory, applicationContext, container, attributeEvaluatorFactory) + ); + } + + /** + * Creates an attribute renderer to render strings. + * + * @param rendererFactory The renderer factory to configure. + * @param applicationContext The Tiles application context. + * @param container The container. + * @param attributeEvaluatorFactory The attribute evaluator factory. + * @return The renderer. + * @since 3.0.0 + */ + protected Renderer createStringAttributeRenderer( + BasicRendererFactory rendererFactory, + ApplicationContext applicationContext, + TilesContainer container, + AttributeEvaluatorFactory attributeEvaluatorFactory + ) { + return new StringRenderer(); + } + + /** + * Creates a {@link Renderer} that uses a {@link DispatchRenderer}. + * + * @param rendererFactory The renderer factory to configure. + * @param applicationContext The Tiles application context. + * @param container The container. + * @param attributeEvaluatorFactory The attribute evaluator factory. + * @return The renderer. + * @since 2.2.1 + */ + protected Renderer createTemplateAttributeRenderer( + BasicRendererFactory rendererFactory, + ApplicationContext applicationContext, + TilesContainer container, + AttributeEvaluatorFactory attributeEvaluatorFactory + ) { + return new DispatchRenderer(); + } + + /** + * Creates a {@link Renderer} using a {@link DefinitionRenderer}. + * + * @param rendererFactory The renderer factory to configure. + * @param applicationContext The Tiles application context. + * @param container The container. + * @param attributeEvaluatorFactory The attribute evaluator factory. + * @return The renderer. + * @since 3.0.0 + */ + protected Renderer createDefinitionAttributeRenderer( + BasicRendererFactory rendererFactory, + ApplicationContext applicationContext, + TilesContainer container, + AttributeEvaluatorFactory attributeEvaluatorFactory + ) { + return new DefinitionRenderer(container); + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/core/factory/TilesContainerFactoryException.java b/plugins/tiles/src/main/java/org/apache/tiles/core/factory/TilesContainerFactoryException.java new file mode 100644 index 000000000..8f1bdd4e5 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/core/factory/TilesContainerFactoryException.java @@ -0,0 +1,41 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.core.factory; + +import org.apache.tiles.api.TilesException; + +/** + * Indicates that something went wrong in {@link AbstractTilesContainerFactory} use. + * + * @since 2.1.0 + */ +public class TilesContainerFactoryException extends TilesException { + + /** + * Constructor. + * + * @param message The detail message. + * @param e The exception to be wrapped. + * @since 2.1.0 + */ + public TilesContainerFactoryException(String message, Throwable e) { + super(message, e); + } + +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/core/factory/package-info.java b/plugins/tiles/src/main/java/org/apache/tiles/core/factory/package-info.java new file mode 100644 index 000000000..a9848e865 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/core/factory/package-info.java @@ -0,0 +1,22 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +/** + * Factory classes, to allow creation of container instances. + */ +package org.apache.tiles.core.factory; diff --git a/plugins/tiles/src/main/java/org/apache/tiles/core/impl/BasicTilesContainer.java b/plugins/tiles/src/main/java/org/apache/tiles/core/impl/BasicTilesContainer.java new file mode 100644 index 000000000..922d01613 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/core/impl/BasicTilesContainer.java @@ -0,0 +1,398 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.core.impl; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.apache.tiles.api.Attribute; +import org.apache.tiles.api.AttributeContext; +import org.apache.tiles.api.BasicAttributeContext; +import org.apache.tiles.api.Definition; +import org.apache.tiles.api.TilesContainer; +import org.apache.tiles.api.preparer.ViewPreparer; +import org.apache.tiles.core.definition.DefinitionsFactory; +import org.apache.tiles.core.definition.NoSuchDefinitionException; +import org.apache.tiles.core.evaluator.AttributeEvaluator; +import org.apache.tiles.core.evaluator.AttributeEvaluatorFactory; +import org.apache.tiles.core.evaluator.AttributeEvaluatorFactoryAware; +import org.apache.tiles.core.prepare.factory.NoSuchPreparerException; +import org.apache.tiles.core.prepare.factory.PreparerFactory; +import org.apache.tiles.request.ApplicationContext; +import org.apache.tiles.request.Request; +import org.apache.tiles.request.render.CannotRenderException; +import org.apache.tiles.request.render.Renderer; +import org.apache.tiles.request.render.RendererFactory; + +import java.io.IOException; +import java.util.Deque; +import java.util.LinkedList; +import java.util.Map; + +/** + * Basic implementation of the tiles container interface. + * In most cases, this container will be customized by + * injecting customized services, not necessarily by + * override the container + * + * @since 2.0 + */ +public class BasicTilesContainer implements TilesContainer, AttributeEvaluatorFactoryAware { + + /** + * Name used to store attribute context stack. + */ + private static final String ATTRIBUTE_CONTEXT_STACK = + "org.apache.tiles.AttributeContext.STACK"; + + /** + * Log instance for all BasicTilesContainer + * instances. + */ + private static final Logger LOG = LogManager.getLogger(BasicTilesContainer.class); + + /** + * The Tiles application context object. + */ + private ApplicationContext context; + + /** + * The definitions factory. + */ + private DefinitionsFactory definitionsFactory; + + /** + * The preparer factory. + */ + private PreparerFactory preparerFactory; + + /** + * The renderer factory. + */ + private RendererFactory rendererFactory; + + /** + * The attribute evaluator. + */ + private AttributeEvaluatorFactory attributeEvaluatorFactory; + + /** + * {@inheritDoc} + */ + public AttributeContext startContext(Request request) { + AttributeContext context = new BasicAttributeContext(); + Deque stack = getContextStack(request); + if (!stack.isEmpty()) { + AttributeContext parent = stack.peek(); + context.inheritCascadedAttributes(parent); + } + stack.push(context); + return context; + } + + /** + * {@inheritDoc} + */ + public void endContext(Request request) { + popContext(request); + } + + /** + * {@inheritDoc} + */ + public void renderContext(Request request) { + AttributeContext attributeContext = getAttributeContext(request); + + render(request, attributeContext); + } + + /** + * Returns the Tiles application context used by this container. + * + * @return the application context for this container. + */ + public ApplicationContext getApplicationContext() { + return context; + } + + /** + * Sets the Tiles application context to use. + * + * @param context The Tiles application context. + */ + public void setApplicationContext(ApplicationContext context) { + this.context = context; + } + + /** + * {@inheritDoc} + */ + public AttributeContext getAttributeContext(Request request) { + AttributeContext context = getContext(request); + if (context == null) { + context = new BasicAttributeContext(); + pushContext(context, request); + } + return context; + + } + + /** + * Set the definitions factory. This method first ensures + * that the container has not yet been initialized. + * + * @param definitionsFactory the definitions factory for this instance. + */ + public void setDefinitionsFactory(DefinitionsFactory definitionsFactory) { + this.definitionsFactory = definitionsFactory; + } + + /** + * Set the preparerInstance factory. This method first ensures + * that the container has not yet been initialized. + * + * @param preparerFactory the preparerInstance factory for this conainer. + */ + public void setPreparerFactory(PreparerFactory preparerFactory) { + this.preparerFactory = preparerFactory; + } + + /** + * Sets the renderer instance factory. + * + * @param rendererFactory the renderer instance factory for this container. + * @since 2.1.0 + */ + public void setRendererFactory(RendererFactory rendererFactory) { + this.rendererFactory = rendererFactory; + } + + /** + * {@inheritDoc} + */ + public void setAttributeEvaluatorFactory( + AttributeEvaluatorFactory attributeEvaluatorFactory) { + this.attributeEvaluatorFactory = attributeEvaluatorFactory; + } + + /** + * {@inheritDoc} + */ + public void prepare(String preparer, Request request) { + prepare(request, preparer, false); + } + + /** + * {@inheritDoc} + */ + public void render(String definitionName, Request request) { + LOG.debug("Render request received for definition '{}'", definitionName); + + Definition definition = getDefinition(definitionName, request); + + if (definition == null) { + throw new NoSuchDefinitionException("Unable to find the definition '" + definitionName + "'"); + } + + render(definition, request); + } + + /** + * Renders the specified definition. + * + * @param definition The definition to render. + * @param request The request context. + * @since 2.1.3 + */ + public void render(Definition definition, Request request) { + AttributeContext originalContext = getAttributeContext(request); + BasicAttributeContext subContext = new BasicAttributeContext(originalContext); + subContext.inherit(definition); + + pushContext(subContext, request); + + try { + render(request, subContext); + } finally { + popContext(request); + } + } + + /** + * {@inheritDoc} + */ + public void render(Attribute attr, Request request) + throws IOException { + if (attr == null) { + throw new CannotRenderException("Cannot render a null attribute"); + } + + if (attr.isPermitted(request)) { + Renderer renderer = rendererFactory.getRenderer(attr.getRenderer()); + Object value = evaluate(attr, request); + if (!(value instanceof String)) { + throw new CannotRenderException( + "Cannot render an attribute that is not a string, toString returns: " + + value); + } + renderer.render((String) value, request); + } + } + + /** + * {@inheritDoc} + */ + public Object evaluate(Attribute attribute, Request request) { + AttributeEvaluator evaluator = attributeEvaluatorFactory.getAttributeEvaluator(attribute); + return evaluator.evaluate(attribute, request); + } + + /** + * {@inheritDoc} + */ + public boolean isValidDefinition(String definitionName, Request request) { + try { + Definition definition = getDefinition(definitionName, request); + return definition != null; + } catch (NoSuchDefinitionException nsde) { + LOG.debug("Cannot find definition '{}'", definitionName); + LOG.debug("Exception related to the not found definition", nsde); + return false; + } + } + + /** + * {@inheritDoc} + */ + @Override + public Definition getDefinition(String definitionName, Request request) { + return definitionsFactory.getDefinition(definitionName, request); + } + + /** + * Returns the context stack. + * + * @param tilesContext The Tiles context object to use. + * @return The needed stack of contexts. + * @since 2.0.6 + */ + @SuppressWarnings("unchecked") + protected Deque getContextStack(Request tilesContext) { + Map requestScope = tilesContext.getContext("request"); + Deque contextStack = (Deque) requestScope + .get(ATTRIBUTE_CONTEXT_STACK); + if (contextStack == null) { + contextStack = new LinkedList<>(); + requestScope.put(ATTRIBUTE_CONTEXT_STACK, contextStack); + } + + return contextStack; + } + + /** + * Pushes a context object in the stack. + * + * @param context The context to push. + * @param tilesContext The Tiles context object to use. + * @since 2.0.6 + */ + protected void pushContext(AttributeContext context, + Request tilesContext) { + Deque contextStack = getContextStack(tilesContext); + contextStack.push(context); + } + + /** + * Pops a context object out of the stack. + * + * @param tilesContext The Tiles context object to use. + * @return The popped context object. + * @since 2.0.6 + */ + protected AttributeContext popContext(Request tilesContext) { + Deque contextStack = getContextStack(tilesContext); + return contextStack.pop(); + } + + /** + * Get attribute context from request. + * + * @param tilesContext current Tiles application context. + * @return BasicAttributeContext or null if context is not found. + * @since 2.0.6 + */ + protected AttributeContext getContext(Request tilesContext) { + Deque contextStack = getContextStack(tilesContext); + if (!contextStack.isEmpty()) { + return contextStack.peek(); + } + return null; + } + + /** + * Execute a preparer. + * + * @param context The request context. + * @param preparerName The name of the preparer. + * @param ignoreMissing If true if the preparer is not found, + * it ignores the problem. + * @throws NoSuchPreparerException If the preparer is not found (and + * ignoreMissing is not set) or if the preparer itself threw an + * exception. + */ + private void prepare(Request context, String preparerName, boolean ignoreMissing) { + + LOG.debug("Prepare request received for '{}'", preparerName); + + ViewPreparer preparer = preparerFactory.getPreparer(preparerName, context); + if (preparer == null && ignoreMissing) { + return; + } + + if (preparer == null) { + throw new NoSuchPreparerException("Preparer '" + preparerName + " not found"); + } + + AttributeContext attributeContext = getContext(context); + + preparer.execute(context, attributeContext); + } + + /** + * Renders the specified attribute context. + * + * @param request The request context. + * @param attributeContext The context to render. + * @throws InvalidTemplateException If the template is not valid. + * @throws CannotRenderException If something goes wrong during rendering. + * @since 2.1.3 + */ + protected void render(Request request, + AttributeContext attributeContext) { + + try { + if (attributeContext.getPreparer() != null) { + prepare(request, attributeContext.getPreparer(), true); + } + + render(attributeContext.getTemplateAttribute(), request); + } catch (IOException e) { + throw new CannotRenderException(e.getMessage(), e); + } + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/core/impl/InvalidTemplateException.java b/plugins/tiles/src/main/java/org/apache/tiles/core/impl/InvalidTemplateException.java new file mode 100644 index 000000000..7b95722ff --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/core/impl/InvalidTemplateException.java @@ -0,0 +1,50 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.core.impl; + +import org.apache.tiles.api.TilesException; + +/** + * An invalid template has been identified. + * + * @since 2.1.0 + */ +public class InvalidTemplateException extends TilesException { + + /** + * Constructor. + * + * @param message The detail message. + * @since 2.1.0 + */ + public InvalidTemplateException(String message) { + super(message); + } + + /** + * Constructor. + * + * @param e The exception to be wrapped. + * @since 2.1.0 + */ + public InvalidTemplateException(Throwable e) { + super(e); + } + +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/core/impl/mgmt/CachingTilesContainer.java b/plugins/tiles/src/main/java/org/apache/tiles/core/impl/mgmt/CachingTilesContainer.java new file mode 100644 index 000000000..0a18c7333 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/core/impl/mgmt/CachingTilesContainer.java @@ -0,0 +1,222 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.core.impl.mgmt; + +import org.apache.tiles.api.Definition; +import org.apache.tiles.api.TilesContainer; +import org.apache.tiles.api.TilesContainerWrapper; +import org.apache.tiles.api.mgmt.MutableTilesContainer; +import org.apache.tiles.core.definition.NoSuchDefinitionException; +import org.apache.tiles.request.Request; + +import java.util.HashMap; +import java.util.Map; + +/** + * Manages custom and configured definitions, so they can be used by the + * container, instead of using a simple {@link org.apache.tiles.core.definition.DefinitionsFactory}. + */ +public class CachingTilesContainer extends TilesContainerWrapper implements MutableTilesContainer { + + /** + * The default name of the attribute in which storing custom definitions. + */ + private static final String DEFAULT_DEFINITIONS_ATTRIBUTE_NAME = "org.apache.tiles.impl.mgmt.DefinitionManager.DEFINITIONS"; + + /** + * The name of the attribute in which storing custom definitions. + */ + private final String definitionsAttributeName; + + /** + * Constructor. + * + * @param originalContainer The original container to wrap. + */ + public CachingTilesContainer(TilesContainer originalContainer) { + super(originalContainer); + definitionsAttributeName = DEFAULT_DEFINITIONS_ATTRIBUTE_NAME; + } + + /** + * Returns a definition by name. + * + * @param definition The name of the definition. + * @param request The current request. + * @return The requested definition, either main or custom. + */ + public Definition getDefinition(String definition, Request request) { + Definition retValue; + retValue = getCustomDefinition(definition, request); + if (retValue == null) { + retValue = super.getDefinition(definition, request); + } + return retValue; + } + + /** + * {@inheritDoc} + */ + @Override + public boolean isValidDefinition(String definition, Request request) { + if (getCustomDefinition(definition, request) != null) { + return true; + } + return super.isValidDefinition(definition, request); + } + + /** + * {@inheritDoc} + */ + @Override + public void register(Definition definition, Request request) { + Map definitions = getOrCreateDefinitions(request); + if (definition.getName() == null) { + definition.setName(getNextUniqueDefinitionName(definitions)); + } + + if (definition.isExtending()) { + this.resolveInheritance(definition, request); + } + + definitions.put(definition.getName(), definition); + } + + /** + * {@inheritDoc} + */ + @Override + public void render(String definition, Request request) { + Definition toRender = getDefinition(definition, request); + if (toRender == null) { + throw new NoSuchDefinitionException("Cannot find definition named '" + definition + "'"); + } + super.render(toRender, request); + } + + /** + * Resolve inheritance. + * First, resolve parent's inheritance, then set template to the parent's + * template. + * Also copy attributes set in parent, and not set in child + * If instance doesn't extend anything, do nothing. + * + * @param definition The definition that needs to have its inheritances + * resolved. + * @param request The current request. + * @throws org.apache.tiles.core.definition.DefinitionsFactoryException If an + * inheritance can not be solved. + */ + private void resolveInheritance(Definition definition, + Request request) { + // Already done, or not needed ? + if (!definition.isExtending()) { + return; + } + + String parentDefinitionName = definition.getExtends(); + + boolean recurse = true; + Definition parent = getCustomDefinition(parentDefinitionName, request); + if (parent == null) { + parent = container.getDefinition(parentDefinitionName, request); + recurse = false; + } + + if (parent == null) { + throw new NoSuchDefinitionException( + "Error while resolving definition inheritance: child '" + + definition.getName() + + "' can't find its ancestor '" + + parentDefinitionName + + "'. Please check your description file."); + } + + // Resolve parent before itself. + if (recurse) { + resolveInheritance(parent, request); + } + definition.inherit(parent); + } + + /** + * Returns the map with custom definitions for the current request. + * + * @param request The current request. + * @return A map that connects a definition name to a definition. + */ + @SuppressWarnings("unchecked") + private Map getDefinitions( + Request request) { + return (Map) request.getContext("request") + .get(definitionsAttributeName); + } + + /** + * Returns a map of type "definition name -> definition" and, if it has not + * been defined before, creates one. + * + * @param request The current request. + * @return A map that connects a definition name to a definition. + */ + @SuppressWarnings("unchecked") + private Map getOrCreateDefinitions(Request request) { + Map definitions = (Map) request.getContext("request").get(definitionsAttributeName); + if (definitions == null) { + definitions = new HashMap<>(); + request.getContext("request").put(definitionsAttributeName, definitions); + } + + return definitions; + } + + /** + * Create a unique definition name usable to store anonymous definitions. + * + * @param definitions The already created definitions. + * @return The unique definition name to be used to store the definition. + * @since 2.1.0 + */ + private String getNextUniqueDefinitionName(Map definitions) { + String candidate; + int anonymousDefinitionIndex = 1; + + do { + candidate = "$anonymousMutableDefinition" + anonymousDefinitionIndex; + anonymousDefinitionIndex++; + } while (definitions.containsKey(candidate)); + + return candidate; + } + + /** + * Returns a custom definition from the cache. + * + * @param definition The definition to search. + * @param request The request. + * @return The requested definition. + */ + private Definition getCustomDefinition(String definition, Request request) { + Map definitions = getDefinitions(request); + if (definitions != null) { + return definitions.get(definition); + } + return null; + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/core/impl/mgmt/package-info.java b/plugins/tiles/src/main/java/org/apache/tiles/core/impl/mgmt/package-info.java new file mode 100644 index 000000000..e63fbe3fb --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/core/impl/mgmt/package-info.java @@ -0,0 +1,22 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +/** + * It contains the basic implementations of mutable Tiles containers. + */ +package org.apache.tiles.core.impl.mgmt; diff --git a/plugins/tiles/src/main/java/org/apache/tiles/core/impl/package-info.java b/plugins/tiles/src/main/java/org/apache/tiles/core/impl/package-info.java new file mode 100644 index 000000000..7b89ff86e --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/core/impl/package-info.java @@ -0,0 +1,22 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +/** + * It contains the basic implementations of Tiles container. + */ +package org.apache.tiles.core.impl; diff --git a/plugins/tiles/src/main/java/org/apache/tiles/core/locale/LocaleResolver.java b/plugins/tiles/src/main/java/org/apache/tiles/core/locale/LocaleResolver.java new file mode 100644 index 000000000..de73dc17e --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/core/locale/LocaleResolver.java @@ -0,0 +1,38 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.core.locale; + +import org.apache.tiles.request.Request; + +import java.util.Locale; + +/** + * It represents an object able to resolve the current locale for the current + * request, where its strategy depends on its implementation. + */ +public interface LocaleResolver { + + /** + * Resolves the locale. + * + * @param request The Tiles request object. + * @return The current locale for the current request. + */ + Locale resolveLocale(Request request); +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/core/locale/impl/DefaultLocaleResolver.java b/plugins/tiles/src/main/java/org/apache/tiles/core/locale/impl/DefaultLocaleResolver.java new file mode 100644 index 000000000..57d63b597 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/core/locale/impl/DefaultLocaleResolver.java @@ -0,0 +1,55 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.core.locale.impl; + +import org.apache.tiles.core.locale.LocaleResolver; +import org.apache.tiles.request.Request; + +import java.util.Locale; +import java.util.Map; + +/** + * Default implementation of LocaleResolver
+ * It tries to take the locale from the session-scoped attribute + * {@link DefaultLocaleResolver#LOCALE_KEY}. If it is not found, it returns the + * locale included in the request. + */ +public class DefaultLocaleResolver implements LocaleResolver { + + /** + * The attribute name that is used to store the current locale. + */ + public static final String LOCALE_KEY = "org.apache.tiles.LOCALE"; + + /** + * {@inheritDoc} + */ + public Locale resolveLocale(Request request) { + Locale retValue = null; + Map session = request.getContext("session"); + if (session != null) { + retValue = (Locale) session.get(DefaultLocaleResolver.LOCALE_KEY); + } + if (retValue == null) { + retValue = request.getRequestLocale(); + } + + return retValue; + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/core/locale/impl/package-info.java b/plugins/tiles/src/main/java/org/apache/tiles/core/locale/impl/package-info.java new file mode 100644 index 000000000..d8bb3d6bc --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/core/locale/impl/package-info.java @@ -0,0 +1,22 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +/** + * Basic implementation of the locale resolver. + */ +package org.apache.tiles.core.locale.impl; diff --git a/plugins/tiles/src/main/java/org/apache/tiles/core/locale/package-info.java b/plugins/tiles/src/main/java/org/apache/tiles/core/locale/package-info.java new file mode 100644 index 000000000..0470b39df --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/core/locale/package-info.java @@ -0,0 +1,23 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +/** + * Classes and interfaces to allow locale resolution in an application, i.e. it + * allows to specify how to access the locale that the user wants to use. + */ +package org.apache.tiles.core.locale; diff --git a/plugins/tiles/src/main/java/org/apache/tiles/core/prepare/factory/BasicPreparerFactory.java b/plugins/tiles/src/main/java/org/apache/tiles/core/prepare/factory/BasicPreparerFactory.java new file mode 100644 index 000000000..b28151da2 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/core/prepare/factory/BasicPreparerFactory.java @@ -0,0 +1,84 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.core.prepare.factory; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.apache.tiles.api.preparer.ViewPreparer; +import org.apache.tiles.request.Request; +import org.apache.tiles.request.reflect.ClassUtil; + +import java.util.HashMap; +import java.util.Map; + +/** + * Default implementation of the {@link org.apache.tiles.core.prepare.factory.PreparerFactory}. + * This factory provides no contextual configuration. It + * simply instantiates the named preparerInstance and returns it. + * + * @since Tiles 2.0 + */ +public class BasicPreparerFactory implements PreparerFactory { + + /** + * The logging object. + */ + private static final Logger LOG = LogManager.getLogger(BasicPreparerFactory.class); + + /** + * Maps a preparer name to the instantiated preparer. + */ + protected Map preparers; + + /** + * Constructor. + */ + public BasicPreparerFactory() { + this.preparers = new HashMap<>(); + } + + + /** + * Create a new instance of the named preparerInstance. This factory + * expects all names to be qualified class names. + * + * @param name the named preparerInstance + * @param context current context + * @return ViewPreparer instance + */ + public ViewPreparer getPreparer(String name, Request context) { + if (!preparers.containsKey(name)) { + preparers.put(name, createPreparer(name)); + } + + return preparers.get(name); + } + + /** + * Creates a view preparer for the given name. + * + * @param name The name of the preparer. + * @return The created preparer. + */ + protected ViewPreparer createPreparer(String name) { + LOG.debug("Creating ViewPreparer '{}'", name); + Object instance = ClassUtil.instantiate(name, true); + return (ViewPreparer) instance; + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/core/prepare/factory/NoSuchPreparerException.java b/plugins/tiles/src/main/java/org/apache/tiles/core/prepare/factory/NoSuchPreparerException.java new file mode 100644 index 000000000..1d4b50282 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/core/prepare/factory/NoSuchPreparerException.java @@ -0,0 +1,39 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.core.prepare.factory; + +import org.apache.tiles.api.preparer.PreparerException; + +/** + * Thrown when the named preparerInstance can not be found. + * + * @since 2.0 + */ +public class NoSuchPreparerException extends PreparerException { + + /** + * Constructor. + * + * @param message The message to include. + */ + public NoSuchPreparerException(String message) { + super(message); + } + +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/core/prepare/factory/PreparerFactory.java b/plugins/tiles/src/main/java/org/apache/tiles/core/prepare/factory/PreparerFactory.java new file mode 100644 index 000000000..073ab3fb6 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/core/prepare/factory/PreparerFactory.java @@ -0,0 +1,49 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.core.prepare.factory; + +import org.apache.tiles.api.preparer.ViewPreparer; +import org.apache.tiles.request.Request; + +/** + *

+ * Factory interface used to create/retrieve instances of + * the {@link ViewPreparer} interface. + *

+ * + *

+ * This factory provides an extension point into the default + * tiles implementation. Implementors wishing to provide + * per request initialization of the ViewPreparer (for instance) + * may provide a custom prerparer. + *

+ * + * @since 2.0 + */ +public interface PreparerFactory { + + /** + * Create the named {link ViewPreparer} for the specified context. + * + * @param name ViewPreparer name, commonly the qualified classname. + * @param context the context within which the preparerInstance will be invoked. + * @return instance of the ViewPreparer + */ + ViewPreparer getPreparer(String name, Request context); +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/core/prepare/factory/package-info.java b/plugins/tiles/src/main/java/org/apache/tiles/core/prepare/factory/package-info.java new file mode 100644 index 000000000..c228befe8 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/core/prepare/factory/package-info.java @@ -0,0 +1,26 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +/** + * "View preparers" are objects that allows the "preparation" of a Tiles artifact + * (definition, template or attribute) before it is rendered.
+ * It is useful, for example, when a view item should be built and stored in a + * particular context (e.g. a menu) and then rendered. + */ +package org.apache.tiles.core.prepare.factory; + diff --git a/plugins/tiles/src/main/java/org/apache/tiles/core/renderer/DefinitionRenderer.java b/plugins/tiles/src/main/java/org/apache/tiles/core/renderer/DefinitionRenderer.java new file mode 100644 index 000000000..9becc6e43 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/core/renderer/DefinitionRenderer.java @@ -0,0 +1,67 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.core.renderer; + +import org.apache.tiles.api.TilesContainer; +import org.apache.tiles.request.Request; +import org.apache.tiles.request.render.CannotRenderException; +import org.apache.tiles.request.render.Renderer; + +import java.io.IOException; + +/** + * Renders an attribute that contains a reference to a definition. + * + * @since 3.0.0 + */ +public class DefinitionRenderer implements Renderer { + + /** + * The Tiles container. + */ + private final TilesContainer container; + + /** + * Constructor. + * + * @param container The Tiles container. + */ + public DefinitionRenderer(TilesContainer container) { + this.container = container; + } + + /** + * {@inheritDoc} + */ + @Override + public void render(String path, Request request) throws IOException { + if (path == null) { + throw new CannotRenderException("Cannot dispatch a null path"); + } + + container.render(path, request); + } + + /** + * {@inheritDoc} + */ + public boolean isRenderable(String path, Request request) { + return path != null && container.isValidDefinition(path, request); + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/core/renderer/package-info.java b/plugins/tiles/src/main/java/org/apache/tiles/core/renderer/package-info.java new file mode 100644 index 000000000..089580e86 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/core/renderer/package-info.java @@ -0,0 +1,22 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +/** + * Interfaces to manage attribute rendering. + */ +package org.apache.tiles.core.renderer; diff --git a/plugins/tiles/src/main/java/org/apache/tiles/core/startup/AbstractTilesInitializer.java b/plugins/tiles/src/main/java/org/apache/tiles/core/startup/AbstractTilesInitializer.java new file mode 100644 index 000000000..012665bf0 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/core/startup/AbstractTilesInitializer.java @@ -0,0 +1,110 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.core.startup; + +import org.apache.tiles.api.TilesContainer; +import org.apache.tiles.api.access.TilesAccess; +import org.apache.tiles.core.factory.AbstractTilesContainerFactory; +import org.apache.tiles.request.ApplicationAccess; +import org.apache.tiles.request.ApplicationContext; + +/** + * Default Tiles initialization delegate implementation under a servlet + * environment. It uses init parameters to create the + * {@link ApplicationContext} and the {@link TilesContainer}. + * + * @since 2.2.0 + */ +public abstract class AbstractTilesInitializer implements TilesInitializer { + + /** + * The initialized application context. + */ + private ApplicationContext applicationContext; + + /** + * {@inheritDoc} + */ + public void initialize(ApplicationContext applicationContext) { + this.applicationContext = createTilesApplicationContext(applicationContext); + ApplicationAccess.register(applicationContext); + String key = getContainerKey(this.applicationContext); + // The initialized container. + TilesContainer container = createContainer(this.applicationContext); + TilesAccess.setContainer(this.applicationContext, container, key); + } + + /** + * {@inheritDoc} + */ + public void destroy() { + TilesAccess.setContainer(applicationContext, null, getContainerKey(applicationContext)); + } + + /** + * Creates the Tiles application context, to be used across all the + * Tiles-based application. If you override this class, please override this + * method.
+ * This implementation returns the preliminary context passed as a parameter + * + * @param preliminaryContext The preliminary application context to use. + * @return The Tiles application context. + * @since 2.2.0 + */ + protected ApplicationContext createTilesApplicationContext(ApplicationContext preliminaryContext) { + return preliminaryContext; + } + + /** + * Returns the container key under which the container will be stored. + * This implementation returns null so that the container will + * be the default one. + * + * @param applicationContext The Tiles application context to use. + * @return The container key. + * @since 2.2.0 + */ + protected String getContainerKey(ApplicationContext applicationContext) { + return null; + } + + /** + * Creates a Tiles container. If you override this class, please override + * this method or {@link #createContainerFactory(ApplicationContext)}. + * + * @param context The servlet context to use. + * @return The created container. + * @since 2.2.0 + */ + protected TilesContainer createContainer(ApplicationContext context) { + AbstractTilesContainerFactory factory = createContainerFactory(context); + return factory.createContainer(context); + } + + /** + * Creates a Tiles container factory. If you override this class, please + * override this method or {@link #createContainer(ApplicationContext)}. + * + * @param context The servlet context to use. + * @return The created container factory. + * @since 2.2.0 + */ + protected abstract AbstractTilesContainerFactory createContainerFactory( + ApplicationContext context); +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/core/startup/TilesInitializer.java b/plugins/tiles/src/main/java/org/apache/tiles/core/startup/TilesInitializer.java new file mode 100644 index 000000000..d9bfc0f6e --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/core/startup/TilesInitializer.java @@ -0,0 +1,45 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.core.startup; + +import org.apache.tiles.request.ApplicationContext; + +/** + * Tiles initialization delegate. It initializes Tiles container(s) and the + * application context to use across all the application. + */ +public interface TilesInitializer { + + /** + * Initializes Tiles. + * + * @param preliminaryContext The preliminary application context to use. It + * will be overwritten with the real instance later. Use a context usable + * under your current environment, like ServletTilesApplicationContext or + * PortletTilesApplicationContext. + */ + void initialize(ApplicationContext preliminaryContext); + + /** + * Destroys the Tiles container. + * + * @since 2.2.0 + */ + void destroy(); +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/core/startup/package-info.java b/plugins/tiles/src/main/java/org/apache/tiles/core/startup/package-info.java new file mode 100644 index 000000000..3c06d86e3 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/core/startup/package-info.java @@ -0,0 +1,24 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +/** + * Classes to start the Tiles engine up. Use these classes in your environment by + * using a preliminary TilesApplicationContext that expose at least the needed + * initialization parameters. + */ +package org.apache.tiles.core.startup; diff --git a/plugins/tiles/src/main/java/org/apache/tiles/core/util/CombinedBeanInfo.java b/plugins/tiles/src/main/java/org/apache/tiles/core/util/CombinedBeanInfo.java new file mode 100644 index 000000000..425a3d7bf --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/core/util/CombinedBeanInfo.java @@ -0,0 +1,95 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tiles.core.util; + +import org.apache.tiles.request.reflect.ClassUtil; + +import java.beans.FeatureDescriptor; +import java.beans.PropertyDescriptor; +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * Contains the bean infos about one or more classes. + * @since 2.2.0 + */ +public class CombinedBeanInfo { + /** + * The descriptors of the introspected classes. + */ + private final List descriptors; + + /** + * Maps analyzed classes to the map of introspected properties. + */ + private final Map, Map> class2descriptors; + + /** + * Constructor. + * @param clazzes The list of classes to analyze and combine. + * + * @since 2.2.0 + */ + public CombinedBeanInfo(Class... clazzes) { + descriptors = new ArrayList<>(); + class2descriptors = new LinkedHashMap<>(); + for (Class clazz : clazzes) { + Map mappedDescriptors = new LinkedHashMap<>(); + ClassUtil.collectBeanInfo(clazz, mappedDescriptors); + descriptors.addAll(mappedDescriptors.values()); + class2descriptors.put(clazz, mappedDescriptors); + } + } + + /** + * Returns the descriptors of all the introspected classes. + * + * @return The feature descriptors. + * @since 2.2.0 + */ + public List getDescriptors() { + return descriptors; + } + + /** + * Returns a map of the introspected properties for the given class. + * + * @param clazz The class to get the properties from. + * @return The map of property descriptors. + * @since 2.2.0 + */ + public Map getMappedDescriptors(Class clazz) { + return class2descriptors.get(clazz); + } + + /** + * Returns the set of properties for the given introspected class. + * + * @param clazz The class to get the properties from. + * @return The set of properties. + * @since 2.2.0 + */ + public Set getProperties(Class clazz) { + return class2descriptors.get(clazz).keySet(); + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/core/util/WildcardHelper.java b/plugins/tiles/src/main/java/org/apache/tiles/core/util/WildcardHelper.java new file mode 100644 index 000000000..35f54a064 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/core/util/WildcardHelper.java @@ -0,0 +1,543 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.core.util; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +/** + * This class is an utility class that perform wilcard-patterns matching and + * isolation taken from Apache Struts that is taken, in turn, from Apache + * Struts. + * + * @since 2.1.0 + */ +public class WildcardHelper { + /** + * The int representing '*' in the pattern int []. + * + * @since 2.1.0 + */ + protected static final int MATCH_FILE = -1; + + /** + * The int representing '**' in the pattern int []. + * + * @since 2.1.0 + */ + protected static final int MATCH_PATH = -2; + + /** + * The int representing begin in the pattern int []. + * + * @since 2.1.0 + */ + protected static final int MATCH_BEGIN = -4; + + /** + * The int representing end in pattern int []. + * + * @since 2.1.0 + */ + protected static final int MATCH_THEEND = -5; + + /** + * The int value that terminates the pattern int []. + * + * @since 2.1.0 + */ + protected static final int MATCH_END = -3; + + /** + * The length of the placeholder. + * + * @since 2.1.0 + */ + private static final int PLACEHOLDER_LENGTH = 3; + + /** + *

+ * Translate the given String into a int [] + * representing the pattern matchable by this class.
+ * This function translates a String into an int array + * converting the special '*' and '\' characters.
+ * Here is how the conversion algorithm works: + *

+ * + *
    + * + *
  • The '*' character is converted to MATCH_FILE, meaning that zero or + * more characters (excluding the path separator '/') are to be matched.
  • + * + *
  • The '**' sequence is converted to MATCH_PATH, meaning that zero or + * more characters (including the path separator '/') are to be matched.
  • + * + *
  • The '\' character is used as an escape sequence ('\*' is translated + * in '*', not in MATCH_FILE). If an exact '\' character is to be matched + * the source string must contain a '\\'. sequence.
  • + * + *
+ * + *

+ * When more than two '*' characters, not separated by another character, + * are found their value is considered as '**' (MATCH_PATH).
+ * The array is always terminated by a special value (MATCH_END).
+ * All MATCH* values are less than zero, while normal characters are equal + * or greater. + *

+ * + * @param data The string to translate. + * @return The encoded string as an int array, terminated by the MATCH_END + * value (don't consider the array length). + * @throws NullPointerException If data is null. + * @since 2.1.0 + */ + public int[] compilePattern(String data) { + // Prepare the arrays + int[] expr = new int[data.length() + 2]; + char[] buff = data.toCharArray(); + + // Prepare variables for the translation loop + int y = 0; + boolean slash = false; + + // Must start from beginning + expr[y++] = MATCH_BEGIN; + + if (buff.length > 0) { + if (buff[0] == '\\') { + slash = true; + } else if (buff[0] == '*') { + expr[y++] = MATCH_FILE; + } else { + expr[y++] = buff[0]; + } + + // Main translation loop + for (int x = 1; x < buff.length; x++) { + // If the previous char was '\' simply copy this char. + if (slash) { + expr[y++] = buff[x]; + slash = false; + + // If the previous char was not '\' we have to do a bunch of + // checks + } else { + // If this char is '\' declare that and continue + if (buff[x] == '\\') { + slash = true; + + // If this char is '*' check the previous one + } else if (buff[x] == '*') { + // If the previous character als was '*' match a path + if (expr[y - 1] <= MATCH_FILE) { + expr[y - 1] = MATCH_PATH; + } else { + expr[y++] = MATCH_FILE; + } + } else { + expr[y++] = buff[x]; + } + } + } + } + + // Must match end at the end + expr[y] = MATCH_THEEND; + + return expr; + } + + /** + * Match a pattern agains a string and isolates wildcard replacement into a + * Stack. + * + * @param data The string to match + * @param expr The compiled wildcard expression + * @return The list of matched variables, or null if it does not match. + * @throws NullPointerException If any parameters are null + * @since 2.2.0 + */ + public List match(String data, int[] expr) { + List varsValues = null; + + if (data == null) { + throw new NullPointerException("No data provided"); + } + + if (expr == null) { + throw new NullPointerException("No pattern expression provided"); + } + + char[] buff = data.toCharArray(); + + // Allocate the result buffer + char[] rslt = new char[expr.length + buff.length]; + + // The previous and current position of the expression character + // (MATCH_*) + int charpos = 0; + + // The position in the expression, input, translation and result arrays + int exprpos = 0; + int buffpos = 0; + int rsltpos = 0; + int offset = -1; + + // First check for MATCH_BEGIN + boolean matchBegin = false; + + if (expr[charpos] == MATCH_BEGIN) { + matchBegin = true; + exprpos = ++charpos; + } + + // Search the fist expression character (except MATCH_BEGIN - already + // skipped) + while (expr[charpos] >= 0) { + charpos++; + } + + // The expression charater (MATCH_*) + int exprchr = expr[charpos]; + + while (true) { + // Check if the data in the expression array before the current + // expression character matches the data in the input buffer + if (matchBegin) { + if (!matchArray(expr, exprpos, charpos, buff, buffpos)) { + return null; + } + + matchBegin = false; + } else { + offset = indexOfArray(expr, exprpos, charpos, buff, buffpos); + + if (offset < 0) { + return null; + } + } + + // Check for MATCH_BEGIN + if (matchBegin) { + if (offset != 0) { + return null; + } + + matchBegin = false; + } + + // Advance buffpos + buffpos += (charpos - exprpos); + + // Check for END's + if (exprchr == MATCH_END) { + if (rsltpos > 0) { + varsValues = addAndCreateList(varsValues, new String(rslt, + 0, rsltpos)); + } + + // Don't care about rest of input buffer + varsValues = addElementOnTop(varsValues, data); + return varsValues; + } else if (exprchr == MATCH_THEEND) { + if (rsltpos > 0) { + varsValues = addAndCreateList(varsValues, new String(rslt, + 0, rsltpos)); + } + + // Check that we reach buffer's end + if (buffpos == buff.length) { + addElementOnTop(varsValues, data); + return varsValues; + } + return null; + } + + // Search the next expression character + exprpos = ++charpos; + + while (expr[charpos] >= 0) { + charpos++; + } + + int prevchr = exprchr; + + exprchr = expr[charpos]; + + // We have here prevchr == * or **. + offset = (prevchr == MATCH_FILE) ? indexOfArray(expr, exprpos, + charpos, buff, buffpos) : lastIndexOfArray(expr, exprpos, + charpos, buff, buffpos); + + if (offset < 0) { + return null; + } + + // Copy the data from the source buffer into the result buffer + // to substitute the expression character + if (prevchr == MATCH_PATH) { + while (buffpos < offset) { + rslt[rsltpos++] = buff[buffpos++]; + } + } else { + // Matching file, don't copy '/' + while (buffpos < offset) { + if (buff[buffpos] == '/') { + return null; + } + + rslt[rsltpos++] = buff[buffpos++]; + } + } + + varsValues = addAndCreateList(varsValues, new String(rslt, 0, + rsltpos)); + rsltpos = 0; + } + } + + /** + * Get the offset of a part of an int array within a char array.
+ * This method return the index in d of the first occurrence after dpos of + * that part of array specified by r, starting at rpos and terminating at + * rend. + * + * @param r The array containing the data that need to be matched in d. + * @param rpos The index of the first character in r to look for. + * @param rend The index of the last character in r to look for plus 1. + * @param d The array of char that should contain a part of r. + * @param dpos The starting offset in d for the matching. + * @return The offset in d of the part of r matched in d or -1 if that was + * not found. + * @since 2.1.0 + */ + protected int indexOfArray(int[] r, int rpos, int rend, char[] d, int dpos) { + // Check if pos and len are legal + if (rend < rpos) { + throw new IllegalArgumentException("rend < rpos"); + } + + // If we need to match a zero length string return current dpos + if (rend == rpos) { + return (d.length); // ?? dpos? + } + + // If we need to match a 1 char length string do it simply + if ((rend - rpos) == 1) { + // Search for the specified character + for (int x = dpos; x < d.length; x++) { + if (r[rpos] == d[x]) { + return (x); + } + } + } + + // Main string matching loop. It gets executed if the characters to + // match are less then the characters left in the d buffer + while (((dpos + rend) - rpos) <= d.length) { + // Set current startpoint in d + int y = dpos; + + // Check every character in d for equity. If the string is matched + // return dpos + for (int x = rpos; x <= rend; x++) { + if (x == rend) { + return (dpos); + } + + if (r[x] != d[y++]) { + break; + } + } + + // Increase dpos to search for the same string at next offset + dpos++; + } + + // The remaining chars in d buffer were not enough or the string + // wasn't matched + return (-1); + } + + /** + * Get the offset of a last occurance of an int array within a char array. + *
+ * This method return the index in d of the last occurrence after dpos of + * that part of array specified by r, starting at rpos and terminating at + * rend. + * + * @param r The array containing the data that need to be matched in d. + * @param rpos The index of the first character in r to look for. + * @param rend The index of the last character in r to look for plus 1. + * @param d The array of char that should contain a part of r. + * @param dpos The starting offset in d for the matching. + * @return The offset in d of the last part of r matched in d or -1 if that + * was not found. + * @since 2.1.0 + */ + protected int lastIndexOfArray(int[] r, int rpos, int rend, char[] d, + int dpos) { + // Check if pos and len are legal + if (rend < rpos) { + throw new IllegalArgumentException("rend < rpos"); + } + + // If we need to match a zero length string return current dpos + if (rend == rpos) { + return (d.length); // ?? dpos? + } + + // If we need to match a 1 char length string do it simply + if ((rend - rpos) == 1) { + // Search for the specified character + for (int x = d.length - 1; x > dpos; x--) { + if (r[rpos] == d[x]) { + return (x); + } + } + } + + // Main string matching loop. It gets executed if the characters to + // match are less then the characters left in the d buffer + int l = d.length - (rend - rpos); + + while (l >= dpos) { + // Set current startpoint in d + int y = l; + + // Check every character in d for equity. If the string is matched + // return dpos + for (int x = rpos; x <= rend; x++) { + if (x == rend) { + return (l); + } + + if (r[x] != d[y++]) { + break; + } + } + + // Decrease l to search for the same string at next offset + l--; + } + + // The remaining chars in d buffer were not enough or the string + // wasn't matched + return (-1); + } + + /** + * Matches elements of array r from rpos to rend with array d, starting from + * dpos.
+ * This method return true if elements of array r from rpos to rend equals + * elements of array d starting from dpos to dpos+(rend-rpos). + * + * @param r The array containing the data that need to be matched in d. + * @param rpos The index of the first character in r to look for. + * @param rend The index of the last character in r to look for. + * @param d The array of char that should start from a part of r. + * @param dpos The starting offset in d for the matching. + * @return true if array d starts from portion of array r. + * @since 2.1.0 + */ + protected boolean matchArray(int[] r, int rpos, int rend, char[] d, int dpos) { + if ((d.length - dpos) < (rend - rpos)) { + return (false); + } + + for (int i = rpos; i < rend; i++) { + if (r[i] != d[dpos++]) { + return (false); + } + } + + return (true); + } + + /** + *

+ * Inserts into a value wildcard-matched strings where specified. + *

+ * + * @param val The value to convert + * @param vars A Map of wildcard-matched strings + * @return The new value + * @since 2.1.0 + */ + public static String convertParam(String val, Map vars) { + if (val == null) { + return null; + } else if (!val.contains("{")) { + return val; + } + + Map.Entry entry; + StringBuilder key = new StringBuilder("{0}"); + StringBuilder ret = new StringBuilder(val); + String keyTmp; + int x; + + for (Map.Entry integerStringEntry : vars.entrySet()) { + entry = integerStringEntry; + key.setCharAt(1, entry.getKey().toString().charAt(0)); + keyTmp = key.toString(); + + // Replace all instances of the placeholder + while ((x = ret.toString().indexOf(keyTmp)) > -1) { + ret.replace(x, x + PLACEHOLDER_LENGTH, entry.getValue()); + } + } + + return ret.toString(); + } + + /** + * Adds and object to a list. If the list is null, it creates it. + * + * @param The type of the element. + * @param list The list. + * @param data The data to add. + * @return The list itself, or a new one if it is null. + */ + private List addAndCreateList(List list, T data) { + if (list == null) { + list = new ArrayList<>(); + } + list.add(data); + return list; + } + + /** + * Adds and object on top of a list. If the list is null, it creates it. + * + * @param The type of the element. + * @param list The list. + * @param data The data to add. + * @return The list itself, or a new one if it is null. + */ + private List addElementOnTop(List list, T data) { + if (list == null) { + list = new ArrayList<>(); + } + list.add(0, data); + return list; + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/core/util/package-info.java b/plugins/tiles/src/main/java/org/apache/tiles/core/util/package-info.java new file mode 100644 index 000000000..9d03dc0e5 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/core/util/package-info.java @@ -0,0 +1,22 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +/** + * Static utility classes used throughout the implementation. + */ +package org.apache.tiles.core.util; diff --git a/plugins/tiles/src/main/java/org/apache/tiles/el/ELAttributeEvaluator.java b/plugins/tiles/src/main/java/org/apache/tiles/el/ELAttributeEvaluator.java new file mode 100644 index 000000000..cfa68da8a --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/el/ELAttributeEvaluator.java @@ -0,0 +1,92 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.el; + +import org.apache.tiles.core.evaluator.AbstractAttributeEvaluator; +import org.apache.tiles.request.ApplicationContext; +import org.apache.tiles.request.Request; + +import javax.el.ELResolver; +import javax.el.ExpressionFactory; +import javax.el.ValueExpression; + +/** + * Evaluates string expression with typical EL syntax.
+ * You can use normal EL syntax, knowing the root objects are + * {@link Request}, {@link ApplicationContext} and beans + * contained in request, session and application scope. + * + * @since 2.2.1 + */ +public class ELAttributeEvaluator extends AbstractAttributeEvaluator { + + /** + * The EL expression factory. + * + * @since 2.2.1 + */ + protected ExpressionFactory expressionFactory; + + /** + * The EL resolver to use. + * + * @since 2.2.1 + */ + protected ELResolver resolver; + + /** + * Constructor. + * + * @since 2.2.1 + */ + public ELAttributeEvaluator() { + } + + /** + * Sets the expression factory to use. + * + * @param expressionFactory The expression factory. + * @since 2.2.1 + */ + public void setExpressionFactory(ExpressionFactory expressionFactory) { + this.expressionFactory = expressionFactory; + } + + /** + * Sets the EL resolver to use. + * + * @param resolver The EL resolver. + * @since 2.2.1 + */ + public void setResolver(ELResolver resolver) { + this.resolver = resolver; + } + + /** {@inheritDoc} */ + public Object evaluate(String expression, Request request) { + ELContextImpl context = new ELContextImpl(resolver); + context.putContext(Request.class, request); + context.putContext(ApplicationContext.class, + request.getApplicationContext()); + ValueExpression valueExpression = expressionFactory + .createValueExpression(context, expression, Object.class); + + return valueExpression.getValue(context); + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/el/ELContextImpl.java b/plugins/tiles/src/main/java/org/apache/tiles/el/ELContextImpl.java new file mode 100644 index 000000000..8e162ae40 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/el/ELContextImpl.java @@ -0,0 +1,144 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tiles.el; + +import javax.el.ELContext; +import javax.el.ELResolver; +import javax.el.FunctionMapper; +import javax.el.ValueExpression; +import javax.el.VariableMapper; +import java.lang.reflect.Method; +import java.util.HashMap; +import java.util.Map; + +/** + * Implementation of ELContext.
+ * Copied from Apache Tomcat 6.0.16 source code. + * + * @since 2.2.1 + */ +public class ELContextImpl extends ELContext { + + /** + * A null function mapper. + */ + private static final FunctionMapper NULL_FUNCTION_MAPPER = new FunctionMapper() { + @Override + public Method resolveFunction(String prefix, String localName) { + return null; + } + }; + + /** + * Default implementation for the variable mapper. + */ + private static final class VariableMapperImpl extends VariableMapper { + + /** + * The mapped variables. + */ + private Map vars; + + /** {@inheritDoc} */ + @Override + public ValueExpression resolveVariable(String variable) { + if (vars == null) { + return null; + } + return vars.get(variable); + } + + /** {@inheritDoc} */ + @Override + public ValueExpression setVariable(String variable, + ValueExpression expression) { + if (vars == null) { + vars = new HashMap<>(); + } + return vars.put(variable, expression); + } + + } + + /** + * The EL resolver to use. + */ + private final ELResolver resolver; + + /** + * The function mapper to use. + */ + private FunctionMapper functionMapper = NULL_FUNCTION_MAPPER; + + /** + * The variable mapper to use. + */ + private VariableMapper variableMapper; + + /** + * Constructor. + * + * @param resolver The resolver to use. + */ + public ELContextImpl(ELResolver resolver) { + this.resolver = resolver; + } + + /** {@inheritDoc} */ + @Override + public ELResolver getELResolver() { + return this.resolver; + } + + /** {@inheritDoc} */ + @Override + public FunctionMapper getFunctionMapper() { + return this.functionMapper; + } + + /** {@inheritDoc} */ + @Override + public VariableMapper getVariableMapper() { + if (this.variableMapper == null) { + this.variableMapper = new VariableMapperImpl(); + } + return this.variableMapper; + } + + /** + * Sets the function mapper to use. + * + * @param functionMapper The function mapper. + * @since 2.2.1 + */ + public void setFunctionMapper(FunctionMapper functionMapper) { + this.functionMapper = functionMapper; + } + + /** + * Sets the variable mapper to use. + * + * @param variableMapper The variable mapper. + * @since 2.2.1 + */ + public void setVariableMapper(VariableMapper variableMapper) { + this.variableMapper = variableMapper; + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/el/ExpressionFactoryFactory.java b/plugins/tiles/src/main/java/org/apache/tiles/el/ExpressionFactoryFactory.java new file mode 100644 index 000000000..f19a9e0e8 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/el/ExpressionFactoryFactory.java @@ -0,0 +1,37 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.el; + +import javax.el.ExpressionFactory; + +/** + * Interface to define a factory of {@link ExpressionFactory}. + * + * @since 2.2.1 + */ +public interface ExpressionFactoryFactory { + + /** + * Returns the expression factory to use. + * + * @return The expression factory. + * @since 2.2.1 + */ + ExpressionFactory getExpressionFactory(); +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/el/JspExpressionFactoryFactory.java b/plugins/tiles/src/main/java/org/apache/tiles/el/JspExpressionFactoryFactory.java new file mode 100644 index 000000000..5b9bd108b --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/el/JspExpressionFactoryFactory.java @@ -0,0 +1,63 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.el; + +import org.apache.tiles.request.ApplicationContext; +import org.apache.tiles.request.ApplicationContextAware; + +import javax.el.ExpressionFactory; +import javax.servlet.ServletContext; +import javax.servlet.jsp.JspFactory; + +/** + * Uses the JSP 2.1 {@link ExpressionFactory} to be used in Tiles. + * + * @since 2.2.1 + */ +public class JspExpressionFactoryFactory implements ExpressionFactoryFactory, ApplicationContextAware { + + /** + * The servlet context. + * + * @since 2.2.1 + */ + protected ServletContext servletContext; + + /** + * {@inheritDoc} + */ + public void setApplicationContext(ApplicationContext applicationContext) { + Object context = applicationContext.getContext(); + if (context instanceof ServletContext) { + this.servletContext = (ServletContext) context; + } else { + throw new IllegalArgumentException( + "The application context does not hold an instance of " + + "ServletContext, consider using JuelExpressionFactoryFactory"); + } + } + + /** + * {@inheritDoc} + */ + public ExpressionFactory getExpressionFactory() { + return JspFactory.getDefaultFactory().getJspApplicationContext( + servletContext).getExpressionFactory(); + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/el/ScopeELResolver.java b/plugins/tiles/src/main/java/org/apache/tiles/el/ScopeELResolver.java new file mode 100644 index 000000000..8086e113a --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/el/ScopeELResolver.java @@ -0,0 +1,143 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.el; + +import org.apache.tiles.request.Request; + +import javax.el.ELContext; +import javax.el.ELResolver; +import java.beans.FeatureDescriptor; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +/** + * Resolves beans in request, session and application scope. + * + * @since 2.2.1 + */ +public class ScopeELResolver extends ELResolver { + + /** + * The length of the suffix: "Scope". + */ + private static final int SUFFIX_LENGTH = 5; + + /** + * {@inheritDoc} + */ + @Override + public Class getCommonPropertyType(ELContext context, Object base) { + // only resolve at the root of the context + if (base != null) { + return null; + } + + return Map.class; + } + + /** + * {@inheritDoc} + */ + @Override + public Iterator getFeatureDescriptors(ELContext context, Object base) { + if (base != null) { + return Collections.emptyIterator(); + } + + List list = new ArrayList<>(); + + Request request = (Request) context + .getContext(Request.class); + for (String scope : request.getAvailableScopes()) { + FeatureDescriptor descriptor = new FeatureDescriptor(); + descriptor.setDisplayName(scope + "Scope"); + descriptor.setExpert(false); + descriptor.setHidden(false); + descriptor.setName(scope + "Scope"); + descriptor.setPreferred(true); + descriptor.setShortDescription(""); + descriptor.setValue("type", Map.class); + descriptor.setValue("resolvableAtDesignTime", Boolean.FALSE); + list.add(descriptor); + } + + return list.iterator(); + } + + /** + * {@inheritDoc} + */ + @Override + public Class getType(ELContext context, Object base, Object property) { + if (base != null || !(property instanceof String) || !((String) property).endsWith("Scope")) { + return null; + } + + return Map.class; + } + + /** + * {@inheritDoc} + */ + @Override + public Object getValue(ELContext context, Object base, Object property) { + if (base != null) { + return null; + } + + Object retValue = null; + String propertyString = (String) property; + if (property != null && propertyString.endsWith("Scope")) { + Request request = (Request) context + .getContext(Request.class); + retValue = request.getContext(propertyString.substring(0, + propertyString.length() - SUFFIX_LENGTH)); + } + + if (retValue != null) { + context.setPropertyResolved(true); + } + + return retValue; + } + + /** + * {@inheritDoc} + */ + @Override + public boolean isReadOnly(ELContext context, Object base, Object property) { + if (context == null) { + throw new NullPointerException(); + } + + return true; + } + + /** + * {@inheritDoc} + */ + @Override + public void setValue(ELContext context, Object base, Object property, + Object value) { + // Does nothing for the moment. + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/el/TilesContextBeanELResolver.java b/plugins/tiles/src/main/java/org/apache/tiles/el/TilesContextBeanELResolver.java new file mode 100644 index 000000000..117b4e614 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/el/TilesContextBeanELResolver.java @@ -0,0 +1,172 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.el; + +import org.apache.tiles.request.Request; + +import javax.el.ELContext; +import javax.el.ELResolver; +import java.beans.FeatureDescriptor; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +/** + * Resolves beans in request, session and application scope. + * + * @since 2.2.1 + */ +public class TilesContextBeanELResolver extends ELResolver { + + /** {@inheritDoc} */ + @Override + public Class getCommonPropertyType(ELContext context, Object base) { + // only resolve at the root of the context + if (base != null) { + return null; + } + + return String.class; + } + + /** {@inheritDoc} */ + @Override + public Iterator getFeatureDescriptors(ELContext context, Object base) { + List list = new ArrayList<>(); + + Request request = (Request) context.getContext(Request.class); + for (String scope : request.getAvailableScopes()) { + collectBeanInfo(request.getContext(scope), list); + } + return list.iterator(); + } + + /** {@inheritDoc} */ + @Override + public Class getType(ELContext context, Object base, Object property) { + if (base != null) { + return null; + } + + Object obj = findObjectByProperty(context, property); + if (obj != null) { + context.setPropertyResolved(true); + return obj.getClass(); + } + return null; + } + + /** {@inheritDoc} */ + @Override + public Object getValue(ELContext context, Object base, Object property) { + if (base != null) { + return null; + } + + Object retValue = findObjectByProperty(context, property); + + if (retValue != null) { + context.setPropertyResolved(true); + } + + return retValue; + } + + /** {@inheritDoc} */ + @Override + public boolean isReadOnly(ELContext context, Object base, Object property) { + if (context == null) { + throw new NullPointerException(); + } + + return true; + } + + /** {@inheritDoc} */ + @Override + public void setValue(ELContext context, Object base, Object property, + Object value) { + // Does nothing for the moment. + } + + /** + * Collects bean infos from a map's values and filling a list. + * + * @param map The map containing the bean to be inspected. + * @param list The list to fill. + * @since 2.2.1 + */ + protected void collectBeanInfo(Map map, List list) { + if (map == null || map.isEmpty()) { + return; + } + + for (Map.Entry entry : map.entrySet()) { + FeatureDescriptor descriptor = new FeatureDescriptor(); + descriptor.setDisplayName(entry.getKey()); + descriptor.setExpert(false); + descriptor.setHidden(false); + descriptor.setName(entry.getKey()); + descriptor.setPreferred(true); + descriptor.setShortDescription(""); + descriptor.setValue("type", String.class); + descriptor.setValue("resolvableAtDesignTime", Boolean.FALSE); + list.add(descriptor); + } + } + + /** + * Finds an object in request, session or application scope, in this order. + * + * @param context The context to use. + * @param property The property used as an attribute name. + * @return The found bean, if it exists, or null otherwise. + * @since 2.2.1 + */ + protected Object findObjectByProperty(ELContext context, Object property) { + Object retValue; + Request request = (Request) context.getContext(Request.class); + String prop = property.toString(); + String[] scopes = request.getAvailableScopes().toArray(new String[0]); + int i = 0; + do { + retValue = getObject(request.getContext(scopes[i]), prop); + i++; + } while (retValue == null && i < scopes.length); + + return retValue; + } + + /** + * Returns an object from a map in a null-safe manner. + * + * @param map The map to use. + * @param property The property to use as a key. + * @return The object, if present, or null otherwise. + * @since 2.2.1 + */ + protected Object getObject(Map map, String property) { + Object retValue = null; + if (map != null) { + retValue = map.get(property); + } + return retValue; + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/el/TilesContextELResolver.java b/plugins/tiles/src/main/java/org/apache/tiles/el/TilesContextELResolver.java new file mode 100644 index 000000000..1296c5c34 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/el/TilesContextELResolver.java @@ -0,0 +1,156 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.el; + +import org.apache.tiles.core.util.CombinedBeanInfo; +import org.apache.tiles.request.ApplicationContext; +import org.apache.tiles.request.Request; + +import javax.el.ELContext; +import javax.el.ELResolver; +import java.beans.FeatureDescriptor; +import java.util.Iterator; + +/** + * Resolves properties of {@link Request} and + * {@link ApplicationContext}. + * + * @since 2.2.1 + */ +public class TilesContextELResolver extends ELResolver { + + /** + * Internal bean resolver to resolve beans in any context. + */ + private final ELResolver beanElResolver; + + /** + * Constructor. + * + * @param beanElResolver The used bean resolver. + */ + public TilesContextELResolver(ELResolver beanElResolver) { + this.beanElResolver = beanElResolver; + } + + /** + * The beaninfos about {@link Request} and {@link ApplicationContext}. + */ + private final CombinedBeanInfo requestBeanInfo = new CombinedBeanInfo(Request.class, ApplicationContext.class); + + /** + * {@inheritDoc} + */ + @Override + public Class getCommonPropertyType(ELContext context, Object base) { + // only resolve at the root of the context + if (base != null) { + return null; + } + + return String.class; + } + + /** + * {@inheritDoc} + */ + @Override + public Iterator getFeatureDescriptors(ELContext context, + Object base) { + // only resolve at the root of the context + if (base != null) { + return null; + } + + return requestBeanInfo.getDescriptors().iterator(); + } + + /** + * {@inheritDoc} + */ + @Override + public Class getType(ELContext context, Object base, Object property) { + // only resolve at the root of the context + if (base != null) { + return null; + } + + Class retValue = null; + if (requestBeanInfo.getProperties(Request.class).contains(property)) { + Request request = (Request) context.getContext(Request.class); + retValue = beanElResolver.getType(context, request, property); + } else if (requestBeanInfo.getProperties(ApplicationContext.class).contains(property)) { + ApplicationContext applicationContext = (ApplicationContext) context.getContext(ApplicationContext.class); + retValue = beanElResolver.getType(context, applicationContext, property); + } + + if (retValue != null) { + context.setPropertyResolved(true); + } + + return retValue; + } + + /** + * {@inheritDoc} + */ + @Override + public Object getValue(ELContext context, Object base, Object property) { + // only resolve at the root of the context + if (base != null) { + return null; + } + + Object retValue = null; + + if (requestBeanInfo.getProperties(Request.class).contains(property)) { + Request request = (Request) context.getContext(Request.class); + retValue = beanElResolver.getValue(context, request, property); + } else if (requestBeanInfo.getProperties(ApplicationContext.class).contains(property)) { + ApplicationContext applicationContext = (ApplicationContext) context.getContext(ApplicationContext.class); + retValue = beanElResolver.getValue(context, applicationContext, property); + } + + if (retValue != null) { + context.setPropertyResolved(true); + } + + return retValue; + } + + /** + * {@inheritDoc} + */ + @Override + public boolean isReadOnly(ELContext context, Object base, Object property) { + if (context == null) { + throw new NullPointerException(); + } + + return true; + } + + /** + * {@inheritDoc} + */ + @Override + public void setValue(ELContext context, Object base, Object property, Object value) { + // Does nothing for the moment. + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/el/package-info.java b/plugins/tiles/src/main/java/org/apache/tiles/el/package-info.java new file mode 100644 index 000000000..f1886e81f --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/el/package-info.java @@ -0,0 +1,22 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +/** + * Attribute evaluator classes that can perform EL evaluation for attributes. + */ +package org.apache.tiles.el; diff --git a/plugins/tiles/src/main/java/org/apache/tiles/freemarker/package-info.java b/plugins/tiles/src/main/java/org/apache/tiles/freemarker/package-info.java new file mode 100644 index 000000000..7f77267d6 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/freemarker/package-info.java @@ -0,0 +1,22 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +/** + * Classes for supporting FreeMarker in Tiles. + */ +package org.apache.tiles.freemarker; diff --git a/plugins/tiles/src/main/java/org/apache/tiles/freemarker/template/AddAttributeFMModel.java b/plugins/tiles/src/main/java/org/apache/tiles/freemarker/template/AddAttributeFMModel.java new file mode 100644 index 000000000..5c656fe87 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/freemarker/template/AddAttributeFMModel.java @@ -0,0 +1,78 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +/* + * This file was automatically generated by Autotag. Please do not edit it manually. + */ +package org.apache.tiles.freemarker.template; + +import java.io.IOException; +import java.util.Map; + +import org.apache.tiles.autotag.core.runtime.ModelBody; +import org.apache.tiles.autotag.core.runtime.AutotagRuntime; + +import freemarker.core.Environment; +import freemarker.template.TemplateDirectiveBody; +import freemarker.template.TemplateDirectiveModel; +import freemarker.template.TemplateException; +import freemarker.template.TemplateModel; + +/** + *

+ * Add an element to the surrounding list. Equivalent to 'putAttribute', but for + * list element. + *

+ * + *

+ * Add an element to the surrounding list. This tag can only be used inside + * 'putListAttribute' or 'addListAttribute' tags. Value can come from a direct + * assignment (value="aValue") + *

+ */ +public class AddAttributeFMModel implements TemplateDirectiveModel { + + /** + * The template model. + */ + private org.apache.tiles.template.AddAttributeModel model; + + /** + * Constructor. + * + * @param model The template model. + */ + public AddAttributeFMModel(org.apache.tiles.template.AddAttributeModel model) { + this.model = model; + } + + @Override + public void execute(Environment env, @SuppressWarnings("rawtypes") Map params, TemplateModel[] loopVars, + TemplateDirectiveBody body) throws TemplateException, IOException { + AutotagRuntime runtime = new org.apache.tiles.request.freemarker.autotag.FreemarkerAutotagRuntime(); + if (runtime instanceof TemplateDirectiveModel) { + ((TemplateDirectiveModel) runtime).execute(env, params, loopVars, body); + } + org.apache.tiles.request.Request request = runtime.createRequest(); + ModelBody modelBody = runtime.createModelBody(); + model.execute(runtime.getParameter("value", java.lang.Object.class, null), + runtime.getParameter("expression", java.lang.String.class, null), + runtime.getParameter("role", java.lang.String.class, null), + runtime.getParameter("type", java.lang.String.class, null), request, modelBody); + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/freemarker/template/AddListAttributeFMModel.java b/plugins/tiles/src/main/java/org/apache/tiles/freemarker/template/AddListAttributeFMModel.java new file mode 100644 index 000000000..ef81f9a44 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/freemarker/template/AddListAttributeFMModel.java @@ -0,0 +1,73 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +/* + * This file was automatically generated by Autotag. Please do not edit it manually. + */ +package org.apache.tiles.freemarker.template; + +import java.io.IOException; +import java.util.Map; + +import org.apache.tiles.autotag.core.runtime.ModelBody; +import org.apache.tiles.autotag.core.runtime.AutotagRuntime; + +import freemarker.core.Environment; +import freemarker.template.TemplateDirectiveBody; +import freemarker.template.TemplateDirectiveModel; +import freemarker.template.TemplateException; +import freemarker.template.TemplateModel; + +/** + *

+ * Declare a list that will be pass as an attribute. + *

+ *

+ * Declare a list that will be pass as an attribute . List elements are added + * using the tag 'addAttribute' or 'addListAttribute'. This tag can only be used + * inside 'insertTemplate', 'insertDefinition' or 'definition' tag. + *

+ */ +public class AddListAttributeFMModel implements TemplateDirectiveModel { + + /** + * The template model. + */ + private org.apache.tiles.template.AddListAttributeModel model; + + /** + * Constructor. + * + * @param model The template model. + */ + public AddListAttributeFMModel(org.apache.tiles.template.AddListAttributeModel model) { + this.model = model; + } + + @Override + public void execute(Environment env, @SuppressWarnings("rawtypes") Map params, TemplateModel[] loopVars, + TemplateDirectiveBody body) throws TemplateException, IOException { + AutotagRuntime runtime = new org.apache.tiles.request.freemarker.autotag.FreemarkerAutotagRuntime(); + if (runtime instanceof TemplateDirectiveModel) { + ((TemplateDirectiveModel) runtime).execute(env, params, loopVars, body); + } + org.apache.tiles.request.Request request = runtime.createRequest(); + ModelBody modelBody = runtime.createModelBody(); + model.execute(runtime.getParameter("role", java.lang.String.class, null), request, modelBody); + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/freemarker/template/DefinitionFMModel.java b/plugins/tiles/src/main/java/org/apache/tiles/freemarker/template/DefinitionFMModel.java new file mode 100644 index 000000000..433f44fbf --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/freemarker/template/DefinitionFMModel.java @@ -0,0 +1,76 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +/* + * This file was automatically generated by Autotag. Please do not edit it manually. + */ +package org.apache.tiles.freemarker.template; + +import java.io.IOException; +import java.util.Map; + +import org.apache.tiles.autotag.core.runtime.ModelBody; +import org.apache.tiles.autotag.core.runtime.AutotagRuntime; + +import freemarker.core.Environment; +import freemarker.template.TemplateDirectiveBody; +import freemarker.template.TemplateDirectiveModel; +import freemarker.template.TemplateException; +import freemarker.template.TemplateModel; + +/** + *

+ * Create a definition at runtime. + *

+ *

+ * Create a new definition at runtime. Newly created definition will be + * available across the entire request. + *

+ */ +public class DefinitionFMModel implements TemplateDirectiveModel { + + /** + * The template model. + */ + private org.apache.tiles.template.DefinitionModel model; + + /** + * Constructor. + * + * @param model The template model. + */ + public DefinitionFMModel(org.apache.tiles.template.DefinitionModel model) { + this.model = model; + } + + @Override + public void execute(Environment env, @SuppressWarnings("rawtypes") Map params, TemplateModel[] loopVars, + TemplateDirectiveBody body) throws TemplateException, IOException { + AutotagRuntime runtime = new org.apache.tiles.request.freemarker.autotag.FreemarkerAutotagRuntime(); + if (runtime instanceof TemplateDirectiveModel) { + ((TemplateDirectiveModel) runtime).execute(env, params, loopVars, body); + } + org.apache.tiles.request.Request request = runtime.createRequest(); + ModelBody modelBody = runtime.createModelBody(); + model.execute(runtime.getParameter("name", java.lang.String.class, null), + runtime.getParameter("template", java.lang.String.class, null), + runtime.getParameter("role", java.lang.String.class, null), + runtime.getParameter("extends", java.lang.String.class, null), + runtime.getParameter("preparer", java.lang.String.class, null), request, modelBody); + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/freemarker/template/GetAsStringFMModel.java b/plugins/tiles/src/main/java/org/apache/tiles/freemarker/template/GetAsStringFMModel.java new file mode 100644 index 000000000..555a708e1 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/freemarker/template/GetAsStringFMModel.java @@ -0,0 +1,81 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +/* + * This file was automatically generated by Autotag. Please do not edit it manually. + */ +package org.apache.tiles.freemarker.template; + +import java.io.IOException; +import java.util.Map; + +import org.apache.tiles.autotag.core.runtime.ModelBody; +import org.apache.tiles.autotag.core.runtime.AutotagRuntime; + +import freemarker.core.Environment; +import freemarker.template.TemplateDirectiveBody; +import freemarker.template.TemplateDirectiveModel; +import freemarker.template.TemplateException; +import freemarker.template.TemplateModel; + +/** + *

+ * Render the value of the specified template attribute to the current Writer + *

+ * + *

+ * Retrieve the value of the specified template attribute property, and render + * it to the current Writer as a String. The usual toString() conversions is + * applied on found value. + *

+ */ +public class GetAsStringFMModel implements TemplateDirectiveModel { + + /** + * The template model. + */ + private org.apache.tiles.template.GetAsStringModel model; + + /** + * Constructor. + * + * @param model The template model. + */ + public GetAsStringFMModel(org.apache.tiles.template.GetAsStringModel model) { + this.model = model; + } + + @Override + public void execute(Environment env, @SuppressWarnings("rawtypes") Map params, TemplateModel[] loopVars, + TemplateDirectiveBody body) throws TemplateException, IOException { + AutotagRuntime runtime = new org.apache.tiles.request.freemarker.autotag.FreemarkerAutotagRuntime(); + if (runtime instanceof TemplateDirectiveModel) { + ((TemplateDirectiveModel) runtime).execute(env, params, loopVars, body); + } + org.apache.tiles.request.Request request = runtime.createRequest(); + ModelBody modelBody = runtime.createModelBody(); + model.execute(runtime.getParameter("ignore", java.lang.Boolean.class, false), + runtime.getParameter("preparer", java.lang.String.class, null), + runtime.getParameter("role", java.lang.String.class, null), + runtime.getParameter("defaultValue", java.lang.Object.class, null), + runtime.getParameter("defaultValueRole", java.lang.String.class, null), + runtime.getParameter("defaultValueType", java.lang.String.class, null), + runtime.getParameter("name", java.lang.String.class, null), + runtime.getParameter("value", org.apache.tiles.api.Attribute.class, null), request, modelBody); + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/freemarker/template/ImportAttributeFMModel.java b/plugins/tiles/src/main/java/org/apache/tiles/freemarker/template/ImportAttributeFMModel.java new file mode 100644 index 000000000..ebee22db9 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/freemarker/template/ImportAttributeFMModel.java @@ -0,0 +1,74 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +/* + * This file was automatically generated by Autotag. Please do not edit it manually. + */ +package org.apache.tiles.freemarker.template; + +import java.io.IOException; +import java.util.Map; + +import org.apache.tiles.autotag.core.runtime.AutotagRuntime; + +import freemarker.core.Environment; +import freemarker.template.TemplateDirectiveBody; +import freemarker.template.TemplateDirectiveModel; +import freemarker.template.TemplateException; +import freemarker.template.TemplateModel; + +/** + *

+ * Import attribute(s) in specified context. + *

+ *

+ * Import attribute(s) to requested scope. Attribute name and scope are + * optional. If not specified, all attributes are imported in page scope. Once + * imported, an attribute can be used as any other beans from jsp contexts. + *

+ */ +public class ImportAttributeFMModel implements TemplateDirectiveModel { + + /** + * The template model. + */ + private org.apache.tiles.template.ImportAttributeModel model; + + /** + * Constructor. + * + * @param model The template model. + */ + public ImportAttributeFMModel(org.apache.tiles.template.ImportAttributeModel model) { + this.model = model; + } + + @Override + public void execute(Environment env, @SuppressWarnings("rawtypes") Map params, TemplateModel[] loopVars, + TemplateDirectiveBody body) throws TemplateException, IOException { + AutotagRuntime runtime = new org.apache.tiles.request.freemarker.autotag.FreemarkerAutotagRuntime(); + if (runtime instanceof TemplateDirectiveModel) { + ((TemplateDirectiveModel) runtime).execute(env, params, loopVars, body); + } + org.apache.tiles.request.Request request = runtime.createRequest(); + model.execute(runtime.getParameter("name", java.lang.String.class, null), + runtime.getParameter("scope", java.lang.String.class, null), + runtime.getParameter("toName", java.lang.String.class, null), + runtime.getParameter("ignore", java.lang.Boolean.class, false), request); + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/freemarker/template/InsertAttributeFMModel.java b/plugins/tiles/src/main/java/org/apache/tiles/freemarker/template/InsertAttributeFMModel.java new file mode 100644 index 000000000..67b36eec4 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/freemarker/template/InsertAttributeFMModel.java @@ -0,0 +1,94 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +/* + * This file was automatically generated by Autotag. Please do not edit it manually. + */ +package org.apache.tiles.freemarker.template; + +import java.io.IOException; +import java.util.Map; + +import org.apache.tiles.autotag.core.runtime.ModelBody; +import org.apache.tiles.autotag.core.runtime.AutotagRuntime; + +import freemarker.core.Environment; +import freemarker.template.TemplateDirectiveBody; +import freemarker.template.TemplateDirectiveModel; +import freemarker.template.TemplateException; +import freemarker.template.TemplateModel; + +/** + *

+ * Inserts the value of an attribute into the page. + *

+ *

+ * This tag can be flexibly used to insert the value of an attribute into a + * page. As in other usages in Tiles, every attribute can be determined to have + * a "type", either set explicitly when it was defined, or "computed". If the + * type is not explicit, then if the attribute value is a valid definition, it + * will be inserted as such. Otherwise, if it begins with a "/" character, it + * will be treated as a "template". Finally, if it has not otherwise been + * assigned a type, it will be treated as a String and included without any + * special handling. + *

+ * + *

+ * Example : + *

+ * + *
+ *     <tiles:insertAttribute name="body" />
+ * 
+ */ +public class InsertAttributeFMModel implements TemplateDirectiveModel { + + /** + * The template model. + */ + private org.apache.tiles.template.InsertAttributeModel model; + + /** + * Constructor. + * + * @param model The template model. + */ + public InsertAttributeFMModel(org.apache.tiles.template.InsertAttributeModel model) { + this.model = model; + } + + @Override + public void execute(Environment env, @SuppressWarnings("rawtypes") Map params, TemplateModel[] loopVars, + TemplateDirectiveBody body) throws TemplateException, IOException { + AutotagRuntime runtime = new org.apache.tiles.request.freemarker.autotag.FreemarkerAutotagRuntime(); + if (runtime instanceof TemplateDirectiveModel) { + ((TemplateDirectiveModel) runtime).execute(env, params, loopVars, body); + } + org.apache.tiles.request.Request request = runtime.createRequest(); + ModelBody modelBody = runtime.createModelBody(); + model.execute(runtime.getParameter("ignore", java.lang.Boolean.class, false), + runtime.getParameter("preparer", java.lang.String.class, null), + runtime.getParameter("role", java.lang.String.class, null), + runtime.getParameter("defaultValue", java.lang.Object.class, null), + runtime.getParameter("defaultValueRole", java.lang.String.class, null), + runtime.getParameter("defaultValueType", java.lang.String.class, null), + runtime.getParameter("name", java.lang.String.class, null), + runtime.getParameter("value", org.apache.tiles.api.Attribute.class, null), + runtime.getParameter("flush", java.lang.Boolean.class, false), request, modelBody); + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/freemarker/template/InsertDefinitionFMModel.java b/plugins/tiles/src/main/java/org/apache/tiles/freemarker/template/InsertDefinitionFMModel.java new file mode 100644 index 000000000..0f1cdd838 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/freemarker/template/InsertDefinitionFMModel.java @@ -0,0 +1,99 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +/* + * This file was automatically generated by Autotag. Please do not edit it manually. + */ +package org.apache.tiles.freemarker.template; + +import java.io.IOException; +import java.util.Map; + +import org.apache.tiles.autotag.core.runtime.ModelBody; +import org.apache.tiles.autotag.core.runtime.AutotagRuntime; + +import freemarker.core.Environment; +import freemarker.template.TemplateDirectiveBody; +import freemarker.template.TemplateDirectiveModel; +import freemarker.template.TemplateException; +import freemarker.template.TemplateModel; + +/** + *

+ * Insert a definition. + *

+ *

+ * Insert a definition with the possibility to override and specify parameters + * (called attributes). A definition can be seen as a (partially or totally) + * filled template that can override or complete attribute values. + * <tiles:insertDefinition> allows to define these attributes and pass + * them to the inserted jsp page, called template. Attributes are defined using + * nested tag <tiles:putAttribute> or <tiles:putListAttribute>. + *

+ *

+ * You must specify name tag attribute, for inserting a definition from + * definitions factory. + *

+ *

+ * Example : + *

+ * + *
+ *     <tiles:insertDefinition name=".my.tiles.defininition flush="true">
+ *         <tiles:putAttribute name="title" value="My first page" />
+ *         <tiles:putAttribute name="header" value="/common/header.jsp" />
+ *         <tiles:putAttribute name="footer" value="/common/footer.jsp" />
+ *         <tiles:putAttribute name="menu" value="/basic/menu.jsp" />
+ *         <tiles:putAttribute name="body" value="/basic/helloBody.jsp" />
+ *     </tiles:insertDefinition>
+ * 
+ */ +public class InsertDefinitionFMModel implements TemplateDirectiveModel { + + /** + * The template model. + */ + private org.apache.tiles.template.InsertDefinitionModel model; + + /** + * Constructor. + * + * @param model The template model. + */ + public InsertDefinitionFMModel(org.apache.tiles.template.InsertDefinitionModel model) { + this.model = model; + } + + @Override + public void execute(Environment env, @SuppressWarnings("rawtypes") Map params, TemplateModel[] loopVars, + TemplateDirectiveBody body) throws TemplateException, IOException { + AutotagRuntime runtime = new org.apache.tiles.request.freemarker.autotag.FreemarkerAutotagRuntime(); + if (runtime instanceof TemplateDirectiveModel) { + ((TemplateDirectiveModel) runtime).execute(env, params, loopVars, body); + } + org.apache.tiles.request.Request request = runtime.createRequest(); + ModelBody modelBody = runtime.createModelBody(); + model.execute(runtime.getParameter("name", java.lang.String.class, null), + runtime.getParameter("template", java.lang.String.class, null), + runtime.getParameter("templateType", java.lang.String.class, null), + runtime.getParameter("templateExpression", java.lang.String.class, null), + runtime.getParameter("role", java.lang.String.class, null), + runtime.getParameter("preparer", java.lang.String.class, null), + runtime.getParameter("flush", java.lang.Boolean.class, false), request, modelBody); + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/freemarker/template/InsertTemplateFMModel.java b/plugins/tiles/src/main/java/org/apache/tiles/freemarker/template/InsertTemplateFMModel.java new file mode 100644 index 000000000..64c04acc9 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/freemarker/template/InsertTemplateFMModel.java @@ -0,0 +1,98 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +/* + * This file was automatically generated by Autotag. Please do not edit it manually. + */ +package org.apache.tiles.freemarker.template; + +import java.io.IOException; +import java.util.Map; + +import org.apache.tiles.autotag.core.runtime.ModelBody; +import org.apache.tiles.autotag.core.runtime.AutotagRuntime; + +import freemarker.core.Environment; +import freemarker.template.TemplateDirectiveBody; +import freemarker.template.TemplateDirectiveModel; +import freemarker.template.TemplateException; +import freemarker.template.TemplateModel; + +/** + *

+ * Insert a template. + *

+ *

+ * Insert a template with the possibility to pass parameters (called + * attributes). A template can be seen as a procedure that can take parameters + * or attributes. <tiles:insertTemplate> allows to define these attributes + * and pass them to the inserted jsp page, called template. Attributes are + * defined using nested tag <tiles:putAttribute> or + * <tiles:putListAttribute>. + *

+ *

+ * You must specify template attribute, for inserting a template + *

+ * + *

+ * Example : + *

+ * + *
+ *     <tiles:insertTemplate template="/basic/myLayout.jsp" flush="true">
+ *         <tiles:putAttribute name="title" value="My first page" />
+ *         <tiles:putAttribute name="header" value="/common/header.jsp" />
+ *         <tiles:putAttribute name="footer" value="/common/footer.jsp" />
+ *         <tiles:putAttribute name="menu" value="/basic/menu.jsp" />
+ *         <tiles:putAttribute name="body" value="/basic/helloBody.jsp" />
+ *     </tiles:insertTemplate>
+ * 
+ */ +public class InsertTemplateFMModel implements TemplateDirectiveModel { + + /** + * The template model. + */ + private org.apache.tiles.template.InsertTemplateModel model; + + /** + * Constructor. + * + * @param model The template model. + */ + public InsertTemplateFMModel(org.apache.tiles.template.InsertTemplateModel model) { + this.model = model; + } + + @Override + public void execute(Environment env, @SuppressWarnings("rawtypes") Map params, TemplateModel[] loopVars, + TemplateDirectiveBody body) throws TemplateException, IOException { + AutotagRuntime runtime = new org.apache.tiles.request.freemarker.autotag.FreemarkerAutotagRuntime(); + if (runtime instanceof TemplateDirectiveModel) { + ((TemplateDirectiveModel) runtime).execute(env, params, loopVars, body); + } + org.apache.tiles.request.Request request = runtime.createRequest(); + ModelBody modelBody = runtime.createModelBody(); + model.execute(runtime.getParameter("template", java.lang.String.class, null), + runtime.getParameter("templateType", java.lang.String.class, null), + runtime.getParameter("templateExpression", java.lang.String.class, null), + runtime.getParameter("role", java.lang.String.class, null), + runtime.getParameter("preparer", java.lang.String.class, null), + runtime.getParameter("flush", java.lang.Boolean.class, false), request, modelBody); + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/freemarker/template/PutAttributeFMModel.java b/plugins/tiles/src/main/java/org/apache/tiles/freemarker/template/PutAttributeFMModel.java new file mode 100644 index 000000000..3d71b32a3 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/freemarker/template/PutAttributeFMModel.java @@ -0,0 +1,101 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +/* + * This file was automatically generated by Autotag. Please do not edit it manually. + */ +package org.apache.tiles.freemarker.template; + +import java.io.IOException; +import java.util.Map; + +import org.apache.tiles.autotag.core.runtime.ModelBody; +import org.apache.tiles.autotag.core.runtime.AutotagRuntime; + +import freemarker.core.Environment; +import freemarker.template.TemplateDirectiveBody; +import freemarker.template.TemplateDirectiveModel; +import freemarker.template.TemplateException; +import freemarker.template.TemplateModel; + +/** + *

+ * Put an attribute in enclosing attribute container tag. + *

+ *

+ * Enclosing attribute container tag can be : + *

    + *
  • <initContainer>
  • + *
  • <definition>
  • + *
  • <insertAttribute>
  • + *
  • <insertDefinition>
  • + *
  • <putListAttribute>
  • + *
+ * (or any other tag which implements the PutAttributeTagParent interface. + * Exception is thrown if no appropriate tag can be found. + *

+ *

+ * Put tag can have following atributes : + *

    + *
  • name : Name of the attribute
  • + *
  • value : value to put as attribute
  • + *
  • type : value type. Possible type are : string (value is used as direct + * string), template (value is used as a page url to insert), definition (value + * is used as a definition name to insert), object (value is used as it is)
  • + *
  • role : Role to check when 'insertAttribute' will be called.
  • + *
+ *

+ *

+ * Value can also come from tag body. Tag body is taken into account only if + * value is not set by one of the tag attributes. In this case Attribute type is + * "string", unless tag body define another type. + *

+ */ +public class PutAttributeFMModel implements TemplateDirectiveModel { + + /** + * The template model. + */ + private org.apache.tiles.template.PutAttributeModel model; + + /** + * Constructor. + * + * @param model The template model. + */ + public PutAttributeFMModel(org.apache.tiles.template.PutAttributeModel model) { + this.model = model; + } + + @Override + public void execute(Environment env, @SuppressWarnings("rawtypes") Map params, TemplateModel[] loopVars, + TemplateDirectiveBody body) throws TemplateException, IOException { + AutotagRuntime runtime = new org.apache.tiles.request.freemarker.autotag.FreemarkerAutotagRuntime(); + if (runtime instanceof TemplateDirectiveModel) { + ((TemplateDirectiveModel) runtime).execute(env, params, loopVars, body); + } + org.apache.tiles.request.Request request = runtime.createRequest(); + ModelBody modelBody = runtime.createModelBody(); + model.execute(runtime.getParameter("name", java.lang.String.class, null), + runtime.getParameter("value", java.lang.Object.class, null), + runtime.getParameter("expression", java.lang.String.class, null), + runtime.getParameter("role", java.lang.String.class, null), + runtime.getParameter("type", java.lang.String.class, null), + runtime.getParameter("cascade", java.lang.Boolean.class, false), request, modelBody); + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/freemarker/template/PutListAttributeFMModel.java b/plugins/tiles/src/main/java/org/apache/tiles/freemarker/template/PutListAttributeFMModel.java new file mode 100644 index 000000000..3eb5cb2c7 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/freemarker/template/PutListAttributeFMModel.java @@ -0,0 +1,76 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +/* + * This file was automatically generated by Autotag. Please do not edit it manually. + */ +package org.apache.tiles.freemarker.template; + +import java.io.IOException; +import java.util.Map; + +import org.apache.tiles.autotag.core.runtime.ModelBody; +import org.apache.tiles.autotag.core.runtime.AutotagRuntime; + +import freemarker.core.Environment; +import freemarker.template.TemplateDirectiveBody; +import freemarker.template.TemplateDirectiveModel; +import freemarker.template.TemplateException; +import freemarker.template.TemplateModel; + +/** + *

+ * Declare a list that will be pass as attribute to tile. + *

+ *

+ * Declare a list that will be pass as attribute to tile. List elements are + * added using the tags 'addAttribute' or 'addListAttribute'. This tag can only + * be used inside 'insertTemplate', 'insertDefinition', 'definition' tags. + *

+ */ +public class PutListAttributeFMModel implements TemplateDirectiveModel { + + /** + * The template model. + */ + private org.apache.tiles.template.PutListAttributeModel model; + + /** + * Constructor. + * + * @param model The template model. + */ + public PutListAttributeFMModel(org.apache.tiles.template.PutListAttributeModel model) { + this.model = model; + } + + @Override + public void execute(Environment env, @SuppressWarnings("rawtypes") Map params, TemplateModel[] loopVars, + TemplateDirectiveBody body) throws TemplateException, IOException { + AutotagRuntime runtime = new org.apache.tiles.request.freemarker.autotag.FreemarkerAutotagRuntime(); + if (runtime instanceof TemplateDirectiveModel) { + ((TemplateDirectiveModel) runtime).execute(env, params, loopVars, body); + } + org.apache.tiles.request.Request request = runtime.createRequest(); + ModelBody modelBody = runtime.createModelBody(); + model.execute(runtime.getParameter("name", java.lang.String.class, null), + runtime.getParameter("role", java.lang.String.class, null), + runtime.getParameter("inherit", java.lang.Boolean.class, false), + runtime.getParameter("cascade", java.lang.Boolean.class, false), request, modelBody); + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/freemarker/template/SetCurrentContainerFMModel.java b/plugins/tiles/src/main/java/org/apache/tiles/freemarker/template/SetCurrentContainerFMModel.java new file mode 100644 index 000000000..66d56ce34 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/freemarker/template/SetCurrentContainerFMModel.java @@ -0,0 +1,64 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +/* + * This file was automatically generated by Autotag. Please do not edit it manually. + */ +package org.apache.tiles.freemarker.template; + +import java.io.IOException; +import java.util.Map; + +import org.apache.tiles.autotag.core.runtime.AutotagRuntime; + +import freemarker.core.Environment; +import freemarker.template.TemplateDirectiveBody; +import freemarker.template.TemplateDirectiveModel; +import freemarker.template.TemplateException; +import freemarker.template.TemplateModel; + +/** + * Selects a container to be used as the "current" container. + */ +public class SetCurrentContainerFMModel implements TemplateDirectiveModel { + + /** + * The template model. + */ + private org.apache.tiles.template.SetCurrentContainerModel model; + + /** + * Constructor. + * + * @param model The template model. + */ + public SetCurrentContainerFMModel(org.apache.tiles.template.SetCurrentContainerModel model) { + this.model = model; + } + + @Override + public void execute(Environment env, @SuppressWarnings("rawtypes") Map params, TemplateModel[] loopVars, + TemplateDirectiveBody body) throws TemplateException, IOException { + AutotagRuntime runtime = new org.apache.tiles.request.freemarker.autotag.FreemarkerAutotagRuntime(); + if (runtime instanceof TemplateDirectiveModel) { + ((TemplateDirectiveModel) runtime).execute(env, params, loopVars, body); + } + org.apache.tiles.request.Request request = runtime.createRequest(); + model.execute(runtime.getParameter("containerKey", java.lang.String.class, null), request); + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/freemarker/template/TilesFMModelRepository.java b/plugins/tiles/src/main/java/org/apache/tiles/freemarker/template/TilesFMModelRepository.java new file mode 100644 index 000000000..d91766a2b --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/freemarker/template/TilesFMModelRepository.java @@ -0,0 +1,199 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +/* + * This file was automatically generated by Autotag. Please do not edit it manually. + */ +package org.apache.tiles.freemarker.template; + +/** + * This tag library provides Tiles tags. + */ +public class TilesFMModelRepository { + + /** + * The "insertDefinition" directive. + */ + private InsertDefinitionFMModel insertDefinition; + + /** + * The "importAttribute" directive. + */ + private ImportAttributeFMModel importAttribute; + + /** + * The "setCurrentContainer" directive. + */ + private SetCurrentContainerFMModel setCurrentContainer; + + /** + * The "addListAttribute" directive. + */ + private AddListAttributeFMModel addListAttribute; + + /** + * The "getAsString" directive. + */ + private GetAsStringFMModel getAsString; + + /** + * The "insertAttribute" directive. + */ + private InsertAttributeFMModel insertAttribute; + + /** + * The "putAttribute" directive. + */ + private PutAttributeFMModel putAttribute; + + /** + * The "definition" directive. + */ + private DefinitionFMModel definition; + + /** + * The "addAttribute" directive. + */ + private AddAttributeFMModel addAttribute; + + /** + * The "putListAttribute" directive. + */ + private PutListAttributeFMModel putListAttribute; + + /** + * The "insertTemplate" directive. + */ + private InsertTemplateFMModel insertTemplate; + + /** + * Constructor. + */ + public TilesFMModelRepository() { + insertDefinition = new InsertDefinitionFMModel(new org.apache.tiles.template.InsertDefinitionModel()); + importAttribute = new ImportAttributeFMModel(new org.apache.tiles.template.ImportAttributeModel()); + setCurrentContainer = new SetCurrentContainerFMModel(new org.apache.tiles.template.SetCurrentContainerModel()); + addListAttribute = new AddListAttributeFMModel(new org.apache.tiles.template.AddListAttributeModel()); + getAsString = new GetAsStringFMModel(new org.apache.tiles.template.GetAsStringModel()); + insertAttribute = new InsertAttributeFMModel(new org.apache.tiles.template.InsertAttributeModel()); + putAttribute = new PutAttributeFMModel(new org.apache.tiles.template.PutAttributeModel()); + definition = new DefinitionFMModel(new org.apache.tiles.template.DefinitionModel()); + addAttribute = new AddAttributeFMModel(new org.apache.tiles.template.AddAttributeModel()); + putListAttribute = new PutListAttributeFMModel(new org.apache.tiles.template.PutListAttributeModel()); + insertTemplate = new InsertTemplateFMModel(new org.apache.tiles.template.InsertTemplateModel()); + } + + /** + * Returns the "insertDefinition" directive. + * + * @return The "insertDefinition" directive. + */ + public InsertDefinitionFMModel getInsertDefinition() { + return insertDefinition; + } + + /** + * Returns the "importAttribute" directive. + * + * @return The "importAttribute" directive. + */ + public ImportAttributeFMModel getImportAttribute() { + return importAttribute; + } + + /** + * Returns the "setCurrentContainer" directive. + * + * @return The "setCurrentContainer" directive. + */ + public SetCurrentContainerFMModel getSetCurrentContainer() { + return setCurrentContainer; + } + + /** + * Returns the "addListAttribute" directive. + * + * @return The "addListAttribute" directive. + */ + public AddListAttributeFMModel getAddListAttribute() { + return addListAttribute; + } + + /** + * Returns the "getAsString" directive. + * + * @return The "getAsString" directive. + */ + public GetAsStringFMModel getGetAsString() { + return getAsString; + } + + /** + * Returns the "insertAttribute" directive. + * + * @return The "insertAttribute" directive. + */ + public InsertAttributeFMModel getInsertAttribute() { + return insertAttribute; + } + + /** + * Returns the "putAttribute" directive. + * + * @return The "putAttribute" directive. + */ + public PutAttributeFMModel getPutAttribute() { + return putAttribute; + } + + /** + * Returns the "definition" directive. + * + * @return The "definition" directive. + */ + public DefinitionFMModel getDefinition() { + return definition; + } + + /** + * Returns the "addAttribute" directive. + * + * @return The "addAttribute" directive. + */ + public AddAttributeFMModel getAddAttribute() { + return addAttribute; + } + + /** + * Returns the "putListAttribute" directive. + * + * @return The "putListAttribute" directive. + */ + public PutListAttributeFMModel getPutListAttribute() { + return putListAttribute; + } + + /** + * Returns the "insertTemplate" directive. + * + * @return The "insertTemplate" directive. + */ + public InsertTemplateFMModel getInsertTemplate() { + return insertTemplate; + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/ognl/AnyScopePropertyAccessor.java b/plugins/tiles/src/main/java/org/apache/tiles/ognl/AnyScopePropertyAccessor.java new file mode 100644 index 000000000..aca95ce5f --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/ognl/AnyScopePropertyAccessor.java @@ -0,0 +1,89 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.ognl; + +import ognl.OgnlContext; +import ognl.PropertyAccessor; +import org.apache.tiles.request.Request; + +import java.util.Map; + +/** + * Accesses attributes in any scope. + */ +public class AnyScopePropertyAccessor implements PropertyAccessor { + + @Override + public Object getProperty(Map context, Object target, Object name) { + Request request = (Request) target; + String attributeName = (String) name; + for (String scopeName : request.getAvailableScopes()) { + Map scope = request.getContext(scopeName); + if (scope.containsKey(attributeName)) { + return scope.get(attributeName); + } + } + return null; + } + + @Override + public String getSourceAccessor(OgnlContext context, Object target, Object index) { + Request request = (Request) target; + String attributeName = (String) index; + for (String scopeName : request.getAvailableScopes()) { + Map scope = request.getContext(scopeName); + if (scope.containsKey(attributeName)) { + return ".getContext(\"" + scopeName + "\").get(index)"; + } + } + return null; + } + + @Override + public String getSourceSetter(OgnlContext context, Object target, Object index) { + Request request = (Request) target; + String attributeName = (String) index; + String[] availableScopes = request.getAvailableScopes().toArray(new String[0]); + for (String scopeName : availableScopes) { + Map scope = request.getContext(scopeName); + if (scope.containsKey(attributeName)) { + return ".getContext(\"" + scopeName + "\").put(index, target)"; + } + } + return ".getContext(\"" + availableScopes[0] + "\").put(index, target)"; + } + + @Override + public void setProperty(Map context, Object target, Object name, Object value) { + Request request = (Request) target; + String attributeName = (String) name; + String[] availableScopes = request.getAvailableScopes().toArray(new String[0]); + for (String scopeName : availableScopes) { + Map scope = request.getContext(scopeName); + if (scope.containsKey(attributeName)) { + scope.put(attributeName, value); + return; + } + } + if (availableScopes.length > 0) { + request.getContext(availableScopes[0]).put(attributeName, value); + } + } + +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/ognl/DelegatePropertyAccessor.java b/plugins/tiles/src/main/java/org/apache/tiles/ognl/DelegatePropertyAccessor.java new file mode 100644 index 000000000..637823a9b --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/ognl/DelegatePropertyAccessor.java @@ -0,0 +1,84 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.ognl; + +import ognl.OgnlContext; +import ognl.OgnlException; +import ognl.PropertyAccessor; + +import java.util.Map; + +/** + * Uses a {@link PropertyAccessorDelegateFactory} to delegate the methods to + * another {@link PropertyAccessor}. + * + * @param The type of the accessed root object. + * @since 2.2.0 + */ +public class DelegatePropertyAccessor implements PropertyAccessor { + + /** + * The property accessor factory. + * + * @since 2.2.0 + */ + private final PropertyAccessorDelegateFactory factory; + + /** + * Constructor. + * + * @param factory The property accessor factory. + * @since 2.2.0 + */ + public DelegatePropertyAccessor(PropertyAccessorDelegateFactory factory) { + this.factory = factory; + } + + /** + * {@inheritDoc} + */ + @SuppressWarnings("unchecked") + public Object getProperty(Map context, Object target, Object name) throws OgnlException { + return factory.getPropertyAccessor((String) name, (T) target).getProperty(context, target, name); + } + + /** + * {@inheritDoc} + */ + @SuppressWarnings("unchecked") + public void setProperty(Map context, Object target, Object name, Object value) throws OgnlException { + factory.getPropertyAccessor((String) name, (T) target).setProperty(context, target, name, value); + } + + /** + * {@inheritDoc} + */ + @SuppressWarnings("unchecked") + public String getSourceAccessor(OgnlContext context, Object target, Object index) { + return factory.getPropertyAccessor((String) index, (T) target).getSourceAccessor(context, target, index); + } + + /** + * {@inheritDoc} + */ + @SuppressWarnings("unchecked") + public String getSourceSetter(OgnlContext context, Object target, Object index) { + return factory.getPropertyAccessor((String) index, (T) target).getSourceSetter(context, target, index); + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/ognl/NestedObjectDelegatePropertyAccessor.java b/plugins/tiles/src/main/java/org/apache/tiles/ognl/NestedObjectDelegatePropertyAccessor.java new file mode 100644 index 000000000..dbafb66c7 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/ognl/NestedObjectDelegatePropertyAccessor.java @@ -0,0 +1,93 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.ognl; + +import ognl.OgnlContext; +import ognl.OgnlException; +import ognl.PropertyAccessor; + +import java.util.Map; + +/** + * Uses a {@link PropertyAccessor} as a delegate, but passing a nested object as + * target. + * + * @param The root object type from which the target object will be extracted. + * @since 2.2.0 + */ +public class NestedObjectDelegatePropertyAccessor implements PropertyAccessor { + + /** + * The extractor of the nested object. + * + * @since 2.2.0 + */ + private final NestedObjectExtractor nestedObjectExtractor; + + /** + * The delegated property accessor. + * + * @since 2.2.0 + */ + private final PropertyAccessor propertyAccessor; + + /** + * Constructor. + * + * @param nestedObjectExtractor The extractor of the nested object. + * @param propertyAccessor The delegated property accessor. + * @since 2.2.0 + */ + public NestedObjectDelegatePropertyAccessor(NestedObjectExtractor nestedObjectExtractor, PropertyAccessor propertyAccessor) { + this.nestedObjectExtractor = nestedObjectExtractor; + this.propertyAccessor = propertyAccessor; + } + + /** + * {@inheritDoc} + */ + @SuppressWarnings("unchecked") + public Object getProperty(Map context, Object target, Object name) throws OgnlException { + return propertyAccessor.getProperty(context, nestedObjectExtractor.getNestedObject((T) target), name); + } + + /** + * {@inheritDoc} + */ + @SuppressWarnings("unchecked") + public void setProperty(Map context, Object target, Object name, Object value) throws OgnlException { + propertyAccessor.setProperty(context, nestedObjectExtractor.getNestedObject((T) target), name, value); + } + + /** + * {@inheritDoc} + */ + @SuppressWarnings("unchecked") + public String getSourceAccessor(OgnlContext context, Object target, Object index) { + return propertyAccessor.getSourceAccessor(context, nestedObjectExtractor.getNestedObject((T) target), index); + } + + /** + * {@inheritDoc} + */ + @SuppressWarnings("unchecked") + public String getSourceSetter(OgnlContext context, Object target, Object index) { + return propertyAccessor.getSourceSetter(context, nestedObjectExtractor.getNestedObject((T) target), index); + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/ognl/NestedObjectExtractor.java b/plugins/tiles/src/main/java/org/apache/tiles/ognl/NestedObjectExtractor.java new file mode 100644 index 000000000..ba994d31b --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/ognl/NestedObjectExtractor.java @@ -0,0 +1,37 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.ognl; + +/** + * Extracts an object using another object as a basis. + * + * @param The type of the root object. + * @since 2.2.0 + */ +public interface NestedObjectExtractor { + + /** + * Extracts the nested object. + * + * @param obj The root object. + * @return The extracted nested object. + * @since 2.2.0 + */ + Object getNestedObject(T obj); +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/ognl/OGNLAttributeEvaluator.java b/plugins/tiles/src/main/java/org/apache/tiles/ognl/OGNLAttributeEvaluator.java new file mode 100644 index 000000000..cac54fdcb --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/ognl/OGNLAttributeEvaluator.java @@ -0,0 +1,45 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.ognl; + +import ognl.Ognl; +import ognl.OgnlException; +import org.apache.tiles.core.evaluator.AbstractAttributeEvaluator; +import org.apache.tiles.core.evaluator.EvaluationException; +import org.apache.tiles.request.Request; + +/** + * Evaluates attribute expressions and expressions with OGNL language. + * + * @since 2.2.0 + */ +public class OGNLAttributeEvaluator extends AbstractAttributeEvaluator { + + /** {@inheritDoc} */ + public Object evaluate(String expression, Request request) { + if (expression == null) { + throw new IllegalArgumentException("The expression parameter cannot be null"); + } + try { + return Ognl.getValue(expression, request); + } catch (OgnlException e) { + throw new EvaluationException("Cannot evaluate OGNL expression '" + expression + "'", e); + } + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/ognl/PropertyAccessorDelegateFactory.java b/plugins/tiles/src/main/java/org/apache/tiles/ognl/PropertyAccessorDelegateFactory.java new file mode 100644 index 000000000..b781b402a --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/ognl/PropertyAccessorDelegateFactory.java @@ -0,0 +1,43 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tiles.ognl; + +import ognl.PropertyAccessor; + +/** + * Decides a {@link PropertyAccessor} depending on the property name and the + * object to evaluate. + * + * @param The type of the root object to evaluate. + * @since 2.2.0 + */ +public interface PropertyAccessorDelegateFactory { + + /** + * Returns a prooerty accessor appropriate for the property name and the + * object passed. + * + * @param propertyName The name of the property. + * @param obj The root object to evaluate. + * @return The appropriate property accessor. + * @since 2.2.0 + */ + PropertyAccessor getPropertyAccessor(String propertyName, T obj); +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/ognl/ScopePropertyAccessor.java b/plugins/tiles/src/main/java/org/apache/tiles/ognl/ScopePropertyAccessor.java new file mode 100644 index 000000000..bb45085b6 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/ognl/ScopePropertyAccessor.java @@ -0,0 +1,68 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.ognl; + +import ognl.OgnlContext; +import ognl.PropertyAccessor; +import org.apache.tiles.request.Request; + +import java.util.Map; + +/** + * Accesses a scope. + */ +public class ScopePropertyAccessor implements PropertyAccessor { + + /** + * The length of the scope suffix: "Scope". + */ + static final int SCOPE_SUFFIX_LENGTH = 5; + + @Override + public Object getProperty(Map context, Object target, Object name) { + Request request = (Request) target; + String scope = (String) name; + if (scope.endsWith("Scope")) { + String scopeName = scope.substring(0, scope.length() - SCOPE_SUFFIX_LENGTH); + return request.getContext(scopeName); + } + return null; + } + + @Override + public String getSourceAccessor(OgnlContext context, Object target, Object index) { + String scope = (String) index; + if (scope.endsWith("Scope")) { + String scopeName = scope.substring(0, scope.length() - SCOPE_SUFFIX_LENGTH); + return ".getContext(\"" + scopeName + "\")"; + } + return null; + } + + @Override + public String getSourceSetter(OgnlContext context, Object target, Object index) { + return null; + } + + @Override + public void setProperty(Map context, Object target, Object name, Object value) { + // Does nothing. + } + +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/ognl/TilesApplicationContextNestedObjectExtractor.java b/plugins/tiles/src/main/java/org/apache/tiles/ognl/TilesApplicationContextNestedObjectExtractor.java new file mode 100644 index 000000000..60f4321af --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/ognl/TilesApplicationContextNestedObjectExtractor.java @@ -0,0 +1,35 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.ognl; + +import org.apache.tiles.request.ApplicationContext; +import org.apache.tiles.request.Request; + +/** + * Extracts the application context from a Tiles request. + * + * @since 2.2.0 + */ +public class TilesApplicationContextNestedObjectExtractor implements NestedObjectExtractor { + + /** {@inheritDoc} */ + public ApplicationContext getNestedObject(Request obj) { + return obj.getApplicationContext(); + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/ognl/TilesContextPropertyAccessorDelegateFactory.java b/plugins/tiles/src/main/java/org/apache/tiles/ognl/TilesContextPropertyAccessorDelegateFactory.java new file mode 100644 index 000000000..5106f656a --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/ognl/TilesContextPropertyAccessorDelegateFactory.java @@ -0,0 +1,103 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.ognl; + +import ognl.PropertyAccessor; +import org.apache.tiles.core.util.CombinedBeanInfo; +import org.apache.tiles.request.ApplicationContext; +import org.apache.tiles.request.Request; + +/** + * Decides the appropriate {@link PropertyAccessor} for the given property name + * and {@link Request}. + * + * @since 2.2.0 + */ +public class TilesContextPropertyAccessorDelegateFactory implements PropertyAccessorDelegateFactory { + + /** + * The plain object property accessor, to be used directly for + * {@link Request}. + */ + private final PropertyAccessor objectPropertyAccessor; + + /** + * The application context property accessor. + */ + private final PropertyAccessor applicationContextPropertyAccessor; + + /** + * The request scope property accessor. + */ + private final PropertyAccessor anyScopePropertyAccessor; + + /** + * The session scope property accessor. + */ + private final PropertyAccessor scopePropertyAccessor; + + /** + * The bean info of {@link Request} and + * {@link ApplicationContext}. + */ + private final CombinedBeanInfo beanInfo; + + /** + * Constructor. + * + * @param objectPropertyAccessor The plain object property accessor, to be + * used directly for {@link Request}. + * @param applicationContextPropertyAccessor The application context + * property accessor. + * @param anyScopePropertyAccessor The request scope property accessor. + * @param scopePropertyAccessor The session scope property accessor. + * @since 2.2.0 + */ + public TilesContextPropertyAccessorDelegateFactory( + PropertyAccessor objectPropertyAccessor, + PropertyAccessor applicationContextPropertyAccessor, + PropertyAccessor anyScopePropertyAccessor, + PropertyAccessor scopePropertyAccessor + ) { + beanInfo = new CombinedBeanInfo(Request.class, ApplicationContext.class); + this.objectPropertyAccessor = objectPropertyAccessor; + this.applicationContextPropertyAccessor = applicationContextPropertyAccessor; + this.anyScopePropertyAccessor = anyScopePropertyAccessor; + this.scopePropertyAccessor = scopePropertyAccessor; + } + + /** {@inheritDoc} */ + public PropertyAccessor getPropertyAccessor(String propertyName, Request request) { + PropertyAccessor retValue; + if (propertyName.endsWith("Scope")) { + String scopeName = propertyName.substring(0, propertyName.length() - ScopePropertyAccessor.SCOPE_SUFFIX_LENGTH); + if (request.getContext(scopeName) != null) { + return scopePropertyAccessor; + } + } + if (beanInfo.getMappedDescriptors(Request.class).containsKey(propertyName)) { + retValue = objectPropertyAccessor; + } else if (beanInfo.getMappedDescriptors(ApplicationContext.class).containsKey(propertyName)) { + retValue = applicationContextPropertyAccessor; + } else { + return anyScopePropertyAccessor; + } + return retValue; + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/ognl/package-info.java b/plugins/tiles/src/main/java/org/apache/tiles/ognl/package-info.java new file mode 100644 index 000000000..69d74a282 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/ognl/package-info.java @@ -0,0 +1,22 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +/** + * Attribute evaluator classes that can perform OGNL evaluation for attributes. + */ +package org.apache.tiles.ognl; diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/AbstractClientRequest.java b/plugins/tiles/src/main/java/org/apache/tiles/request/AbstractClientRequest.java new file mode 100644 index 000000000..459c54c1b --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/AbstractClientRequest.java @@ -0,0 +1,91 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.request; + +import java.io.IOException; +import java.util.Map; + +/** + * Base class for "client" requests, i.e. requests that come unchanged by the + * container, such as ServletRequest and PortletRequest. + */ +public abstract class AbstractClientRequest extends AbstractRequest { + + /** + * The application context. + */ + private final ApplicationContext applicationContext; + + /** + * Constructor. + * + * @param applicationContext The application context. + */ + public AbstractClientRequest(ApplicationContext applicationContext) { + this.applicationContext = applicationContext; + } + + + @Override + public void dispatch(String path) throws IOException { + if (isForceInclude()) { + doInclude(path); + } else { + setForceInclude(true); + doForward(path); + } + } + + @Override + public void include(String path) throws IOException { + setForceInclude(true); + doInclude(path); + } + + @Override + public ApplicationContext getApplicationContext() { + return applicationContext; + } + + /** + * Returns the application scope. + * + * @return The application scope. + */ + public Map getApplicationScope() { + return applicationContext.getApplicationScope(); + } + + /** + * Forwards to a path. + * + * @param path The path to forward to. + * @throws IOException If something goes wrong when forwarding. + */ + protected abstract void doForward(String path) throws IOException; + + /** + * Includes the result of a path. + * + * @param path The path to forward to. + * @throws IOException If something goes wrong when forwarding. + */ + protected abstract void doInclude(String path) throws IOException; + +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/AbstractRequest.java b/plugins/tiles/src/main/java/org/apache/tiles/request/AbstractRequest.java new file mode 100644 index 000000000..7fd52d9c6 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/AbstractRequest.java @@ -0,0 +1,54 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.request; + +/** + * Base request. + */ +public abstract class AbstractRequest implements DispatchRequest { + + /** + * Name of the attribute used to store the force-include option. + */ + public static final String FORCE_INCLUDE_ATTRIBUTE_NAME = AbstractRequest.class.getName() + ".FORCE_INCLUDE"; + + /** + * Sets the flag to force inclusion at next dispatch. + * + * @param forceInclude true means that, at the next dispatch, response + * will be included and never forwarded. + */ + protected void setForceInclude(boolean forceInclude) { + getContext(REQUEST_SCOPE).put(FORCE_INCLUDE_ATTRIBUTE_NAME, forceInclude); + } + + /** + * Checks if, when dispatching to a resource, the result must be included + * and not forwarded to. + * + * @return true if inclusion is forced. + */ + protected boolean isForceInclude() { + Boolean forceInclude = (Boolean) getContext(REQUEST_SCOPE).get(FORCE_INCLUDE_ATTRIBUTE_NAME); + if (forceInclude != null) { + return forceInclude; + } + return false; + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/AbstractViewRequest.java b/plugins/tiles/src/main/java/org/apache/tiles/request/AbstractViewRequest.java new file mode 100644 index 000000000..9cd74cd74 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/AbstractViewRequest.java @@ -0,0 +1,60 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.request; + +import java.io.IOException; + +/** + * Base class for "view" requests, i.e. requests created into view technologies, + * such as JSP, Velocity and Freemarker. In particular, all calls to + * {@link #dispatch(String)} will cause an inclusion and never a forward. + */ +public class AbstractViewRequest extends DispatchRequestWrapper { + + /** + * Constructor. + * + * @param request The base request. + */ + public AbstractViewRequest(DispatchRequest request) { + super(request); + } + + @Override + public void dispatch(String path) throws IOException { + setForceInclude(true); + doInclude(path); + } + + @Override + public void include(String path) throws IOException { + setForceInclude(true); + doInclude(path); + } + + /** + * Includes the result. By default, uses the wrapped request for the inclusion. + * + * @param path The path whose result will be included. + * @throws IOException If something goes wrong. + */ + protected void doInclude(String path) throws IOException { + getWrappedRequest().include(path); + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/ApplicationAccess.java b/plugins/tiles/src/main/java/org/apache/tiles/request/ApplicationAccess.java new file mode 100644 index 000000000..35a1d29ed --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/ApplicationAccess.java @@ -0,0 +1,47 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.request; + +/** + * Entry point to get information about the application. + */ +public final class ApplicationAccess { + + /** + * The attribute name that will be used to store the application context itself. + */ + public static final String APPLICATION_CONTEXT_ATTRIBUTE = ApplicationContext.class.getName() + ".ATTRIBUTE"; + + /** + * Constructor. + */ + private ApplicationAccess() { + } + + /** + * Registers an application context. It will be registered into itself as an + * attribute, using the {@link #APPLICATION_CONTEXT_ATTRIBUTE} name. + * + * @param applicationContext The application context to register. + */ + public static void register(ApplicationContext applicationContext) { + applicationContext.getApplicationScope().put(APPLICATION_CONTEXT_ATTRIBUTE, applicationContext); + } + +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/ApplicationContext.java b/plugins/tiles/src/main/java/org/apache/tiles/request/ApplicationContext.java new file mode 100644 index 000000000..d45d90720 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/ApplicationContext.java @@ -0,0 +1,79 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.request; + +import java.util.Collection; +import java.util.Locale; +import java.util.Map; + +/** + * Defines a set of methods which tiles use to communicate to + * the tiles container and runtime environment. There is only + * one application context per container. + */ +public interface ApplicationContext { + + /** + * Returns the original, technology-dependent, context. + * + * @return The original application context. + */ + Object getContext(); + + /** + * Returns a mutable Map that maps application scope attribute names to + * their values. + * + * @return Map of key value pairs. + */ + Map getApplicationScope(); + + /** + * Return an immutable Map that maps context application initialization + * parameters to their values. + * + * @return initialization parameters + */ + Map getInitParams(); + + /** + * Return the application resource mapped to the specified path. + * + * @param localePath path to the desired resource, including the Locale suffix. + * @return the first located resource which matches the given path or null if no such resource exists. + */ + ApplicationResource getResource(String localePath); + + /** + * Return a localized version of an ApplicationResource. + * + * @param base the ApplicationResource. + * @param locale the desired Locale. + * @return the first located resource which matches the given path or null if no such resource exists. + */ + ApplicationResource getResource(ApplicationResource base, Locale locale); + + /** + * Return the application resources mapped to the specified path. + * + * @param path to the desired resource. + * @return all resources which match the given path. + */ + Collection getResources(String path); +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/ApplicationContextAware.java b/plugins/tiles/src/main/java/org/apache/tiles/request/ApplicationContextAware.java new file mode 100644 index 000000000..5775c72e9 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/ApplicationContextAware.java @@ -0,0 +1,34 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.request; + + +/** + * It represents an object that can have a reference to the + * {@link ApplicationContext}. + */ +public interface ApplicationContextAware { + + /** + * Sets the Tiles application context. + * + * @param applicationContext The Tiles application context. + */ + void setApplicationContext(ApplicationContext applicationContext); +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/ApplicationResource.java b/plugins/tiles/src/main/java/org/apache/tiles/request/ApplicationResource.java new file mode 100644 index 000000000..cf868e888 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/ApplicationResource.java @@ -0,0 +1,80 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tiles.request; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Locale; + +/** + * A (localized) resource accessible through the ApplicationContext. + * Typically, this is a file inside the web application's war. + */ +public interface ApplicationResource { + + /** + * Get the path name for this resource. + * You can access this resource by passing the path to + * {@link ApplicationContext#getResource(String) getResource}. + * + * @return the path including localization. + */ + String getLocalePath(); + + /** + * Get the path name for this resource. Multiple versions of + * a resource can share the same path if the locale part is different. + * + * @return the path excluding localization. + */ + String getPath(); + + /** + * Get the Locale for this resource. + * + * @return the Locale. + */ + Locale getLocale(); + + /** + * Get the path name of another version of the resource. + * + * @param locale the Locale for the new version. + * @return the path including localization. + */ + String getLocalePath(Locale locale); + + /** + * Get a java.io.InputStream to read the contents of this resource. + * + * @return the InputStream. + * @throws IOException if the contents cannot be read. + */ + InputStream getInputStream() throws IOException; + + /** + * Get the last modification date for this resource. + * + * @return the difference, measured in milliseconds, between the current + * time and midnight, January 1, 1970 UTC. + * @throws IOException if the last modification date cannot be found. + */ + long getLastModified() throws IOException; +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/DispatchRequest.java b/plugins/tiles/src/main/java/org/apache/tiles/request/DispatchRequest.java new file mode 100644 index 000000000..30d208ca0 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/DispatchRequest.java @@ -0,0 +1,51 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.request; + +import java.io.IOException; + +/** + * Encapsulation of request information. + */ +public interface DispatchRequest extends Request { + + /** + * Dispatches the request to a specified path. + * + * @param path The path to dispatch to. + * @throws IOException If something goes wrong during dispatching. + */ + void dispatch(String path) throws IOException; + + /** + * Includes the response from the specified URL in the current response output. + * + * @param path The path to include. + * @throws IOException If something goes wrong during inclusion. + */ + void include(String path) throws IOException; + + /** + * Sets the content type when rendering the result. + * + * @param contentType The content type. It should follow the specifications + * from W3C about content types. + */ + void setContentType(String contentType); +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/DispatchRequestWrapper.java b/plugins/tiles/src/main/java/org/apache/tiles/request/DispatchRequestWrapper.java new file mode 100644 index 000000000..cc2ca6a1e --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/DispatchRequestWrapper.java @@ -0,0 +1,139 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.request; + +import java.io.IOException; +import java.io.OutputStream; +import java.io.PrintWriter; +import java.io.Writer; +import java.util.List; +import java.util.Locale; +import java.util.Map; + +import org.apache.tiles.request.attribute.Addable; + +/** + * Delegate for ease of customization. + */ +public class DispatchRequestWrapper extends AbstractRequest implements RequestWrapper { + + /** + * The wrapper request context object. + */ + private final DispatchRequest context; + + /** + * Constructor. + * + * @param context The request context to wrap. + */ + public DispatchRequestWrapper(DispatchRequest context) { + this.context = context; + } + + /** {@inheritDoc} */ + public DispatchRequest getWrappedRequest() { + return context; + } + + /** {@inheritDoc} */ + public Map getHeader() { + return context.getHeader(); + } + + /** {@inheritDoc} */ + public Map getHeaderValues() { + return context.getHeaderValues(); + } + + /** {@inheritDoc} */ + public Addable getResponseHeaders() { + return context.getResponseHeaders(); + } + + /** {@inheritDoc} */ + public Map getContext(String scope) { + return context.getContext(scope); + } + + /** {@inheritDoc} */ + public List getAvailableScopes() { + return context.getAvailableScopes(); + } + + /** {@inheritDoc} */ + public ApplicationContext getApplicationContext() { + return context.getApplicationContext(); + } + + /** {@inheritDoc} */ + public void dispatch(String path) throws IOException { + context.dispatch(path); + } + + /** {@inheritDoc} */ + public void include(String path) throws IOException { + context.include(path); + } + + /** {@inheritDoc} */ + public OutputStream getOutputStream() throws IOException { + return context.getOutputStream(); + } + + /** {@inheritDoc} */ + public Writer getWriter() throws IOException { + return context.getWriter(); + } + + /** {@inheritDoc} */ + public PrintWriter getPrintWriter() throws IOException { + return context.getPrintWriter(); + } + + /** {@inheritDoc} */ + public boolean isResponseCommitted() { + return context.isResponseCommitted(); + } + + /** {@inheritDoc} */ + public void setContentType(String contentType) { + context.setContentType(contentType); + } + + /** {@inheritDoc} */ + public Map getParam() { + return context.getParam(); + } + + /** {@inheritDoc} */ + public Map getParamValues() { + return context.getParamValues(); + } + + /** {@inheritDoc} */ + public Locale getRequestLocale() { + return context.getRequestLocale(); + } + + /** {@inheritDoc} */ + public boolean isUserInRole(String role) { + return context.isUserInRole(role); + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/NotAvailableFeatureException.java b/plugins/tiles/src/main/java/org/apache/tiles/request/NotAvailableFeatureException.java new file mode 100644 index 000000000..ded24acd9 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/NotAvailableFeatureException.java @@ -0,0 +1,36 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tiles.request; + +/** + * Exception that indicates that a feature could not be used since it is not available. + */ +public class NotAvailableFeatureException extends RequestException { + + /** + * Constructor. + * + * @param message The detail message. + * @param e The cause to be wrapped. + */ + public NotAvailableFeatureException(String message, Throwable e) { + super(message, e); + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/Request.java b/plugins/tiles/src/main/java/org/apache/tiles/request/Request.java new file mode 100644 index 000000000..9a1709f15 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/Request.java @@ -0,0 +1,161 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.request; + +import java.io.IOException; +import java.io.OutputStream; +import java.io.PrintWriter; +import java.io.Writer; +import java.util.List; +import java.util.Locale; +import java.util.Map; + +import org.apache.tiles.request.attribute.Addable; + +/** + * Encapsulation of request information. + */ +public interface Request { + + /** the name of the (mandatory) "application" scope */ + String APPLICATION_SCOPE = "application"; + + /** the name of the "request" context */ + String REQUEST_SCOPE = "request"; + + /** + * Return an immutable Map that maps header names to the first (or only) + * header value (as a String). + * + * @return The header map. + */ + Map getHeader(); + + /** + * Return an immutable Map that maps header names to the set of all values + * specified in the request (as a String array). Header names must be + * matched in a case-insensitive manner. + * + * @return The header values map. + */ + Map getHeaderValues(); + + /** + * Return an Addable object that can be used to write headers to the response. + * + * @return An Addable object. + */ + Addable getResponseHeaders(); + + /** + * Returns a context map, given the scope name. + * This method always return a map for all the scope names returned by + * getAvailableScopes(). That map may be writable, or immutable, depending + * on the implementation. + * + * @param scope The name of the scope. + * @return The context. + */ + Map getContext(String scope); + + /** + * Returns all available scopes. + * The scopes are ordered according to their lifetime, + * the innermost, shorter lived scope appears first, + * and the outermost, longer lived scope appears last. + * Besides, the scopes "request" and "application" always included + * in the list. + * + * @return All the available scopes. + */ + List getAvailableScopes(); + + /** + * Returns the associated application context. + * + * @return The application context associated to this request. + */ + ApplicationContext getApplicationContext(); + + /** + * Returns an output stream to be used to write directly in the response. + * + * @return The output stream that writes in the response. + * @throws IOException If something goes wrong when getting the output stream. + */ + OutputStream getOutputStream() throws IOException; + + /** + * Returns a writer to be used to write directly in the response. + * + * @return The writer that writes in the response. + * @throws IOException If something goes wrong when getting the writer. + */ + Writer getWriter() throws IOException; + + /** + * Returns a print writer to be used to write directly in the response. + * + * @return The print writer that writes in the response. + * @throws IOException If something goes wrong when getting the print + * writer. + */ + PrintWriter getPrintWriter() throws IOException; + + /** + * Checks if the response has been committed. + * + * @return true only if the response has been committed. + */ + boolean isResponseCommitted(); + + /** + * Return an immutable Map that maps request parameter names to the first + * (or only) value (as a String). + * + * @return The parameter map. + */ + Map getParam(); + + /** + * Return an immutable Map that maps request parameter names to the set of + * all values (as a String array). + * + * @return The parameter values map. + */ + Map getParamValues(); + + /** + * Return the preferred Locale in which the client will accept content. + * + * @return The current request locale. It is the locale of the request + * object itself, and it is NOT the locale that the user wants to use. See + * {@link org.apache.tiles.core.locale.LocaleResolver} to implement strategies to + * resolve locales. + */ + Locale getRequestLocale(); + + /** + * Determine whether the specified user is in the given role. + * @param role the role to check against. + * @return true if the user is in the given role. + */ + boolean isUserInRole(String role); + +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/RequestException.java b/plugins/tiles/src/main/java/org/apache/tiles/request/RequestException.java new file mode 100644 index 000000000..dcd8daeae --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/RequestException.java @@ -0,0 +1,45 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.request; + +/** + * Thrown when something related to a request fails. + */ +public class RequestException extends RuntimeException { + + /** + * Constructor. + * + * @param message The message of the exception. + */ + public RequestException(String message) { + super(message); + } + + /** + * Constructor. + * + * @param message The message of the exception. + * @param cause The cause. + */ + public RequestException(String message, Throwable cause) { + super(message, cause); + } + +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/RequestWrapper.java b/plugins/tiles/src/main/java/org/apache/tiles/request/RequestWrapper.java new file mode 100644 index 000000000..a9826d369 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/RequestWrapper.java @@ -0,0 +1,33 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.request; + +/** + * Delegate for ease of customization. + */ +public interface RequestWrapper extends Request { + + /** + * Returns the wrapped Tiles request. + * + * @return The wrapped Tiles request. + */ + Request getWrappedRequest(); + +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/attribute/Addable.java b/plugins/tiles/src/main/java/org/apache/tiles/request/attribute/Addable.java new file mode 100644 index 000000000..0a6178a56 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/attribute/Addable.java @@ -0,0 +1,35 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.request.attribute; + +/** + * Allows to get and set attributes. + * + * @param The type of the value of the attribute. + */ +public interface Addable { + + /** + * Sets a value for the given key. + * + * @param key The key of the attribute. + * @param value The value of the attribute. + */ + void setValue(String key, V value); +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/attribute/AttributeExtractor.java b/plugins/tiles/src/main/java/org/apache/tiles/request/attribute/AttributeExtractor.java new file mode 100644 index 000000000..b855123f7 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/attribute/AttributeExtractor.java @@ -0,0 +1,25 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.request.attribute; + +/** + * Allows to get, put and remove Object-type attributes. + */ +public interface AttributeExtractor extends HasRemovableKeys, HasAddableKeys { +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/attribute/EnumeratedValuesExtractor.java b/plugins/tiles/src/main/java/org/apache/tiles/request/attribute/EnumeratedValuesExtractor.java new file mode 100644 index 000000000..13240b044 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/attribute/EnumeratedValuesExtractor.java @@ -0,0 +1,35 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.request.attribute; + +import java.util.Enumeration; + +/** + * Allows to get values from multi-valued attributes. + */ +public interface EnumeratedValuesExtractor extends HasAddableKeys { + + /** + * Returns the values stored at the given key. + * + * @param key The key of the attribute. + * @return The values of the attribute. + */ + Enumeration getValues(String key); +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/attribute/HasAddableKeys.java b/plugins/tiles/src/main/java/org/apache/tiles/request/attribute/HasAddableKeys.java new file mode 100644 index 000000000..1bff1f2c5 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/attribute/HasAddableKeys.java @@ -0,0 +1,27 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.request.attribute; + +/** + * Allows to get and set attributes. + * + * @param The type of the value of the attribute. + */ +public interface HasAddableKeys extends HasKeys, Addable { +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/attribute/HasKeys.java b/plugins/tiles/src/main/java/org/apache/tiles/request/attribute/HasKeys.java new file mode 100644 index 000000000..692cf61cb --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/attribute/HasKeys.java @@ -0,0 +1,44 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.request.attribute; + +import java.util.Enumeration; + +/** + * Allows to get attributes. + * + * @param The type of the value of the attribute. + */ +public interface HasKeys { + + /** + * The enumeration of the keys of the stored attributes. + * + * @return The keys. + */ + Enumeration getKeys(); + + /** + * Returns the value of the attribute with the given key. + * + * @param key The key of the attribute. + * @return The value. + */ + V getValue(String key); +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/attribute/HasRemovableKeys.java b/plugins/tiles/src/main/java/org/apache/tiles/request/attribute/HasRemovableKeys.java new file mode 100644 index 000000000..4cb31e317 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/attribute/HasRemovableKeys.java @@ -0,0 +1,34 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.request.attribute; + +/** + * Allows to get and remove attributes. + * + * @param The type of the value of the attribute. + */ +public interface HasRemovableKeys extends HasKeys { + + /** + * Removes an attribute. + * + * @param key The key of the attribute to remove. + */ + void removeValue(String key); +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/attribute/package-info.java b/plugins/tiles/src/main/java/org/apache/tiles/request/attribute/package-info.java new file mode 100644 index 000000000..054b0e4f9 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/attribute/package-info.java @@ -0,0 +1,26 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +/** + * Methods to get, set and remove attributes from different sources (like HTTP requests + * or sessions). + * By implementing {@link org.apache.tiles.request.attribute.AttributeExtractor}, + * you can use a Map from {@link org.apache.tiles.request.collection} to manipulate the + * attributes of another class. + */ +package org.apache.tiles.request.attribute; diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/collection/AddableParameterMap.java b/plugins/tiles/src/main/java/org/apache/tiles/request/collection/AddableParameterMap.java new file mode 100644 index 000000000..d88b90503 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/collection/AddableParameterMap.java @@ -0,0 +1,95 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.request.collection; + +import org.apache.tiles.request.attribute.HasAddableKeys; + +import java.util.Collection; +import java.util.Map; +import java.util.Set; + +/** + * Exposes an {@link HasAddableKeys} object as a put/get (no remove) map. + */ +public class AddableParameterMap extends ReadOnlyEnumerationMap { + + /** + * The request. + */ + private final HasAddableKeys request; + + /** + * Constructor. + * + * @param request The request object to use. + */ + public AddableParameterMap(HasAddableKeys request) { + super(request); + this.request = request; + } + + /** + * {@inheritDoc} + */ + public Set> entrySet() { + return new AddableParameterEntrySet(); + } + + /** + * {@inheritDoc} + */ + public String put(String key, String value) { + String oldValue = request.getValue(key); + request.setValue(key, value); + return oldValue; + } + + + /** + * {@inheritDoc} + */ + public void putAll(Map map) { + for (Entry entry : map + .entrySet()) { + request.setValue(entry.getKey(), entry.getValue()); + } + } + + + /** + * Entry set implementation for {@link AddableParameterMap}. + */ + private class AddableParameterEntrySet extends ReadOnlyEnumerationMap.ReadOnlyEnumerationMapEntrySet { + + @Override + public boolean add(Entry e) { + request.setValue(e.getKey(), e.getValue()); + return true; + } + + @Override + public boolean addAll( + Collection> c) { + for (Entry entry : c) { + request.setValue(entry.getKey(), entry.getValue()); + } + return true; + } + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/collection/CollectionUtil.java b/plugins/tiles/src/main/java/org/apache/tiles/request/collection/CollectionUtil.java new file mode 100644 index 000000000..54cc254a6 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/collection/CollectionUtil.java @@ -0,0 +1,66 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.request.collection; + +import java.util.Enumeration; + +/** + * Utilities for requests. + */ +public final class CollectionUtil { + + /** + * Constructor. + */ + private CollectionUtil() { + + } + + /** + * Returns the string representation of the key. + * + * @param key The key. + * @return The string representation of the key. + * @throws IllegalArgumentException If the key is null. + */ + public static String key(Object key) { + if (key == null) { + throw new IllegalArgumentException(); + } else if (key instanceof String) { + return ((String) key); + } else { + return (key.toString()); + } + } + + /** + * Returns the number of elements in an enumeration, by iterating it. + * + * @param keys The enumeration. + * @return The number of elements. + */ + public static int enumerationSize(Enumeration keys) { + int n = 0; + while (keys.hasMoreElements()) { + keys.nextElement(); + n++; + } + return n; + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/collection/HeaderValuesMap.java b/plugins/tiles/src/main/java/org/apache/tiles/request/collection/HeaderValuesMap.java new file mode 100644 index 000000000..fa50dbab9 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/collection/HeaderValuesMap.java @@ -0,0 +1,556 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.request.collection; + +import org.apache.tiles.request.attribute.EnumeratedValuesExtractor; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Enumeration; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.NoSuchElementException; +import java.util.Set; + +import static org.apache.tiles.request.collection.CollectionUtil.enumerationSize; +import static org.apache.tiles.request.collection.CollectionUtil.key; + +/** + * Exposes an {@link EnumeratedValuesExtractor} object as a read-only map. + */ +public class HeaderValuesMap implements Map { + + /** + * The request. + */ + private final EnumeratedValuesExtractor request; + + /** + * Constructor. + * + * @param request The request object to use. + */ + public HeaderValuesMap(EnumeratedValuesExtractor request) { + this.request = request; + } + + + /** + * {@inheritDoc} + */ + public void clear() { + throw new UnsupportedOperationException(); + } + + + /** + * {@inheritDoc} + */ + public boolean containsKey(Object key) { + return (request.getValue(key(key)) != null); + } + + + /** + * {@inheritDoc} + */ + public boolean containsValue(Object value) { + if (!(value instanceof String[])) { + return (false); + } + String[] test = (String[]) value; + Enumeration names = request.getKeys(); + while (names.hasMoreElements()) { + String name = names.nextElement(); + if (compareHeaders(name, array2set(test))) { + return true; + } + } + return false; + } + + + /** + * {@inheritDoc} + */ + public Set> entrySet() { + return new HeadersEntrySet(); + } + + + /** + * {@inheritDoc} + */ + @Override + public boolean equals(Object obj) { + if (obj == null) { + return false; + } + if (!(obj instanceof HeaderValuesMap)) { + return false; + } + EnumeratedValuesExtractor otherRequest = ((HeaderValuesMap) obj).request; + boolean retValue = true; + for (Enumeration attribs = request.getKeys(); attribs.hasMoreElements() && retValue; ) { + String parameterName = attribs.nextElement(); + Set valueSet = enumeration2set(otherRequest.getValues(parameterName)); + retValue = compareHeaders(parameterName, valueSet); + } + + return retValue; + } + + + /** + * {@inheritDoc} + */ + public String[] get(Object key) { + return getHeaderValues(key(key)); + } + + /** + * {@inheritDoc} + */ + @Override + public int hashCode() { + int retValue = 0; + for (Enumeration attribs = request.getKeys(); attribs + .hasMoreElements(); ) { + String parameterName = attribs.nextElement(); + Enumeration values = request.getValues(parameterName); + int valueHash = 0; + while (values.hasMoreElements()) { + valueHash += values.nextElement().hashCode(); + } + retValue += parameterName.hashCode() ^ valueHash; + } + return retValue; + } + + + /** + * {@inheritDoc} + */ + public boolean isEmpty() { + return !request.getKeys().hasMoreElements(); + } + + + /** + * {@inheritDoc} + */ + public Set keySet() { + return new KeySet(request); + } + + + /** + * {@inheritDoc} + */ + public String[] put(String key, String[] value) { + throw new UnsupportedOperationException(); + } + + + /** + * {@inheritDoc} + */ + public void putAll(Map map) { + throw new UnsupportedOperationException(); + } + + + /** + * {@inheritDoc} + */ + public String[] remove(Object key) { + throw new UnsupportedOperationException(); + } + + + /** + * {@inheritDoc} + */ + public int size() { + return enumerationSize(request.getKeys()); + } + + + /** + * {@inheritDoc} + */ + public Collection values() { + return new HeaderValuesCollection(); + } + + /** + * Extracts values enumeration of an attribute and returns the corresponding array of values. + * + * @param key The key of the attribute. + * @return The values of the attribute. + */ + private String[] getHeaderValues(String key) { + List list = new ArrayList<>(); + Enumeration values = request.getValues(key); + while (values.hasMoreElements()) { + list.add(values.nextElement()); + } + return list.toArray(new String[0]); + } + + /** + * Converts the content of a string enumeration to an array of strings. + * + * @param enumeration The enumeration to convert. + * @return The corresponding array. + */ + private Set enumeration2set(Enumeration enumeration) { + Set retValue = new HashSet<>(); + while (enumeration.hasMoreElements()) { + retValue.add(enumeration.nextElement()); + } + return retValue; + } + + /** + * Transforms a string array in a string set. + * + * @param valueArray The array to convert. + * @return The corresponding set. + */ + private Set array2set(String[] valueArray) { + Set values = new HashSet<>(); + Collections.addAll(values, valueArray); + return values; + } + + /** + * Checks if values of a header attribute are the same as the one passed in + * the set. + * + * @param name The name of the header. + * @param testSet The set of values it must contain. + * @return true if all the values, and only them, are present + * in the header values. + */ + private boolean compareHeaders(String name, Set testSet) { + Enumeration values = request.getValues(name); + boolean matched = true; + while (values.hasMoreElements() && matched) { + String currentValue = values.nextElement(); + matched = testSet.remove(currentValue); + } + matched = matched && testSet.isEmpty(); + return matched; + } + + /** + * Entry set implementation for {@link HeaderValuesMap}. + */ + private class HeadersEntrySet implements Set> { + + @Override + public boolean add(Entry e) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean addAll( + Collection> c) { + throw new UnsupportedOperationException(); + } + + @Override + public void clear() { + throw new UnsupportedOperationException(); + } + + @SuppressWarnings("unchecked") + @Override + public boolean contains(Object o) { + return containsEntry((Entry) o); + } + + @SuppressWarnings("unchecked") + @Override + public boolean containsAll(Collection c) { + Collection> realCollection = + (Collection>) c; + for (Entry entry : realCollection) { + if (!containsEntry(entry)) { + return false; + } + } + return true; + } + + @Override + public boolean isEmpty() { + return HeaderValuesMap.this.isEmpty(); + } + + @Override + public Iterator> iterator() { + return new HeadersEntrySetIterator(); + } + + @Override + public boolean remove(Object o) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean removeAll(Collection c) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean retainAll(Collection c) { + throw new UnsupportedOperationException(); + } + + @Override + public int size() { + return HeaderValuesMap.this.size(); + } + + @Override + public Object[] toArray() { + return toList().toArray(); + } + + @Override + public T[] toArray(T[] a) { + return toList().toArray(a); + } + + /** + * Checks whether the given entry is present in the headers. + * + * @param entry The entry to check. + * @return if the key and the values of the entry are present. + */ + private boolean containsEntry(Entry entry) { + Enumeration entryValues = request.getValues(key(entry.getKey())); + String[] valueArray = entry.getValue(); + Set values = array2set(valueArray); + while (entryValues.hasMoreElements()) { + if (!values.remove(entryValues.nextElement())) { + return false; + } + } + return values.isEmpty(); + } + + /** + * Turns this entry set into a list. + * + * @return The collection, turned into a list. + */ + private List> toList() { + List> entries = new ArrayList<>(); + Enumeration names = request.getKeys(); + while (names.hasMoreElements()) { + entries.add(extractNextEntry(names)); + } + return entries; + } + + /** + * Returns the next entry, by getting the next element in the given enumeration. + * + * @param names The enumeration to get the next name from.. + * @return The next map entry. + */ + private MapEntry extractNextEntry(Enumeration names) { + String name = names.nextElement(); + return new MapEntryArrayValues<>(name, getHeaderValues(name), false); + } + + /** + * Iterates {@link HeadersEntrySet} elements. + */ + private class HeadersEntrySetIterator implements Iterator> { + + /** + * The enumeration to use. + */ + private final Enumeration namesEnumeration = request.getKeys(); + + @Override + public boolean hasNext() { + return namesEnumeration.hasMoreElements(); + } + + @Override + public Entry next() { + if (namesEnumeration.hasMoreElements()) { + return extractNextEntry(namesEnumeration); + } + throw new NoSuchElementException(); + } + + @Override + public void remove() { + throw new UnsupportedOperationException(); + } + + } + } + + /** + * It is a collection of all values of the header. Each element is an array + * of values of a single header. + */ + private class HeaderValuesCollection implements Collection { + + @Override + public boolean add(String[] e) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean addAll(Collection c) { + throw new UnsupportedOperationException(); + } + + @Override + public void clear() { + throw new UnsupportedOperationException(); + } + + @Override + public boolean contains(Object o) { + return containsValue(o); + } + + @SuppressWarnings("unchecked") + @Override + public boolean containsAll(Collection c) { + Collection realCollection = (Collection) c; + for (String[] value : realCollection) { + if (!containsValue(value)) { + return false; + } + } + return true; + } + + @Override + public boolean isEmpty() { + return HeaderValuesMap.this.isEmpty(); + } + + @Override + public Iterator iterator() { + return new HeaderValuesCollectionIterator(); + } + + @Override + public boolean remove(Object o) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean removeAll(Collection c) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean retainAll(Collection c) { + throw new UnsupportedOperationException(); + } + + @Override + public int size() { + return HeaderValuesMap.this.size(); + } + + @Override + public Object[] toArray() { + return toList().toArray(); + } + + @Override + public T[] toArray(T[] a) { + return toList().toArray(a); + } + + /** + * Turns this collection into a list. + * + * @return The list. + */ + private List toList() { + List entries = new ArrayList<>(); + Enumeration names = request.getKeys(); + while (names.hasMoreElements()) { + entries.add(enumeration2array(request.getValues(names.nextElement()))); + } + return entries; + } + + /** + * Converts the content of a string enumeration to an array of strings. + * + * @param enumeration The enumeration to convert. + * @return The corresponding array. + */ + private String[] enumeration2array(Enumeration enumeration) { + List list1 = new ArrayList<>(); + while (enumeration.hasMoreElements()) { + list1.add(enumeration.nextElement()); + } + + return list1.toArray(new String[0]); + } + + /** + * Iterates elements of {@link HeaderValuesCollection}. + */ + private class HeaderValuesCollectionIterator implements Iterator { + + /** + * The enumeration of the name of header attributes. + */ + private final Enumeration namesEnumeration = request.getKeys(); + + @Override + public boolean hasNext() { + return namesEnumeration.hasMoreElements(); + } + + @Override + public String[] next() { + if (namesEnumeration.hasMoreElements()) { + return enumeration2array(request.getValues(namesEnumeration.nextElement())); + } + throw new NoSuchElementException(); + } + + @Override + public void remove() { + throw new UnsupportedOperationException(); + } + } + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/collection/KeySet.java b/plugins/tiles/src/main/java/org/apache/tiles/request/collection/KeySet.java new file mode 100644 index 000000000..f34688088 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/collection/KeySet.java @@ -0,0 +1,167 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.request.collection; + +import org.apache.tiles.request.attribute.HasKeys; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Enumeration; +import java.util.Iterator; +import java.util.List; +import java.util.NoSuchElementException; +import java.util.Set; + +import static org.apache.tiles.request.collection.CollectionUtil.enumerationSize; +import static org.apache.tiles.request.collection.CollectionUtil.key; + +/** + * Exposes keys of a {@link HasKeys} object as a set. + */ +public class KeySet implements Set { + + /** + * The request to read. + */ + private final HasKeys request; + + /** + * Constructor. + * + * @param request The request to read. + */ + public KeySet(HasKeys request) { + this.request = request; + } + + @Override + public boolean add(String e) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean addAll(Collection c) { + throw new UnsupportedOperationException(); + } + + @Override + public void clear() { + throw new UnsupportedOperationException(); + } + + @Override + public boolean contains(Object o) { + return request.getValue(key(o)) != null; + } + + @SuppressWarnings("unchecked") + @Override + public boolean containsAll(Collection c) { + Collection realCollection = (Collection) c; + for (String key : realCollection) { + if (request.getValue(key(key)) == null) { + return false; + } + } + return true; + } + + @Override + public boolean isEmpty() { + return !request.getKeys().hasMoreElements(); + } + + @Override + public Iterator iterator() { + return new KeySetIterator(); + } + + @Override + public boolean remove(Object o) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean removeAll(Collection c) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean retainAll(Collection c) { + throw new UnsupportedOperationException(); + } + + @Override + public int size() { + return enumerationSize(request.getKeys()); + } + + @Override + public Object[] toArray() { + return toList().toArray(); + } + + @Override + public T[] toArray(T[] a) { + return toList().toArray(a); + } + + /** + * Turns this set into a list. + * + * @return The corresponding list. + */ + private List toList() { + List entries = new ArrayList(); + Enumeration names = request.getKeys(); + while (names.hasMoreElements()) { + entries.add(names.nextElement()); + } + return entries; + } + + /** + * Iterates elements of {@link KeySet}. + */ + private class KeySetIterator implements Iterator { + + /** + * The key names enumeration. + */ + private final Enumeration namesEnumeration = request.getKeys(); + + @Override + public boolean hasNext() { + return namesEnumeration.hasMoreElements(); + } + + @Override + public String next() { + if (namesEnumeration.hasMoreElements()) { + return namesEnumeration.nextElement(); + } + throw new NoSuchElementException(); + } + + @Override + public void remove() { + throw new UnsupportedOperationException(); + } + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/collection/MapEntry.java b/plugins/tiles/src/main/java/org/apache/tiles/request/collection/MapEntry.java new file mode 100644 index 000000000..58e590816 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/collection/MapEntry.java @@ -0,0 +1,124 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.request.collection; + +import java.util.Map; + +/** + *

Map.Entry implementation that can be constructed to either be read-only + * or not.

+ * + * @param The key type. + * @param The value type. + */ + +public class MapEntry implements Map.Entry { + + /** + *

The entry key.

+ */ + private final K key; + + /** + *

The entry value.

+ */ + private V value; + + /** + *

Whether the entry can be modified.

+ */ + private final boolean modifiable; + + /** + *

Creates a map entry that can either allow modifications or not.

+ * + * @param key The entry key + * @param value The entry value + * @param modifiable Whether the entry should allow modification or not + */ + public MapEntry(K key, V value, boolean modifiable) { + this.key = key; + this.value = value; + this.modifiable = modifiable; + } + + /** + *

Gets the entry key.

+ * + * @return The entry key + */ + public K getKey() { + return key; + } + + /** + *

Gets the entry value.

+ * + * @return The entry key + */ + public V getValue() { + return value; + } + + /** + *

Sets the entry value if the entry can be modified.

+ * + * @param val The new value + * @return The old entry value + * @throws UnsupportedOperationException If the entry cannot be modified + */ + public V setValue(V val) { + if (modifiable) { + V oldVal = this.value; + this.value = val; + return oldVal; + } + throw new UnsupportedOperationException("The map entry is not modifiable"); + } + + /** + *

Determines if this entry is equal to the passed object.

+ * + * @param o The object to test + * @return True if equal, else false + */ + @Override + @SuppressWarnings("unchecked") + public boolean equals(Object o) { + if (o instanceof Map.Entry) { + Map.Entry entry = (Map.Entry) o; + return (this.getKey() == null ? entry.getKey() == null : this + .getKey().equals(entry.getKey())) + && (this.getValue() == null ? entry.getValue() == null + : this.getValue().equals(entry.getValue())); + } + return false; + } + + /** + *

Returns the hashcode for this entry.

+ * + * @return The and'ed hashcode of the key and value + */ + @Override + public int hashCode() { + return (this.getKey() == null ? 0 : this.getKey().hashCode()) + ^ (this.getValue() == null ? 0 : this.getValue().hashCode()); + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/collection/MapEntryArrayValues.java b/plugins/tiles/src/main/java/org/apache/tiles/request/collection/MapEntryArrayValues.java new file mode 100644 index 000000000..c9aff7fd3 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/collection/MapEntryArrayValues.java @@ -0,0 +1,95 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.request.collection; + +import java.util.Map; +import java.util.Objects; + +/** + * Multi-valued map entry. + * + * @param The key type. + * @param The value type. + */ +public class MapEntryArrayValues extends MapEntry { + + /** + * Constructor. + * + * @param key The key of the entry. + * @param value The array of values. + * @param modifiable If true the entry is modifiable. + */ + public MapEntryArrayValues(K key, V[] value, boolean modifiable) { + super(key, value, modifiable); + } + + /** + *

Returns the hashcode for this entry.

+ * + * @return The and'ed hashcode of the key and value + */ + @Override + public int hashCode() { + int valueHash = 0; + V[] value = getValue(); + if (value != null) { + for (V v : value) { + valueHash += v.hashCode(); + } + } + + return (this.getKey() == null ? 0 : this.getKey().hashCode()) ^ valueHash; + } + + /** + *

Determines if this entry is equal to the passed object.

+ * + * @param o The object to test + * @return True if equal, else false + */ + @Override + @SuppressWarnings("unchecked") + public boolean equals(Object o) { + if (o instanceof Map.Entry) { + Map.Entry entry = (Map.Entry) o; + if (this.getKey() == null ? entry.getKey() == null : this + .getKey().equals(entry.getKey())) { + V[] values = getValue(); + V[] otherValues = entry.getValue(); + if (values != null) { + if (otherValues != null) { + if (values.length == otherValues.length) { + boolean same = true; + for (int i = 0; i < values.length && same; i++) { + same = Objects.equals(values[i], otherValues[i]); + } + return same; + } + } else { + return false; + } + } else { + return otherValues == null; + } + } + } + return false; + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/collection/ReadOnlyEnumerationMap.java b/plugins/tiles/src/main/java/org/apache/tiles/request/collection/ReadOnlyEnumerationMap.java new file mode 100644 index 000000000..d5cc16978 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/collection/ReadOnlyEnumerationMap.java @@ -0,0 +1,461 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.request.collection; + +import org.apache.tiles.request.attribute.HasKeys; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Enumeration; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.NoSuchElementException; +import java.util.Set; + +import static org.apache.tiles.request.collection.CollectionUtil.enumerationSize; +import static org.apache.tiles.request.collection.CollectionUtil.key; + +/** + * Wraps an {@link HasKeys} object into a read-only map. + * + * @param The type of the values. + */ +public class ReadOnlyEnumerationMap implements Map { + + /** + * The request. + */ + protected HasKeys request; + + /** + * Constructor. + * + * @param request The request object to use. + */ + public ReadOnlyEnumerationMap(HasKeys request) { + this.request = request; + } + + /** + * {@inheritDoc} + */ + public void clear() { + throw new UnsupportedOperationException(); + } + + /** + * {@inheritDoc} + */ + public boolean containsKey(Object key) { + return (request.getValue(key(key)) != null); + } + + /** + * {@inheritDoc} + */ + @SuppressWarnings("unchecked") + public boolean containsValue(Object value) { + V realValue = (V) value; + for (Enumeration keysIt = request.getKeys(); keysIt.hasMoreElements(); ) { + if (realValue.equals(request.getValue(keysIt.nextElement()))) { + return true; + } + } + return false; + } + + /** + * {@inheritDoc} + */ + public Set> entrySet() { + return new ReadOnlyEnumerationMapEntrySet(); + } + + /** + * {@inheritDoc} + */ + public V get(Object key) { + return (request.getValue(key(key))); + } + + /** + * {@inheritDoc} + */ + public boolean isEmpty() { + return !request.getKeys().hasMoreElements(); + } + + /** + * {@inheritDoc} + */ + public Set keySet() { + return new KeySet(request); + } + + /** + * {@inheritDoc} + */ + public V put(String key, V value) { + throw new UnsupportedOperationException(); + } + + /** + * {@inheritDoc} + */ + public void putAll(Map map) { + throw new UnsupportedOperationException(); + } + + /** + * {@inheritDoc} + */ + public V remove(Object key) { + throw new UnsupportedOperationException(); + } + + /** + * {@inheritDoc} + */ + public int size() { + return enumerationSize(request.getKeys()); + } + + /** + * {@inheritDoc} + */ + public Collection values() { + return new ReadOnlyEnumerationMapValuesCollection(); + } + + /** + * {@inheritDoc} + */ + @Override + public boolean equals(Object obj) { + if (obj == null) { + return false; + } + if (!(obj instanceof ReadOnlyEnumerationMap)) { + return false; + } + @SuppressWarnings("unchecked") + HasKeys otherRequest = ((ReadOnlyEnumerationMap) obj).request; + boolean retValue = true; + Set otherKeys; + otherKeys = new HashSet<>(); + for (Enumeration attribs = otherRequest.getKeys(); attribs.hasMoreElements(); ) { + otherKeys.add(attribs.nextElement()); + } + for (Enumeration attribs = request.getKeys(); attribs.hasMoreElements() && retValue; ) { + String parameterName = attribs.nextElement(); + retValue = request.getValue(parameterName).equals(otherRequest.getValue(parameterName)); + otherKeys.remove(parameterName); + } + + return retValue && otherKeys.isEmpty(); + } + + /** + * {@inheritDoc} + */ + @Override + public int hashCode() { + int retValue = 0; + for (Enumeration attribs = request.getKeys(); attribs + .hasMoreElements(); ) { + String parameterName = attribs.nextElement(); + V value = request.getValue(parameterName); + retValue += parameterName.hashCode() ^ (value == null ? 0 : value.hashCode()); + } + return retValue; + } + + /** + * Entry set implementation for {@link ReadOnlyEnumerationMap}. + */ + class ReadOnlyEnumerationMapEntrySet implements Set> { + + @Override + public boolean add(Entry e) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean addAll( + Collection> c) { + throw new UnsupportedOperationException(); + } + + @Override + public void clear() { + throw new UnsupportedOperationException(); + } + + @SuppressWarnings("unchecked") + @Override + public boolean contains(Object o) { + return containsEntry((Entry) o); + } + + @SuppressWarnings("unchecked") + @Override + public boolean containsAll(Collection c) { + Collection> realCollection = + (Collection>) c; + for (Entry entry : realCollection) { + if (!containsEntry(entry)) { + return false; + } + } + return true; + } + + @Override + public boolean isEmpty() { + return ReadOnlyEnumerationMap.this.isEmpty(); + } + + @Override + public Iterator> iterator() { + return new ReadOnlyEnumerationMapEntrySetIterator(); + } + + @Override + public boolean remove(Object o) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean removeAll(Collection c) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean retainAll(Collection c) { + throw new UnsupportedOperationException(); + } + + @Override + public int size() { + return ReadOnlyEnumerationMap.this.size(); + } + + @Override + public Object[] toArray() { + return toList().toArray(); + } + + @Override + public T[] toArray(T[] a) { + return toList().toArray(a); + } + + /** + * Checks whether the entry is present. + * + * @param entry The entry to check. + * @return true if the entry is present. + */ + protected boolean containsEntry(Entry entry) { + V storedValue = request.getValue(key(entry.getKey())); + return storedValue != null && storedValue.equals(entry.getValue()); + } + + /** + * Turns this set into a list. + * + * @return The list. + */ + private List> toList() { + List> entries = new ArrayList<>(); + Enumeration names = request.getKeys(); + while (names.hasMoreElements()) { + entries.add(extractNextEntry(names)); + } + return entries; + } + + /** + * Returns the next entry, given the enumeration. + * + * @param names The enumeration to get the next key from. + * @return The next entry. + */ + private MapEntry extractNextEntry( + Enumeration names) { + String name = names.nextElement(); + return new MapEntry<>(name, request.getValue(name), false); + } + + /** + * Iterates entries of {@link ReadOnlyEnumerationMap}. + */ + private class ReadOnlyEnumerationMapEntrySetIterator implements Iterator> { + + /** + * Enumerates keys. + */ + private final Enumeration namesEnumeration = request.getKeys(); + + @Override + public boolean hasNext() { + return namesEnumeration.hasMoreElements(); + } + + @Override + public Entry next() { + if (namesEnumeration.hasMoreElements()) { + return extractNextEntry(namesEnumeration); + } + throw new NoSuchElementException(); + } + + @Override + public void remove() { + throw new UnsupportedOperationException(); + } + + } + } + + /** + * Values collection for {@link ReadOnlyEnumerationMap}. + */ + private class ReadOnlyEnumerationMapValuesCollection implements Collection { + + @Override + public boolean add(V e) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean addAll(Collection c) { + throw new UnsupportedOperationException(); + } + + @Override + public void clear() { + throw new UnsupportedOperationException(); + } + + @Override + public boolean contains(Object o) { + return containsValue(o); + } + + @SuppressWarnings("unchecked") + @Override + public boolean containsAll(Collection c) { + Collection realCollection = (Collection) c; + List valueList = new ArrayList<>(realCollection); + for (Enumeration keysEnum = request.getKeys(); keysEnum.hasMoreElements(); ) { + valueList.remove(request.getValue(keysEnum.nextElement())); + if (valueList.isEmpty()) { + return true; + } + } + return false; + } + + @Override + public boolean isEmpty() { + return ReadOnlyEnumerationMap.this.isEmpty(); + } + + @Override + public Iterator iterator() { + return new ReadOnlyEnumerationMapValuesCollectionIterator(); + } + + @Override + public boolean remove(Object o) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean removeAll(Collection c) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean retainAll(Collection c) { + throw new UnsupportedOperationException(); + } + + @Override + public int size() { + return ReadOnlyEnumerationMap.this.size(); + } + + @Override + public Object[] toArray() { + return toList().toArray(); + } + + @Override + public T[] toArray(T[] a) { + return toList().toArray(a); + } + + /** + * Turns this collection into a list. + * + * @return The list. + */ + private List toList() { + List entries = new ArrayList<>(); + Enumeration names = request.getKeys(); + while (names.hasMoreElements()) { + entries.add(request.getValue(names.nextElement())); + } + return entries; + } + + /** + * Iterates values of {@link ReadOnlyEnumerationMap}. + */ + private class ReadOnlyEnumerationMapValuesCollectionIterator implements Iterator { + + /** + * Enumerates attribute keys. + */ + private final Enumeration namesEnumeration = request.getKeys(); + + @Override + public boolean hasNext() { + return namesEnumeration.hasMoreElements(); + } + + @Override + public V next() { + if (namesEnumeration.hasMoreElements()) { + return request.getValue(namesEnumeration.nextElement()); + } + throw new NoSuchElementException(); + } + + @Override + public void remove() { + throw new UnsupportedOperationException(); + } + } + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/collection/RemovableKeySet.java b/plugins/tiles/src/main/java/org/apache/tiles/request/collection/RemovableKeySet.java new file mode 100644 index 000000000..1ce23f66b --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/collection/RemovableKeySet.java @@ -0,0 +1,91 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.request.collection; + +import static org.apache.tiles.request.collection.CollectionUtil.*; + +import java.util.Collection; +import java.util.Enumeration; +import java.util.LinkedHashSet; +import java.util.Set; + +import org.apache.tiles.request.attribute.HasRemovableKeys; + +/** + * Wraps {@link HasRemovableKeys} keys as a set. + */ +public class RemovableKeySet extends KeySet { + + /** + * The request. + */ + private final HasRemovableKeys request; + + /** + * Constructor. + * + * @param request The request. + */ + public RemovableKeySet(HasRemovableKeys request) { + super(request); + this.request = request; + } + + @Override + public boolean remove(Object o) { + String strKey = key(o); + Object previous = request.getValue(strKey); + if (previous != null) { + request.removeValue(strKey); + return true; + } + return false; + } + + @SuppressWarnings("unchecked") + @Override + public boolean removeAll(Collection c) { + Collection realCollection = (Collection) c; + boolean retValue = false; + for (String entry : realCollection) { + retValue |= remove(entry); + } + return retValue; + } + + @SuppressWarnings("unchecked") + @Override + public boolean retainAll(Collection c) { + Collection realCollection = (Collection) c; + boolean retValue = false; + Set keysToRemove = new LinkedHashSet<>(); + for (Enumeration keys = request.getKeys(); keys.hasMoreElements();) { + String key = keys.nextElement(); + if (!realCollection.contains(key)) { + retValue = true; + keysToRemove.add(key); + } + } + for (String key : keysToRemove) { + request.removeValue(key); + } + return retValue; + } + +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/collection/ScopeMap.java b/plugins/tiles/src/main/java/org/apache/tiles/request/collection/ScopeMap.java new file mode 100644 index 000000000..a03ec1f3b --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/collection/ScopeMap.java @@ -0,0 +1,169 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.request.collection; + +import static org.apache.tiles.request.collection.CollectionUtil.*; + +import java.util.Collection; +import java.util.Enumeration; +import java.util.LinkedHashSet; +import java.util.Map; +import java.util.Set; + +import org.apache.tiles.request.attribute.AttributeExtractor; + +/** + * Exposes a scope context as a map. + */ +public class ScopeMap extends ReadOnlyEnumerationMap { + + /** + * The context to read. + */ + private final AttributeExtractor context; + + /** + * Constructor. + * + * @param context The servlet context to use. + */ + public ScopeMap(AttributeExtractor context) { + super(context); + this.context = context; + } + + /** {@inheritDoc} */ + public void clear() { + Enumeration keys = context.getKeys(); + while (keys.hasMoreElements()) { + context.removeValue(keys.nextElement()); + } + } + + /** {@inheritDoc} */ + public Set> entrySet() { + return new ScopeEntrySet(); + } + + /** {@inheritDoc} */ + public Set keySet() { + return new RemovableKeySet(context); + } + + /** {@inheritDoc} */ + public Object put(String key, Object value) { + String strKey = key(key); + Object previous = context.getValue(strKey); + context.setValue(strKey, value); + return previous; + } + + /** {@inheritDoc} */ + public void putAll(Map map) { + for (String key : map.keySet()) { + context.setValue(key, map.get(key)); + } + } + + /** {@inheritDoc} */ + public Object remove(Object key) { + String strKey = key(key); + Object previous = context.getValue(strKey); + context.removeValue(strKey); + return (previous); + } + + /** + * Entry set implementation for {@link ScopeMap}. + */ + private class ScopeEntrySet extends ReadOnlyEnumerationMap.ReadOnlyEnumerationMapEntrySet { + + @Override + public boolean add(Map.Entry e) { + String key = e.getKey(); + Object value = e.getValue(); + Object oldValue = get(key); + if (oldValue == null || !oldValue.equals(value)) { + context.setValue(key, value); + return true; + } + return false; + } + + @Override + public boolean addAll( + Collection> c) { + boolean retValue = false; + for (Map.Entry entry : c) { + retValue |= add(entry); + } + return retValue; + } + + @Override + public void clear() { + ScopeMap.this.clear(); + } + + @SuppressWarnings("unchecked") + @Override + public boolean remove(Object o) { + Map.Entry entry = (Map.Entry) o; + String key = entry.getKey(); + Object currentValue = context.getValue(key); + if (currentValue != null && currentValue.equals(entry.getValue())) { + context.removeValue(key); + return true; + } + return false; + } + + @SuppressWarnings("unchecked") + @Override + public boolean removeAll(Collection c) { + Collection> realCollection = (Collection>) c; + boolean retValue = false; + for (Map.Entry entry : realCollection) { + retValue |= remove(entry); + } + return retValue; + } + + @SuppressWarnings("unchecked") + @Override + public boolean retainAll(Collection c) { + Collection> realCollection = (Collection>) c; + boolean retValue = false; + Set keysToRemove = new LinkedHashSet<>(); + for (Enumeration keys = context.getKeys(); keys.hasMoreElements();) { + String key = keys.nextElement(); + Object value = context.getValue(key); + Map.Entry entry = new MapEntry<>(key, value, false); + if (!realCollection.contains(entry)) { + retValue = true; + keysToRemove.add(key); + } + } + for (String key : keysToRemove) { + context.removeValue(key); + } + return retValue; + } + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/collection/package-info.java b/plugins/tiles/src/main/java/org/apache/tiles/request/collection/package-info.java new file mode 100644 index 000000000..e236964a8 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/collection/package-info.java @@ -0,0 +1,34 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +/** + * Special collections and maps for attributes (like HTTP request + * or session attributes). + * These can be used to access another object's attributes through + * a Map interface. + *
    + *
  • {@link org.apache.tiles.request.collection.ScopeMap} provides + * full get/put/remove access to the attributes. + *
  • {@link org.apache.tiles.request.collection.ReadOnlyEnumerationMap} + * provides get-only access. + *
  • {@link org.apache.tiles.request.collection.HeaderValuesMap} + * provides get-only access to a multi-valued map (typically, headers). + *
+ */ +package org.apache.tiles.request.collection; + diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/freemarker/EnvironmentScopeMap.java b/plugins/tiles/src/main/java/org/apache/tiles/request/freemarker/EnvironmentScopeMap.java new file mode 100644 index 000000000..e55c38582 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/freemarker/EnvironmentScopeMap.java @@ -0,0 +1,58 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.request.freemarker; + +import freemarker.core.Environment; +import freemarker.template.TemplateModelException; +import org.apache.tiles.request.collection.ScopeMap; +import org.apache.tiles.request.freemarker.extractor.EnvironmentScopeExtractor; + +import java.util.Set; + +/** + * Private implementation of Map for servlet request attributes. + */ +final class EnvironmentScopeMap extends ScopeMap { + + /** + * The request object to use. + */ + private final Environment request; + + /** + * Constructor. + * + * @param request The request object to use. + */ + public EnvironmentScopeMap(Environment request) { + super(new EnvironmentScopeExtractor(request)); + this.request = request; + } + + @SuppressWarnings("unchecked") + @Override + public Set keySet() { + try { + return request.getKnownVariableNames(); + } catch (TemplateModelException e) { + throw new FreemarkerRequestException( + "Cannot get known variable names", e); + } + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/freemarker/FreemarkerRequest.java b/plugins/tiles/src/main/java/org/apache/tiles/request/freemarker/FreemarkerRequest.java new file mode 100644 index 000000000..cd82fccb0 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/freemarker/FreemarkerRequest.java @@ -0,0 +1,143 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tiles.request.freemarker; + +import freemarker.core.Environment; +import freemarker.ext.servlet.HttpRequestHashModel; +import org.apache.tiles.request.AbstractViewRequest; +import org.apache.tiles.request.ApplicationContext; +import org.apache.tiles.request.DispatchRequest; +import org.apache.tiles.request.servlet.ServletRequest; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.PrintWriter; +import java.io.Writer; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Locale; +import java.util.Map; + +/** + * The FreeMarker-specific request context. + */ +public class FreemarkerRequest extends AbstractViewRequest { + + /** + * The natively available scopes. In fact, only "page". + */ + private final List scopes; + + /** + * The FreeMarker current environment. + */ + private final Environment env; + + /** + * The page scope map. + */ + private Map pageScope; + + /** + * Creates a new Freemarker request. + * + * @param applicationContext The application context. + * @param env The Freemarker environment object. + * @return A new request. + */ + public static FreemarkerRequest createServletFreemarkerRequest(ApplicationContext applicationContext, Environment env) { + HttpRequestHashModel requestModel = FreemarkerRequestUtil.getRequestHashModel(env); + HttpServletRequest request = requestModel.getRequest(); + HttpServletResponse response = requestModel.getResponse(); + DispatchRequest enclosedRequest = new ServletRequest(applicationContext, request, response); + return new FreemarkerRequest(enclosedRequest, env); + } + + /** + * Constructor. + * + * @param enclosedRequest + * The request that exposes non-FreeMarker specific properties + * @param env + * The FreeMarker environment. + */ + public FreemarkerRequest(DispatchRequest enclosedRequest, Environment env) { + super(enclosedRequest); + List scopes = new ArrayList<>(enclosedRequest.getAvailableScopes()); + scopes.add("page"); + this.scopes = Collections.unmodifiableList(scopes); + this.env = env; + } + + /** + * Returns the environment object. + * + * @return The environment. + */ + public Environment getEnvironment() { + return env; + } + + /** {@inheritDoc} */ + @Override + public Locale getRequestLocale() { + return env.getLocale(); + } + + /** + * Returns the page scope. + * + * @return The page scope. + */ + public Map getPageScope() { + if (pageScope == null) { + pageScope = new EnvironmentScopeMap(env); + } + return pageScope; + } + + @Override + public List getAvailableScopes() { + return scopes; + } + + /** {@inheritDoc} */ + @Override + public PrintWriter getPrintWriter() { + Writer writer = env.getOut(); + if (writer instanceof PrintWriter) { + return (PrintWriter) writer; + } + return new PrintWriter(writer); + } + + /** {@inheritDoc} */ + @Override + public Writer getWriter() { + return env.getOut(); + } + + @Override + public Map getContext(String scope) { + return "page".equals(scope) ? getPageScope() : super.getContext(scope); + } + +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/freemarker/FreemarkerRequestException.java b/plugins/tiles/src/main/java/org/apache/tiles/request/freemarker/FreemarkerRequestException.java new file mode 100644 index 000000000..a03ae300e --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/freemarker/FreemarkerRequestException.java @@ -0,0 +1,37 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.request.freemarker; + +import org.apache.tiles.request.RequestException; + +/** + * Thrown when a Freemarker request fails. + */ +public class FreemarkerRequestException extends RequestException { + + /** + * Constructor. + * + * @param message The detail message. + * @param cause The cause to be wrapped. + */ + public FreemarkerRequestException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/freemarker/FreemarkerRequestUtil.java b/plugins/tiles/src/main/java/org/apache/tiles/request/freemarker/FreemarkerRequestUtil.java new file mode 100644 index 000000000..6c43f231e --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/freemarker/FreemarkerRequestUtil.java @@ -0,0 +1,82 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.request.freemarker; + +import freemarker.core.Environment; +import freemarker.ext.servlet.FreemarkerServlet; +import freemarker.ext.servlet.HttpRequestHashModel; +import freemarker.ext.servlet.ServletContextHashModel; +import freemarker.template.TemplateModelException; +import org.apache.tiles.request.ApplicationContext; +import org.apache.tiles.request.servlet.ServletUtil; + +/** + * Utilities to work with Freemarker requests. + */ +public final class FreemarkerRequestUtil { + + /** + * Constructor. + */ + private FreemarkerRequestUtil() { + } + + /** + * Returns the HTTP request hash model. + * + * @param env The current FreeMarker environment. + * @return The request hash model. + */ + public static HttpRequestHashModel getRequestHashModel(Environment env) { + try { + return (HttpRequestHashModel) env.getDataModel().get(FreemarkerServlet.KEY_REQUEST); + } catch (TemplateModelException e) { + throw new NotAvailableFreemarkerServletException("Exception got when obtaining the request hash model", e); + } + } + + /** + * Returns the servlet context hash model. + * + * @param env The current FreeMarker environment. + * @return The servlet context hash model. + */ + public static ServletContextHashModel getServletContextHashModel(Environment env) { + try { + return (ServletContextHashModel) env.getDataModel().get(FreemarkerServlet.KEY_APPLICATION); + } catch (TemplateModelException e) { + throw new NotAvailableFreemarkerServletException("Exception got when obtaining the application hash model", e); + } + } + + /** + * Returns the application context. It must be + * first saved creating an {@link ApplicationContext} and using + * {@link org.apache.tiles.request.ApplicationAccess#register(ApplicationContext)}. + * + * @param env The Freemarker environment. + * @return The + */ + public static ApplicationContext getApplicationContext(Environment env) { + return ServletUtil.getApplicationContext( + getServletContextHashModel(env).getServlet().getServletContext() + ); + } + +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/freemarker/NotAvailableFreemarkerServletException.java b/plugins/tiles/src/main/java/org/apache/tiles/request/freemarker/NotAvailableFreemarkerServletException.java new file mode 100644 index 000000000..c34b91168 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/freemarker/NotAvailableFreemarkerServletException.java @@ -0,0 +1,37 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.request.freemarker; + +import org.apache.tiles.request.NotAvailableFeatureException; + +/** + * Thrown when the Freemarker servlet is not available. + */ +public class NotAvailableFreemarkerServletException extends NotAvailableFeatureException { + + /** + * Constructor. + * + * @param message The detail message. + * @param e The cause to be wrapped. + */ + public NotAvailableFreemarkerServletException(String message, Throwable e) { + super(message, e); + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/freemarker/autotag/FreemarkerAutotagException.java b/plugins/tiles/src/main/java/org/apache/tiles/request/freemarker/autotag/FreemarkerAutotagException.java new file mode 100644 index 000000000..9ba13c882 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/freemarker/autotag/FreemarkerAutotagException.java @@ -0,0 +1,36 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.request.freemarker.autotag; + +/** + * Thrown when a Freemarker problem under Autotag runtime part happens. + */ +public class FreemarkerAutotagException extends RuntimeException { + + /** + * Constructor. + * + * @param message The message of the exception. + * @param cause The cause. + */ + public FreemarkerAutotagException(String message, Throwable cause) { + super(message, cause); + } + +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/freemarker/autotag/FreemarkerAutotagRuntime.java b/plugins/tiles/src/main/java/org/apache/tiles/request/freemarker/autotag/FreemarkerAutotagRuntime.java new file mode 100644 index 000000000..9fe1a7de6 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/freemarker/autotag/FreemarkerAutotagRuntime.java @@ -0,0 +1,68 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.request.freemarker.autotag; + +import freemarker.core.Environment; +import freemarker.template.TemplateDirectiveBody; +import freemarker.template.TemplateDirectiveModel; +import freemarker.template.TemplateModel; +import org.apache.tiles.autotag.core.runtime.AutotagRuntime; +import org.apache.tiles.autotag.core.runtime.ModelBody; +import org.apache.tiles.request.Request; +import org.apache.tiles.request.freemarker.FreemarkerRequest; +import org.apache.tiles.request.freemarker.FreemarkerRequestUtil; + +import java.util.Map; + +/** + * A Runtime for implementing a Freemarker Template Directive. + */ +public class FreemarkerAutotagRuntime implements AutotagRuntime, TemplateDirectiveModel { + + private Environment env; + private TemplateDirectiveBody body; + private Map params; + + /** {@inheritDoc} */ + @SuppressWarnings("unchecked") + @Override + public void execute(Environment env, Map params, TemplateModel[] loopVars, TemplateDirectiveBody body) { + this.env = env; + this.body = body; + this.params = params; + } + + /** {@inheritDoc} */ + @Override + public Request createRequest() { + return FreemarkerRequest.createServletFreemarkerRequest(FreemarkerRequestUtil.getApplicationContext(env), env); + } + + /** {@inheritDoc} */ + @Override + public ModelBody createModelBody() { + return new FreemarkerModelBody(env.getOut(), body); + } + + /** {@inheritDoc} */ + @Override + public T getParameter(String name, Class type, T defaultValue) { + return FreemarkerUtil.getAsObject(params.get(name), type, defaultValue); + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/freemarker/autotag/FreemarkerModelBody.java b/plugins/tiles/src/main/java/org/apache/tiles/request/freemarker/autotag/FreemarkerModelBody.java new file mode 100644 index 000000000..85f52b7e3 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/freemarker/autotag/FreemarkerModelBody.java @@ -0,0 +1,62 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.request.freemarker.autotag; + +import freemarker.template.TemplateDirectiveBody; +import freemarker.template.TemplateException; +import org.apache.tiles.autotag.core.runtime.AbstractModelBody; + +import java.io.IOException; +import java.io.Writer; + +/** + * Body implementation of a Freemarker model body. + */ +public class FreemarkerModelBody extends AbstractModelBody { + + /** + * The real body. + */ + private final TemplateDirectiveBody templateDirectiveBody; + + /** + * Constructor. + * + * @param defaultWriter The default writer. + * @param templateDirectiveBody The real body. + */ + public FreemarkerModelBody(Writer defaultWriter, TemplateDirectiveBody templateDirectiveBody) { + super(defaultWriter); + this.templateDirectiveBody = templateDirectiveBody; + } + + @Override + public void evaluate(Writer writer) throws IOException { + if (templateDirectiveBody == null) { + return; + } + + try { + templateDirectiveBody.render(writer); + } catch (TemplateException e) { + throw new IOException("TemplateException when rendering body", e); + } + } + +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/freemarker/autotag/FreemarkerUtil.java b/plugins/tiles/src/main/java/org/apache/tiles/request/freemarker/autotag/FreemarkerUtil.java new file mode 100644 index 000000000..37362edc3 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/freemarker/autotag/FreemarkerUtil.java @@ -0,0 +1,60 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tiles.request.freemarker.autotag; + +import freemarker.template.TemplateModel; +import freemarker.template.TemplateModelException; +import freemarker.template.utility.DeepUnwrap; + +/** + * Utilities for FreeMarker usage in Tiles. + */ +public final class FreemarkerUtil { + + /** + * Private constructor to avoid instantiation. + */ + private FreemarkerUtil() { + } + + /** + * Unwraps a TemplateModel to extract an object. + * + * @param model The TemplateModel to unwrap. + * @param defaultValue The default value, as specified in the template + * model, or null if not specified. + * @return The unwrapped object. + */ + public static T getAsObject(TemplateModel model, Class type, T defaultValue) { + try { + T retValue = defaultValue; + if (model != null) { + @SuppressWarnings("unchecked") + T value = (T) DeepUnwrap.unwrap(model); + if (value != null) { + retValue = value; + } + } + return retValue; + } catch (TemplateModelException e) { + throw new FreemarkerAutotagException("Cannot unwrap a model", e); + } + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/freemarker/autotag/package-info.java b/plugins/tiles/src/main/java/org/apache/tiles/request/freemarker/autotag/package-info.java new file mode 100644 index 000000000..af78d7b2d --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/freemarker/autotag/package-info.java @@ -0,0 +1,22 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +/** + * Runtime part of Autotag support for Freemarker. + */ +package org.apache.tiles.request.freemarker.autotag; diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/freemarker/extractor/EnvironmentScopeExtractor.java b/plugins/tiles/src/main/java/org/apache/tiles/request/freemarker/extractor/EnvironmentScopeExtractor.java new file mode 100644 index 000000000..e7ce577d6 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/freemarker/extractor/EnvironmentScopeExtractor.java @@ -0,0 +1,87 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.request.freemarker.extractor; + +import freemarker.core.Environment; +import freemarker.template.TemplateModel; +import freemarker.template.TemplateModelException; +import freemarker.template.utility.DeepUnwrap; +import org.apache.tiles.request.attribute.AttributeExtractor; +import org.apache.tiles.request.freemarker.FreemarkerRequestException; + +import java.util.Collections; +import java.util.Enumeration; + +/** + * Extract attributes from {@link Environment} objects as a scope. + */ +public class EnvironmentScopeExtractor implements AttributeExtractor { + + /** + * The environment. + */ + private final Environment request; + + /** + * Constructor. + * + * @param request The environment. + */ + public EnvironmentScopeExtractor(Environment request) { + this.request = request; + } + + @Override + public void removeValue(String name) { + request.setVariable(name, null); + } + + @SuppressWarnings("unchecked") + @Override + public Enumeration getKeys() { + try { + return Collections. enumeration(request.getKnownVariableNames()); + } catch (TemplateModelException e) { + throw new FreemarkerRequestException("Cannot iterate variable names correctly", e); + } + } + + @Override + public Object getValue(String key) { + try { + TemplateModel variable = request.getVariable(key); + if (variable != null) { + return DeepUnwrap.unwrap(variable); + } + return null; + } catch (TemplateModelException e) { + throw new FreemarkerRequestException("Cannot get attribute with name '" + key + "'", e); + } + } + + @Override + public void setValue(String key, Object value) { + try { + TemplateModel model = request.getObjectWrapper().wrap(value); + request.setVariable(key, model); + } catch (TemplateModelException e) { + throw new FreemarkerRequestException("Error when wrapping an object setting the '" + key + "' attribute", e); + } + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/freemarker/extractor/package-info.java b/plugins/tiles/src/main/java/org/apache/tiles/request/freemarker/extractor/package-info.java new file mode 100644 index 000000000..8e94691d6 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/freemarker/extractor/package-info.java @@ -0,0 +1,24 @@ +/* + * $Id: package-info.java 1049711 2010-12-15 21:12:00Z apetrelli $ + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +/** + * Extractors to get information from Freemarker objects. + */ +package org.apache.tiles.request.freemarker.extractor; diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/freemarker/package-info.java b/plugins/tiles/src/main/java/org/apache/tiles/request/freemarker/package-info.java new file mode 100644 index 000000000..234a67c5b --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/freemarker/package-info.java @@ -0,0 +1,24 @@ +/* + * $Id: package-info.java 1049711 2010-12-15 21:12:00Z apetrelli $ + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +/** + * Support for Freemarker's Environment as a request. + */ +package org.apache.tiles.request.freemarker; diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/freemarker/servlet/SharedVariableFactory.java b/plugins/tiles/src/main/java/org/apache/tiles/request/freemarker/servlet/SharedVariableFactory.java new file mode 100644 index 000000000..18642640d --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/freemarker/servlet/SharedVariableFactory.java @@ -0,0 +1,34 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.request.freemarker.servlet; + +import freemarker.template.TemplateModel; + +/** + * It is an object that can create a shared variable, as a template model. + */ +public interface SharedVariableFactory { + + /** + * Creates a new shared variable. + * + * @return The shared variable. + */ + TemplateModel create(); +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/freemarker/servlet/WebappClassTemplateLoader.java b/plugins/tiles/src/main/java/org/apache/tiles/request/freemarker/servlet/WebappClassTemplateLoader.java new file mode 100644 index 000000000..5103903a5 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/freemarker/servlet/WebappClassTemplateLoader.java @@ -0,0 +1,81 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tiles.request.freemarker.servlet; + +import freemarker.cache.ClassTemplateLoader; +import freemarker.cache.TemplateLoader; +import freemarker.cache.WebappTemplateLoader; + +import javax.servlet.ServletContext; +import java.io.IOException; +import java.io.Reader; + +/** + * Delegates loading templates using a {@link WebappTemplateLoader} and, if not + * found, a {@link ClassTemplateLoader}. The resources are loaded from the + * webapp root and from the classpath root. + */ +public class WebappClassTemplateLoader implements TemplateLoader { + + /** + * The webapp template loader. + */ + private final WebappTemplateLoader webappTemplateLoader; + + /** + * The webapp template loader. + */ + private final ClassTemplateLoader classTemplateLoader; + + /** + * Constructor. + * + * @param servletContext The servlet context. + */ + public WebappClassTemplateLoader(ServletContext servletContext) { + webappTemplateLoader = new WebappTemplateLoader(servletContext); + classTemplateLoader = new ClassTemplateLoader(getClass(), "/"); + } + + /** {@inheritDoc} */ + public Object findTemplateSource(String name) throws IOException { + Object retValue = webappTemplateLoader.findTemplateSource(name); + if (retValue == null) { + retValue = classTemplateLoader.findTemplateSource(name); + } + return retValue; + } + + /** {@inheritDoc} */ + public void closeTemplateSource(Object templateSource) throws IOException { + webappTemplateLoader.closeTemplateSource(templateSource); + } + + /** {@inheritDoc} */ + public long getLastModified(Object templateSource) { + return webappTemplateLoader.getLastModified(templateSource); + } + + /** {@inheritDoc} */ + public Reader getReader(Object templateSource, String encoding) + throws IOException { + return webappTemplateLoader.getReader(templateSource, encoding); + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/freemarker/servlet/package-info.java b/plugins/tiles/src/main/java/org/apache/tiles/request/freemarker/servlet/package-info.java new file mode 100644 index 000000000..c93d7b0c7 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/freemarker/servlet/package-info.java @@ -0,0 +1,24 @@ +/* + * $Id: package-info.java 1049711 2010-12-15 21:12:00Z apetrelli $ + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +/** + * Servlets for easy addition of shared variables. + */ +package org.apache.tiles.request.freemarker.servlet; diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/jsp/JspPrintWriterAdapter.java b/plugins/tiles/src/main/java/org/apache/tiles/request/jsp/JspPrintWriterAdapter.java new file mode 100644 index 000000000..a7b2e2629 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/jsp/JspPrintWriterAdapter.java @@ -0,0 +1,432 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.request.jsp; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import javax.servlet.jsp.JspWriter; +import java.io.IOException; +import java.io.PrintWriter; + +/** + * Adapts a {@link JspWriter} to a {@link PrintWriter}, swallowing {@link IOException}. + */ +public class JspPrintWriterAdapter extends PrintWriter { + + /** + * The JSP writer. + */ + private final JspWriter writer; + + /** + * The logging object. + */ + private static final Logger LOG = LogManager.getLogger(JspPrintWriterAdapter.class); + + /** + * Constructor. + * + * @param writer The JSP writer. + */ + public JspPrintWriterAdapter(JspWriter writer) { + super(writer); + this.writer = writer; + } + + /** + * {@inheritDoc} + */ + @Override + public PrintWriter append(char c) { + try { + writer.append(c); + } catch (IOException e) { + LOG.error("Error when writing in JspWriter", e); + setError(); + } + return this; + } + + /** + * {@inheritDoc} + */ + @Override + public PrintWriter append(CharSequence csq, int start, int end) { + try { + writer.append(csq, start, end); + } catch (IOException e) { + LOG.error("Error when writing in JspWriter", e); + setError(); + } + return this; + } + + /** + * {@inheritDoc} + */ + @Override + public PrintWriter append(CharSequence csq) { + try { + writer.append(csq); + } catch (IOException e) { + LOG.error("Error when writing in JspWriter", e); + setError(); + } + return this; + } + + /** + * {@inheritDoc} + */ + @Override + public void close() { + try { + writer.close(); + } catch (IOException e) { + LOG.error("Error when writing in JspWriter", e); + setError(); + } + } + + /** + * {@inheritDoc} + */ + @Override + public void flush() { + try { + writer.flush(); + } catch (IOException e) { + LOG.error("Error when writing in JspWriter", e); + setError(); + } + } + + /** + * {@inheritDoc} + */ + @Override + public void print(boolean b) { + try { + writer.print(b); + } catch (IOException e) { + LOG.error("Error when writing in JspWriter", e); + setError(); + } + } + + /** + * {@inheritDoc} + */ + @Override + public void print(char c) { + try { + writer.print(c); + } catch (IOException e) { + LOG.error("Error when writing in JspWriter", e); + setError(); + } + } + + /** + * {@inheritDoc} + */ + @Override + public void print(char[] s) { + try { + writer.print(s); + } catch (IOException e) { + LOG.error("Error when writing in JspWriter", e); + setError(); + } + } + + /** + * {@inheritDoc} + */ + @Override + public void print(double d) { + try { + writer.print(d); + } catch (IOException e) { + LOG.error("Error when writing in JspWriter", e); + setError(); + } + } + + /** + * {@inheritDoc} + */ + @Override + public void print(float f) { + try { + writer.print(f); + } catch (IOException e) { + LOG.error("Error when writing in JspWriter", e); + setError(); + } + } + + /** + * {@inheritDoc} + */ + @Override + public void print(int i) { + try { + writer.print(i); + } catch (IOException e) { + LOG.error("Error when writing in JspWriter", e); + setError(); + } + } + + /** + * {@inheritDoc} + */ + @Override + public void print(long l) { + try { + writer.print(l); + } catch (IOException e) { + LOG.error("Error when writing in JspWriter", e); + setError(); + } + } + + /** + * {@inheritDoc} + */ + @Override + public void print(Object obj) { + try { + writer.print(obj); + } catch (IOException e) { + LOG.error("Error when writing in JspWriter", e); + setError(); + } + } + + /** + * {@inheritDoc} + */ + @Override + public void print(String s) { + try { + writer.print(s); + } catch (IOException e) { + LOG.error("Error when writing in JspWriter", e); + setError(); + } + } + + /** + * {@inheritDoc} + */ + @Override + public void println() { + try { + writer.println(); + } catch (IOException e) { + LOG.error("Error when writing in JspWriter", e); + setError(); + } + } + + /** + * {@inheritDoc} + */ + @Override + public void println(boolean x) { + try { + writer.println(x); + } catch (IOException e) { + LOG.error("Error when writing in JspWriter", e); + setError(); + } + } + + /** + * {@inheritDoc} + */ + @Override + public void println(char x) { + try { + writer.println(x); + } catch (IOException e) { + LOG.error("Error when writing in JspWriter", e); + setError(); + } + } + + /** + * {@inheritDoc} + */ + @Override + public void println(char[] x) { + try { + writer.println(x); + } catch (IOException e) { + LOG.error("Error when writing in JspWriter", e); + setError(); + } + } + + /** + * {@inheritDoc} + */ + @Override + public void println(double x) { + try { + writer.println(x); + } catch (IOException e) { + LOG.error("Error when writing in JspWriter", e); + setError(); + } + } + + /** + * {@inheritDoc} + */ + @Override + public void println(float x) { + try { + writer.println(x); + } catch (IOException e) { + LOG.error("Error when writing in JspWriter", e); + setError(); + } + } + + /** + * {@inheritDoc} + */ + @Override + public void println(int x) { + try { + writer.println(x); + } catch (IOException e) { + LOG.error("Error when writing in JspWriter", e); + setError(); + } + } + + /** + * {@inheritDoc} + */ + @Override + public void println(long x) { + try { + writer.println(x); + } catch (IOException e) { + LOG.error("Error when writing in JspWriter", e); + setError(); + } + } + + /** + * {@inheritDoc} + */ + @Override + public void println(Object x) { + try { + writer.println(x); + } catch (IOException e) { + LOG.error("Error when writing in JspWriter", e); + setError(); + } + } + + /** + * {@inheritDoc} + */ + @Override + public void println(String x) { + try { + writer.println(x); + } catch (IOException e) { + LOG.error("Error when writing in JspWriter", e); + setError(); + } + } + + /** + * {@inheritDoc} + */ + @Override + public void write(char[] buf, int off, int len) { + try { + writer.write(buf, off, len); + } catch (IOException e) { + LOG.error("Error when writing in JspWriter", e); + setError(); + } + } + + /** + * {@inheritDoc} + */ + @Override + public void write(char[] buf) { + try { + writer.write(buf); + } catch (IOException e) { + LOG.error("Error when writing in JspWriter", e); + setError(); + } + } + + /** + * {@inheritDoc} + */ + @Override + public void write(int c) { + try { + writer.write(c); + } catch (IOException e) { + LOG.error("Error when writing in JspWriter", e); + setError(); + } + } + + /** + * {@inheritDoc} + */ + @Override + public void write(String s, int off, int len) { + try { + writer.write(s, off, len); + } catch (IOException e) { + LOG.error("Error when writing in JspWriter", e); + setError(); + } + } + + /** + * {@inheritDoc} + */ + @Override + public void write(String s) { + try { + writer.write(s); + } catch (IOException e) { + LOG.error("Error when writing in JspWriter", e); + setError(); + } + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/jsp/JspRequest.java b/plugins/tiles/src/main/java/org/apache/tiles/request/jsp/JspRequest.java new file mode 100644 index 000000000..7e94e331e --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/jsp/JspRequest.java @@ -0,0 +1,199 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.request.jsp; + +import org.apache.tiles.request.AbstractViewRequest; +import org.apache.tiles.request.ApplicationContext; +import org.apache.tiles.request.DispatchRequest; +import org.apache.tiles.request.collection.ScopeMap; +import org.apache.tiles.request.jsp.extractor.ScopeExtractor; +import org.apache.tiles.request.jsp.extractor.SessionScopeExtractor; +import org.apache.tiles.request.servlet.ServletRequest; +import org.apache.tiles.request.servlet.ServletUtil; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.jsp.PageContext; +import java.io.IOException; +import java.io.PrintWriter; +import java.io.Writer; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +/** + * Context implementation used for executing tiles within a jsp tag library. + */ +public class JspRequest extends AbstractViewRequest { + + /** + * The native available scopes. + */ + private static final List SCOPES = Collections.unmodifiableList(Arrays.asList("page", REQUEST_SCOPE, "session", APPLICATION_SCOPE)); + + /** + * The current page context. + */ + private final PageContext pageContext; + + /** + *

The lazily instantiated Map of page scope + * attributes.

+ */ + private Map pageScope = null; + + /** + *

The lazily instantiated Map of request scope + * attributes.

+ */ + private Map requestScope = null; + + /** + *

The lazily instantiated Map of session scope + * attributes.

+ */ + private Map sessionScope = null; + + /** + *

The lazily instantiated Map of application scope + * attributes.

+ */ + private Map applicationScope = null; + + /** + * Creates a JSP request. + * + * @param applicationContext The application context. + * @param pageContext The page context. + * @return A new JSP request. + */ + public static JspRequest createServletJspRequest(ApplicationContext applicationContext, PageContext pageContext) { + return new JspRequest(new ServletRequest( + applicationContext, (HttpServletRequest) pageContext + .getRequest(), (HttpServletResponse) pageContext + .getResponse()), pageContext); + } + + /** + * Constructor. + * + * @param enclosedRequest The request that is wrapped here. + * @param pageContext The page context to use. + */ + public JspRequest(DispatchRequest enclosedRequest, + PageContext pageContext) { + super(enclosedRequest); + this.pageContext = pageContext; + } + + @Override + public List getAvailableScopes() { + return SCOPES; + } + + /** {@inheritDoc} */ + @Override + protected void doInclude(String path) throws IOException { + try { + pageContext.include(path, false); + } catch (ServletException e) { + throw ServletUtil.wrapServletException(e, "JSPException including path '" + + path + "'."); + } + } + + /** {@inheritDoc} */ + @Override + public PrintWriter getPrintWriter() { + return new JspPrintWriterAdapter(pageContext.getOut()); + } + + /** {@inheritDoc} */ + @Override + public Writer getWriter() { + return pageContext.getOut(); + } + + /** + * Returns the page scope. + * + * @return The page scope. + */ + public Map getPageScope() { + if ((pageScope == null) && (pageContext != null)) { + pageScope = new ScopeMap(new ScopeExtractor(pageContext, + PageContext.PAGE_SCOPE)); + } + return (pageScope); + } + + /** + * Returns the request scope. + * + * @return The request scope. + */ + public Map getRequestScope() { + if ((requestScope == null) && (pageContext != null)) { + requestScope = new ScopeMap(new ScopeExtractor(pageContext, + PageContext.REQUEST_SCOPE)); + } + return (requestScope); + } + + /** + * Returns the session scope. + * + * @return The session scope. + */ + public Map getSessionScope() { + if ((sessionScope == null) && (pageContext != null)) { + sessionScope = new ScopeMap(new SessionScopeExtractor(pageContext)); + } + return (sessionScope); + } + + /** + * Returns the application scope. + * + * @return The application scope. + */ + public Map getApplicationScope() { + if ((applicationScope == null) && (pageContext != null)) { + applicationScope = new ScopeMap(new ScopeExtractor(pageContext, + PageContext.APPLICATION_SCOPE)); + } + return (applicationScope); + } + + @Override + public Map getContext(String scope) { + if("page".equals(scope)){ + return getPageScope(); + }else if(REQUEST_SCOPE.equals(scope)){ + return getRequestScope(); + }else if("session".equals(scope)){ + return getSessionScope(); + }else if(APPLICATION_SCOPE.equals(scope)){ + return getApplicationScope(); + } + throw new IllegalArgumentException(scope + " does not exist. Call getAvailableScopes() first to check."); + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/jsp/JspUtil.java b/plugins/tiles/src/main/java/org/apache/tiles/request/jsp/JspUtil.java new file mode 100644 index 000000000..0a79145a0 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/jsp/JspUtil.java @@ -0,0 +1,52 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.request.jsp; + +import org.apache.tiles.request.ApplicationAccess; +import org.apache.tiles.request.ApplicationContext; + +import javax.servlet.jsp.JspContext; +import javax.servlet.jsp.PageContext; + +/** + * JSP utilities for JSP requests and related. + */ +public final class JspUtil { + + /** + * Constructor. + */ + private JspUtil() { + } + + /** + * Returns the application context. It must be + * first saved creating an {@link ApplicationContext} and using + * {@link ApplicationAccess#register(ApplicationContext)}. + * + * @param jspContext The JSP context. + * @return The application context. + */ + public static ApplicationContext getApplicationContext(JspContext jspContext) { + return (ApplicationContext) jspContext.getAttribute( + ApplicationAccess.APPLICATION_CONTEXT_ATTRIBUTE, + PageContext.APPLICATION_SCOPE + ); + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/jsp/autotag/JspAutotagRuntime.java b/plugins/tiles/src/main/java/org/apache/tiles/request/jsp/autotag/JspAutotagRuntime.java new file mode 100644 index 000000000..ac15efa7e --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/jsp/autotag/JspAutotagRuntime.java @@ -0,0 +1,69 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.request.jsp.autotag; + +import org.apache.tiles.autotag.core.runtime.AutotagRuntime; +import org.apache.tiles.autotag.core.runtime.ModelBody; +import org.apache.tiles.request.Request; +import org.apache.tiles.request.jsp.JspRequest; + +import javax.servlet.jsp.JspContext; +import javax.servlet.jsp.PageContext; +import javax.servlet.jsp.tagext.SimpleTagSupport; + +/** + * A Runtime for implementing JSP tag libraries. + */ +public class JspAutotagRuntime extends SimpleTagSupport implements AutotagRuntime { + + /** + * {@inheritDoc} + */ + @Override + public void doTag() { + // do nothing like the parent implementation, + // but don't throw exceptions either + } + + /** + * {@inheritDoc} + */ + @Override + public Request createRequest() { + JspContext pageContext = getJspContext(); + return JspRequest.createServletJspRequest(org.apache.tiles.request.jsp.JspUtil.getApplicationContext(pageContext), + (PageContext) pageContext); + } + + /** + * {@inheritDoc} + */ + @Override + public ModelBody createModelBody() { + return new JspModelBody(getJspBody(), getJspContext()); + } + + /** + * {@inheritDoc} + */ + @Override + public T getParameter(String name, Class type, T defaultValue) { + throw new UnsupportedOperationException("the parameters are injected into the tag itself, no need to fetch them"); + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/jsp/autotag/JspModelBody.java b/plugins/tiles/src/main/java/org/apache/tiles/request/jsp/autotag/JspModelBody.java new file mode 100644 index 000000000..ad9721575 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/jsp/autotag/JspModelBody.java @@ -0,0 +1,63 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.request.jsp.autotag; + +import org.apache.tiles.autotag.core.runtime.AbstractModelBody; + +import javax.servlet.jsp.JspContext; +import javax.servlet.jsp.JspException; +import javax.servlet.jsp.tagext.JspFragment; +import java.io.IOException; +import java.io.Writer; + +/** + * The body abstraction in a JSP tag. + */ +public class JspModelBody extends AbstractModelBody { + + /** + * The real body. + */ + private final JspFragment jspFragment; + + /** + * Constructor. + * + * @param jspFragment The real body. + * @param jspContext The page context. + */ + public JspModelBody(JspFragment jspFragment, JspContext jspContext) { + super(jspContext.getOut()); + this.jspFragment = jspFragment; + } + + @Override + public void evaluate(Writer writer) throws IOException { + if (jspFragment == null) { + return; + } + + try { + jspFragment.invoke(writer); + } catch (JspException e) { + throw new IOException("JspException when evaluating the body", e); + } + } + +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/jsp/autotag/package-info.java b/plugins/tiles/src/main/java/org/apache/tiles/request/jsp/autotag/package-info.java new file mode 100644 index 000000000..ce77fc427 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/jsp/autotag/package-info.java @@ -0,0 +1,22 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +/** + * Runtime part of Autotag support for JavaServer pages. + */ +package org.apache.tiles.request.jsp.autotag; diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/jsp/extractor/ScopeExtractor.java b/plugins/tiles/src/main/java/org/apache/tiles/request/jsp/extractor/ScopeExtractor.java new file mode 100644 index 000000000..e3485226a --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/jsp/extractor/ScopeExtractor.java @@ -0,0 +1,71 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.request.jsp.extractor; + +import org.apache.tiles.request.attribute.AttributeExtractor; + +import javax.servlet.jsp.JspContext; +import java.util.Enumeration; + +/** + * Extracts attributes from a numbered scope from {@link JspContext}. + */ +public class ScopeExtractor implements AttributeExtractor { + + /** + * The JSP context. + */ + private final JspContext context; + + /** + * The scope number to use. + */ + private final int scope; + + /** + * Constructor. + * + * @param context The JSP context. + * @param scope The scope number. + */ + public ScopeExtractor(JspContext context, int scope) { + this.context = context; + this.scope = scope; + } + + @Override + public void removeValue(String name) { + context.removeAttribute(name, scope); + } + + @Override + public Enumeration getKeys() { + return context.getAttributeNamesInScope(scope); + } + + @Override + public Object getValue(String key) { + return context.getAttribute(key, scope); + } + + @Override + public void setValue(String key, Object value) { + context.setAttribute(key, value, scope); + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/jsp/extractor/SessionScopeExtractor.java b/plugins/tiles/src/main/java/org/apache/tiles/request/jsp/extractor/SessionScopeExtractor.java new file mode 100644 index 000000000..73eec8df1 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/jsp/extractor/SessionScopeExtractor.java @@ -0,0 +1,76 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.request.jsp.extractor; + +import org.apache.tiles.request.attribute.AttributeExtractor; + +import javax.servlet.jsp.PageContext; +import java.util.Enumeration; + +/** + * Extracts attributes from session scope from {@link PageContext}. + */ +public class SessionScopeExtractor implements AttributeExtractor { + + /** + * The page context. + */ + private final PageContext context; + + /** + * Constructor. + * + * @param context The page context. + */ + public SessionScopeExtractor(PageContext context) { + this.context = context; + } + + @Override + public void removeValue(String name) { + if (context.getSession() == null) { + return; + } + context.removeAttribute(name, PageContext.SESSION_SCOPE); + } + + @Override + public Enumeration getKeys() { + if (context.getSession() == null) { + return null; + } + return context.getAttributeNamesInScope(PageContext.SESSION_SCOPE); + } + + @Override + public Object getValue(String key) { + if (context.getSession() == null) { + return null; + } + return context.getAttribute(key, PageContext.SESSION_SCOPE); + } + + @Override + public void setValue(String key, Object value) { + if (context.getSession() == null) { + return; + } + context.setAttribute(key, value, PageContext.SESSION_SCOPE); + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/jsp/extractor/package-info.java b/plugins/tiles/src/main/java/org/apache/tiles/request/jsp/extractor/package-info.java new file mode 100644 index 000000000..0e2d9cbbc --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/jsp/extractor/package-info.java @@ -0,0 +1,24 @@ +/* + * $Id: package-info.java 1049711 2010-12-15 21:12:00Z apetrelli $ + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +/** + * Extractors to get scopes from {@link javax.servlet.jsp.PageContext}. + */ +package org.apache.tiles.request.jsp.extractor; diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/jsp/package-info.java b/plugins/tiles/src/main/java/org/apache/tiles/request/jsp/package-info.java new file mode 100644 index 000000000..edf2b2128 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/jsp/package-info.java @@ -0,0 +1,24 @@ +/* + * $Id: package-info.java 1049711 2010-12-15 21:12:00Z apetrelli $ + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +/** + * Support of Tiles request in a JSP environment. + */ +package org.apache.tiles.request.jsp; diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/locale/LocaleUtil.java b/plugins/tiles/src/main/java/org/apache/tiles/request/locale/LocaleUtil.java new file mode 100644 index 000000000..0b3650480 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/locale/LocaleUtil.java @@ -0,0 +1,58 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.request.locale; + +import java.util.Locale; + +/** + * Utilities for locale manipulation. + */ +public final class LocaleUtil { + + /** + * Private constructor to avoid instantiation. + */ + private LocaleUtil() { + } + + /** + *

+ * Returns the "parent" locale of a given locale. If the original locale is only language-based, + * the {@link Locale#ROOT} object is returned. + *

+ * + * @param locale The original locale. + * @return The parent locale. + */ + public static Locale getParentLocale(Locale locale) { + Locale retValue = null; + String language = locale.getLanguage(); + String country = locale.getCountry(); + String variant = locale.getVariant(); + if (!"".equals(variant)) { + retValue = new Locale(language, country); + } else if (!"".equals(country)) { + retValue = new Locale(language); + } else if (!"".equals(language)) { + retValue = Locale.ROOT; + } + + return retValue; + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/locale/PostfixedApplicationResource.java b/plugins/tiles/src/main/java/org/apache/tiles/request/locale/PostfixedApplicationResource.java new file mode 100644 index 000000000..85c44745b --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/locale/PostfixedApplicationResource.java @@ -0,0 +1,235 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.request.locale; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.apache.tiles.request.ApplicationResource; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.Locale; +import java.util.Set; + +/** + * An ApplicationResource whose localization is managed by postfixing the file name. + * The various localizations are file sitting next to each other, with the locale identified in the postfix. + *

+ * For instance: + *

+ * /WEB-INF/tiles.xml
+ * /WEB-INF/tiles_fr.xml
+ * /WEB-INF/tiles_it.xml
+ * /WEB-INF/tiles_it_IT.xml
+ * 
+ * + * Two PostfixedApplicationResources are equals if they share the same localized path and the same class. + */ +public abstract class PostfixedApplicationResource implements ApplicationResource { + + private static final Logger LOG = LogManager.getLogger(PostfixedApplicationResource.class); + + /** The path without its suffix and its locale postfix. */ + private String pathPrefix; + /** The suffix. */ + private final String suffix; + /** The Locale. */ + private final Locale locale; + + /** + * Create a new PostfixedApplicationResource for the specified path. + * @param localePath the path including localization. + */ + protected PostfixedApplicationResource(String localePath) { + int prefixIndex = localePath.indexOf('_', localePath.lastIndexOf("/")); + int suffixIndex = localePath.lastIndexOf('.'); + if (suffixIndex < 0) { + suffix = ""; + suffixIndex = localePath.length(); + } else { + suffix = localePath.substring(suffixIndex); + } + if (prefixIndex < 0) { + pathPrefix = localePath.substring(0, suffixIndex); + locale = Locale.ROOT; + } else { + pathPrefix = localePath.substring(0, prefixIndex); + String localeString = localePath.substring(prefixIndex + 1, suffixIndex); + Locale found = localeFrom(localeString); + locale = validateLocale(found); + if (Locale.ROOT.equals(locale)) { + pathPrefix = localePath.substring(0, suffixIndex); + + LOG.warn("No supported matching language for locale \"" + localeString + "\". Using " + + getPath() + " as a non-localized resource path. see TILES-571"); + + } else if (!localeString.equalsIgnoreCase(getPostfix(locale).substring(1))) { + LOG.warn("For resource " + localePath + + " the closest supported matching locale to \"" + localeString + "\" is \"" + locale + + "\". Using " + getPath() + " as resource path. see TILES-571"); + } + } + } + + /** + * Create a new PostfixedApplicationResource for the specified path. + * @param path the path excluding localization. + * @param locale the Locale. + */ + protected PostfixedApplicationResource(String path, Locale locale) { + int suffixIndex = path.lastIndexOf('.'); + if (suffixIndex < 0) { + suffix = ""; + pathPrefix = path; + } else { + pathPrefix = path.substring(0, suffixIndex); + suffix = path.substring(suffixIndex); + } + this.locale = locale; + } + + /** {@inheritDoc} */ + @Override + public final String getLocalePath() { + return getLocalePath(locale); + } + + /** {@inheritDoc} */ + @Override + public final String getPath() { + return pathPrefix + suffix; + } + + /** {@inheritDoc} */ + @Override + public final String getLocalePath(Locale newLocale) { + return pathPrefix + getPostfix(newLocale) + suffix; + } + + /** + * Get the postfix for that Locale. + * @param locale a locale. + * @return the matching postfix. + */ + private static String getPostfix(Locale locale) { + if (locale == null) { + return ""; + } + + StringBuilder builder = new StringBuilder(); + String language = locale.getLanguage(); + String country = locale.getCountry(); + String variant = locale.getVariant(); + if (!"".equals(language)) { + builder.append("_"); + builder.append(language); + if (!"".equals(country)) { + builder.append("_"); + builder.append(country); + if (!"".equals(variant)) { + builder.append("_"); + builder.append(variant); + } + } + } + return builder.toString(); + } + + /** {@inheritDoc} */ + @Override + public final Locale getLocale() { + return locale; + } + + /** {@inheritDoc} */ + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((locale == null) ? 0 : locale.hashCode()); + result = prime * result + ((pathPrefix == null) ? 0 : pathPrefix.hashCode()); + result = prime * result + ((suffix == null) ? 0 : suffix.hashCode()); + return result; + } + + /** {@inheritDoc} */ + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + PostfixedApplicationResource other = (PostfixedApplicationResource) obj; + if (locale == null) { + if (other.locale != null) + return false; + } else if (!locale.equals(other.locale)) + return false; + if (pathPrefix == null) { + if (other.pathPrefix != null) + return false; + } else if (!pathPrefix.equals(other.pathPrefix)) + return false; + if (suffix == null) { + return other.suffix == null; + } else return suffix.equals(other.suffix); + } + + private static Locale localeFrom(String localeString) { + Locale result; + int countryIndex = localeString.indexOf('_'); + if (countryIndex < 0) { + result = new Locale(localeString); + } else { + int variantIndex = localeString.indexOf('_', countryIndex + 1); + if (variantIndex < 0) { + result = new Locale( + localeString.substring(0, countryIndex), + localeString.substring(countryIndex + 1)); + } else { + result = new Locale( + localeString.substring(0, countryIndex), + localeString.substring(countryIndex + 1, variantIndex), + localeString.substring(variantIndex + 1)); + } + } + return result; + } + + private static final Set availableLocales = new HashSet<>(Arrays.asList(Locale.getAvailableLocales())); + + private static Locale validateLocale(Locale locale) { + Locale withoutVariant = locale.getVariant().isEmpty() + ? locale + : new Locale(locale.getLanguage(), locale.getCountry()); + + Locale result = locale; + if (!availableLocales.contains(withoutVariant)) { + if (!result.getCountry().isEmpty()) { + result = new Locale(result.getLanguage()); + } + if (!availableLocales.contains(result)) { + result = Locale.ROOT; + } + } + return result; + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/locale/URLApplicationResource.java b/plugins/tiles/src/main/java/org/apache/tiles/request/locale/URLApplicationResource.java new file mode 100644 index 000000000..a4e71a818 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/locale/URLApplicationResource.java @@ -0,0 +1,213 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.request.locale; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.net.JarURLConnection; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.URL; +import java.net.URLConnection; +import java.nio.file.Files; +import java.util.Collections; +import java.util.HashSet; +import java.util.Locale; +import java.util.Set; + +/** + * A {@link PostfixedApplicationResource} that can be accessed through a URL. + */ + +public class URLApplicationResource extends PostfixedApplicationResource { + /** + * System parameter to specify additional remote protocols. If an url has a remote protocol, then any + * {@link IOException} will be thrown directly. If an url has a local protocol, then any {@link IOException} + * will be caught and transformed into a {@link FileNotFoundException}. + */ + static final String REMOTE_PROTOCOLS_PROPERTY = "tiles.remoteProtocols"; + + private static final Logger LOG = LogManager.getLogger(URLApplicationResource.class); + + private static final Set REMOTE_PROTOCOLS; + + static { + REMOTE_PROTOCOLS = initRemoteProtocols(); + } + + /** + * Creates an unmodifiable set of remote protocols which are used in {@link URL} objects, see {@link URL#getProtocol()}. + * AN url with a remote protocol establishes a network connection when its {@link URL#openConnection()} is being called. + * The set will always contain the built-in remote protocols below: + * + * It's possible, that your environment provides additional remote protocols because of following reasons: + *
    + *
  • your application server adds more remote protocols, see its documentation for further details.
  • + *
  • your application supplies custom remote protocols trough its own {@link java.net.URLStreamHandlerFactory} + * (see following excellent explanation + * for getting an idea how to do this)
  • + *
+ * If you need to use such extra remote protocols in Tiles, you may enhance the set via system property {@code tiles.remoteProtocols}. Suppose + * you need to add your custom remote protocols "foo" and "bar". To do so, add following parameter to the command line (use ";" as separator): + *
+     *     -Dtiles.remoteProtocols=foo;bar
+     * 
+ * The resulting set will then contain the built-in protocols plus "foo" and "bar". + * + * @return Unmodifiable set of remote protocols, never {@code null} + */ + static Set initRemoteProtocols() { + Set remoteProtocols = new HashSet<>(); + remoteProtocols.add("ftp"); + remoteProtocols.add("http"); + remoteProtocols.add("https"); + + String protocolsProp = System.getProperty(REMOTE_PROTOCOLS_PROPERTY); + if (protocolsProp != null) { + for (String protocol : protocolsProp.split(";")) { + remoteProtocols.add(protocol.trim()); + } + } + return Collections.unmodifiableSet(remoteProtocols); + } + + private boolean isLocal(URL url) { + return !REMOTE_PROTOCOLS.contains(url.getProtocol()); + } + + /** + * the URL where the contents can be found. + */ + private final URL url; + /** + * if the URL matches a file, this is the file. + */ + private File file; + /** + * if the URL points to a local resource + */ + private final boolean local; + + /** + * Creates a URLApplicationResource for the specified path that can be accessed through the specified URL. + * + * @param localePath the path including localization. + * @param url the URL where the contents can be found. + */ + public URLApplicationResource(String localePath, URL url) { + super(localePath); + this.url = url; + if ("file".equals(url.getProtocol())) { + file = getFile(url); + } + local = isLocal(url); + } + + /** + * Creates a URLApplicationResource for the specified path that can be accessed through the specified URL. + * + * @param path the path excluding localization. + * @param locale the Locale. + * @param url the URL where the contents can be found. + */ + public URLApplicationResource(String path, Locale locale, URL url) { + super(path, locale); + this.url = url; + if ("file".equals(url.getProtocol())) { + file = getFile(url); + } + local = isLocal(url); + } + + private URLConnection openConnection() throws IOException { + try { + return url.openConnection(); + } catch (IOException e) { + // If the url points to a local resource, but it cannot be + // opened, then the resource actually does not exist. In this + // case throw a FileNotFoundException + if (local) { + FileNotFoundException fne = new FileNotFoundException(url.toString()); + fne.initCause(e); + throw fne; + } + throw e; + } + } + + private File getFile(URL url) { + try { + return new File(new URI(url.toExternalForm()).getSchemeSpecificPart()); + } catch (URISyntaxException e) { + LOG.debug("Cannot translate URL to file name, expect a performance impact", e); + return null; + } + } + + /** + * {@inheritDoc} + */ + @Override + public InputStream getInputStream() throws IOException { + if (file != null) { + if (file.exists()) { + return Files.newInputStream(file.toPath()); + } else { + throw new FileNotFoundException("File does not exist: " + file); + } + } else { + return openConnection().getInputStream(); + } + } + + /** + * {@inheritDoc} + */ + @Override + public long getLastModified() throws IOException { + if (file != null) { + return file.lastModified(); + } else { + URLConnection connection = openConnection(); + if (connection instanceof JarURLConnection) { + return ((JarURLConnection) connection).getJarEntry().getTime(); + } else { + return connection.getLastModified(); + } + } + } + + /** + * {@inheritDoc} + */ + @Override + public String toString() { + return "Resource " + getLocalePath() + " at " + url.toString(); + } + +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/reflect/CannotInstantiateObjectException.java b/plugins/tiles/src/main/java/org/apache/tiles/request/reflect/CannotInstantiateObjectException.java new file mode 100644 index 000000000..7b922fd8f --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/reflect/CannotInstantiateObjectException.java @@ -0,0 +1,38 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.request.reflect; + +import org.apache.tiles.request.RequestException; + +/** + * Indicates that an object cannot be instantiated. + */ +public class CannotInstantiateObjectException extends RequestException { + + /** + * Constructor. + * + * @param message The detail message. + * @param e The exception to be wrapped. + */ + public CannotInstantiateObjectException(String message, Throwable e) { + super(message, e); + } + +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/reflect/ClassUtil.java b/plugins/tiles/src/main/java/org/apache/tiles/request/reflect/ClassUtil.java new file mode 100644 index 000000000..8211b3ac6 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/reflect/ClassUtil.java @@ -0,0 +1,123 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.request.reflect; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import java.beans.BeanInfo; +import java.beans.Introspector; +import java.beans.PropertyDescriptor; +import java.util.Map; + +/** + * Utilities to work with dynamic class loading and instantiation. + */ +public final class ClassUtil { + + private static final Logger LOG = LogManager.getLogger(ClassUtil.class); + + /** + * Constructor, private to avoid instantiation. + */ + private ClassUtil() { + } + + /** + * Returns the class and casts it to the correct subclass.
+ * It tries to use the thread's current classloader first and, if it does + * not succeed, uses the classloader of ClassUtil. + * + * @param The subclass to use. + * @param className The name of the class to load. + * @param baseClass The base class to subclass to. + * @return The loaded class. + * @throws ClassNotFoundException If the class has not been found. + */ + public static Class getClass(String className, Class baseClass) throws ClassNotFoundException { + ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); + if (classLoader == null) { + classLoader = ClassUtil.class.getClassLoader(); + } + return Class.forName(className, true, classLoader).asSubclass(baseClass); + } + + /** + * Returns an instance of the given class name, by calling the default + * constructor. + * + * @param className The class name to load and to instantiate. + * @return The new instance of the class name. + * @throws CannotInstantiateObjectException If something goes wrong during + * instantiation. + */ + public static Object instantiate(String className) { + return instantiate(className, false); + } + + /** + * Returns an instance of the given class name, by calling the default + * constructor. + * + * @param className The class name to load and to instantiate. + * @param returnNull If true, if the class is not found it + * returns true, otherwise it throws a + * TilesException. + * @return The new instance of the class name. + * @throws CannotInstantiateObjectException If something goes wrong during instantiation. + */ + public static Object instantiate(String className, boolean returnNull) { + try { + Class namedClass = getClass(className, Object.class); + return namedClass.newInstance(); + } catch (ClassNotFoundException e) { + if (returnNull) { + return null; + } + throw new CannotInstantiateObjectException("Unable to resolve factory class: '" + className + "'", e); + } catch (IllegalAccessException e) { + throw new CannotInstantiateObjectException("Unable to access factory class: '" + className + "'", e); + } catch (InstantiationException e) { + throw new CannotInstantiateObjectException("Unable to instantiate factory class: '" + className + "'. Make sure that this class has a default constructor", e); + } + } + + /** + * Collects bean infos from a class and filling a list. + * + * @param clazz The class to be inspected. + * @param name2descriptor The map in the form: name of the property -> descriptor. + */ + public static void collectBeanInfo(Class clazz, Map name2descriptor) { + BeanInfo info = null; + try { + info = Introspector.getBeanInfo(clazz); + } catch (Exception ex) { + LOG.debug("Cannot inspect class " + clazz, ex); + } + if (info == null) { + return; + } + for (PropertyDescriptor pd : info.getPropertyDescriptors()) { + pd.setValue("type", pd.getPropertyType()); + pd.setValue("resolvableAtDesignTime", Boolean.TRUE); + name2descriptor.put(pd.getName(), pd); + } + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/reflect/package-info.java b/plugins/tiles/src/main/java/org/apache/tiles/request/reflect/package-info.java new file mode 100644 index 000000000..c7b0d3cdc --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/reflect/package-info.java @@ -0,0 +1,22 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +/** + * Utilities to work with dynamic class loading and instantiation. + */ +package org.apache.tiles.request.reflect; diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/render/BasicRendererFactory.java b/plugins/tiles/src/main/java/org/apache/tiles/request/render/BasicRendererFactory.java new file mode 100644 index 000000000..eb6b00fdf --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/render/BasicRendererFactory.java @@ -0,0 +1,79 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.request.render; + +import java.util.HashMap; +import java.util.Map; + +/** + * Basic renderer factory implementation. + */ +public class BasicRendererFactory implements RendererFactory { + + /** + * The renderer name/renderer map. + */ + protected Map renderers; + + /** + * The default renderer. + */ + protected Renderer defaultRenderer; + + /** + * Constructor. + */ + public BasicRendererFactory() { + renderers = new HashMap<>(); + } + + /** {@inheritDoc} */ + public Renderer getRenderer(String name) { + Renderer retValue; + if (name != null) { + retValue = renderers.get(name); + if (retValue == null) { + throw new NoSuchRendererException("Cannot find a renderer named '" + name + "'"); + } + } else { + retValue = defaultRenderer; + } + + return retValue; + } + + /** + * Sets the default renderer. + * + * @param renderer The default renderer. + */ + public void setDefaultRenderer(Renderer renderer) { + this.defaultRenderer = renderer; + } + + /** + * Registers a renderer. + * + * @param name The name of the renderer. + * @param renderer The renderer to register. + */ + public void registerRenderer(String name, Renderer renderer) { + renderers.put(name, renderer); + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/render/CannotRenderException.java b/plugins/tiles/src/main/java/org/apache/tiles/request/render/CannotRenderException.java new file mode 100644 index 000000000..d2c5e39f8 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/render/CannotRenderException.java @@ -0,0 +1,46 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.request.render; + + +/** + * Indicates that something went wrong during the rendering process. + */ +public class CannotRenderException extends RenderException { + + /** + * Constructor. + * + * @param message The detail message. + */ + public CannotRenderException(String message) { + super(message); + } + + /** + * Constructor. + * + * @param message The detail message. + * @param e The exception to be wrapped. + */ + public CannotRenderException(String message, Throwable e) { + super(message, e); + } + +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/render/ChainedDelegateRenderer.java b/plugins/tiles/src/main/java/org/apache/tiles/request/render/ChainedDelegateRenderer.java new file mode 100644 index 000000000..ff0bdc136 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/render/ChainedDelegateRenderer.java @@ -0,0 +1,80 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.request.render; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import org.apache.tiles.request.Request; + +/** + * Renders an attribute that has no associated renderer using delegation to other renderers. + */ +public class ChainedDelegateRenderer implements Renderer { + + /** + * The list of chained renderers. + */ + private final List renderers; + + /** + * Constructor. + */ + public ChainedDelegateRenderer() { + renderers = new ArrayList<>(); + } + + /** + * Adds an attribute renderer to the list. The first inserted this way, the + * first is checked when rendering. + * + * @param renderer The renderer to add. + */ + public void addAttributeRenderer(Renderer renderer) { + renderers.add(renderer); + } + + + @Override + public void render(String value, Request request) throws IOException { + if (value == null) { + throw new NullPointerException("The attribute value is null"); + } + + for (Renderer renderer : renderers) { + if (renderer.isRenderable(value, request)) { + renderer.render(value, request); + return; + } + } + + throw new CannotRenderException("Cannot renderer value '" + value + "'"); + } + + /** {@inheritDoc} */ + public boolean isRenderable(String value, Request request) { + for (Renderer renderer : renderers) { + if (renderer.isRenderable(value, request)) { + return true; + } + } + return false; + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/render/DispatchRenderer.java b/plugins/tiles/src/main/java/org/apache/tiles/request/render/DispatchRenderer.java new file mode 100644 index 000000000..b1db6a09e --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/render/DispatchRenderer.java @@ -0,0 +1,61 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.request.render; + +import java.io.IOException; + +import org.apache.tiles.request.Request; +import org.apache.tiles.request.DispatchRequest; +import org.apache.tiles.request.RequestWrapper; + +/** + * Renders an attribute that contains a reference to a template. + */ +public class DispatchRenderer implements Renderer { + + /** {@inheritDoc} */ + @Override + public void render(String path, Request request) throws IOException { + if (path == null) { + throw new CannotRenderException("Cannot dispatch a null path"); + } + DispatchRequest dispatchRequest = getDispatchRequest(request); + if (dispatchRequest == null) { + throw new CannotRenderException("Cannot dispatch outside of a web environment"); + } + + dispatchRequest.dispatch(path); + } + + /** {@inheritDoc} */ + public boolean isRenderable(String path, Request request) { + return path != null && getDispatchRequest(request) != null && path.startsWith("/"); + } + + private DispatchRequest getDispatchRequest(Request request) { + Request result = request; + while (!(result instanceof DispatchRequest) && result instanceof RequestWrapper) { + result = ((RequestWrapper) result).getWrappedRequest(); + } + if (!(result instanceof DispatchRequest)) { + result = null; + } + return (DispatchRequest) result; + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/render/NoSuchRendererException.java b/plugins/tiles/src/main/java/org/apache/tiles/request/render/NoSuchRendererException.java new file mode 100644 index 000000000..f3a71983f --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/render/NoSuchRendererException.java @@ -0,0 +1,35 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.request.render; + +/** + * It is raised when a named renderer has not been found with that name. + */ +public class NoSuchRendererException extends RenderException { + + /** + * Constructor. + * + * @param message The detail message. + */ + public NoSuchRendererException(String message) { + super(message); + } + +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/render/RenderException.java b/plugins/tiles/src/main/java/org/apache/tiles/request/render/RenderException.java new file mode 100644 index 000000000..f99ee6024 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/render/RenderException.java @@ -0,0 +1,46 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.request.render; + +import org.apache.tiles.request.RequestException; + +/** + * Thrown when rendering fails. + */ +public class RenderException extends RequestException { + + /** + * Constructor. + * + * @param message The message of the exception. + */ + public RenderException(String message) { + super(message); + } + + /** + * Constructor. + * + * @param message The message of the exception. + * @param cause The cause. + */ + public RenderException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/render/Renderer.java b/plugins/tiles/src/main/java/org/apache/tiles/request/render/Renderer.java new file mode 100644 index 000000000..076837240 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/render/Renderer.java @@ -0,0 +1,48 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.request.render; + +import org.apache.tiles.request.Request; + +import java.io.IOException; + +/** + * An object that can render a path, depending on the request passed as a parameter. + */ +public interface Renderer { + + /** + * Renders a path. + * + * @param path The path to render. + * @param request The Tiles request context. + * @throws IOException If something goes wrong during rendition. + */ + void render(String path, Request request) throws IOException; + + /** + * Checks if this renderer can render a path. Note that this does not mean + * it is the best renderer available, but checks only its capability. + * + * @param path The path to be rendered. + * @param request The request context. + * @return true if this renderer can render the attribute. + */ + boolean isRenderable(String path, Request request); +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/render/RendererFactory.java b/plugins/tiles/src/main/java/org/apache/tiles/request/render/RendererFactory.java new file mode 100644 index 000000000..7119d6455 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/render/RendererFactory.java @@ -0,0 +1,41 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.request.render; + +/** + *

+ * Factory interface used to create/retrieve instances of the {@link Renderer} interface. + *

+ * + *

+ * This factory provides an extension point into the default tiles + * implementation. Implementors wishing to provide per request initialization of + * the AttributeRenderer (for instance) may provide a custom renderer. + *

+ */ +public interface RendererFactory { + + /** + * Returns a renderer by its name. + * + * @param name The name of the renderer. + * @return The renderer. + */ + Renderer getRenderer(String name); +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/render/StringRenderer.java b/plugins/tiles/src/main/java/org/apache/tiles/request/render/StringRenderer.java new file mode 100644 index 000000000..309546a2f --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/render/StringRenderer.java @@ -0,0 +1,43 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.request.render; + +import java.io.IOException; + +import org.apache.tiles.request.Request; + +/** + * Renders an attribute that contains a string. + */ +public class StringRenderer implements Renderer { + + /** {@inheritDoc} */ + @Override + public void render(String value, Request request) throws IOException { + if (value == null) { + throw new CannotRenderException("Cannot render a null string"); + } + request.getWriter().write(value); + } + + /** {@inheritDoc} */ + public boolean isRenderable(String value, Request request) { + return value != null; + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/servlet/ExternalWriterHttpServletResponse.java b/plugins/tiles/src/main/java/org/apache/tiles/request/servlet/ExternalWriterHttpServletResponse.java new file mode 100644 index 000000000..492530e7e --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/servlet/ExternalWriterHttpServletResponse.java @@ -0,0 +1,58 @@ +/* + * $Id: ExternalWriterHttpServletResponse.java 1306435 2012-03-28 15:39:11Z nlebas $ + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tiles.request.servlet; + +import java.io.PrintWriter; + +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpServletResponseWrapper; + +/** + * Wraps an HTTP response and overrides its print writer. + * + * @version $Rev: 1306435 $ $Date: 2012-03-29 02:39:11 +1100 (Thu, 29 Mar 2012) $ + */ +public class ExternalWriterHttpServletResponse extends + HttpServletResponseWrapper { + + /** + * The print writer to use, instead of the response's one. + */ + private PrintWriter writer; + + /** + * Constructor. + * + * @param response The response to wrap. + * @param writer The print writer to use, instead of the response's one. + */ + public ExternalWriterHttpServletResponse(HttpServletResponse response, PrintWriter writer) { + super(response); + this.writer = writer; + } + + /** {@inheritDoc} */ + @Override + public PrintWriter getWriter() { + return writer; + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/servlet/NotAServletEnvironmentException.java b/plugins/tiles/src/main/java/org/apache/tiles/request/servlet/NotAServletEnvironmentException.java new file mode 100644 index 000000000..ce4bf5471 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/servlet/NotAServletEnvironmentException.java @@ -0,0 +1,36 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.request.servlet; + +/** + * Exception that indicates that a resource could not be used because it is not + * in a servlet environment. + */ +public class NotAServletEnvironmentException extends RuntimeException { + + /** + * Constructor. + * + * @param message The detail message. + */ + public NotAServletEnvironmentException(String message) { + super(message); + } + +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/servlet/ServletApplicationContext.java b/plugins/tiles/src/main/java/org/apache/tiles/request/servlet/ServletApplicationContext.java new file mode 100644 index 000000000..27f2b0e63 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/servlet/ServletApplicationContext.java @@ -0,0 +1,127 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.request.servlet; + +import org.apache.tiles.request.ApplicationContext; +import org.apache.tiles.request.ApplicationResource; +import org.apache.tiles.request.collection.ReadOnlyEnumerationMap; +import org.apache.tiles.request.collection.ScopeMap; +import org.apache.tiles.request.locale.URLApplicationResource; +import org.apache.tiles.request.servlet.extractor.ApplicationScopeExtractor; +import org.apache.tiles.request.servlet.extractor.InitParameterExtractor; + +import javax.servlet.ServletContext; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Locale; +import java.util.Map; + +/** + * Servlet-based implementation of the TilesApplicationContext interface. + */ +public class ServletApplicationContext implements ApplicationContext { + + /** + * The servlet context to use. + */ + private final ServletContext servletContext; + + /** + *

The lazily instantiated Map of application scope + * attributes.

+ */ + private Map applicationScope = null; + + /** + *

The lazily instantiated Map of context initialization + * parameters.

+ */ + private Map initParam = null; + + /** + * Creates a new instance of ServletTilesApplicationContext. + * + * @param servletContext The servlet context to use. + */ + public ServletApplicationContext(ServletContext servletContext) { + this.servletContext = servletContext; + } + + /** {@inheritDoc} */ + public Object getContext() { + return servletContext; + } + + /** {@inheritDoc} */ + public Map getApplicationScope() { + + if ((applicationScope == null) && (servletContext != null)) { + applicationScope = new ScopeMap(new ApplicationScopeExtractor(servletContext)); + } + return (applicationScope); + + } + + /** {@inheritDoc} */ + public Map getInitParams() { + + if ((initParam == null) && (servletContext != null)) { + initParam = new ReadOnlyEnumerationMap<>(new InitParameterExtractor(servletContext)); + } + return (initParam); + + } + + /** {@inheritDoc} */ + public ApplicationResource getResource(String localePath) { + try { + URL url = servletContext.getResource(localePath); + if (url != null) { + return new URLApplicationResource(localePath, url); + } else { + return null; + } + } catch (MalformedURLException e) { + return null; + } + } + + /** {@inheritDoc} */ + public ApplicationResource getResource(ApplicationResource base, Locale locale) { + try { + URL url = servletContext.getResource(base.getLocalePath(locale)); + if (url != null) { + return new URLApplicationResource(base.getPath(), locale, url); + } else { + return null; + } + } catch (MalformedURLException e) { + return null; + } + } + + /** {@inheritDoc} */ + public Collection getResources(String path) { + ArrayList resources = new ArrayList<>(); + resources.add(getResource(path)); + return resources; + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/servlet/ServletRequest.java b/plugins/tiles/src/main/java/org/apache/tiles/request/servlet/ServletRequest.java new file mode 100644 index 000000000..a21a025d4 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/servlet/ServletRequest.java @@ -0,0 +1,343 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.request.servlet; + +import org.apache.tiles.request.AbstractClientRequest; +import org.apache.tiles.request.ApplicationContext; +import org.apache.tiles.request.attribute.Addable; +import org.apache.tiles.request.collection.HeaderValuesMap; +import org.apache.tiles.request.collection.ReadOnlyEnumerationMap; +import org.apache.tiles.request.collection.ScopeMap; +import org.apache.tiles.request.servlet.extractor.HeaderExtractor; +import org.apache.tiles.request.servlet.extractor.ParameterExtractor; +import org.apache.tiles.request.servlet.extractor.RequestScopeExtractor; +import org.apache.tiles.request.servlet.extractor.SessionScopeExtractor; + +import javax.servlet.RequestDispatcher; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.io.OutputStream; +import java.io.PrintWriter; +import java.io.Writer; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Locale; +import java.util.Map; + +/** + * Servlet-based implementation of the TilesApplicationContext interface. + */ +public class ServletRequest extends AbstractClientRequest { + + /** + * The native available scopes: request, session and application. + */ + private static final List SCOPES = Collections.unmodifiableList(Arrays.asList(REQUEST_SCOPE, "session", APPLICATION_SCOPE)); + + /** + * The request object to use. + */ + private final HttpServletRequest request; + + /** + * The response object to use. + */ + private final HttpServletResponse response; + + /** + * The response output stream, lazily initialized. + */ + private OutputStream outputStream; + + /** + * The response writer, lazily initialized. + */ + private PrintWriter writer; + + /** + *

The lazily instantiated Map of header name-value + * combinations (immutable).

+ */ + private Map header = null; + + /** + *

The lazily instantiated Map of header name-value + * combinations (write-only).

+ */ + private Addable responseHeaders = null; + + + /** + *

The lazily instantiated Map of header name-values + * combinations (immutable).

+ */ + private Map headerValues = null; + + + /** + *

The lazily instantiated Map of request + * parameter name-value.

+ */ + private Map param = null; + + + /** + *

The lazily instantiated Map of request scope + * attributes.

+ */ + private Map requestScope = null; + + /** + *

The lazily instantiated Map of session scope + * attributes.

+ */ + private Map sessionScope = null; + + + /** + * Creates a new instance of ServletTilesRequestContext. + * + * @param applicationContext The application context. + * @param request The request object. + * @param response The response object. + */ + public ServletRequest(ApplicationContext applicationContext, HttpServletRequest request, HttpServletResponse response) { + super(applicationContext); + this.request = request; + this.response = response; + } + + /** + * {@inheritDoc} + */ + public Map getHeader() { + + if ((header == null) && (request != null)) { + header = new ReadOnlyEnumerationMap<>(new HeaderExtractor(request, null)); + } + return (header); + + } + + /** + * {@inheritDoc} + */ + public Addable getResponseHeaders() { + + if ((responseHeaders == null) && (response != null)) { + responseHeaders = new HeaderExtractor(null, response); + } + return (responseHeaders); + + } + + /** + * {@inheritDoc} + */ + public Map getHeaderValues() { + + if ((headerValues == null) && (request != null)) { + headerValues = new HeaderValuesMap(new HeaderExtractor(request, response)); + } + return (headerValues); + + } + + + /** + * {@inheritDoc} + */ + public Map getParam() { + + if ((param == null) && (request != null)) { + param = new ReadOnlyEnumerationMap<>(new ParameterExtractor(request)); + } + return (param); + + } + + + /** + * {@inheritDoc} + */ + public Map getParamValues() { + return request.getParameterMap(); + } + + @Override + public Map getContext(String scope) { + if (REQUEST_SCOPE.equals(scope)) { + return getRequestScope(); + } else if ("session".equals(scope)) { + return getSessionScope(); + } else if (APPLICATION_SCOPE.equals(scope)) { + return getApplicationScope(); + } + throw new IllegalArgumentException(scope + " does not exist. Call getAvailableScopes() first to check."); + } + + /** + * {@inheritDoc} + */ + public Map getRequestScope() { + + if ((requestScope == null) && (request != null)) { + requestScope = new ScopeMap(new RequestScopeExtractor(request)); + } + return (requestScope); + + } + + + /** + * {@inheritDoc} + */ + public Map getSessionScope() { + + if ((sessionScope == null) && (request != null)) { + sessionScope = new ScopeMap(new SessionScopeExtractor(request)); + } + return (sessionScope); + + } + + @Override + public List getAvailableScopes() { + return SCOPES; + } + + /** + * {@inheritDoc} + */ + public void doForward(String path) throws IOException { + if (response.isCommitted()) { + doInclude(path); + } else { + forward(path); + } + } + + + /** + * {@inheritDoc} + */ + public void doInclude(String path) throws IOException { + RequestDispatcher rd = request.getRequestDispatcher(path); + + if (rd == null) { + throw new IOException("No request dispatcher returned for path '" + + path + "'"); + } + + try { + rd.include(request, response); + } catch (ServletException ex) { + throw ServletUtil.wrapServletException(ex, "ServletException including path '" + + path + "'."); + } + } + + /** + * Forwards to a path. + * + * @param path The path to forward to. + * @throws IOException If something goes wrong during the operation. + */ + private void forward(String path) throws IOException { + RequestDispatcher rd = request.getRequestDispatcher(path); + + if (rd == null) { + throw new IOException("No request dispatcher returned for path '" + + path + "'"); + } + + try { + rd.forward(request, response); + } catch (ServletException ex) { + throw ServletUtil.wrapServletException(ex, "ServletException including path '" + + path + "'."); + } + } + + /** + * {@inheritDoc} + */ + public OutputStream getOutputStream() throws IOException { + if (outputStream == null) { + outputStream = response.getOutputStream(); + } + return outputStream; + } + + /** + * {@inheritDoc} + */ + public Writer getWriter() throws IOException { + return getPrintWriter(); + } + + /** + * {@inheritDoc} + */ + public PrintWriter getPrintWriter() throws IOException { + if (writer == null) { + writer = response.getWriter(); + } + return writer; + } + + /** + * {@inheritDoc} + */ + public boolean isResponseCommitted() { + return response.isCommitted(); + } + + /** + * {@inheritDoc} + */ + public void setContentType(String contentType) { + response.setContentType(contentType); + } + + /** + * {@inheritDoc} + */ + public Locale getRequestLocale() { + return request.getLocale(); + } + + public HttpServletRequest getRequest() { + return request; + } + + public HttpServletResponse getResponse() { + return response; + } + + /** + * {@inheritDoc} + */ + public boolean isUserInRole(String role) { + return request.isUserInRole(role); + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/servlet/ServletUtil.java b/plugins/tiles/src/main/java/org/apache/tiles/request/servlet/ServletUtil.java new file mode 100644 index 000000000..0646774b0 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/servlet/ServletUtil.java @@ -0,0 +1,117 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tiles.request.servlet; + +import org.apache.tiles.request.ApplicationAccess; +import org.apache.tiles.request.ApplicationContext; +import org.apache.tiles.request.Request; +import org.apache.tiles.request.RequestWrapper; + +import javax.servlet.ServletContext; +import javax.servlet.ServletException; +import java.io.IOException; + +/** + * Utilities for Tiles request servlet support. + */ +public final class ServletUtil { + + /** + * Constructor. + */ + private ServletUtil() { + } + + /** + * Wraps a ServletException to create an IOException with the root cause if present. + * + * @param ex The exception to wrap. + * @param message The message of the exception. + * @return The wrapped exception. + */ + public static IOException wrapServletException(ServletException ex, + String message) { + IOException retValue; + Throwable rootCause = ex.getRootCause(); + if (rootCause != null) { + // Replace the ServletException with an IOException, with the root + // cause of the first as the cause of the latter. + retValue = new IOException(message, rootCause); + } else { + retValue = new IOException(message, ex); + } + + return retValue; + } + + /** + * Returns the application context getting it from the servlet context. It must be + * first saved creating a {@link ServletApplicationContext} and using + * {@link ApplicationAccess#register(ApplicationContext)}. + * + * @param servletContext The servlet context. + * @return The application context, if found, null otherwise. + */ + public static ApplicationContext getApplicationContext(ServletContext servletContext) { + return (ApplicationContext) servletContext + .getAttribute(ApplicationAccess.APPLICATION_CONTEXT_ATTRIBUTE); + } + + /** + * Opens a TilesRequestContext until it finds a ServletTilesRequestContext. + * + * @param request The request to open. + * @return The servlet-based request context. + * @throws NotAServletEnvironmentException If a servlet-based request + * context could not be found. + */ + public static ServletRequest getServletRequest(Request request) { + Request currentRequest = request; + while (true) { + if (currentRequest == null) { + throw new NotAServletEnvironmentException("Last Tiles request context is null"); + } + + if (currentRequest instanceof ServletRequest) { + return (ServletRequest) currentRequest; + } + if (!(currentRequest instanceof RequestWrapper)) { + throw new NotAServletEnvironmentException("Not a Servlet environment, not supported"); + } + currentRequest = ((RequestWrapper) currentRequest).getWrappedRequest(); + } + } + + /** + * Gets a servlet context from a TilesApplicationContext. + * + * @param applicationContext The application context to analyze. + * @return The servlet context. + * @throws NotAServletEnvironmentException If the application context is not + * servlet-based. + */ + public static ServletContext getServletContext(ApplicationContext applicationContext) { + if (applicationContext instanceof ServletApplicationContext) { + return (ServletContext) applicationContext.getContext(); + } + + throw new NotAServletEnvironmentException("Not a Servlet-based environment"); + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/servlet/extractor/ApplicationScopeExtractor.java b/plugins/tiles/src/main/java/org/apache/tiles/request/servlet/extractor/ApplicationScopeExtractor.java new file mode 100644 index 000000000..52af00a9c --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/servlet/extractor/ApplicationScopeExtractor.java @@ -0,0 +1,64 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.request.servlet.extractor; + +import org.apache.tiles.request.attribute.AttributeExtractor; + +import javax.servlet.ServletContext; +import java.util.Enumeration; + +/** + * Extract attributes from application scope. + */ +public class ApplicationScopeExtractor implements AttributeExtractor { + + /** + * The servlet context. + */ + private final ServletContext context; + + /** + * Constructor. + * + * @param context The servlet context. + */ + public ApplicationScopeExtractor(ServletContext context) { + this.context = context; + } + + @Override + public void setValue(String name, Object value) { + context.setAttribute(name, value); + } + + @Override + public void removeValue(String name) { + context.removeAttribute(name); + } + + @Override + public Enumeration getKeys() { + return context.getAttributeNames(); + } + + @Override + public Object getValue(String key) { + return context.getAttribute(key); + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/servlet/extractor/HeaderExtractor.java b/plugins/tiles/src/main/java/org/apache/tiles/request/servlet/extractor/HeaderExtractor.java new file mode 100644 index 000000000..e7c366238 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/servlet/extractor/HeaderExtractor.java @@ -0,0 +1,72 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.request.servlet.extractor; + +import org.apache.tiles.request.attribute.EnumeratedValuesExtractor; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.util.Enumeration; + +/** + * Extract header values from an HTTP request. + */ +public class HeaderExtractor implements EnumeratedValuesExtractor { + + /** + * The request. + */ + private final HttpServletRequest request; + + /** + * The response. + */ + private final HttpServletResponse response; + + /** + * Constructor. + * + * @param request The request. + * @param response The response. + */ + public HeaderExtractor(HttpServletRequest request, HttpServletResponse response) { + this.request = request; + this.response = response; + } + + @Override + public Enumeration getKeys() { + return request.getHeaderNames(); + } + + @Override + public String getValue(String key) { + return request.getHeader(key); + } + + @Override + public Enumeration getValues(String key) { + return request.getHeaders(key); + } + + @Override + public void setValue(String key, String value) { + response.setHeader(key, value); + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/servlet/extractor/InitParameterExtractor.java b/plugins/tiles/src/main/java/org/apache/tiles/request/servlet/extractor/InitParameterExtractor.java new file mode 100644 index 000000000..6c67aaed9 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/servlet/extractor/InitParameterExtractor.java @@ -0,0 +1,55 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.request.servlet.extractor; + +import org.apache.tiles.request.attribute.HasKeys; + +import javax.servlet.ServletContext; +import java.util.Enumeration; + +/** + * Extract initialization parameters from the servlet context. + */ +public class InitParameterExtractor implements HasKeys { + + /** + * The servlet context. + */ + private final ServletContext context; + + /** + * Constructor. + * + * @param context The servlet context. + */ + public InitParameterExtractor(ServletContext context) { + this.context = context; + } + + @Override + public Enumeration getKeys() { + return context.getInitParameterNames(); + } + + @Override + public String getValue(String key) { + return context.getInitParameter(key); + } + +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/servlet/extractor/ParameterExtractor.java b/plugins/tiles/src/main/java/org/apache/tiles/request/servlet/extractor/ParameterExtractor.java new file mode 100644 index 000000000..6925d253f --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/servlet/extractor/ParameterExtractor.java @@ -0,0 +1,54 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.request.servlet.extractor; + +import org.apache.tiles.request.attribute.HasKeys; + +import javax.servlet.http.HttpServletRequest; +import java.util.Enumeration; + +/** + * Extract parameters from the request. + */ +public class ParameterExtractor implements HasKeys { + + /** + * The servlet request. + */ + private final HttpServletRequest request; + + /** + * Constructor. + * + * @param request The servlet request. + */ + public ParameterExtractor(HttpServletRequest request) { + this.request = request; + } + + @Override + public Enumeration getKeys() { + return request.getParameterNames(); + } + + @Override + public String getValue(String key) { + return request.getParameter(key); + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/servlet/extractor/RequestScopeExtractor.java b/plugins/tiles/src/main/java/org/apache/tiles/request/servlet/extractor/RequestScopeExtractor.java new file mode 100644 index 000000000..8bb3682e8 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/servlet/extractor/RequestScopeExtractor.java @@ -0,0 +1,64 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.request.servlet.extractor; + +import org.apache.tiles.request.attribute.AttributeExtractor; + +import javax.servlet.http.HttpServletRequest; +import java.util.Enumeration; + +/** + * Extracts attributes from request scope. + */ +public class RequestScopeExtractor implements AttributeExtractor { + + /** + * The servlet request. + */ + private final HttpServletRequest request; + + /** + * Constructor. + * + * @param request The servlet request. + */ + public RequestScopeExtractor(HttpServletRequest request) { + this.request = request; + } + + @Override + public void setValue(String name, Object value) { + request.setAttribute(name, value); + } + + @Override + public void removeValue(String name) { + request.removeAttribute(name); + } + + @Override + public Enumeration getKeys() { + return request.getAttributeNames(); + } + + @Override + public Object getValue(String key) { + return request.getAttribute(key); + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/servlet/extractor/SessionScopeExtractor.java b/plugins/tiles/src/main/java/org/apache/tiles/request/servlet/extractor/SessionScopeExtractor.java new file mode 100644 index 000000000..3753d9f2b --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/servlet/extractor/SessionScopeExtractor.java @@ -0,0 +1,77 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.request.servlet.extractor; + +import org.apache.tiles.request.attribute.AttributeExtractor; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpSession; +import java.util.Collections; +import java.util.Enumeration; + +/** + * Extract attributes from session scope. + */ +public class SessionScopeExtractor implements AttributeExtractor { + + /** + * The servlet request. + */ + private final HttpServletRequest request; + + /** + * Constructor. + * + * @param request The servlet request. + */ + public SessionScopeExtractor(HttpServletRequest request) { + this.request = request; + } + + @Override + public void setValue(String name, Object value) { + request.getSession().setAttribute(name, value); + } + + @Override + public void removeValue(String name) { + HttpSession session = request.getSession(false); + if (session != null) { + session.removeAttribute(name); + } + } + + @Override + public Enumeration getKeys() { + HttpSession session = request.getSession(false); + if (session != null) { + return session.getAttributeNames(); + } + return Collections.enumeration(Collections.emptySet()); + } + + @Override + public Object getValue(String key) { + HttpSession session = request.getSession(false); + if (session != null) { + return session.getAttribute(key); + } + return null; + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/servlet/extractor/package-info.java b/plugins/tiles/src/main/java/org/apache/tiles/request/servlet/extractor/package-info.java new file mode 100644 index 000000000..0df933439 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/servlet/extractor/package-info.java @@ -0,0 +1,24 @@ +/* + * $Id: package-info.java 1049711 2010-12-15 21:12:00Z apetrelli $ + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +/** + * Extractors to get attributes and other info from servlet requests and contexts. + */ +package org.apache.tiles.request.servlet.extractor; diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/servlet/package-info.java b/plugins/tiles/src/main/java/org/apache/tiles/request/servlet/package-info.java new file mode 100644 index 000000000..331e1f1fc --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/servlet/package-info.java @@ -0,0 +1,24 @@ +/* + * $Id: package-info.java 1049711 2010-12-15 21:12:00Z apetrelli $ + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +/** + * Tiles request support for Servlet technology. + */ +package org.apache.tiles.request.servlet; diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/velocity/VelocityRequest.java b/plugins/tiles/src/main/java/org/apache/tiles/request/velocity/VelocityRequest.java new file mode 100644 index 000000000..328d67c9e --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/velocity/VelocityRequest.java @@ -0,0 +1,169 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tiles.request.velocity; + +import java.io.IOException; +import java.io.PrintWriter; +import java.io.Writer; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import javax.servlet.RequestDispatcher; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.tiles.request.AbstractViewRequest; +import org.apache.tiles.request.ApplicationContext; +import org.apache.tiles.request.DispatchRequest; +import org.apache.tiles.request.servlet.ExternalWriterHttpServletResponse; +import org.apache.tiles.request.servlet.ServletRequest; +import org.apache.tiles.request.servlet.ServletUtil; +import org.apache.velocity.context.Context; + +/** + * The implementation of the Tiles request context specific for Velocity. + */ +public class VelocityRequest extends AbstractViewRequest { + + /** + * The native available scopes, in fact only "page". + */ + private final List scopes; + + /** + * The Velocity current context. + */ + private final Context ctx; + + /** + * The writer to use to render the response. It may be null, if not necessary. + */ + private Writer writer; + + /** + * The map of the page scope. + */ + private Map pageScope; + + /** + * Factory method to create a Velocity request. + * + * @param applicationContext The application context. + * @param request The request. + * @param response The response. + * @param velocityContext The Velocity context. + * @param writer The writer to write into. + * @return The request. + */ + public static VelocityRequest createVelocityRequest(ApplicationContext applicationContext, + HttpServletRequest request, HttpServletResponse response, Context velocityContext, Writer writer) { + DispatchRequest servletRequest = new ServletRequest(applicationContext, request, response); + VelocityRequest velocityRequest = new VelocityRequest(servletRequest, velocityContext, writer); + return velocityRequest; + } + + /** + * Constructor. + * + * @param enclosedRequest The request that exposes non-Velocity specific + * properties + * @param ctx The Velocity current context. + * @param writer The writer to use to render the response. It may be + * null, if not necessary. + */ + public VelocityRequest(DispatchRequest enclosedRequest, Context ctx, Writer writer) { + super(enclosedRequest); + List scopes = new ArrayList(); + scopes.addAll(enclosedRequest.getAvailableScopes()); + scopes.add("page"); + this.scopes = Collections.unmodifiableList(scopes); + this.ctx = ctx; + this.writer = writer; + } + + @Override + public List getAvailableScopes() { + return scopes; + } + + /** {@inheritDoc} */ + @Override + protected void doInclude(String path) throws IOException { + ServletRequest servletRequest = org.apache.tiles.request.servlet.ServletUtil.getServletRequest(this); + HttpServletRequest request = servletRequest.getRequest(); + HttpServletResponse response = servletRequest.getResponse(); + RequestDispatcher rd = request.getRequestDispatcher(path); + + if (rd == null) { + throw new IOException("No request dispatcher returned for path '" + path + "'"); + } + + PrintWriter printWriter = getPrintWriter(); + try { + rd.include(request, new ExternalWriterHttpServletResponse(response, printWriter)); + } catch (ServletException ex) { + throw ServletUtil.wrapServletException(ex, "ServletException including path '" + path + "'."); + } + } + + /** {@inheritDoc} */ + @Override + public PrintWriter getPrintWriter() { + if (writer == null) { + throw new IllegalStateException( + "A writer-less Tiles request has been created, cannot return a PrintWriter"); + } + if (writer instanceof PrintWriter) { + return (PrintWriter) writer; + } + return new PrintWriter(writer); + } + + /** {@inheritDoc} */ + @Override + public Writer getWriter() { + if (writer == null) { + throw new IllegalStateException( + "A writer-less Tiles request has been created, cannot return a PrintWriter"); + } + return writer; + } + + /** + * Returns the page scope. + * + * @return The page scope. + */ + public Map getPageScope() { + if (pageScope == null) { + pageScope = new VelocityScopeMap(ctx); + } + return pageScope; + } + + @Override + public Map getContext(String scope) { + return "page".equals(scope) ? getPageScope() : super.getContext(scope); + } + +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/velocity/VelocityScopeMap.java b/plugins/tiles/src/main/java/org/apache/tiles/request/velocity/VelocityScopeMap.java new file mode 100644 index 000000000..36e7c21be --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/velocity/VelocityScopeMap.java @@ -0,0 +1,87 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.request.velocity; + +import static org.apache.tiles.request.collection.CollectionUtil.key; + +import java.util.HashSet; +import java.util.Set; + +import org.apache.tiles.request.collection.ScopeMap; +import org.apache.tiles.request.velocity.extractor.VelocityScopeExtractor; +import org.apache.velocity.context.Context; + +/** + *

+ * Private implementation of Map for servlet request attributes. + *

+ * + */ + +final class VelocityScopeMap extends ScopeMap { + + /** + * The request object to use. + */ + private Context request = null; + + /** + * Constructor. + * + * @param request The request object to use. + */ + public VelocityScopeMap(Context request) { + super(new VelocityScopeExtractor(request)); + this.request = request; + } + + @Override + public Object remove(Object key) { + return request.remove(key(key)); + } + + @Override + public Object put(String key, Object value) { + return request.put(key, value); + } + + /** {@inheritDoc} */ + public boolean containsKey(Object key) { + return request.containsKey(key(key)); + } + + /** {@inheritDoc} */ + public boolean isEmpty() { + return size() < 1; + } + + /** {@inheritDoc} */ + public Set keySet() { + Set set = new HashSet(); + for (Object key : request.getKeys()) { + set.add((String) key); + } + return (set); + } + + /** {@inheritDoc} */ + public int size() { + return request.getKeys().length; + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/velocity/autotag/VelocityAutotagRuntime.java b/plugins/tiles/src/main/java/org/apache/tiles/request/velocity/autotag/VelocityAutotagRuntime.java new file mode 100644 index 000000000..32e00e745 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/velocity/autotag/VelocityAutotagRuntime.java @@ -0,0 +1,102 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.request.velocity.autotag; + +import java.io.Writer; +import java.util.Map; + +import javax.servlet.ServletContext; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.tiles.autotag.core.runtime.AutotagRuntime; +import org.apache.tiles.autotag.core.runtime.ModelBody; +import org.apache.tiles.request.Request; +import org.apache.tiles.request.servlet.ServletUtil; +import org.apache.tiles.request.velocity.VelocityRequest; +import org.apache.velocity.context.InternalContextAdapter; +import org.apache.velocity.runtime.directive.Directive; +import org.apache.velocity.runtime.parser.node.ASTBlock; +import org.apache.velocity.runtime.parser.node.ASTMap; +import org.apache.velocity.runtime.parser.node.Node; +import org.apache.velocity.tools.view.ViewContext; + +/** + * A Runtime for implementing Velocity Directives. + */ +public class VelocityAutotagRuntime extends Directive implements AutotagRuntime { + private InternalContextAdapter context; + private Writer writer; + private Node node; + private Map params; + + @Override + public Request createRequest() { + ViewContext viewContext = (ViewContext) context.getInternalUserContext(); + HttpServletRequest request = viewContext.getRequest(); + HttpServletResponse response = viewContext.getResponse(); + ServletContext servletContext = viewContext.getServletContext(); + return VelocityRequest.createVelocityRequest(ServletUtil.getApplicationContext(servletContext), request, + response, context, writer); + } + + /** {@inheritDoc} */ + @Override + public ModelBody createModelBody() { + ASTBlock block = (ASTBlock) node.jjtGetChild(1); + return new VelocityModelBody(context, block, writer); + } + + /** {@inheritDoc} */ + @Override + @SuppressWarnings("unchecked") + public T getParameter(String name, Class type, T defaultValue) { + if (params == null) { + ASTMap astMap = (ASTMap) node.jjtGetChild(0); + params = (Map) astMap.value(context); + } + T result = (T) params.get(name); + if (result == null) { + result = defaultValue; + } + return result; + } + + /** {@inheritDoc} */ + @Override + public String getName() { + return null; + } + + /** {@inheritDoc} */ + @Override + public int getType() { + return 0; + } + + /** {@inheritDoc} */ + @Override + public boolean render(InternalContextAdapter context, Writer writer, Node node) { + this.context = context; + this.writer = writer; + this.node = node; + return false; + } + +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/velocity/autotag/VelocityModelBody.java b/plugins/tiles/src/main/java/org/apache/tiles/request/velocity/autotag/VelocityModelBody.java new file mode 100644 index 000000000..1022175f6 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/velocity/autotag/VelocityModelBody.java @@ -0,0 +1,61 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.request.velocity.autotag; + +import java.io.IOException; +import java.io.Writer; + +import org.apache.tiles.autotag.core.runtime.AbstractModelBody; +import org.apache.velocity.context.InternalContextAdapter; +import org.apache.velocity.runtime.parser.node.ASTBlock; + +/** + * Body abstraction for a Velocity directive body. + */ +public class VelocityModelBody extends AbstractModelBody { + + /** + * The real body. + */ + private ASTBlock body; + + /** + * The Velocity context. + */ + private InternalContextAdapter context; + + /** + * Constructor. + * + * @param context The Velocity context. + * @param body The real body. + * @param defaultWriter The default writer. + */ + public VelocityModelBody(InternalContextAdapter context, ASTBlock body, Writer defaultWriter) { + super(defaultWriter); + this.context = context; + this.body = body; + } + + @Override + public void evaluate(Writer writer) throws IOException { + body.render(context, writer); + } + +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/velocity/autotag/VelocityUtil.java b/plugins/tiles/src/main/java/org/apache/tiles/request/velocity/autotag/VelocityUtil.java new file mode 100644 index 000000000..bca193836 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/velocity/autotag/VelocityUtil.java @@ -0,0 +1,67 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.request.velocity.autotag; + +import java.util.Map; + +import org.apache.velocity.context.InternalContextAdapter; +import org.apache.velocity.runtime.parser.node.ASTMap; +import org.apache.velocity.runtime.parser.node.Node; + +/** + * Utilities for Velocity usage in Tiles. + */ +public final class VelocityUtil { + + /** + * Private constructor to avoid instantiation. + */ + private VelocityUtil() { + } + + /** + * Extracts the parameters from the directives, by getting the child at position + * 0 supposing it is a map. + * + * @param context The Velocity context. + * @param node The node to use. + * @return The extracted parameters. + */ + @SuppressWarnings("unchecked") + public static Map getParameters(InternalContextAdapter context, Node node) { + ASTMap astMap = (ASTMap) node.jjtGetChild(0); + Map params = (Map) astMap.value(context); + return params; + } + + /** + * Returns the "value" parameter if it is not null, otherwise returns + * "defaultValue". + * + * @param value The value to return, if it is not null. + * @param defaultValue The value to return, if value is null. + * @return The value, defaulted if necessary. + */ + public static Object getObject(Object value, Object defaultValue) { + if (value == null) { + value = defaultValue; + } + return value; + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/velocity/autotag/package-info.java b/plugins/tiles/src/main/java/org/apache/tiles/request/velocity/autotag/package-info.java new file mode 100644 index 000000000..456abb238 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/velocity/autotag/package-info.java @@ -0,0 +1,22 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +/** + * Runtime part of Autotag support for Velocity. + */ +package org.apache.tiles.request.velocity.autotag; diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/velocity/extractor/VelocityScopeExtractor.java b/plugins/tiles/src/main/java/org/apache/tiles/request/velocity/extractor/VelocityScopeExtractor.java new file mode 100644 index 000000000..1481c3844 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/velocity/extractor/VelocityScopeExtractor.java @@ -0,0 +1,99 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.request.velocity.extractor; + +import java.util.Enumeration; + +import org.apache.tiles.request.attribute.AttributeExtractor; +import org.apache.velocity.context.Context; + +/** + * Extracts attributes from Velocity context.. + */ +public class VelocityScopeExtractor implements AttributeExtractor { + + /** + * The Velocity context. + */ + private Context context; + + /** + * Constructor. + * + * @param context The Velocity context. + */ + public VelocityScopeExtractor(Context context) { + this.context = context; + } + + @Override + public void removeValue(String name) { + context.remove(name); + } + + @Override + public Enumeration getKeys() { + return new KeyEnumeration(context.getKeys()); + } + + @Override + public Object getValue(String key) { + return context.get(key); + } + + @Override + public void setValue(String key, Object value) { + context.put(key, value); + } + + /** + * Enumerates an array. + */ + private static class KeyEnumeration implements Enumeration { + + /** + * The current index. + */ + private int index = 0; + + /** + * The array to enumerate. + */ + private Object[] keys; + + /** + * Constructor. + * + * @param keys The array to enumerate. + */ + public KeyEnumeration(Object[] keys) { + this.keys = keys; + } + + @Override + public boolean hasMoreElements() { + return index < keys.length; + } + + @Override + public String nextElement() { + return (String) keys[index++]; + } + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/velocity/extractor/package-info.java b/plugins/tiles/src/main/java/org/apache/tiles/request/velocity/extractor/package-info.java new file mode 100644 index 000000000..d0c099c58 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/velocity/extractor/package-info.java @@ -0,0 +1,22 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +/** + * Extractors to get info about Velocity-specific objects. + */ +package org.apache.tiles.request.velocity.extractor; diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/velocity/package-info.java b/plugins/tiles/src/main/java/org/apache/tiles/request/velocity/package-info.java new file mode 100644 index 000000000..2a3e45f0a --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/velocity/package-info.java @@ -0,0 +1,22 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +/** + * Tiles request support for Velocity. + */ +package org.apache.tiles.request.velocity; diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/velocity/render/ApplicationContextJeeConfig.java b/plugins/tiles/src/main/java/org/apache/tiles/request/velocity/render/ApplicationContextJeeConfig.java new file mode 100644 index 000000000..9810ce3d9 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/velocity/render/ApplicationContextJeeConfig.java @@ -0,0 +1,77 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.request.velocity.render; + +import java.util.Collections; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.Map; + +import javax.servlet.ServletContext; + +import org.apache.tiles.request.ApplicationContext; +import org.apache.tiles.request.servlet.ServletUtil; +import org.apache.velocity.tools.view.JeeConfig; + +/** + * Implements JeeConfig to use parameters set through + */ +public class ApplicationContextJeeConfig implements JeeConfig { + + /** + * The application context. + */ + private ApplicationContext applicationContext; + + /** + * The initialization parameters for VelocityView. + */ + private Map params; + + /** + * Constructor. + * + * @param applicationContext The application context. + * @param params Configuration parameters. + */ + public ApplicationContextJeeConfig(ApplicationContext applicationContext, Map params) { + this.applicationContext = applicationContext; + this.params = new HashMap(params); + } + + public String getInitParameter(String name) { + return params.get(name); + } + + public String findInitParameter(String key) { + return params.get(key); + } + + public Enumeration getInitParameterNames() { + return Collections.enumeration(params.keySet()); + } + + public String getName() { + return "Application Context JEE Config"; + } + + public ServletContext getServletContext() { + return ServletUtil.getServletContext(applicationContext); + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/velocity/render/VelocityRenderer.java b/plugins/tiles/src/main/java/org/apache/tiles/request/velocity/render/VelocityRenderer.java new file mode 100644 index 000000000..780a28569 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/velocity/render/VelocityRenderer.java @@ -0,0 +1,75 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tiles.request.velocity.render; + +import java.io.IOException; + +import org.apache.tiles.request.Request; +import org.apache.tiles.request.render.CannotRenderException; +import org.apache.tiles.request.render.Renderer; +import org.apache.tiles.request.servlet.ServletRequest; +import org.apache.tiles.request.servlet.ServletUtil; +import org.apache.velocity.Template; +import org.apache.velocity.context.Context; +import org.apache.velocity.tools.view.VelocityView; + +/** + * Attribute renderer for rendering Velocity templates as attributes. It is + * available only to Servlet-based environment. It uses VelocityView to render + * the response. To initialize it correctly, call #setParameter(String, String) + * for all the parameters that you want to set, and then call #commit(). + */ +public class VelocityRenderer implements Renderer { + + /** + * The VelocityView object to use. + */ + private VelocityView velocityView; + + /** + * Constructor. + * + * @param velocityView The Velocity view manager. + */ + public VelocityRenderer(VelocityView velocityView) { + this.velocityView = velocityView; + } + + @Override + public void render(String path, Request request) throws IOException { + if (path == null) { + throw new CannotRenderException("Cannot dispatch a null path"); + } + + ServletRequest servletRequest = ServletUtil.getServletRequest(request); + // then get a context + Context context = velocityView.createContext(servletRequest.getRequest(), servletRequest.getResponse()); + + // get the template + Template template = velocityView.getTemplate((String) path); + + // merge the template and context into the writer + velocityView.merge(template, context, request.getWriter()); + } + + public boolean isRenderable(String path, Request request) { + return path != null && path.startsWith("/") && path.endsWith(".vm"); + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/velocity/render/VelocityRendererBuilder.java b/plugins/tiles/src/main/java/org/apache/tiles/request/velocity/render/VelocityRendererBuilder.java new file mode 100644 index 000000000..6f028ea01 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/velocity/render/VelocityRendererBuilder.java @@ -0,0 +1,91 @@ +/* + * $Id: VelocityRendererBuilder.java 1066512 2011-02-02 16:13:31Z apetrelli $ + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.request.velocity.render; + +import java.util.HashMap; +import java.util.Map; + +import org.apache.tiles.request.ApplicationContext; +import org.apache.velocity.tools.view.VelocityView; + +/** + * Builds a VelocityRenderer. + */ +public final class VelocityRendererBuilder { + + /** + * The initialization parameters for VelocityView. + */ + private Map params = new HashMap(); + + /** + * The application context. + */ + private ApplicationContext applicationContext; + + /** + * Constructor. + */ + private VelocityRendererBuilder() { + } + + /** + * Returns a new instance of the builder. + * + * @return A new builder. + */ + public static VelocityRendererBuilder createInstance() { + return new VelocityRendererBuilder(); + } + + /** + * Sets a parameter for the internal servlet. + * + * @param key The name of the parameter. + * @param value The value of the parameter. + * @return This builder. + */ + public VelocityRendererBuilder setParameter(String key, String value) { + params.put(key, value); + return this; + } + + /** + * Sets the application context. + * + * @param applicationContext The application context. + * @return This builder. + */ + public VelocityRendererBuilder setApplicationContext(ApplicationContext applicationContext) { + this.applicationContext = applicationContext; + return this; + } + + /** + * Creates the Velocity renderer. + * + * @return The Velocity renderer. + */ + public VelocityRenderer build() { + VelocityView velocityView = new VelocityView(new ApplicationContextJeeConfig(applicationContext, params)); + return new VelocityRenderer(velocityView); + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/request/velocity/render/package-info.java b/plugins/tiles/src/main/java/org/apache/tiles/request/velocity/render/package-info.java new file mode 100644 index 000000000..bb0b2d39d --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/request/velocity/render/package-info.java @@ -0,0 +1,22 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +/** + * Renderering support for Velocity. + */ +package org.apache.tiles.request.velocity.render; diff --git a/plugins/tiles/src/main/java/org/apache/tiles/template/AddAttributeModel.java b/plugins/tiles/src/main/java/org/apache/tiles/template/AddAttributeModel.java new file mode 100644 index 000000000..2ccb42348 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/template/AddAttributeModel.java @@ -0,0 +1,124 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.template; + +import org.apache.tiles.api.Attribute; +import org.apache.tiles.api.Expression; +import org.apache.tiles.api.ListAttribute; +import org.apache.tiles.autotag.core.runtime.ModelBody; +import org.apache.tiles.request.Request; + +import java.io.IOException; +import java.util.Deque; + +/** + *

+ * Add an element to the surrounding list. Equivalent to 'putAttribute', + * but for list element. + *

+ * + *

+ * Add an element to the surrounding list. This tag can only be used inside + * 'putListAttribute' or 'addListAttribute' tags. Value can come from a direct + * assignment (value="aValue") + *

+ * + * @since 2.2.0 + */ +public class AddAttributeModel { + + /** + * Executes the operation. + * + * @param value The value of the attribute. Use this parameter, or + * expression, or body. + * @param expression The expression to calculate the value from. Use this + * parameter, or value, or body. + * @param role A comma-separated list of roles. If present, the attribute + * will be rendered only if the current user belongs to one of the roles. + * @param type The type (renderer) of the attribute. + * @param request The request. + * @param modelBody The body. + * @throws IOException If the body cannot be correctly evaluated. + * @since 2.2.0 + */ + public void execute( + Object value, + String expression, + String role, + String type, + Request request, + ModelBody modelBody + ) throws IOException { + Attribute attribute = new Attribute(); + Deque composeStack = ComposeStackUtil.getComposeStack(request); + composeStack.push(attribute); + String body = modelBody.evaluateAsString(); + attribute = (Attribute) composeStack.pop(); + addAttributeToList(attribute, composeStack, value, expression, body, role, type); + } + + /** + * Adds the attribute to the containing list attribute. + * + * @param attribute The attribute to add to the list attribute. + * @param composeStack The composing stack. + * @param value The value of the attribute. Use this parameter, or + * expression, or body. + * @param expression The expression to calculate the value from. Use this + * parameter, or value, or body. + * @param body The body of the tag. Use this parameter, or value, or + * expression. + * @param role A comma-separated list of roles. If present, the attribute + * will be rendered only if the current user belongs to one of the roles. + * @param type The type (renderer) of the attribute. + * @since 2.2.0 + */ + private void addAttributeToList( + Attribute attribute, + Deque composeStack, + Object value, + String expression, + String body, + String role, + String type + ) { + ListAttribute listAttribute = (ListAttribute) ComposeStackUtil.findAncestorWithClass(composeStack, ListAttribute.class); + + if (listAttribute == null) { + throw new NullPointerException("There is no ListAttribute in the stack"); + } + if (value != null) { + attribute.setValue(value); + } else if (attribute.getValue() == null && body != null) { + attribute.setValue(body); + } + if (expression != null) { + attribute.setExpressionObject(Expression + .createExpressionFromDescribedExpression(expression)); + } + if (role != null) { + attribute.setRole(role); + } + if (type != null) { + attribute.setRenderer(type); + } + listAttribute.add(attribute); + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/template/AddListAttributeModel.java b/plugins/tiles/src/main/java/org/apache/tiles/template/AddListAttributeModel.java new file mode 100644 index 000000000..09e7433c1 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/template/AddListAttributeModel.java @@ -0,0 +1,60 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.template; + +import org.apache.tiles.api.ListAttribute; +import org.apache.tiles.autotag.core.runtime.ModelBody; +import org.apache.tiles.request.Request; + +import java.io.IOException; +import java.util.Deque; + +/** + *

+ * Declare a list that will be pass as an attribute. + *

+ *

+ * Declare a list that will be pass as an attribute . List elements are added + * using the tag 'addAttribute' or 'addListAttribute'. This tag can only be used + * inside 'insertTemplate', 'insertDefinition' or 'definition' tag. + *

+ * @since 2.2.0 + */ +public class AddListAttributeModel { + + /** + * Executes the model. + * + * @param role The comma-separated list of roles that can use the list attribute. + * @param request The request. + * @param modelBody The body. + * @throws IOException If the body cannot be evaluated. + */ + public void execute(String role, Request request, ModelBody modelBody) throws IOException { + Deque composeStack = ComposeStackUtil.getComposeStack(request); + ListAttribute listAttribute = new ListAttribute(); + listAttribute.setRole(role); + composeStack.push(listAttribute); + modelBody.evaluateWithoutWriting(); + listAttribute = (ListAttribute) composeStack.pop(); + ListAttribute parent = (ListAttribute) composeStack.peek(); + assert parent != null; + parent.add(listAttribute); + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/template/AttributeResolver.java b/plugins/tiles/src/main/java/org/apache/tiles/template/AttributeResolver.java new file mode 100644 index 000000000..786e258f8 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/template/AttributeResolver.java @@ -0,0 +1,58 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.template; + +import org.apache.tiles.api.Attribute; +import org.apache.tiles.api.TilesContainer; +import org.apache.tiles.request.Request; + +/** + * Resolves an attribute, depending on the given parameters. + * + * @since 2.2.0 + */ +public interface AttributeResolver { + + /** + * Computes the attribute. + * + * @param container The Tiles container to use. + * @param attribute The attribute to return immediately, if not null. + * @param name The name of the attribute. + * @param role A comma-separated list of roles. If present, the attribute + * will be rendered only if the current user belongs to one of the roles. + * @param ignore If true if the computed attribute is null, this problem will be ignored. + * @param defaultValue The default value of the attribute. To use only if the attribute was not computed. + * @param defaultValueRole The default comma-separated list of roles. To use only if the attribute was not computed. + * @param defaultValueType The default type of the attribute. To use only if the attribute was not computed. + * @param request TODO + * @return The computed attribute. + * @since 2.2.0 + */ + Attribute computeAttribute( + TilesContainer container, + Attribute attribute, + String name, + String role, + boolean ignore, + Object defaultValue, + String defaultValueRole, + String defaultValueType, + Request request); +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/template/ComposeStackUtil.java b/plugins/tiles/src/main/java/org/apache/tiles/template/ComposeStackUtil.java new file mode 100644 index 000000000..0b255e58e --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/template/ComposeStackUtil.java @@ -0,0 +1,83 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tiles.template; + +import org.apache.tiles.request.Request; + +import java.util.Deque; +import java.util.LinkedList; +import java.util.Map; + +/** + * Utilities to work with compose stacks. + * + * @since 3.0.0 + */ +public final class ComposeStackUtil { + + /** + * The name of the attribute that holds to compose stack. + */ + public static final String COMPOSE_STACK_ATTRIBUTE_NAME = "org.apache.tiles.template.COMPOSE_STACK"; + + /** + * Private constructor to avoid instantiation. + */ + private ComposeStackUtil() { + + } + + /** + * Finds the first ancestor in the stack, that is assignable to the given class. + * + * @param composeStack To compose stack to evaluate. + * @param clazz The class to check. + * @return The first ancestor that is assignable to the class, or null if not found. + * @since 3.0.0 + */ + public static Object findAncestorWithClass(Deque composeStack, Class clazz) { + for (Object obj : composeStack) { + if (clazz.isAssignableFrom(obj.getClass())) { + return obj; + } + } + + return null; + } + + /** + * Returns the current compose stack, or creates a new one if not present. + * + * @param request The request. + * @return The compose stack. + * @since 3.0.0 + */ + @SuppressWarnings("unchecked") + public static Deque getComposeStack(Request request) { + Map requestScope = request.getContext("request"); + Deque composeStack = (Deque) requestScope + .get(COMPOSE_STACK_ATTRIBUTE_NAME); + if (composeStack == null) { + composeStack = new LinkedList<>(); + requestScope.put(ComposeStackUtil.COMPOSE_STACK_ATTRIBUTE_NAME, composeStack); + } + return composeStack; + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/template/DefaultAttributeResolver.java b/plugins/tiles/src/main/java/org/apache/tiles/template/DefaultAttributeResolver.java new file mode 100644 index 000000000..c1ee10ae1 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/template/DefaultAttributeResolver.java @@ -0,0 +1,85 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.template; + +import org.apache.tiles.api.Attribute; +import org.apache.tiles.api.AttributeContext; +import org.apache.tiles.api.TilesContainer; +import org.apache.tiles.request.Request; + +/** + * The default implementation of AttributeResolver. + * + * @since 2.2.0 + */ +public class DefaultAttributeResolver implements AttributeResolver { + + /** + * {@inheritDoc} + */ + public Attribute computeAttribute( + TilesContainer container, + Attribute attribute, + String name, + String role, + boolean ignore, + Object defaultValue, + String defaultValueRole, + String defaultValueType, + Request request + ) { + if (attribute == null) { + AttributeContext evaluatingContext = container + .getAttributeContext(request); + attribute = evaluatingContext.getAttribute(name); + if (attribute == null) { + attribute = computeDefaultAttribute(defaultValue, + defaultValueRole, defaultValueType); + if (attribute == null && !ignore) { + throw new NoSuchAttributeException("Attribute '" + name + "' not found."); + } + } + } + if (attribute != null && role != null && !"".equals(role.trim())) { + attribute = new Attribute(attribute); + attribute.setRole(role); + } + return attribute; + } + + /** + * Computes the default attribute. + * + * @param defaultValue The default value of the attribute. + * @param defaultValueRole The default role of tha attribute. + * @param defaultValueType The default type of the attribute. + * @return The default attribute. + */ + private Attribute computeDefaultAttribute(Object defaultValue, String defaultValueRole, String defaultValueType) { + Attribute attribute = null; + if (defaultValue != null) { + if (defaultValue instanceof Attribute) { + attribute = (Attribute) defaultValue; + } else if (defaultValue instanceof String) { + attribute = new Attribute(defaultValue, null, defaultValueRole, defaultValueType); + } + } + return attribute; + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/template/DefinitionModel.java b/plugins/tiles/src/main/java/org/apache/tiles/template/DefinitionModel.java new file mode 100644 index 000000000..7302d2ea1 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/template/DefinitionModel.java @@ -0,0 +1,139 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.template; + +import org.apache.tiles.api.Attribute; +import org.apache.tiles.api.Definition; +import org.apache.tiles.api.access.TilesAccess; +import org.apache.tiles.api.mgmt.MutableTilesContainer; +import org.apache.tiles.autotag.core.runtime.ModelBody; +import org.apache.tiles.autotag.core.runtime.annotation.Parameter; +import org.apache.tiles.request.Request; + +import java.io.IOException; +import java.util.Deque; + +/** + *

+ * Create a definition at runtime. + *

+ *

+ * Create a new definition at runtime. Newly created definition will be + * available across the entire request. + *

+ * + * @since 2.2.0 + */ +public class DefinitionModel { + + /** + * Executes the operation. + * + * @param name The name of the definition to create. If not specified, an + * anonymous definition will be created. + * @param template The template of this definition. + * @param role A comma-separated list of roles. If present, the definition + * will be rendered only if the current user belongs to one of the roles. + * @param extendsParam The definition name that this definition extends. + * @param preparer The preparer to use to invoke before the definition is + * rendered. + * @param request The request. + * @param modelBody The body. + * @throws IOException If something goes wrong. + * @since 2.2.0 + */ + public void execute( + String name, + String template, + String role, + @Parameter(name = "extends") String extendsParam, + String preparer, + Request request, + ModelBody modelBody + ) throws IOException { + Deque composeStack = ComposeStackUtil.getComposeStack(request); + Definition definition = createDefinition(name, template, role, extendsParam, preparer); + composeStack.push(definition); + modelBody.evaluateWithoutWriting(); + MutableTilesContainer container = (MutableTilesContainer) TilesAccess.getCurrentContainer(request); + definition = (Definition) composeStack.pop(); + registerDefinition(definition, container, composeStack, request); + } + + /** + * Creates the definition to store. + * + * @param name The name of the definition to create. If not specified, an + * anonymous definition will be created. + * @param template The template of this definition. + * @param role A comma-separated list of roles. If present, the definition + * will be rendered only if the current user belongs to one of the roles. + * @param extendsParam The definition name that this definition extends. + * @param preparer The preparer to use to invoke before the definition is + * rendered. + * @return The created definition. + */ + private Definition createDefinition( + String name, + String template, + String role, + String extendsParam, + String preparer + ) { + Definition definition = new Definition(); + definition.setName(name); + Attribute templateAttribute = Attribute.createTemplateAttribute(template); + templateAttribute.setRole(role); + definition.setTemplateAttribute(templateAttribute); + definition.setExtends(extendsParam); + definition.setPreparer(preparer); + return definition; + } + + /** + * Registers a definition in the container. + * + * @param definition The definition to register. + * @param container The container into which the definition will be + * registered. + * @param composeStack The compose stack, + * @param request The request. + */ + private void registerDefinition( + Definition definition, + MutableTilesContainer container, + Deque composeStack, + Request request + ) { + container.register(definition, request); + + if (composeStack.isEmpty()) { + return; + } + + Object obj = composeStack.peek(); + if (obj instanceof Attribute) { + Attribute attribute = (Attribute) obj; + attribute.setValue(definition.getName()); + if (attribute.getRenderer() == null) { + attribute.setRenderer("definition"); + } + } + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/template/GetAsStringModel.java b/plugins/tiles/src/main/java/org/apache/tiles/template/GetAsStringModel.java new file mode 100644 index 000000000..1bf1de742 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/template/GetAsStringModel.java @@ -0,0 +1,224 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.template; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.apache.tiles.api.Attribute; +import org.apache.tiles.api.TilesContainer; +import org.apache.tiles.api.access.TilesAccess; +import org.apache.tiles.autotag.core.runtime.ModelBody; +import org.apache.tiles.autotag.core.runtime.annotation.Parameter; +import org.apache.tiles.request.Request; + +import java.io.IOException; +import java.io.Writer; +import java.util.Deque; + +/** + *

+ * Render the value of the specified template attribute to the current + * Writer + *

+ * + *

+ * Retrieve the value of the specified template attribute property, and render + * it to the current Writer as a String. The usual toString() conversions is + * applied on found value. + *

+ * + * @since 2.2.0 + */ +public class GetAsStringModel { + + /** + * The logging object. + */ + private static final Logger LOG = LogManager.getLogger(GetAsStringModel.class); + + /** + * The attribute resolver to use. + */ + private final AttributeResolver attributeResolver; + + /** + * Constructor that uses the defaut attribute resolver. + * + * @since 3.0.0 + */ + public GetAsStringModel() { + this(new DefaultAttributeResolver()); + } + + /** + * Constructor. + * + * @param attributeResolver The attribute resolver to use. + * @since 2.2.0 + */ + public GetAsStringModel(AttributeResolver attributeResolver) { + this.attributeResolver = attributeResolver; + } + + /** + * Executes the operation. + * + * @param ignore If true, if an exception happens during + * rendering, of if the attribute is null, the problem will be ignored. + * @param preparer The preparer to invoke before rendering the attribute. + * @param role A comma-separated list of roles. If present, the attribute + * will be rendered only if the current user belongs to one of the roles. + * @param defaultValue The default value of the attribute. To use only if + * the attribute was not computed. + * @param defaultValueRole The default comma-separated list of roles. To use + * only if the attribute was not computed. + * @param defaultValueType The default type of the attribute. To use only if + * the attribute was not computed. + * @param name The name of the attribute. + * @param value The attribute to use immediately, if not null. + * @param request The request. + * @param modelBody The body. + * @throws IOException If an I/O error happens during rendering. + * @since 2.2.0 + */ + public void execute( + boolean ignore, + String preparer, + String role, + Object defaultValue, + String defaultValueRole, + String defaultValueType, + @Parameter(required = true) String name, + Attribute value, + Request request, + ModelBody modelBody + ) throws IOException { + TilesContainer container = TilesAccess.getCurrentContainer(request); + Deque composeStack = ComposeStackUtil.getComposeStack(request); + Attribute attribute = resolveAttribute( + container, + ignore, + preparer, + role, + defaultValue, + defaultValueRole, + defaultValueType, + name, + value, + request + ); + if (attribute != null) { + composeStack.push(attribute); + } + modelBody.evaluateWithoutWriting(); + container = TilesAccess.getCurrentContainer(request); + Writer writer = request.getWriter(); + if (attribute != null) { + attribute = (Attribute) composeStack.pop(); + } + renderAttribute(attribute, container, writer, ignore, request); + } + + /** + * Resolves the attribute. and starts the context. + * + * @param container The Tiles container to use. + * @param ignore If true, if an exception happens during + * rendering, of if the attribute is null, the problem will be ignored. + * @param preparer The preparer to invoke before rendering the attribute. + * @param role A comma-separated list of roles. If present, the attribute + * will be rendered only if the current user belongs to one of the roles. + * @param defaultValue The default value of the attribute. To use only if + * the attribute was not computed. + * @param defaultValueRole The default comma-separated list of roles. To use + * only if the attribute was not computed. + * @param defaultValueType The default type of the attribute. To use only if + * the attribute was not computed. + * @param name The name of the attribute. + * @param value The attribute to use immediately, if not null. + * @param request The request. + * @return The resolved attribute. + */ + private Attribute resolveAttribute( + TilesContainer container, + boolean ignore, + String preparer, + String role, + Object defaultValue, + String defaultValueRole, + String defaultValueType, + String name, + Attribute value, + Request request + ) { + if (preparer != null) { + container.prepare(preparer, request); + } + Attribute attribute = attributeResolver.computeAttribute( + container, + value, + name, + role, + ignore, + defaultValue, + defaultValueRole, + defaultValueType, + request + ); + container.startContext(request); + return attribute; + } + + /** + * Renders the attribute as a string. + * + * @param attribute The attribute to use, previously resolved. + * @param container The Tiles container to use. + * @param writer The writer into which the attribute will be written. + * @param ignore If true, if an exception happens during + * rendering, of if the attribute is null, the problem will be ignored. + * @param request The request. + * @throws IOException If an I/O error happens during rendering. + */ + private void renderAttribute( + Attribute attribute, + TilesContainer container, + Writer writer, + boolean ignore, + Request request + ) throws IOException { + try { + if (attribute == null && ignore) { + return; + } + Object value = container.evaluate(attribute, request); + if (value != null) { + writer.write(value.toString()); + } + } catch (IOException | RuntimeException e) { + if (!ignore) { + throw e; + } else if (LOG.isDebugEnabled()) { + LOG.debug("Ignoring exception", e); + } + } finally { + container.endContext(request); + } + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/template/ImportAttributeModel.java b/plugins/tiles/src/main/java/org/apache/tiles/template/ImportAttributeModel.java new file mode 100644 index 000000000..ecf07bf7e --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/template/ImportAttributeModel.java @@ -0,0 +1,194 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.template; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.apache.tiles.api.Attribute; +import org.apache.tiles.api.AttributeContext; +import org.apache.tiles.api.TilesContainer; +import org.apache.tiles.api.access.TilesAccess; +import org.apache.tiles.request.Request; + +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; + +/** + *

+ * Import attribute(s) in specified context. + *

+ *

+ * Import attribute(s) to requested scope. Attribute name and scope are + * optional. If not specified, all attributes are imported in page scope. Once + * imported, an attribute can be used as any other beans from jsp contexts. + *

+ * + * @since 2.2.0 + */ +public class ImportAttributeModel { + + /** + * The logging object. + */ + private static final Logger LOG = LogManager.getLogger(ImportAttributeModel.class); + + /** + * Executes the model. + * + * @param name The name of the attribute to import. If it is + * null, all the attributes will be imported. + * @param scope The scope into which the attribute(s) will be imported. If + * null, the import will go in page scope. + * @param toName The name of the attribute into which the attribute will be + * imported. To be used in conjunction to name. If + * null, the value of name will be used. + * @param ignore If true, if the attribute is not present, the + * problem will be ignored. + * @param request The request. + */ + public void execute( + String name, + String scope, + String toName, + boolean ignore, + Request request + ) { + Map attributes = getImportedAttributes(name, toName, ignore, request); + if (scope == null) { + scope = request.getAvailableScopes().get(0); + } + request.getContext(scope).putAll(attributes); + } + + /** + * Retuns a Map that contains the attributes to be imported. The importing + * code must be done by the caller. + * + * @param name The attribute to import. If null, all the attributes will be + * imported. + * @param toName The destination name of the attribute to import. Valid only + * if name is specified. + * @param ignore If true and the attribute is not found, or an + * exception happens, the problem will be ignored. + * @param request The request. + * @return A Map of the attributes to be imported: the key is the name of an + * attribute, the value is the value of that attribute. + * @since 2.2.0 + */ + private Map getImportedAttributes(String name, String toName, boolean ignore, Request request) { + TilesContainer container = TilesAccess.getCurrentContainer(request); + Map retValue = new HashMap<>(); + AttributeContext attributeContext = container.getAttributeContext(request); + // Some tags allow for unspecified attributes. This + // implies that the tag should use all the attributes. + if (name != null) { + importSingleAttribute(container, attributeContext, name, toName, ignore, retValue, request); + } else { + importAttributes(attributeContext.getCascadedAttributeNames(), container, attributeContext, retValue, ignore, request); + importAttributes(attributeContext.getLocalAttributeNames(), container, attributeContext, retValue, ignore, request); + } + return retValue; + } + + /** + * Imports a single attribute. + * + * @param container The Tiles container to use. + * @param attributeContext The context from which the attributes will be + * got. + * @param name The name of the attribute. + * @param toName The name of the destination attribute. If null, + * name will be used. + * @param ignore If true and the attribute is not found, or an + * exception happens, the problem will be ignored. + * @param attributes The map of the attributes to fill. + * @param request The request. + */ + private void importSingleAttribute( + TilesContainer container, + AttributeContext attributeContext, + String name, String toName, + boolean ignore, + Map attributes, + Request request + ) { + Attribute attr = attributeContext.getAttribute(name); + if (attr != null) { + try { + Object attributeValue = container.evaluate(attr, + request); + if (attributeValue == null) { + if (!ignore) { + throw new NoSuchAttributeException("Error importing attributes. " + "Attribute '" + name + "' has a null value "); + } + } else { + if (toName != null) { + attributes.put(toName, attributeValue); + } else { + attributes.put(name, attributeValue); + } + } + } catch (RuntimeException e) { + if (!ignore) { + throw e; + } else if (LOG.isDebugEnabled()) { + LOG.debug("Ignoring Tiles Exception", e); + } + } + } else if (!ignore) { + throw new NoSuchAttributeException("Error importing attributes. " + "Attribute '" + name + "' is null"); + } + } + + /** + * Imports all the attributes. + * + * @param names The names of the attributes to be imported. + * @param container The Tiles container to use. + * @param attributeContext The context from which the attributes will be + * got. + * @param attributes The map of the attributes to fill. + * @param ignore If true and the attribute is not found, or an + * exception happens, the problem will be ignored. + * @param request The request. + */ + private void importAttributes( + Collection names, + TilesContainer container, + AttributeContext attributeContext, + Map attributes, + boolean ignore, + Request request + ) { + if (names == null || names.isEmpty()) { + return; + } + + for (String name : names) { + if (name == null && !ignore) { + throw new NoSuchAttributeException("Error importing attributes. Attribute with null key found."); + } else if (name == null) { + continue; + } + + importSingleAttribute(container, attributeContext, name, name, ignore, attributes, request); + } + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/template/InsertAttributeModel.java b/plugins/tiles/src/main/java/org/apache/tiles/template/InsertAttributeModel.java new file mode 100644 index 000000000..4c2ea7ef1 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/template/InsertAttributeModel.java @@ -0,0 +1,204 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.template; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.apache.tiles.api.Attribute; +import org.apache.tiles.api.TilesContainer; +import org.apache.tiles.api.access.TilesAccess; +import org.apache.tiles.autotag.core.runtime.ModelBody; +import org.apache.tiles.request.Request; + +import java.io.IOException; +import java.util.Deque; + +/** + *

+ * Inserts the value of an attribute into the page. + *

+ *

+ * This tag can be flexibly used to insert the value of an attribute into a + * page. As in other usages in Tiles, every attribute can be determined to have + * a "type", either set explicitly when it was defined, or "computed". If the + * type is not explicit, then if the attribute value is a valid definition, it + * will be inserted as such. Otherwise, if it begins with a "/" character, it + * will be treated as a "template". Finally, if it has not otherwise been + * assigned a type, it will be treated as a String and included without any + * special handling. + *

+ * + *

+ * Example : + *

+ * + *
+ * <code>
+ *           <tiles:insertAttribute name="body" />
+ *         </code>
+ * 
+ * @since 2.2.0 + */ +public class InsertAttributeModel { + + /** + * The logging object. + */ + private static final Logger LOG = LogManager.getLogger(InsertAttributeModel.class); + + /** + * The attribute resolver to use. + */ + private final AttributeResolver attributeResolver; + + /** + * Constructor that uses the defaut attribute resolver. + * + * @since 3.0.0 + */ + public InsertAttributeModel() { + this(new DefaultAttributeResolver()); + } + + /** + * Constructor. + * + * @param attributeResolver The attribute resolver to use. + * @since 2.2.0 + */ + public InsertAttributeModel(AttributeResolver attributeResolver) { + this.attributeResolver = attributeResolver; + } + + /** + * Executes the operation. + * + * @param ignore If true, if an exception happens during + * rendering, of if the attribute is null, the problem will be ignored. + * @param preparer The preparer to invoke before rendering the attribute. + * @param role A comma-separated list of roles. If present, the attribute + * will be rendered only if the current user belongs to one of the roles. + * @param defaultValue The default value of the attribute. To use only if + * the attribute was not computed. + * @param defaultValueRole The default comma-separated list of roles. To use + * only if the attribute was not computed. + * @param defaultValueType The default type of the attribute. To use only if + * the attribute was not computed. + * @param name The name of the attribute. + * @param value The attribute to use immediately, if not null. + * @param flush If true, the response will be flushed after the insert. + * @param request The request. + * @param modelBody The body. + * @throws IOException If an I/O error happens during rendering. + * @since 2.2.0 + */ + public void execute( + boolean ignore, + String preparer, + String role, + Object defaultValue, + String defaultValueRole, + String defaultValueType, + String name, + Attribute value, + boolean flush, + Request request, + ModelBody modelBody + ) throws IOException { + TilesContainer container = TilesAccess.getCurrentContainer(request); + Deque composeStack = ComposeStackUtil.getComposeStack(request); + Attribute attribute = resolveAttribute(container, ignore, preparer, + role, defaultValue, defaultValueRole, defaultValueType, name, + value, request); + if (attribute != null) { + composeStack.push(attribute); + } + modelBody.evaluateWithoutWriting(); + container = TilesAccess.getCurrentContainer(request); + if (attribute != null) { + attribute = (Attribute) composeStack.pop(); + } + renderAttribute(container, ignore, attribute, request); + if (flush) { + request.getWriter().flush(); + } + } + + /** + * Resolves the attribute. and starts the context. + * + * @param container The Tiles container to use. + * @param ignore If true, if an exception happens during + * rendering, of if the attribute is null, the problem will be ignored. + * @param preparer The preparer to invoke before rendering the attribute. + * @param role A comma-separated list of roles. If present, the attribute + * will be rendered only if the current user belongs to one of the roles. + * @param defaultValue The default value of the attribute. To use only if + * the attribute was not computed. + * @param defaultValueRole The default comma-separated list of roles. To use + * only if the attribute was not computed. + * @param defaultValueType The default type of the attribute. To use only if + * the attribute was not computed. + * @param name The name of the attribute. + * @param value The attribute to use immediately, if not null. + * @param request The request. + * @return The resolved attribute. + */ + private Attribute resolveAttribute(TilesContainer container, + boolean ignore, String preparer, String role, Object defaultValue, + String defaultValueRole, String defaultValueType, String name, + Attribute value, Request request) { + if (preparer != null) { + container.prepare(preparer, request); + } + Attribute attribute = attributeResolver.computeAttribute(container, + value, name, role, ignore, defaultValue, defaultValueRole, + defaultValueType, request); + container.startContext(request); + return attribute; + } + + /** + * Renders the attribute as a string. + * + * @param container The Tiles container to use. + * @param ignore If true, if an exception happens during + * rendering, of if the attribute is null, the problem will be ignored. + * @param attribute The attribute to use, previously resolved. + * @param request The request. + * @throws IOException If an I/O error happens during rendering. + */ + private void renderAttribute(TilesContainer container, boolean ignore, + Attribute attribute, Request request) throws IOException { + try { + if (attribute == null && ignore) { + return; + } + container.render(attribute, request); + } catch (IOException | RuntimeException e) { + if (!ignore) { + throw e; + } else if (LOG.isDebugEnabled()) { + LOG.debug("Ignoring exception", e); + } + } finally { + container.endContext(request); + } + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/template/InsertDefinitionModel.java b/plugins/tiles/src/main/java/org/apache/tiles/template/InsertDefinitionModel.java new file mode 100644 index 000000000..a34bb3760 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/template/InsertDefinitionModel.java @@ -0,0 +1,147 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tiles.template; + +import org.apache.tiles.api.Attribute; +import org.apache.tiles.api.AttributeContext; +import org.apache.tiles.api.TilesContainer; +import org.apache.tiles.api.access.TilesAccess; +import org.apache.tiles.autotag.core.runtime.ModelBody; +import org.apache.tiles.autotag.core.runtime.annotation.Parameter; +import org.apache.tiles.request.Request; + +import java.io.IOException; + +/** + *

+ * Insert a definition. + *

+ *

+ * Insert a definition with the possibility to override and specify parameters + * (called attributes). A definition can be seen as a (partially or totally) + * filled template that can override or complete attribute values. + * <tiles:insertDefinition> allows to define these attributes + * and pass them to the inserted jsp page, called template. Attributes are + * defined using nested tag <tiles:putAttribute> or + * <tiles:putListAttribute>. + *

+ *

+ * You must specify name tag attribute, for inserting a definition + * from definitions factory. + *

+ *

+ * Example : + *

+ * + *
+ * <code>
+ *           <tiles:insertDefinition name=".my.tiles.defininition flush="true">
+ *              <tiles:putAttribute name="title" value="My first page" />
+ *              <tiles:putAttribute name="header" value="/common/header.jsp" />
+ *              <tiles:putAttribute name="footer" value="/common/footer.jsp" />
+ *              <tiles:putAttribute name="menu" value="/basic/menu.jsp" />
+ *              <tiles:putAttribute name="body" value="/basic/helloBody.jsp" />
+ *           </tiles:insertDefinition>
+ *         </code>
+ * 
+ * @since 2.2.0 + */ +public class InsertDefinitionModel { + + /** + * Executes the operation. + * + * @param definitionName The name of the definition to render. + * @param template If specified, this template will be used instead of the + * one used by the definition. + * @param templateType The type of the template attribute. + * @param templateExpression The expression to evaluate to get the value of the template. + * @param role A comma-separated list of roles. If present, the definition + * will be rendered only if the current user belongs to one of the roles. + * @param preparer The preparer to use to invoke before the definition is + * rendered. If specified, it overrides the preparer specified in the + * definition itself. + * @param flush If true, the response will be flushed after the insert. + * @param request The request. + * @param modelBody The body. + * @throws IOException If something goes wrong. + * @since 2.2.0 + */ + public void execute( + @Parameter(name = "name", required = true) String definitionName, + String template, + String templateType, + String templateExpression, + String role, + String preparer, + boolean flush, + Request request, + ModelBody modelBody + ) throws IOException { + TilesContainer container = TilesAccess.getCurrentContainer(request); + container.startContext(request); + modelBody.evaluateWithoutWriting(); + container = TilesAccess.getCurrentContainer(request); + renderDefinition(container, definitionName, template, templateType, templateExpression, role, preparer, flush, request); + } + + /** + * Renders a definition. + * + * @param container The container to use. + * @param definitionName The name of the definition to render. + * @param template If specified, this template will be used instead of the + * one used by the definition. + * @param templateType The type of the template attribute. + * @param templateExpression The expression to evaluate to get the value of the template. + * @param role A comma-separated list of roles. If present, the definition + * will be rendered only if the current user belongs to one of the roles. + * @param preparer The preparer to use to invoke before the definition is + * rendered. If specified, it overrides the preparer specified in the + * definition itself. + * @param flush If true, the response will be flushed after the insert. + * @param request The request. + * @throws IOException If something goes wrong. + */ + private void renderDefinition( + TilesContainer container, + String definitionName, + String template, + String templateType, + String templateExpression, + String role, + String preparer, + boolean flush, + Request request + ) throws IOException { + try { + AttributeContext attributeContext = container.getAttributeContext(request); + Attribute templateAttribute = Attribute.createTemplateAttribute(template, templateExpression, templateType, role); + attributeContext.setPreparer(preparer); + attributeContext.setTemplateAttribute(templateAttribute); + container.render(definitionName, request); + if (flush) { + request.getWriter().flush(); + } + } finally { + container.endContext(request); + } + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/template/InsertTemplateModel.java b/plugins/tiles/src/main/java/org/apache/tiles/template/InsertTemplateModel.java new file mode 100644 index 000000000..0856e24d8 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/template/InsertTemplateModel.java @@ -0,0 +1,141 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.template; + +import org.apache.tiles.api.Attribute; +import org.apache.tiles.api.AttributeContext; +import org.apache.tiles.api.TilesContainer; +import org.apache.tiles.api.access.TilesAccess; +import org.apache.tiles.autotag.core.runtime.ModelBody; +import org.apache.tiles.autotag.core.runtime.annotation.Parameter; +import org.apache.tiles.request.Request; + +import java.io.IOException; + +/** + *

+ * Insert a template. + *

+ *

+ * Insert a template with the possibility to pass parameters (called + * attributes). A template can be seen as a procedure that can take parameters + * or attributes. <tiles:insertTemplate> allows to define + * these attributes and pass them to the inserted jsp page, called template. + * Attributes are defined using nested tag + * <tiles:putAttribute> or + * <tiles:putListAttribute>. + *

+ *

+ * You must specify template attribute, for inserting a template + *

+ * + *

+ * Example : + *

+ * + *
+ * <code>
+ *           <tiles:insertTemplate template="/basic/myLayout.jsp" flush="true">
+ *              <tiles:putAttribute name="title" value="My first page" />
+ *              <tiles:putAttribute name="header" value="/common/header.jsp" />
+ *              <tiles:putAttribute name="footer" value="/common/footer.jsp" />
+ *              <tiles:putAttribute name="menu" value="/basic/menu.jsp" />
+ *              <tiles:putAttribute name="body" value="/basic/helloBody.jsp" />
+ *           </tiles:insertTemplate>
+ *         </code>
+ * 
+ * + * @since 2.2.0 + */ +public class InsertTemplateModel { + + /** + * Executes the operation. + * + * @param template The template to render. + * @param templateType The type of the template attribute. + * @param templateExpression The expression to evaluate to get the value of the template. + * @param role A comma-separated list of roles. If present, the template + * will be rendered only if the current user belongs to one of the roles. + * @param preparer The preparer to use to invoke before the definition is + * rendered. If specified, it overrides the preparer specified in the + * definition itself. + * @param flush If true, the response will be flushed after the insert. + * @param request The request. + * @param modelBody The body. + * @throws IOException If something goes wrong. + * @since 2.2.0 + */ + public void execute( + @Parameter(required = true) String template, + String templateType, + String templateExpression, + String role, + String preparer, + boolean flush, + Request request, + ModelBody modelBody + ) throws IOException { + TilesContainer container = TilesAccess.getCurrentContainer(request); + container.startContext(request); + modelBody.evaluateWithoutWriting(); + container = TilesAccess.getCurrentContainer(request); + renderTemplate(container, template, templateType, templateExpression, role, preparer, flush, request); + } + + /** + * Renders a template. + * + * @param container The container to use. + * @param template The template to render. + * @param templateType The type of the template attribute. + * @param templateExpression The expression to evaluate to get the value of the template. + * @param role A comma-separated list of roles. If present, the template + * will be rendered only if the current user belongs to one of the roles. + * @param preparer The preparer to use to invoke before the definition is + * rendered. If specified, it overrides the preparer specified in the + * definition itself. + * @param flush If true, the response will be flushed after the insert. + * @param request The request. + * @throws IOException If something goes wrong. + */ + private void renderTemplate( + TilesContainer container, + String template, + String templateType, + String templateExpression, + String role, + String preparer, + boolean flush, + Request request + ) throws IOException { + try { + AttributeContext attributeContext = container.getAttributeContext(request); + Attribute templateAttribute = Attribute.createTemplateAttribute(template, templateExpression, templateType, role); + attributeContext.setPreparer(preparer); + attributeContext.setTemplateAttribute(templateAttribute); + container.renderContext(request); + if (flush) { + request.getWriter().flush(); + } + } finally { + container.endContext(request); + } + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/template/NoSuchAttributeException.java b/plugins/tiles/src/main/java/org/apache/tiles/template/NoSuchAttributeException.java new file mode 100644 index 000000000..5de6b0f18 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/template/NoSuchAttributeException.java @@ -0,0 +1,40 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.template; + +import org.apache.tiles.api.TilesException; + +/** + * Indicates that a named attribute has not been found. + * + * @since 2.2.0 + */ +public class NoSuchAttributeException extends TilesException { + + /** + * Constructor. + * + * @param message The detail message. + * @since 2.2.0 + */ + public NoSuchAttributeException(String message) { + super(message); + } + +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/template/PutAttributeModel.java b/plugins/tiles/src/main/java/org/apache/tiles/template/PutAttributeModel.java new file mode 100644 index 000000000..9391f14bf --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/template/PutAttributeModel.java @@ -0,0 +1,165 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.template; + +import org.apache.tiles.api.Attribute; +import org.apache.tiles.api.AttributeContext; +import org.apache.tiles.api.Expression; +import org.apache.tiles.api.TilesContainer; +import org.apache.tiles.api.access.TilesAccess; +import org.apache.tiles.autotag.core.runtime.ModelBody; +import org.apache.tiles.autotag.core.runtime.annotation.Parameter; +import org.apache.tiles.request.Request; + +import java.io.IOException; +import java.util.Deque; + +/** + *

+ * Put an attribute in enclosing attribute container tag. + *

+ *

+ * Enclosing attribute container tag can be : + *

    + *
  • <initContainer>
  • + *
  • <definition>
  • + *
  • <insertAttribute>
  • + *
  • <insertDefinition>
  • + *
  • <putListAttribute>
  • + *
+ * (or any other tag which implements the PutAttributeTagParent + * interface. Exception is thrown if no appropriate tag can be found. + *

+ *

+ * Put tag can have following atributes : + *

    + *
  • name : Name of the attribute
  • + *
  • value : value to put as attribute
  • + *
  • type : value type. Possible type are : string (value is used as direct + * string), template (value is used as a page url to insert), definition (value + * is used as a definition name to insert), object (value is used as it is)
  • + *
  • role : Role to check when 'insertAttribute' will be called.
  • + *
+ *

+ *

+ * Value can also come from tag body. Tag body is taken into account only if + * value is not set by one of the tag attributes. In this case Attribute type is + * "string", unless tag body define another type. + *

+ * + * @since 2.2.0 + */ +public class PutAttributeModel { + + /** + * Executes the operation. + * + * @param name The name of the attribute to put. + * @param value The value of the attribute. Use this parameter, or + * expression, or body. + * @param expression The expression to calculate the value from. Use this + * parameter, or value, or body. + * @param role A comma-separated list of roles. If present, the attribute + * will be rendered only if the current user belongs to one of the roles. + * @param type The type (renderer) of the attribute. + * @param cascade If true the attribute will be cascaded to all nested attributes. + * @param request The request. + * @param modelBody The body. + * @throws IOException If the body cannot be evaluated. + * @since 2.2.0 + */ + public void execute( + @Parameter(required = true) String name, + Object value, + String expression, + String role, + String type, + boolean cascade, + Request request, + ModelBody modelBody + ) throws IOException { + Deque composeStack = ComposeStackUtil.getComposeStack(request); + Attribute attribute = new Attribute(); + composeStack.push(attribute); + String currentBody = modelBody.evaluateAsString(); + TilesContainer container = TilesAccess.getCurrentContainer(request); + attribute = (Attribute) composeStack.pop(); + putAttributeInParent(attribute, container, composeStack, name, value, expression, currentBody, role, type, cascade, request); + } + + /** + * Determines the parent and puts the attribute inside it. + * + * @param attribute The attribute to put; + * @param container The Tiles container to use. + * @param composeStack The composing stack. + * @param name The name of the attribute to put. + * @param value The value of the attribute. Use this parameter, or + * expression, or body. + * @param expression The expression to calculate the value from. Use this + * parameter, or value, or body. + * @param body The body of the tag. Use this parameter, or value, or + * expression. + * @param role A comma-separated list of roles. If present, the attribute + * will be rendered only if the current user belongs to one of the roles. + * @param type The type (renderer) of the attribute. + * @param cascade If true the attribute will be cascaded to all nested attributes. + * @param request The request. + */ + private void putAttributeInParent( + Attribute attribute, + TilesContainer container, + Deque composeStack, + String name, + Object value, + String expression, + String body, + String role, + String type, + boolean cascade, + Request request + ) { + AttributeContext attributeContext = null; + if (!composeStack.isEmpty()) { + Object obj = composeStack.peek(); + if (obj instanceof AttributeContext) { + attributeContext = (AttributeContext) obj; + } + } + if (attributeContext == null) { + attributeContext = container.getAttributeContext(request); + } + if (value != null) { + attribute.setValue(value); + } else if (attribute.getValue() == null && body != null) { + attribute.setValue(body); + } + if (expression != null) { + attribute.setExpressionObject(Expression.createExpressionFromDescribedExpression(expression)); + } + if (role != null) { + attribute.setRole(role); + } + if (type != null) { + attribute.setRenderer(type); + } + + attributeContext.putAttribute(name, attribute, cascade); + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/template/PutListAttributeModel.java b/plugins/tiles/src/main/java/org/apache/tiles/template/PutListAttributeModel.java new file mode 100644 index 000000000..30e858802 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/template/PutListAttributeModel.java @@ -0,0 +1,88 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.template; + +import org.apache.tiles.api.AttributeContext; +import org.apache.tiles.api.Definition; +import org.apache.tiles.api.ListAttribute; +import org.apache.tiles.api.TilesContainer; +import org.apache.tiles.api.access.TilesAccess; +import org.apache.tiles.autotag.core.runtime.ModelBody; +import org.apache.tiles.autotag.core.runtime.annotation.Parameter; +import org.apache.tiles.request.Request; + +import java.io.IOException; +import java.util.Deque; + +/** + *

+ * Declare a list that will be pass as attribute to tile. + *

+ *

+ * Declare a list that will be pass as attribute to tile. List elements are + * added using the tags 'addAttribute' or 'addListAttribute'. This tag can only + * be used inside 'insertTemplate', 'insertDefinition', 'definition' tags. + *

+ * + * @since 2.2.0 + */ +public class PutListAttributeModel { + + /** + * Executes the model. + * + * @param name The name of the attribute to put. + * @param role A comma-separated list of roles. If present, the attribute + * will be rendered only if the current user belongs to one of the roles. + * @param inherit If true, the list attribute will use, as first elements, the + * list contained in the list attribute, put with the same name, of the containing definition. + * @param cascade If true the attribute will be cascaded to all nested attributes. + * @param request The request. + * @param modelBody The body. + * @throws IOException If the body cannot be evaluated. + */ + public void execute( + @Parameter(required = true) String name, + String role, + boolean inherit, + boolean cascade, + Request request, + ModelBody modelBody + ) throws IOException { + Deque composeStack = ComposeStackUtil.getComposeStack(request); + ListAttribute listAttribute = new ListAttribute(); + listAttribute.setRole(role); + listAttribute.setInherit(inherit); + composeStack.push(listAttribute); + modelBody.evaluateWithoutWriting(); + TilesContainer container = TilesAccess.getCurrentContainer(request); + listAttribute = (ListAttribute) composeStack.pop(); + AttributeContext attributeContext = null; + if (!composeStack.isEmpty()) { + Object obj = composeStack.peek(); + if (obj instanceof Definition) { + attributeContext = (AttributeContext) obj; + } + } + if (attributeContext == null) { + attributeContext = container.getAttributeContext(request); + } + attributeContext.putAttribute(name, listAttribute, cascade); + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/template/SetCurrentContainerModel.java b/plugins/tiles/src/main/java/org/apache/tiles/template/SetCurrentContainerModel.java new file mode 100644 index 000000000..80b7174ed --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/template/SetCurrentContainerModel.java @@ -0,0 +1,41 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.template; + +import org.apache.tiles.api.access.TilesAccess; +import org.apache.tiles.request.Request; + +/** + * Selects a container to be used as the "current" container. + * + * @since 3.0.0 + */ +public class SetCurrentContainerModel { + + /** + * Executes the model. + * + * @param containerKey The key of the container to be used as "current". If + * null, the default one will be used. + * @param request The request. + */ + public void execute(String containerKey, Request request) { + TilesAccess.setCurrentContainer(request, containerKey); + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/template/package-info.java b/plugins/tiles/src/main/java/org/apache/tiles/template/package-info.java new file mode 100644 index 000000000..828b7ac3d --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/template/package-info.java @@ -0,0 +1,24 @@ +/* + * $Id: package-info.java 1049711 2010-12-15 21:12:00Z apetrelli $ + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +/** + * Tiles template classes, that enable to write support code for template languages (JSP, FreeMarker, Velocity). + */ +package org.apache.tiles.template; diff --git a/plugins/tiles/src/main/java/org/apache/tiles/velocity/TilesVelocityException.java b/plugins/tiles/src/main/java/org/apache/tiles/velocity/TilesVelocityException.java new file mode 100644 index 000000000..165bce373 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/velocity/TilesVelocityException.java @@ -0,0 +1,71 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tiles.velocity; + +import org.apache.tiles.api.TilesException; + +/** + * Exception connected to the usage of Velocity and Tiles. + * + * @since 2.2.0 + */ +public class TilesVelocityException extends TilesException { + + private static final long serialVersionUID = -7013866521398042363L; + + /** + * Constructor. + * + * @since 2.2.0 + */ + public TilesVelocityException() { + } + + /** + * Constructor. + * + * @param message The message of the exception. + * @since 2.2.0 + */ + public TilesVelocityException(String message) { + super(message); + } + + /** + * Constructor. + * + * @param e The cause of the exception. + * @since 2.2.0 + */ + public TilesVelocityException(Throwable e) { + super(e); + } + + /** + * Constructor. + * + * @param message The message of the exception. + * @param e The cause of the exception. + * @since 2.2.0 + */ + public TilesVelocityException(String message, Throwable e) { + super(message, e); + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/velocity/package-info.java b/plugins/tiles/src/main/java/org/apache/tiles/velocity/package-info.java new file mode 100644 index 000000000..084432124 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/velocity/package-info.java @@ -0,0 +1,22 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +/** + * Classes to support Velocity under a servlet environment in Tiles. + */ +package org.apache.tiles.velocity; diff --git a/plugins/tiles/src/main/java/org/apache/tiles/velocity/template/AbstractDefaultToStringRenderable.java b/plugins/tiles/src/main/java/org/apache/tiles/velocity/template/AbstractDefaultToStringRenderable.java new file mode 100644 index 000000000..3628833bb --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/velocity/template/AbstractDefaultToStringRenderable.java @@ -0,0 +1,119 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tiles.velocity.template; + +import java.io.IOException; +import java.io.StringWriter; +import java.util.Map; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.tiles.velocity.TilesVelocityException; +import org.apache.velocity.context.Context; +import org.apache.velocity.exception.MethodInvocationException; +import org.apache.velocity.exception.ParseErrorException; +import org.apache.velocity.exception.ResourceNotFoundException; +import org.apache.velocity.runtime.Renderable; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Renderable that provides a default implementation of Renderable#toString() + * and allows access to parameters and context objects. + * + * @since 2.2.0 + */ +public abstract class AbstractDefaultToStringRenderable implements Renderable { + + /** + * The Velocity context. + * + * @since 2.2.0 + */ + protected final Context velocityContext; + + /** + * The parameters used in the current tool call. + * + * @since 2.2.0 + */ + protected final Map params; + + /** + * The HTTP response. + * + * @since 2.2.0 + */ + protected final HttpServletResponse response; + + /** + * The HTTP request. + * + * @since 2.2.0 + */ + protected final HttpServletRequest request; + + /** + * The logging object. + */ + private final Logger log = LoggerFactory.getLogger(getClass()); + + /** + * Constructor. + * + * @param velocityContext The Velocity context. + * @param params The parameters used in the current tool call. + * @param response The HTTP response. + * @param request The HTTP request. + * @since 2.2.0 + */ + public AbstractDefaultToStringRenderable(Context velocityContext, Map params, + HttpServletResponse response, HttpServletRequest request) { + this.velocityContext = velocityContext; + this.params = params; + this.response = response; + this.request = request; + } + + /** {@inheritDoc} */ + @Override + public String toString() { + StringWriter writer = new StringWriter(); + try { + render(null, writer); + } catch (MethodInvocationException e) { + throw new TilesVelocityException("Cannot invoke method when rendering", e); + } catch (ParseErrorException e) { + throw new TilesVelocityException("Cannot parse when rendering", e); + } catch (ResourceNotFoundException e) { + throw new TilesVelocityException("Cannot find resource when rendering", e); + } catch (IOException e) { + throw new TilesVelocityException("I/O exception when rendering", e); + } finally { + try { + writer.close(); + } catch (IOException e) { + log.error("Error when closing a StringWriter, the impossible happened!", e); + } + } + return writer.toString(); + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/velocity/template/AddAttributeDirective.java b/plugins/tiles/src/main/java/org/apache/tiles/velocity/template/AddAttributeDirective.java new file mode 100644 index 000000000..49f6c3112 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/velocity/template/AddAttributeDirective.java @@ -0,0 +1,78 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +/* + * This file was automatically generated by Autotag. Please do not edit it manually. + */ +package org.apache.tiles.velocity.template; + +import java.io.IOException; +import java.io.Writer; + +import org.apache.tiles.autotag.core.runtime.ModelBody; +import org.apache.tiles.autotag.core.runtime.AutotagRuntime; +import org.apache.velocity.context.InternalContextAdapter; +import org.apache.velocity.runtime.directive.Directive; +import org.apache.velocity.runtime.parser.node.Node; + +/** + *

+ * Add an element to the surrounding list. Equivalent to 'putAttribute', but for + * list element. + *

+ * + *

+ * Add an element to the surrounding list. This tag can only be used inside + * 'putListAttribute' or 'addListAttribute' tags. Value can come from a direct + * assignment (value="aValue") + *

+ */ +public class AddAttributeDirective extends Directive { + + /** + * The template model. + */ + private org.apache.tiles.template.AddAttributeModel model = new org.apache.tiles.template.AddAttributeModel(); + + @Override + public String getName() { + return "tiles_addAttribute"; + } + + @Override + public int getType() { + return BLOCK; + } + + @Override + public boolean render(InternalContextAdapter context, Writer writer, Node node) throws IOException { + AutotagRuntime runtime = new org.apache.tiles.request.velocity.autotag.VelocityAutotagRuntime(); + if (runtime instanceof Directive) { + ((Directive) runtime).render(context, writer, node); + } + org.apache.tiles.request.Request request = runtime.createRequest(); + ModelBody modelBody = runtime.createModelBody(); + model.execute(runtime.getParameter("value", java.lang.Object.class, null), + runtime.getParameter("expression", java.lang.String.class, null), + runtime.getParameter("role", java.lang.String.class, null), + runtime.getParameter("type", java.lang.String.class, null), request, modelBody + + ); + return true; + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/velocity/template/AddListAttributeDirective.java b/plugins/tiles/src/main/java/org/apache/tiles/velocity/template/AddListAttributeDirective.java new file mode 100644 index 000000000..b42b120b0 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/velocity/template/AddListAttributeDirective.java @@ -0,0 +1,73 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +/* + * This file was automatically generated by Autotag. Please do not edit it manually. + */ +package org.apache.tiles.velocity.template; + +import java.io.IOException; +import java.io.Writer; + +import org.apache.tiles.autotag.core.runtime.ModelBody; +import org.apache.tiles.autotag.core.runtime.AutotagRuntime; +import org.apache.velocity.context.InternalContextAdapter; +import org.apache.velocity.runtime.directive.Directive; +import org.apache.velocity.runtime.parser.node.Node; + +/** + *

+ * Declare a list that will be pass as an attribute. + *

+ *

+ * Declare a list that will be pass as an attribute . List elements are added + * using the tag 'addAttribute' or 'addListAttribute'. This tag can only be used + * inside 'insertTemplate', 'insertDefinition' or 'definition' tag. + *

+ */ +public class AddListAttributeDirective extends Directive { + + /** + * The template model. + */ + private org.apache.tiles.template.AddListAttributeModel model = new org.apache.tiles.template.AddListAttributeModel(); + + @Override + public String getName() { + return "tiles_addListAttribute"; + } + + @Override + public int getType() { + return BLOCK; + } + + @Override + public boolean render(InternalContextAdapter context, Writer writer, Node node) throws IOException { + AutotagRuntime runtime = new org.apache.tiles.request.velocity.autotag.VelocityAutotagRuntime(); + if (runtime instanceof Directive) { + ((Directive) runtime).render(context, writer, node); + } + org.apache.tiles.request.Request request = runtime.createRequest(); + ModelBody modelBody = runtime.createModelBody(); + model.execute(runtime.getParameter("role", java.lang.String.class, null), request, modelBody + + ); + return true; + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/velocity/template/ContextHolder.java b/plugins/tiles/src/main/java/org/apache/tiles/velocity/template/ContextHolder.java new file mode 100644 index 000000000..ad43f3941 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/velocity/template/ContextHolder.java @@ -0,0 +1,154 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tiles.velocity.template; + +import javax.servlet.ServletContext; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.velocity.context.Context; + +/** + * An object that holds the current state of Velocity in a Servlet environment. + * + * @since 2.2.0 + */ +public class ContextHolder { + + /** + * The Velocity context. + */ + private Context velocityContext; + + /** + * The HTTP request. + */ + private HttpServletRequest request; + + /** + * The HTTP response. + */ + private HttpServletResponse response; + + /** + * The servlet context. + */ + private ServletContext application; + + /** + * Sets the current {@link HttpServletRequest}. This is required for this tool + * to operate and will throw a NullPointerException if this is not set or is set + * to {@code null}. + * + * @param request The HTTP request. + * @since 2.2.0 + */ + public void setRequest(HttpServletRequest request) { + if (request == null) { + throw new NullPointerException("request should not be null"); + } + this.request = request; + } + + /** + * Sets the current {@link HttpServletResponse}. This is required for this tool + * to operate and will throw a NullPointerException if this is not set or is set + * to {@code null}. + * + * @param response The HTTP response. + * @since 2.2.0 + */ + public void setResponse(HttpServletResponse response) { + if (response == null) { + throw new NullPointerException("response should not be null"); + } + this.response = response; + } + + /** + * Sets the {@link ServletContext}. This is required for this tool to operate + * and will throw a NullPointerException if this is not set or is set to + * {@code null}. + * + * @param application The Servlet context. + * @since 2.2.0 + */ + public void setServletContext(ServletContext application) { + if (application == null) { + throw new NullPointerException("servlet context should not be null"); + } + this.application = application; + } + + /** + * Sets the Velocity {@link Context}. This is required for this tool to operate + * and will throw a NullPointerException if this is not set or is set to + * {@code null}. + * + * @param context The Velocity context. + * @since 2.2.0 + */ + public void setVelocityContext(Context context) { + if (context == null) { + throw new NullPointerException("velocity context should not be null"); + } + this.velocityContext = context; + } + + /** + * Returns the HTTP request. + * + * @return The HTTP request. + * @since 2.2.0 + */ + protected HttpServletRequest getRequest() { + return request; + } + + /** + * Returns the HTTP response. + * + * @return The HTTP response. + * @since 2.2.0 + */ + protected HttpServletResponse getResponse() { + return response; + } + + /** + * Returns the Servlet context. + * + * @return The Servlet context.. + * @since 2.2.0 + */ + protected ServletContext getServletContext() { + return application; + } + + /** + * Returns the Velocity context.. + * + * @return The Velocity context. + * @since 2.2.0 + */ + protected Context getVelocityContext() { + return velocityContext; + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/velocity/template/DefinitionDirective.java b/plugins/tiles/src/main/java/org/apache/tiles/velocity/template/DefinitionDirective.java new file mode 100644 index 000000000..90373e332 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/velocity/template/DefinitionDirective.java @@ -0,0 +1,76 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +/* + * This file was automatically generated by Autotag. Please do not edit it manually. + */ +package org.apache.tiles.velocity.template; + +import java.io.IOException; +import java.io.Writer; + +import org.apache.tiles.autotag.core.runtime.ModelBody; +import org.apache.tiles.autotag.core.runtime.AutotagRuntime; +import org.apache.velocity.context.InternalContextAdapter; +import org.apache.velocity.runtime.directive.Directive; +import org.apache.velocity.runtime.parser.node.Node; + +/** + *

+ * Create a definition at runtime. + *

+ *

+ * Create a new definition at runtime. Newly created definition will be + * available across the entire request. + *

+ */ +public class DefinitionDirective extends Directive { + + /** + * The template model. + */ + private org.apache.tiles.template.DefinitionModel model = new org.apache.tiles.template.DefinitionModel(); + + @Override + public String getName() { + return "tiles_definition"; + } + + @Override + public int getType() { + return BLOCK; + } + + @Override + public boolean render(InternalContextAdapter context, Writer writer, Node node) throws IOException { + AutotagRuntime runtime = new org.apache.tiles.request.velocity.autotag.VelocityAutotagRuntime(); + if (runtime instanceof Directive) { + ((Directive) runtime).render(context, writer, node); + } + org.apache.tiles.request.Request request = runtime.createRequest(); + ModelBody modelBody = runtime.createModelBody(); + model.execute(runtime.getParameter("name", java.lang.String.class, null), + runtime.getParameter("template", java.lang.String.class, null), + runtime.getParameter("role", java.lang.String.class, null), + runtime.getParameter("extends", java.lang.String.class, null), + runtime.getParameter("preparer", java.lang.String.class, null), request, modelBody + + ); + return true; + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/velocity/template/GetAsStringDirective.java b/plugins/tiles/src/main/java/org/apache/tiles/velocity/template/GetAsStringDirective.java new file mode 100644 index 000000000..24109ab3f --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/velocity/template/GetAsStringDirective.java @@ -0,0 +1,81 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +/* + * This file was automatically generated by Autotag. Please do not edit it manually. + */ +package org.apache.tiles.velocity.template; + +import java.io.IOException; +import java.io.Writer; + +import org.apache.tiles.autotag.core.runtime.ModelBody; +import org.apache.tiles.autotag.core.runtime.AutotagRuntime; +import org.apache.velocity.context.InternalContextAdapter; +import org.apache.velocity.runtime.directive.Directive; +import org.apache.velocity.runtime.parser.node.Node; + +/** + *

+ * Render the value of the specified template attribute to the current Writer + *

+ * + *

+ * Retrieve the value of the specified template attribute property, and render + * it to the current Writer as a String. The usual toString() conversions is + * applied on found value. + *

+ */ +public class GetAsStringDirective extends Directive { + + /** + * The template model. + */ + private org.apache.tiles.template.GetAsStringModel model = new org.apache.tiles.template.GetAsStringModel(); + + @Override + public String getName() { + return "tiles_getAsString"; + } + + @Override + public int getType() { + return BLOCK; + } + + @Override + public boolean render(InternalContextAdapter context, Writer writer, Node node) throws IOException { + AutotagRuntime runtime = new org.apache.tiles.request.velocity.autotag.VelocityAutotagRuntime(); + if (runtime instanceof Directive) { + ((Directive) runtime).render(context, writer, node); + } + org.apache.tiles.request.Request request = runtime.createRequest(); + ModelBody modelBody = runtime.createModelBody(); + model.execute(runtime.getParameter("ignore", java.lang.Boolean.class, false), + runtime.getParameter("preparer", java.lang.String.class, null), + runtime.getParameter("role", java.lang.String.class, null), + runtime.getParameter("defaultValue", java.lang.Object.class, null), + runtime.getParameter("defaultValueRole", java.lang.String.class, null), + runtime.getParameter("defaultValueType", java.lang.String.class, null), + runtime.getParameter("name", java.lang.String.class, null), + runtime.getParameter("value", org.apache.tiles.api.Attribute.class, null), request, modelBody + + ); + return true; + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/velocity/template/ImportAttributeDirective.java b/plugins/tiles/src/main/java/org/apache/tiles/velocity/template/ImportAttributeDirective.java new file mode 100644 index 000000000..7fa6f4f9f --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/velocity/template/ImportAttributeDirective.java @@ -0,0 +1,74 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +/* + * This file was automatically generated by Autotag. Please do not edit it manually. + */ +package org.apache.tiles.velocity.template; + +import java.io.IOException; +import java.io.Writer; + +import org.apache.tiles.autotag.core.runtime.AutotagRuntime; +import org.apache.velocity.context.InternalContextAdapter; +import org.apache.velocity.runtime.directive.Directive; +import org.apache.velocity.runtime.parser.node.Node; + +/** + *

+ * Import attribute(s) in specified context. + *

+ *

+ * Import attribute(s) to requested scope. Attribute name and scope are + * optional. If not specified, all attributes are imported in page scope. Once + * imported, an attribute can be used as any other beans from jsp contexts. + *

+ */ +public class ImportAttributeDirective extends Directive { + + /** + * The template model. + */ + private org.apache.tiles.template.ImportAttributeModel model = new org.apache.tiles.template.ImportAttributeModel(); + + @Override + public String getName() { + return "tiles_importAttribute"; + } + + @Override + public int getType() { + return LINE; + } + + @Override + public boolean render(InternalContextAdapter context, Writer writer, Node node) throws IOException { + AutotagRuntime runtime = new org.apache.tiles.request.velocity.autotag.VelocityAutotagRuntime(); + if (runtime instanceof Directive) { + ((Directive) runtime).render(context, writer, node); + } + org.apache.tiles.request.Request request = runtime.createRequest(); + model.execute(runtime.getParameter("name", java.lang.String.class, null), + runtime.getParameter("scope", java.lang.String.class, null), + runtime.getParameter("toName", java.lang.String.class, null), + runtime.getParameter("ignore", java.lang.Boolean.class, false), request + + ); + return true; + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/velocity/template/InsertAttributeDirective.java b/plugins/tiles/src/main/java/org/apache/tiles/velocity/template/InsertAttributeDirective.java new file mode 100644 index 000000000..4a980cd1d --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/velocity/template/InsertAttributeDirective.java @@ -0,0 +1,94 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +/* + * This file was automatically generated by Autotag. Please do not edit it manually. + */ +package org.apache.tiles.velocity.template; + +import java.io.IOException; +import java.io.Writer; + +import org.apache.tiles.autotag.core.runtime.ModelBody; +import org.apache.tiles.autotag.core.runtime.AutotagRuntime; +import org.apache.velocity.context.InternalContextAdapter; +import org.apache.velocity.runtime.directive.Directive; +import org.apache.velocity.runtime.parser.node.Node; + +/** + *

+ * Inserts the value of an attribute into the page. + *

+ *

+ * This tag can be flexibly used to insert the value of an attribute into a + * page. As in other usages in Tiles, every attribute can be determined to have + * a "type", either set explicitly when it was defined, or "computed". If the + * type is not explicit, then if the attribute value is a valid definition, it + * will be inserted as such. Otherwise, if it begins with a "/" character, it + * will be treated as a "template". Finally, if it has not otherwise been + * assigned a type, it will be treated as a String and included without any + * special handling. + *

+ * + *

+ * Example : + *

+ * + *
+ *     <tiles:insertAttribute name="body" />
+ * 
+ */ +public class InsertAttributeDirective extends Directive { + + /** + * The template model. + */ + private org.apache.tiles.template.InsertAttributeModel model = new org.apache.tiles.template.InsertAttributeModel(); + + @Override + public String getName() { + return "tiles_insertAttribute"; + } + + @Override + public int getType() { + return BLOCK; + } + + @Override + public boolean render(InternalContextAdapter context, Writer writer, Node node) throws IOException { + AutotagRuntime runtime = new org.apache.tiles.request.velocity.autotag.VelocityAutotagRuntime(); + if (runtime instanceof Directive) { + ((Directive) runtime).render(context, writer, node); + } + org.apache.tiles.request.Request request = runtime.createRequest(); + ModelBody modelBody = runtime.createModelBody(); + model.execute(runtime.getParameter("ignore", java.lang.Boolean.class, false), + runtime.getParameter("preparer", java.lang.String.class, null), + runtime.getParameter("role", java.lang.String.class, null), + runtime.getParameter("defaultValue", java.lang.Object.class, null), + runtime.getParameter("defaultValueRole", java.lang.String.class, null), + runtime.getParameter("defaultValueType", java.lang.String.class, null), + runtime.getParameter("name", java.lang.String.class, null), + runtime.getParameter("value", org.apache.tiles.api.Attribute.class, null), + runtime.getParameter("flush", java.lang.Boolean.class, false), request, modelBody + + ); + return true; + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/velocity/template/InsertDefinitionDirective.java b/plugins/tiles/src/main/java/org/apache/tiles/velocity/template/InsertDefinitionDirective.java new file mode 100644 index 000000000..51a098882 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/velocity/template/InsertDefinitionDirective.java @@ -0,0 +1,99 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +/* + * This file was automatically generated by Autotag. Please do not edit it manually. + */ +package org.apache.tiles.velocity.template; + +import java.io.IOException; +import java.io.Writer; + +import org.apache.tiles.autotag.core.runtime.ModelBody; +import org.apache.tiles.autotag.core.runtime.AutotagRuntime; +import org.apache.velocity.context.InternalContextAdapter; +import org.apache.velocity.runtime.directive.Directive; +import org.apache.velocity.runtime.parser.node.Node; + +/** + *

+ * Insert a definition. + *

+ *

+ * Insert a definition with the possibility to override and specify parameters + * (called attributes). A definition can be seen as a (partially or totally) + * filled template that can override or complete attribute values. + * <tiles:insertDefinition> allows to define these attributes and pass + * them to the inserted jsp page, called template. Attributes are defined using + * nested tag <tiles:putAttribute> or <tiles:putListAttribute>. + *

+ *

+ * You must specify name tag attribute, for inserting a definition from + * definitions factory. + *

+ *

+ * Example : + *

+ * + *
+ *     <tiles:insertDefinition name=".my.tiles.defininition flush="true">
+ *         <tiles:putAttribute name="title" value="My first page" />
+ *         <tiles:putAttribute name="header" value="/common/header.jsp" />
+ *         <tiles:putAttribute name="footer" value="/common/footer.jsp" />
+ *         <tiles:putAttribute name="menu" value="/basic/menu.jsp" />
+ *         <tiles:putAttribute name="body" value="/basic/helloBody.jsp" />
+ *     </tiles:insertDefinition>
+ * 
+ */ +public class InsertDefinitionDirective extends Directive { + + /** + * The template model. + */ + private org.apache.tiles.template.InsertDefinitionModel model = new org.apache.tiles.template.InsertDefinitionModel(); + + @Override + public String getName() { + return "tiles_insertDefinition"; + } + + @Override + public int getType() { + return BLOCK; + } + + @Override + public boolean render(InternalContextAdapter context, Writer writer, Node node) throws IOException { + AutotagRuntime runtime = new org.apache.tiles.request.velocity.autotag.VelocityAutotagRuntime(); + if (runtime instanceof Directive) { + ((Directive) runtime).render(context, writer, node); + } + org.apache.tiles.request.Request request = runtime.createRequest(); + ModelBody modelBody = runtime.createModelBody(); + model.execute(runtime.getParameter("name", java.lang.String.class, null), + runtime.getParameter("template", java.lang.String.class, null), + runtime.getParameter("templateType", java.lang.String.class, null), + runtime.getParameter("templateExpression", java.lang.String.class, null), + runtime.getParameter("role", java.lang.String.class, null), + runtime.getParameter("preparer", java.lang.String.class, null), + runtime.getParameter("flush", java.lang.Boolean.class, false), request, modelBody + + ); + return true; + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/velocity/template/InsertTemplateDirective.java b/plugins/tiles/src/main/java/org/apache/tiles/velocity/template/InsertTemplateDirective.java new file mode 100644 index 000000000..1ce0e53df --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/velocity/template/InsertTemplateDirective.java @@ -0,0 +1,98 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +/* + * This file was automatically generated by Autotag. Please do not edit it manually. + */ +package org.apache.tiles.velocity.template; + +import java.io.IOException; +import java.io.Writer; + +import org.apache.tiles.autotag.core.runtime.ModelBody; +import org.apache.tiles.autotag.core.runtime.AutotagRuntime; +import org.apache.velocity.context.InternalContextAdapter; +import org.apache.velocity.runtime.directive.Directive; +import org.apache.velocity.runtime.parser.node.Node; + +/** + *

+ * Insert a template. + *

+ *

+ * Insert a template with the possibility to pass parameters (called + * attributes). A template can be seen as a procedure that can take parameters + * or attributes. <tiles:insertTemplate> allows to define these attributes + * and pass them to the inserted jsp page, called template. Attributes are + * defined using nested tag <tiles:putAttribute> or + * <tiles:putListAttribute>. + *

+ *

+ * You must specify template attribute, for inserting a template + *

+ * + *

+ * Example : + *

+ * + *
+ *     <tiles:insertTemplate template="/basic/myLayout.jsp" flush="true">
+ *         <tiles:putAttribute name="title" value="My first page" />
+ *         <tiles:putAttribute name="header" value="/common/header.jsp" />
+ *         <tiles:putAttribute name="footer" value="/common/footer.jsp" />
+ *         <tiles:putAttribute name="menu" value="/basic/menu.jsp" />
+ *         <tiles:putAttribute name="body" value="/basic/helloBody.jsp" />
+ *     </tiles:insertTemplate>
+ * 
+ */ +public class InsertTemplateDirective extends Directive { + + /** + * The template model. + */ + private org.apache.tiles.template.InsertTemplateModel model = new org.apache.tiles.template.InsertTemplateModel(); + + @Override + public String getName() { + return "tiles_insertTemplate"; + } + + @Override + public int getType() { + return BLOCK; + } + + @Override + public boolean render(InternalContextAdapter context, Writer writer, Node node) throws IOException { + AutotagRuntime runtime = new org.apache.tiles.request.velocity.autotag.VelocityAutotagRuntime(); + if (runtime instanceof Directive) { + ((Directive) runtime).render(context, writer, node); + } + org.apache.tiles.request.Request request = runtime.createRequest(); + ModelBody modelBody = runtime.createModelBody(); + model.execute(runtime.getParameter("template", java.lang.String.class, null), + runtime.getParameter("templateType", java.lang.String.class, null), + runtime.getParameter("templateExpression", java.lang.String.class, null), + runtime.getParameter("role", java.lang.String.class, null), + runtime.getParameter("preparer", java.lang.String.class, null), + runtime.getParameter("flush", java.lang.Boolean.class, false), request, modelBody + + ); + return true; + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/velocity/template/PutAttributeDirective.java b/plugins/tiles/src/main/java/org/apache/tiles/velocity/template/PutAttributeDirective.java new file mode 100644 index 000000000..acac9b1fa --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/velocity/template/PutAttributeDirective.java @@ -0,0 +1,101 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +/* + * This file was automatically generated by Autotag. Please do not edit it manually. + */ +package org.apache.tiles.velocity.template; + +import java.io.IOException; +import java.io.Writer; + +import org.apache.tiles.autotag.core.runtime.ModelBody; +import org.apache.tiles.autotag.core.runtime.AutotagRuntime; +import org.apache.velocity.context.InternalContextAdapter; +import org.apache.velocity.runtime.directive.Directive; +import org.apache.velocity.runtime.parser.node.Node; + +/** + *

+ * Put an attribute in enclosing attribute container tag. + *

+ *

+ * Enclosing attribute container tag can be : + *

    + *
  • <initContainer>
  • + *
  • <definition>
  • + *
  • <insertAttribute>
  • + *
  • <insertDefinition>
  • + *
  • <putListAttribute>
  • + *
+ * (or any other tag which implements the PutAttributeTagParent interface. + * Exception is thrown if no appropriate tag can be found. + *

+ *

+ * Put tag can have following atributes : + *

    + *
  • name : Name of the attribute
  • + *
  • value : value to put as attribute
  • + *
  • type : value type. Possible type are : string (value is used as direct + * string), template (value is used as a page url to insert), definition (value + * is used as a definition name to insert), object (value is used as it is)
  • + *
  • role : Role to check when 'insertAttribute' will be called.
  • + *
+ *

+ *

+ * Value can also come from tag body. Tag body is taken into account only if + * value is not set by one of the tag attributes. In this case Attribute type is + * "string", unless tag body define another type. + *

+ */ +public class PutAttributeDirective extends Directive { + + /** + * The template model. + */ + private org.apache.tiles.template.PutAttributeModel model = new org.apache.tiles.template.PutAttributeModel(); + + @Override + public String getName() { + return "tiles_putAttribute"; + } + + @Override + public int getType() { + return BLOCK; + } + + @Override + public boolean render(InternalContextAdapter context, Writer writer, Node node) throws IOException { + AutotagRuntime runtime = new org.apache.tiles.request.velocity.autotag.VelocityAutotagRuntime(); + if (runtime instanceof Directive) { + ((Directive) runtime).render(context, writer, node); + } + org.apache.tiles.request.Request request = runtime.createRequest(); + ModelBody modelBody = runtime.createModelBody(); + model.execute(runtime.getParameter("name", java.lang.String.class, null), + runtime.getParameter("value", java.lang.Object.class, null), + runtime.getParameter("expression", java.lang.String.class, null), + runtime.getParameter("role", java.lang.String.class, null), + runtime.getParameter("type", java.lang.String.class, null), + runtime.getParameter("cascade", java.lang.Boolean.class, false), request, modelBody + + ); + return true; + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/velocity/template/PutListAttributeDirective.java b/plugins/tiles/src/main/java/org/apache/tiles/velocity/template/PutListAttributeDirective.java new file mode 100644 index 000000000..c55dd9274 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/velocity/template/PutListAttributeDirective.java @@ -0,0 +1,76 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +/* + * This file was automatically generated by Autotag. Please do not edit it manually. + */ +package org.apache.tiles.velocity.template; + +import java.io.IOException; +import java.io.Writer; + +import org.apache.tiles.autotag.core.runtime.ModelBody; +import org.apache.tiles.autotag.core.runtime.AutotagRuntime; +import org.apache.velocity.context.InternalContextAdapter; +import org.apache.velocity.runtime.directive.Directive; +import org.apache.velocity.runtime.parser.node.Node; + +/** + *

+ * Declare a list that will be pass as attribute to tile. + *

+ *

+ * Declare a list that will be pass as attribute to tile. List elements are + * added using the tags 'addAttribute' or 'addListAttribute'. This tag can only + * be used inside 'insertTemplate', 'insertDefinition', 'definition' tags. + *

+ */ +public class PutListAttributeDirective extends Directive { + + /** + * The template model. + */ + private org.apache.tiles.template.PutListAttributeModel model = new org.apache.tiles.template.PutListAttributeModel(); + + @Override + public String getName() { + return "tiles_putListAttribute"; + } + + @Override + public int getType() { + return BLOCK; + } + + @Override + public boolean render(InternalContextAdapter context, Writer writer, Node node) throws IOException { + AutotagRuntime runtime = new org.apache.tiles.request.velocity.autotag.VelocityAutotagRuntime(); + if (runtime instanceof Directive) { + ((Directive) runtime).render(context, writer, node); + } + org.apache.tiles.request.Request request = runtime.createRequest(); + ModelBody modelBody = runtime.createModelBody(); + model.execute(runtime.getParameter("name", java.lang.String.class, null), + runtime.getParameter("role", java.lang.String.class, null), + runtime.getParameter("inherit", java.lang.Boolean.class, false), + runtime.getParameter("cascade", java.lang.Boolean.class, false), request, modelBody + + ); + return true; + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/velocity/template/SetCurrentContainerDirective.java b/plugins/tiles/src/main/java/org/apache/tiles/velocity/template/SetCurrentContainerDirective.java new file mode 100644 index 000000000..d7ff03e80 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/velocity/template/SetCurrentContainerDirective.java @@ -0,0 +1,64 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +/* + * This file was automatically generated by Autotag. Please do not edit it manually. + */ +package org.apache.tiles.velocity.template; + +import java.io.IOException; +import java.io.Writer; + +import org.apache.tiles.autotag.core.runtime.AutotagRuntime; +import org.apache.velocity.context.InternalContextAdapter; +import org.apache.velocity.runtime.directive.Directive; +import org.apache.velocity.runtime.parser.node.Node; + +/** + * Selects a container to be used as the "current" container. + */ +public class SetCurrentContainerDirective extends Directive { + + /** + * The template model. + */ + private org.apache.tiles.template.SetCurrentContainerModel model = new org.apache.tiles.template.SetCurrentContainerModel(); + + @Override + public String getName() { + return "tiles_setCurrentContainer"; + } + + @Override + public int getType() { + return LINE; + } + + @Override + public boolean render(InternalContextAdapter context, Writer writer, Node node) throws IOException { + AutotagRuntime runtime = new org.apache.tiles.request.velocity.autotag.VelocityAutotagRuntime(); + if (runtime instanceof Directive) { + ((Directive) runtime).render(context, writer, node); + } + org.apache.tiles.request.Request request = runtime.createRequest(); + model.execute(runtime.getParameter("containerKey", java.lang.String.class, null), request + + ); + return true; + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/velocity/template/VelocityStyleTilesTool.java b/plugins/tiles/src/main/java/org/apache/tiles/velocity/template/VelocityStyleTilesTool.java new file mode 100644 index 000000000..e9c3852ac --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/velocity/template/VelocityStyleTilesTool.java @@ -0,0 +1,224 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tiles.velocity.template; + +import java.io.IOException; +import java.io.Writer; + +import javax.servlet.ServletContext; + +import org.apache.tiles.api.Attribute; +import org.apache.tiles.api.AttributeContext; +import org.apache.tiles.api.TilesContainer; +import org.apache.tiles.api.access.TilesAccess; +import org.apache.tiles.request.Request; +import org.apache.tiles.request.servlet.ServletUtil; +import org.apache.tiles.request.velocity.VelocityRequest; +import org.apache.velocity.context.InternalContextAdapter; +import org.apache.velocity.runtime.Renderable; + +/** + * Tiles Tool to be used "the classic way". + * + * @since 2.2.0 + */ +public class VelocityStyleTilesTool extends ContextHolder { + + /** + * Returns an attribute. + * + * @param key The name of the attribute to get. + * @return The Attribute. + * @since 2.2.0 + */ + public Attribute get(String key) { + Request velocityRequest = createVelocityRequest(getServletContext(), null); + TilesContainer container = TilesAccess.getCurrentContainer(velocityRequest); + AttributeContext attributeContext = container.getAttributeContext(velocityRequest); + Attribute attribute = attributeContext.getAttribute(key); + return attribute; + } + + /** + * Creates a new empty attribute. + * + * @return The created attribute. + * @since 2.2.0 + */ + public Attribute createAttribute() { + return new Attribute(); + } + + /** + * Creates an attribute that is a copy of the one passed as a parameter. + * + * @param attribute The attribute to copy. + * @return The copied attribute. + * @since 2.2.0 + */ + public Attribute clone(Attribute attribute) { + return new Attribute(attribute); + } + + /** + * Creates an attribute that represents a template. + * + * @param template The template. + * @return The attribute. + * @since 2.2.0 + */ + public Attribute createTemplateAttribute(String template) { + return Attribute.createTemplateAttribute(template); + } + + /** + * Renders an attribute. + * + * @param attribute The attribute to render. + * @return The renderable object, ready to be rendered. + * @since 2.2.0 + */ + public Renderable render(final Attribute attribute) { + return new AbstractDefaultToStringRenderable(getVelocityContext(), null, getResponse(), getRequest()) { + + public boolean render(InternalContextAdapter context, Writer writer) throws IOException { + Request velocityRequest = createVelocityRequest(getServletContext(), writer); + TilesContainer container = TilesAccess.getCurrentContainer(velocityRequest); + container.render(attribute, velocityRequest); + return true; + } + + }; + } + + /** + * Renders a definition. It can be used in conjunction with + * {@link #startAttributeContext()} and {@link #endAttributeContext()} to + * customize appearance. + * + * @param definitionName The name of the definition to render. + * @return The renderable that renders the definition. + * @since 2.2.0 + */ + public Renderable renderDefinition(final String definitionName) { + return new AbstractDefaultToStringRenderable(getVelocityContext(), null, getResponse(), getRequest()) { + + public boolean render(InternalContextAdapter context, Writer writer) { + Request velocityRequest = createVelocityRequest(getServletContext(), writer); + TilesContainer container = TilesAccess.getCurrentContainer(velocityRequest); + container.render(definitionName, velocityRequest); + return true; + } + + }; + } + + /** + * Renders the current attribute context. It can be used in conjunction with + * {@link #startAttributeContext()} and {@link #endAttributeContext()} to + * customize appearance. + * + * @return The renderable that renders the current attribute context. + * @since 2.2.0 + */ + public Renderable renderAttributeContext() { + return new AbstractDefaultToStringRenderable(getVelocityContext(), null, getResponse(), getRequest()) { + + public boolean render(InternalContextAdapter context, Writer writer) { + Request velocityRequest = createVelocityRequest(getServletContext(), writer); + TilesContainer container = TilesAccess.getCurrentContainer(velocityRequest); + container.renderContext(velocityRequest); + return true; + } + + }; + } + + /** + * Starts the attribute context. Remember to call {@link #endAttributeContext()} + * when finished! + * + * @return The started attribute context, ready to be customized. + * @since 2.2.0 + */ + public AttributeContext startAttributeContext() { + Request velocityRequest = createVelocityRequest(getServletContext(), null); + TilesContainer container = TilesAccess.getCurrentContainer(velocityRequest); + return container.startContext(velocityRequest); + } + + /** + * Ends the current attribute context. To be called after + * {@link #startAttributeContext()}. + * + * @return The tool itself. + * @since 2.2.0 + */ + public VelocityStyleTilesTool endAttributeContext() { + Request velocityRequest = createVelocityRequest(getServletContext(), null); + TilesContainer container = TilesAccess.getCurrentContainer(velocityRequest); + container.endContext(velocityRequest); + return this; + } + + /** + * Returns the current attribute context. + * + * @return The current attribute context. + * @since 2.2.0 + */ + public AttributeContext getAttributeContext() { + Request velocityRequest = createVelocityRequest(getServletContext(), null); + TilesContainer container = TilesAccess.getCurrentContainer(velocityRequest); + return container.getAttributeContext(velocityRequest); + } + + /** + * Sets the current container for the current request. + * + * @param containerKey The key of the container to set as "current" for the + * current request. + * @return The tool itself. + * @since 2.2.0 + */ + public VelocityStyleTilesTool setCurrentContainer(String containerKey) { + Request velocityRequest = createVelocityRequest(getServletContext(), null); + TilesAccess.setCurrentContainer(velocityRequest, containerKey); + return this; + } + + /** {@inheritDoc} */ + @Override + public String toString() { + return ""; + } + + /** + * Creates a Velocity request. + * + * @param servletContext The servlet context. + * @param writer The writer. + * @return The created request. + */ + protected Request createVelocityRequest(ServletContext servletContext, Writer writer) { + return VelocityRequest.createVelocityRequest(ServletUtil.getApplicationContext(servletContext), getRequest(), + getResponse(), getVelocityContext(), writer); + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/velocity/template/package-info.java b/plugins/tiles/src/main/java/org/apache/tiles/velocity/template/package-info.java new file mode 100644 index 000000000..eeb9e3a27 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/velocity/template/package-info.java @@ -0,0 +1,22 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +/** + * Classes that allow the use of "Tiles template" as a Velocity tool. + */ +package org.apache.tiles.velocity.template; diff --git a/plugins/tiles/src/main/java/org/apache/tiles/web/jsp/taglib/AddAttributeTag.java b/plugins/tiles/src/main/java/org/apache/tiles/web/jsp/taglib/AddAttributeTag.java new file mode 100644 index 000000000..53c42cef2 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/web/jsp/taglib/AddAttributeTag.java @@ -0,0 +1,165 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +/* +* This file was automatically generated by Autotag. Please do not edit it manually. +*/ +package org.apache.tiles.web.jsp.taglib; + +import java.io.IOException; + +import javax.servlet.jsp.JspException; +import javax.servlet.jsp.tagext.SimpleTagSupport; + +import org.apache.tiles.autotag.core.runtime.ModelBody; +import org.apache.tiles.autotag.core.runtime.AutotagRuntime; + +/** + *

+ * Add an element to the surrounding list. Equivalent to 'putAttribute', but for + * list element. + *

+ * + *

+ * Add an element to the surrounding list. This tag can only be used inside + * 'putListAttribute' or 'addListAttribute' tags. Value can come from a direct + * assignment (value="aValue") + *

+ */ +public class AddAttributeTag extends SimpleTagSupport { + + /** + * The template model. + */ + private org.apache.tiles.template.AddAttributeModel model = new org.apache.tiles.template.AddAttributeModel(); + + /** + * The value of the attribute. Use this parameter, or expression, or body. + */ + private java.lang.Object value; + + /** + * The expression to calculate the value from. Use this parameter, or value, or + * body. + */ + private java.lang.String expression; + + /** + * A comma-separated list of roles. If present, the attribute will be rendered + * only if the current user belongs to one of the roles. + */ + private java.lang.String role; + + /** + * The type (renderer) of the attribute. + */ + private java.lang.String type; + + /** + * Getter for value property. + * + * @return The value of the attribute. Use this parameter, or expression, or + * body. + */ + public java.lang.Object getValue() { + return value; + } + + /** + * Setter for value property. + * + * @param value The value of the attribute. Use this parameter, or expression, + * or body. + */ + public void setValue(java.lang.Object value) { + this.value = value; + } + + /** + * Getter for expression property. + * + * @return The expression to calculate the value from. Use this parameter, or + * value, or body. + */ + public java.lang.String getExpression() { + return expression; + } + + /** + * Setter for expression property. + * + * @param expression The expression to calculate the value from. Use this + * parameter, or value, or body. + */ + public void setExpression(java.lang.String expression) { + this.expression = expression; + } + + /** + * Getter for role property. + * + * @return A comma-separated list of roles. If present, the attribute will be + * rendered only if the current user belongs to one of the roles. + */ + public java.lang.String getRole() { + return role; + } + + /** + * Setter for role property. + * + * @param role A comma-separated list of roles. If present, the attribute will + * be rendered only if the current user belongs to one of the roles. + */ + public void setRole(java.lang.String role) { + this.role = role; + } + + /** + * Getter for type property. + * + * @return The type (renderer) of the attribute. + */ + public java.lang.String getType() { + return type; + } + + /** + * Setter for type property. + * + * @param type The type (renderer) of the attribute. + */ + public void setType(java.lang.String type) { + this.type = type; + } + + @Override + public void doTag() throws JspException, IOException { + AutotagRuntime runtime = new org.apache.tiles.request.jsp.autotag.JspAutotagRuntime(); + if (runtime instanceof SimpleTagSupport) { + SimpleTagSupport tag = (SimpleTagSupport) runtime; + tag.setJspContext(getJspContext()); + tag.setJspBody(getJspBody()); + tag.setParent(getParent()); + tag.doTag(); + } + org.apache.tiles.request.Request request = runtime.createRequest(); + ModelBody modelBody = runtime.createModelBody(); + model.execute(value, expression, role, type, request, modelBody); + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/web/jsp/taglib/AddListAttributeTag.java b/plugins/tiles/src/main/java/org/apache/tiles/web/jsp/taglib/AddListAttributeTag.java new file mode 100644 index 000000000..0dc5c9fde --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/web/jsp/taglib/AddListAttributeTag.java @@ -0,0 +1,87 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +/* +* This file was automatically generated by Autotag. Please do not edit it manually. +*/ +package org.apache.tiles.web.jsp.taglib; + +import java.io.IOException; + +import javax.servlet.jsp.JspException; +import javax.servlet.jsp.tagext.SimpleTagSupport; + +import org.apache.tiles.autotag.core.runtime.ModelBody; +import org.apache.tiles.autotag.core.runtime.AutotagRuntime; + +/** + *

+ * Declare a list that will be pass as an attribute. + *

+ *

+ * Declare a list that will be pass as an attribute . List elements are added + * using the tag 'addAttribute' or 'addListAttribute'. This tag can only be used + * inside 'insertTemplate', 'insertDefinition' or 'definition' tag. + *

+ */ +public class AddListAttributeTag extends SimpleTagSupport { + + /** + * The template model. + */ + private org.apache.tiles.template.AddListAttributeModel model = new org.apache.tiles.template.AddListAttributeModel(); + + /** + * The comma-separated list of roles that can use the list attribute. + */ + private java.lang.String role; + + /** + * Getter for role property. + * + * @return The comma-separated list of roles that can use the list attribute. + */ + public java.lang.String getRole() { + return role; + } + + /** + * Setter for role property. + * + * @param role The comma-separated list of roles that can use the list + * attribute. + */ + public void setRole(java.lang.String role) { + this.role = role; + } + + @Override + public void doTag() throws JspException, IOException { + AutotagRuntime runtime = new org.apache.tiles.request.jsp.autotag.JspAutotagRuntime(); + if (runtime instanceof SimpleTagSupport) { + SimpleTagSupport tag = (SimpleTagSupport) runtime; + tag.setJspContext(getJspContext()); + tag.setJspBody(getJspBody()); + tag.setParent(getParent()); + tag.doTag(); + } + org.apache.tiles.request.Request request = runtime.createRequest(); + ModelBody modelBody = runtime.createModelBody(); + model.execute(role, request, modelBody); + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/web/jsp/taglib/DefinitionTag.java b/plugins/tiles/src/main/java/org/apache/tiles/web/jsp/taglib/DefinitionTag.java new file mode 100644 index 000000000..eac32da5a --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/web/jsp/taglib/DefinitionTag.java @@ -0,0 +1,184 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +/* +* This file was automatically generated by Autotag. Please do not edit it manually. +*/ +package org.apache.tiles.web.jsp.taglib; + +import java.io.IOException; + +import javax.servlet.jsp.JspException; +import javax.servlet.jsp.tagext.SimpleTagSupport; + +import org.apache.tiles.autotag.core.runtime.ModelBody; +import org.apache.tiles.autotag.core.runtime.AutotagRuntime; + +/** + *

+ * Create a definition at runtime. + *

+ *

+ * Create a new definition at runtime. Newly created definition will be + * available across the entire request. + *

+ */ +public class DefinitionTag extends SimpleTagSupport { + + /** + * The template model. + */ + private org.apache.tiles.template.DefinitionModel model = new org.apache.tiles.template.DefinitionModel(); + + /** + * The name of the definition to create. If not specified, an anonymous + * definition will be created. + */ + private java.lang.String name; + + /** + * The template of this definition. + */ + private java.lang.String template; + + /** + * A comma-separated list of roles. If present, the definition will be rendered + * only if the current user belongs to one of the roles. + */ + private java.lang.String role; + + /** + * The definition name that this definition extends. + */ + private java.lang.String extendsParam; + + /** + * The preparer to use to invoke before the definition is rendered. + */ + private java.lang.String preparer; + + /** + * Getter for name property. + * + * @return The name of the definition to create. If not specified, an anonymous + * definition will be created. + */ + public java.lang.String getName() { + return name; + } + + /** + * Setter for name property. + * + * @param name The name of the definition to create. If not specified, an + * anonymous definition will be created. + */ + public void setName(java.lang.String name) { + this.name = name; + } + + /** + * Getter for template property. + * + * @return The template of this definition. + */ + public java.lang.String getTemplate() { + return template; + } + + /** + * Setter for template property. + * + * @param template The template of this definition. + */ + public void setTemplate(java.lang.String template) { + this.template = template; + } + + /** + * Getter for role property. + * + * @return A comma-separated list of roles. If present, the definition will be + * rendered only if the current user belongs to one of the roles. + */ + public java.lang.String getRole() { + return role; + } + + /** + * Setter for role property. + * + * @param role A comma-separated list of roles. If present, the definition will + * be rendered only if the current user belongs to one of the roles. + */ + public void setRole(java.lang.String role) { + this.role = role; + } + + /** + * Getter for extends property. + * + * @return The definition name that this definition extends. + */ + public java.lang.String getExtends() { + return extendsParam; + } + + /** + * Setter for extends property. + * + * @param extendsParam The definition name that this definition extends. + */ + public void setExtends(java.lang.String extendsParam) { + this.extendsParam = extendsParam; + } + + /** + * Getter for preparer property. + * + * @return The preparer to use to invoke before the definition is rendered. + */ + public java.lang.String getPreparer() { + return preparer; + } + + /** + * Setter for preparer property. + * + * @param preparer The preparer to use to invoke before the definition is + * rendered. + */ + public void setPreparer(java.lang.String preparer) { + this.preparer = preparer; + } + + @Override + public void doTag() throws JspException, IOException { + AutotagRuntime runtime = new org.apache.tiles.request.jsp.autotag.JspAutotagRuntime(); + if (runtime instanceof SimpleTagSupport) { + SimpleTagSupport tag = (SimpleTagSupport) runtime; + tag.setJspContext(getJspContext()); + tag.setJspBody(getJspBody()); + tag.setParent(getParent()); + tag.doTag(); + } + org.apache.tiles.request.Request request = runtime.createRequest(); + ModelBody modelBody = runtime.createModelBody(); + model.execute(name, template, role, extendsParam, preparer, request, modelBody); + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/web/jsp/taglib/GetAsStringTag.java b/plugins/tiles/src/main/java/org/apache/tiles/web/jsp/taglib/GetAsStringTag.java new file mode 100644 index 000000000..e34a1efc1 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/web/jsp/taglib/GetAsStringTag.java @@ -0,0 +1,264 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +/* +* This file was automatically generated by Autotag. Please do not edit it manually. +*/ +package org.apache.tiles.web.jsp.taglib; + +import java.io.IOException; + +import javax.servlet.jsp.JspException; +import javax.servlet.jsp.tagext.SimpleTagSupport; + +import org.apache.tiles.autotag.core.runtime.ModelBody; +import org.apache.tiles.autotag.core.runtime.AutotagRuntime; + +/** + *

+ * Render the value of the specified template attribute to the current Writer + *

+ * + *

+ * Retrieve the value of the specified template attribute property, and render + * it to the current Writer as a String. The usual toString() conversions is + * applied on found value. + *

+ */ +public class GetAsStringTag extends SimpleTagSupport { + + /** + * The template model. + */ + private org.apache.tiles.template.GetAsStringModel model = new org.apache.tiles.template.GetAsStringModel(); + + /** + * If true, if an exception happens during rendering, of if the attribute is + * null, the problem will be ignored. + */ + private boolean ignore; + + /** + * The preparer to invoke before rendering the attribute. + */ + private java.lang.String preparer; + + /** + * A comma-separated list of roles. If present, the attribute will be rendered + * only if the current user belongs to one of the roles. + */ + private java.lang.String role; + + /** + * The default value of the attribute. To use only if the attribute was not + * computed. + */ + private java.lang.Object defaultValue; + + /** + * The default comma-separated list of roles. To use only if the attribute was + * not computed. + */ + private java.lang.String defaultValueRole; + + /** + * The default type of the attribute. To use only if the attribute was not + * computed. + */ + private java.lang.String defaultValueType; + + /** + * The name of the attribute. + */ + private java.lang.String name; + + /** + * The attribute to use immediately, if not null. + */ + private org.apache.tiles.api.Attribute value; + + /** + * Getter for ignore property. + * + * @return If true, if an exception happens during rendering, of if the + * attribute is null, the problem will be ignored. + */ + public boolean isIgnore() { + return ignore; + } + + /** + * Setter for ignore property. + * + * @param ignore If true, if an exception happens during rendering, of if the + * attribute is null, the problem will be ignored. + */ + public void setIgnore(boolean ignore) { + this.ignore = ignore; + } + + /** + * Getter for preparer property. + * + * @return The preparer to invoke before rendering the attribute. + */ + public java.lang.String getPreparer() { + return preparer; + } + + /** + * Setter for preparer property. + * + * @param preparer The preparer to invoke before rendering the attribute. + */ + public void setPreparer(java.lang.String preparer) { + this.preparer = preparer; + } + + /** + * Getter for role property. + * + * @return A comma-separated list of roles. If present, the attribute will be + * rendered only if the current user belongs to one of the roles. + */ + public java.lang.String getRole() { + return role; + } + + /** + * Setter for role property. + * + * @param role A comma-separated list of roles. If present, the attribute will + * be rendered only if the current user belongs to one of the roles. + */ + public void setRole(java.lang.String role) { + this.role = role; + } + + /** + * Getter for defaultValue property. + * + * @return The default value of the attribute. To use only if the attribute was + * not computed. + */ + public java.lang.Object getDefaultValue() { + return defaultValue; + } + + /** + * Setter for defaultValue property. + * + * @param defaultValue The default value of the attribute. To use only if the + * attribute was not computed. + */ + public void setDefaultValue(java.lang.Object defaultValue) { + this.defaultValue = defaultValue; + } + + /** + * Getter for defaultValueRole property. + * + * @return The default comma-separated list of roles. To use only if the + * attribute was not computed. + */ + public java.lang.String getDefaultValueRole() { + return defaultValueRole; + } + + /** + * Setter for defaultValueRole property. + * + * @param defaultValueRole The default comma-separated list of roles. To use + * only if the attribute was not computed. + */ + public void setDefaultValueRole(java.lang.String defaultValueRole) { + this.defaultValueRole = defaultValueRole; + } + + /** + * Getter for defaultValueType property. + * + * @return The default type of the attribute. To use only if the attribute was + * not computed. + */ + public java.lang.String getDefaultValueType() { + return defaultValueType; + } + + /** + * Setter for defaultValueType property. + * + * @param defaultValueType The default type of the attribute. To use only if the + * attribute was not computed. + */ + public void setDefaultValueType(java.lang.String defaultValueType) { + this.defaultValueType = defaultValueType; + } + + /** + * Getter for name property. + * + * @return The name of the attribute. + */ + public java.lang.String getName() { + return name; + } + + /** + * Setter for name property. + * + * @param name The name of the attribute. + */ + public void setName(java.lang.String name) { + this.name = name; + } + + /** + * Getter for value property. + * + * @return The attribute to use immediately, if not null. + */ + public org.apache.tiles.api.Attribute getValue() { + return value; + } + + /** + * Setter for value property. + * + * @param value The attribute to use immediately, if not null. + */ + public void setValue(org.apache.tiles.api.Attribute value) { + this.value = value; + } + + @Override + public void doTag() throws JspException, IOException { + AutotagRuntime runtime = new org.apache.tiles.request.jsp.autotag.JspAutotagRuntime(); + if (runtime instanceof SimpleTagSupport) { + SimpleTagSupport tag = (SimpleTagSupport) runtime; + tag.setJspContext(getJspContext()); + tag.setJspBody(getJspBody()); + tag.setParent(getParent()); + tag.doTag(); + } + org.apache.tiles.request.Request request = runtime.createRequest(); + ModelBody modelBody = runtime.createModelBody(); + model.execute(ignore, preparer, role, defaultValue, defaultValueRole, defaultValueType, name, value, request, + modelBody); + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/web/jsp/taglib/ImportAttributeTag.java b/plugins/tiles/src/main/java/org/apache/tiles/web/jsp/taglib/ImportAttributeTag.java new file mode 100644 index 000000000..56ca370e4 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/web/jsp/taglib/ImportAttributeTag.java @@ -0,0 +1,166 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +/* +* This file was automatically generated by Autotag. Please do not edit it manually. +*/ +package org.apache.tiles.web.jsp.taglib; + +import java.io.IOException; + +import javax.servlet.jsp.JspException; +import javax.servlet.jsp.tagext.SimpleTagSupport; + +import org.apache.tiles.autotag.core.runtime.AutotagRuntime; + +/** + *

+ * Import attribute(s) in specified context. + *

+ *

+ * Import attribute(s) to requested scope. Attribute name and scope are + * optional. If not specified, all attributes are imported in page scope. Once + * imported, an attribute can be used as any other beans from jsp contexts. + *

+ */ +public class ImportAttributeTag extends SimpleTagSupport { + + /** + * The template model. + */ + private org.apache.tiles.template.ImportAttributeModel model = new org.apache.tiles.template.ImportAttributeModel(); + + /** + * The name of the attribute to import. If it is null, all the attributes will + * be imported. + */ + private java.lang.String name; + + /** + * The scope into which the attribute(s) will be imported. If null, the import + * will go in page scope. + */ + private java.lang.String scope; + + /** + * The name of the attribute into which the attribute will be imported. To be + * used in conjunction to name. If null, the value of name will be used. + */ + private java.lang.String toName; + + /** + * If true, if the attribute is not present, the problem will be ignored. + */ + private boolean ignore; + + /** + * Getter for name property. + * + * @return The name of the attribute to import. If it is null, all the + * attributes will be imported. + */ + public java.lang.String getName() { + return name; + } + + /** + * Setter for name property. + * + * @param name The name of the attribute to import. If it is null, all the + * attributes will be imported. + */ + public void setName(java.lang.String name) { + this.name = name; + } + + /** + * Getter for scope property. + * + * @return The scope into which the attribute(s) will be imported. If null, the + * import will go in page scope. + */ + public java.lang.String getScope() { + return scope; + } + + /** + * Setter for scope property. + * + * @param scope The scope into which the attribute(s) will be imported. If null, + * the import will go in page scope. + */ + public void setScope(java.lang.String scope) { + this.scope = scope; + } + + /** + * Getter for toName property. + * + * @return The name of the attribute into which the attribute will be imported. + * To be used in conjunction to name. If null, the value of name will be + * used. + */ + public java.lang.String getToName() { + return toName; + } + + /** + * Setter for toName property. + * + * @param toName The name of the attribute into which the attribute will be + * imported. To be used in conjunction to name. If null, the value + * of name will be used. + */ + public void setToName(java.lang.String toName) { + this.toName = toName; + } + + /** + * Getter for ignore property. + * + * @return If true, if the attribute is not present, the problem will be + * ignored. + */ + public boolean isIgnore() { + return ignore; + } + + /** + * Setter for ignore property. + * + * @param ignore If true, if the attribute is not present, the problem will be + * ignored. + */ + public void setIgnore(boolean ignore) { + this.ignore = ignore; + } + + @Override + public void doTag() throws JspException, IOException { + AutotagRuntime runtime = new org.apache.tiles.request.jsp.autotag.JspAutotagRuntime(); + if (runtime instanceof SimpleTagSupport) { + SimpleTagSupport tag = (SimpleTagSupport) runtime; + tag.setJspContext(getJspContext()); + tag.setJspBody(getJspBody()); + tag.setParent(getParent()); + tag.doTag(); + } + org.apache.tiles.request.Request request = runtime.createRequest(); + model.execute(name, scope, toName, ignore, request); + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/web/jsp/taglib/InsertAttributeTag.java b/plugins/tiles/src/main/java/org/apache/tiles/web/jsp/taglib/InsertAttributeTag.java new file mode 100644 index 000000000..be288e864 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/web/jsp/taglib/InsertAttributeTag.java @@ -0,0 +1,299 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +/* +* This file was automatically generated by Autotag. Please do not edit it manually. +*/ +package org.apache.tiles.web.jsp.taglib; + +import java.io.IOException; + +import javax.servlet.jsp.JspException; +import javax.servlet.jsp.tagext.SimpleTagSupport; + +import org.apache.tiles.autotag.core.runtime.ModelBody; +import org.apache.tiles.autotag.core.runtime.AutotagRuntime; + +/** + *

+ * Inserts the value of an attribute into the page. + *

+ *

+ * This tag can be flexibly used to insert the value of an attribute into a + * page. As in other usages in Tiles, every attribute can be determined to have + * a "type", either set explicitly when it was defined, or "computed". If the + * type is not explicit, then if the attribute value is a valid definition, it + * will be inserted as such. Otherwise, if it begins with a "/" character, it + * will be treated as a "template". Finally, if it has not otherwise been + * assigned a type, it will be treated as a String and included without any + * special handling. + *

+ * + *

+ * Example : + *

+ * + *
+ *     <tiles:insertAttribute name="body" />
+ * 
+ */ +public class InsertAttributeTag extends SimpleTagSupport { + + /** + * The template model. + */ + private org.apache.tiles.template.InsertAttributeModel model = new org.apache.tiles.template.InsertAttributeModel(); + + /** + * If true, if an exception happens during rendering, of if the attribute is + * null, the problem will be ignored. + */ + private boolean ignore; + + /** + * The preparer to invoke before rendering the attribute. + */ + private java.lang.String preparer; + + /** + * A comma-separated list of roles. If present, the attribute will be rendered + * only if the current user belongs to one of the roles. + */ + private java.lang.String role; + + /** + * The default value of the attribute. To use only if the attribute was not + * computed. + */ + private java.lang.Object defaultValue; + + /** + * The default comma-separated list of roles. To use only if the attribute was + * not computed. + */ + private java.lang.String defaultValueRole; + + /** + * The default type of the attribute. To use only if the attribute was not + * computed. + */ + private java.lang.String defaultValueType; + + /** + * The name of the attribute. + */ + private java.lang.String name; + + /** + * The attribute to use immediately, if not null. + */ + private org.apache.tiles.api.Attribute value; + + /** + * If true, the response will be flushed after the insert. + */ + private boolean flush; + + /** + * Getter for ignore property. + * + * @return If true, if an exception happens during rendering, of if the + * attribute is null, the problem will be ignored. + */ + public boolean isIgnore() { + return ignore; + } + + /** + * Setter for ignore property. + * + * @param ignore If true, if an exception happens during rendering, of if the + * attribute is null, the problem will be ignored. + */ + public void setIgnore(boolean ignore) { + this.ignore = ignore; + } + + /** + * Getter for preparer property. + * + * @return The preparer to invoke before rendering the attribute. + */ + public java.lang.String getPreparer() { + return preparer; + } + + /** + * Setter for preparer property. + * + * @param preparer The preparer to invoke before rendering the attribute. + */ + public void setPreparer(java.lang.String preparer) { + this.preparer = preparer; + } + + /** + * Getter for role property. + * + * @return A comma-separated list of roles. If present, the attribute will be + * rendered only if the current user belongs to one of the roles. + */ + public java.lang.String getRole() { + return role; + } + + /** + * Setter for role property. + * + * @param role A comma-separated list of roles. If present, the attribute will + * be rendered only if the current user belongs to one of the roles. + */ + public void setRole(java.lang.String role) { + this.role = role; + } + + /** + * Getter for defaultValue property. + * + * @return The default value of the attribute. To use only if the attribute was + * not computed. + */ + public java.lang.Object getDefaultValue() { + return defaultValue; + } + + /** + * Setter for defaultValue property. + * + * @param defaultValue The default value of the attribute. To use only if the + * attribute was not computed. + */ + public void setDefaultValue(java.lang.Object defaultValue) { + this.defaultValue = defaultValue; + } + + /** + * Getter for defaultValueRole property. + * + * @return The default comma-separated list of roles. To use only if the + * attribute was not computed. + */ + public java.lang.String getDefaultValueRole() { + return defaultValueRole; + } + + /** + * Setter for defaultValueRole property. + * + * @param defaultValueRole The default comma-separated list of roles. To use + * only if the attribute was not computed. + */ + public void setDefaultValueRole(java.lang.String defaultValueRole) { + this.defaultValueRole = defaultValueRole; + } + + /** + * Getter for defaultValueType property. + * + * @return The default type of the attribute. To use only if the attribute was + * not computed. + */ + public java.lang.String getDefaultValueType() { + return defaultValueType; + } + + /** + * Setter for defaultValueType property. + * + * @param defaultValueType The default type of the attribute. To use only if the + * attribute was not computed. + */ + public void setDefaultValueType(java.lang.String defaultValueType) { + this.defaultValueType = defaultValueType; + } + + /** + * Getter for name property. + * + * @return The name of the attribute. + */ + public java.lang.String getName() { + return name; + } + + /** + * Setter for name property. + * + * @param name The name of the attribute. + */ + public void setName(java.lang.String name) { + this.name = name; + } + + /** + * Getter for value property. + * + * @return The attribute to use immediately, if not null. + */ + public org.apache.tiles.api.Attribute getValue() { + return value; + } + + /** + * Setter for value property. + * + * @param value The attribute to use immediately, if not null. + */ + public void setValue(org.apache.tiles.api.Attribute value) { + this.value = value; + } + + /** + * Getter for flush property. + * + * @return If true, the response will be flushed after the insert. + */ + public boolean isFlush() { + return flush; + } + + /** + * Setter for flush property. + * + * @param flush If true, the response will be flushed after the insert. + */ + public void setFlush(boolean flush) { + this.flush = flush; + } + + @Override + public void doTag() throws JspException, IOException { + AutotagRuntime runtime = new org.apache.tiles.request.jsp.autotag.JspAutotagRuntime(); + if (runtime instanceof SimpleTagSupport) { + SimpleTagSupport tag = (SimpleTagSupport) runtime; + tag.setJspContext(getJspContext()); + tag.setJspBody(getJspBody()); + tag.setParent(getParent()); + tag.doTag(); + } + org.apache.tiles.request.Request request = runtime.createRequest(); + ModelBody modelBody = runtime.createModelBody(); + model.execute(ignore, preparer, role, defaultValue, defaultValueRole, defaultValueType, name, value, flush, + request, modelBody); + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/web/jsp/taglib/InsertDefinitionTag.java b/plugins/tiles/src/main/java/org/apache/tiles/web/jsp/taglib/InsertDefinitionTag.java new file mode 100644 index 000000000..0beec1aa1 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/web/jsp/taglib/InsertDefinitionTag.java @@ -0,0 +1,257 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +/* +* This file was automatically generated by Autotag. Please do not edit it manually. +*/ +package org.apache.tiles.web.jsp.taglib; + +import java.io.IOException; + +import javax.servlet.jsp.JspException; +import javax.servlet.jsp.tagext.SimpleTagSupport; + +import org.apache.tiles.autotag.core.runtime.ModelBody; +import org.apache.tiles.autotag.core.runtime.AutotagRuntime; + +/** + *

+ * Insert a definition. + *

+ *

+ * Insert a definition with the possibility to override and specify parameters + * (called attributes). A definition can be seen as a (partially or totally) + * filled template that can override or complete attribute values. + * <tiles:insertDefinition> allows to define these attributes and pass + * them to the inserted jsp page, called template. Attributes are defined using + * nested tag <tiles:putAttribute> or <tiles:putListAttribute>. + *

+ *

+ * You must specify name tag attribute, for inserting a definition from + * definitions factory. + *

+ *

+ * Example : + *

+ * + *
+ *     <tiles:insertDefinition name=".my.tiles.defininition flush="true">
+ *         <tiles:putAttribute name="title" value="My first page" />
+ *         <tiles:putAttribute name="header" value="/common/header.jsp" />
+ *         <tiles:putAttribute name="footer" value="/common/footer.jsp" />
+ *         <tiles:putAttribute name="menu" value="/basic/menu.jsp" />
+ *         <tiles:putAttribute name="body" value="/basic/helloBody.jsp" />
+ *     </tiles:insertDefinition>
+ * 
+ */ +public class InsertDefinitionTag extends SimpleTagSupport { + + /** + * The template model. + */ + private org.apache.tiles.template.InsertDefinitionModel model = new org.apache.tiles.template.InsertDefinitionModel(); + + /** + * The name of the definition to render. + */ + private java.lang.String definitionName; + + /** + * If specified, this template will be used instead of the one used by the + * definition. + */ + private java.lang.String template; + + /** + * The type of the template attribute. + */ + private java.lang.String templateType; + + /** + * The expression to evaluate to get the value of the template. + */ + private java.lang.String templateExpression; + + /** + * A comma-separated list of roles. If present, the definition will be rendered + * only if the current user belongs to one of the roles. + */ + private java.lang.String role; + + /** + * The preparer to use to invoke before the definition is rendered. If + * specified, it overrides the preparer specified in the definition itself. + */ + private java.lang.String preparer; + + /** + * If true, the response will be flushed after the insert. + */ + private boolean flush; + + /** + * Getter for name property. + * + * @return The name of the definition to render. + */ + public java.lang.String getName() { + return definitionName; + } + + /** + * Setter for name property. + * + * @param definitionName The name of the definition to render. + */ + public void setName(java.lang.String definitionName) { + this.definitionName = definitionName; + } + + /** + * Getter for template property. + * + * @return If specified, this template will be used instead of the one used by + * the definition. + */ + public java.lang.String getTemplate() { + return template; + } + + /** + * Setter for template property. + * + * @param template If specified, this template will be used instead of the one + * used by the definition. + */ + public void setTemplate(java.lang.String template) { + this.template = template; + } + + /** + * Getter for templateType property. + * + * @return The type of the template attribute. + */ + public java.lang.String getTemplateType() { + return templateType; + } + + /** + * Setter for templateType property. + * + * @param templateType The type of the template attribute. + */ + public void setTemplateType(java.lang.String templateType) { + this.templateType = templateType; + } + + /** + * Getter for templateExpression property. + * + * @return The expression to evaluate to get the value of the template. + */ + public java.lang.String getTemplateExpression() { + return templateExpression; + } + + /** + * Setter for templateExpression property. + * + * @param templateExpression The expression to evaluate to get the value of the + * template. + */ + public void setTemplateExpression(java.lang.String templateExpression) { + this.templateExpression = templateExpression; + } + + /** + * Getter for role property. + * + * @return A comma-separated list of roles. If present, the definition will be + * rendered only if the current user belongs to one of the roles. + */ + public java.lang.String getRole() { + return role; + } + + /** + * Setter for role property. + * + * @param role A comma-separated list of roles. If present, the definition will + * be rendered only if the current user belongs to one of the roles. + */ + public void setRole(java.lang.String role) { + this.role = role; + } + + /** + * Getter for preparer property. + * + * @return The preparer to use to invoke before the definition is rendered. If + * specified, it overrides the preparer specified in the definition + * itself. + */ + public java.lang.String getPreparer() { + return preparer; + } + + /** + * Setter for preparer property. + * + * @param preparer The preparer to use to invoke before the definition is + * rendered. If specified, it overrides the preparer specified + * in the definition itself. + */ + public void setPreparer(java.lang.String preparer) { + this.preparer = preparer; + } + + /** + * Getter for flush property. + * + * @return If true, the response will be flushed after the insert. + */ + public boolean isFlush() { + return flush; + } + + /** + * Setter for flush property. + * + * @param flush If true, the response will be flushed after the insert. + */ + public void setFlush(boolean flush) { + this.flush = flush; + } + + @Override + public void doTag() throws JspException, IOException { + AutotagRuntime runtime = new org.apache.tiles.request.jsp.autotag.JspAutotagRuntime(); + if (runtime instanceof SimpleTagSupport) { + SimpleTagSupport tag = (SimpleTagSupport) runtime; + tag.setJspContext(getJspContext()); + tag.setJspBody(getJspBody()); + tag.setParent(getParent()); + tag.doTag(); + } + org.apache.tiles.request.Request request = runtime.createRequest(); + ModelBody modelBody = runtime.createModelBody(); + model.execute(definitionName, template, templateType, templateExpression, role, preparer, flush, request, + modelBody); + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/web/jsp/taglib/InsertTemplateTag.java b/plugins/tiles/src/main/java/org/apache/tiles/web/jsp/taglib/InsertTemplateTag.java new file mode 100644 index 000000000..afe633881 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/web/jsp/taglib/InsertTemplateTag.java @@ -0,0 +1,230 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +/* +* This file was automatically generated by Autotag. Please do not edit it manually. +*/ +package org.apache.tiles.web.jsp.taglib; + +import java.io.IOException; + +import javax.servlet.jsp.JspException; +import javax.servlet.jsp.tagext.SimpleTagSupport; + +import org.apache.tiles.autotag.core.runtime.ModelBody; +import org.apache.tiles.autotag.core.runtime.AutotagRuntime; + +/** + *

+ * Insert a template. + *

+ *

+ * Insert a template with the possibility to pass parameters (called + * attributes). A template can be seen as a procedure that can take parameters + * or attributes. <tiles:insertTemplate> allows to define these attributes + * and pass them to the inserted jsp page, called template. Attributes are + * defined using nested tag <tiles:putAttribute> or + * <tiles:putListAttribute>. + *

+ *

+ * You must specify template attribute, for inserting a template + *

+ * + *

+ * Example : + *

+ * + *
+ *     <tiles:insertTemplate template="/basic/myLayout.jsp" flush="true">
+ *         <tiles:putAttribute name="title" value="My first page" />
+ *         <tiles:putAttribute name="header" value="/common/header.jsp" />
+ *         <tiles:putAttribute name="footer" value="/common/footer.jsp" />
+ *         <tiles:putAttribute name="menu" value="/basic/menu.jsp" />
+ *         <tiles:putAttribute name="body" value="/basic/helloBody.jsp" />
+ *     </tiles:insertTemplate>
+ * 
+ */ +public class InsertTemplateTag extends SimpleTagSupport { + + /** + * The template model. + */ + private org.apache.tiles.template.InsertTemplateModel model = new org.apache.tiles.template.InsertTemplateModel(); + + /** + * The template to render. + */ + private java.lang.String template; + + /** + * The type of the template attribute. + */ + private java.lang.String templateType; + + /** + * The expression to evaluate to get the value of the template. + */ + private java.lang.String templateExpression; + + /** + * A comma-separated list of roles. If present, the template will be rendered + * only if the current user belongs to one of the roles. + */ + private java.lang.String role; + + /** + * The preparer to use to invoke before the definition is rendered. If + * specified, it overrides the preparer specified in the definition itself. + */ + private java.lang.String preparer; + + /** + * If true, the response will be flushed after the insert. + */ + private boolean flush; + + /** + * Getter for template property. + * + * @return The template to render. + */ + public java.lang.String getTemplate() { + return template; + } + + /** + * Setter for template property. + * + * @param template The template to render. + */ + public void setTemplate(java.lang.String template) { + this.template = template; + } + + /** + * Getter for templateType property. + * + * @return The type of the template attribute. + */ + public java.lang.String getTemplateType() { + return templateType; + } + + /** + * Setter for templateType property. + * + * @param templateType The type of the template attribute. + */ + public void setTemplateType(java.lang.String templateType) { + this.templateType = templateType; + } + + /** + * Getter for templateExpression property. + * + * @return The expression to evaluate to get the value of the template. + */ + public java.lang.String getTemplateExpression() { + return templateExpression; + } + + /** + * Setter for templateExpression property. + * + * @param templateExpression The expression to evaluate to get the value of the + * template. + */ + public void setTemplateExpression(java.lang.String templateExpression) { + this.templateExpression = templateExpression; + } + + /** + * Getter for role property. + * + * @return A comma-separated list of roles. If present, the template will be + * rendered only if the current user belongs to one of the roles. + */ + public java.lang.String getRole() { + return role; + } + + /** + * Setter for role property. + * + * @param role A comma-separated list of roles. If present, the template will be + * rendered only if the current user belongs to one of the roles. + */ + public void setRole(java.lang.String role) { + this.role = role; + } + + /** + * Getter for preparer property. + * + * @return The preparer to use to invoke before the definition is rendered. If + * specified, it overrides the preparer specified in the definition + * itself. + */ + public java.lang.String getPreparer() { + return preparer; + } + + /** + * Setter for preparer property. + * + * @param preparer The preparer to use to invoke before the definition is + * rendered. If specified, it overrides the preparer specified + * in the definition itself. + */ + public void setPreparer(java.lang.String preparer) { + this.preparer = preparer; + } + + /** + * Getter for flush property. + * + * @return If true, the response will be flushed after the insert. + */ + public boolean isFlush() { + return flush; + } + + /** + * Setter for flush property. + * + * @param flush If true, the response will be flushed after the insert. + */ + public void setFlush(boolean flush) { + this.flush = flush; + } + + @Override + public void doTag() throws JspException, IOException { + AutotagRuntime runtime = new org.apache.tiles.request.jsp.autotag.JspAutotagRuntime(); + if (runtime instanceof SimpleTagSupport) { + SimpleTagSupport tag = (SimpleTagSupport) runtime; + tag.setJspContext(getJspContext()); + tag.setJspBody(getJspBody()); + tag.setParent(getParent()); + tag.doTag(); + } + org.apache.tiles.request.Request request = runtime.createRequest(); + ModelBody modelBody = runtime.createModelBody(); + model.execute(template, templateType, templateExpression, role, preparer, flush, request, modelBody); + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/web/jsp/taglib/PutAttributeTag.java b/plugins/tiles/src/main/java/org/apache/tiles/web/jsp/taglib/PutAttributeTag.java new file mode 100644 index 000000000..c4fa7c91c --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/web/jsp/taglib/PutAttributeTag.java @@ -0,0 +1,233 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +/* +* This file was automatically generated by Autotag. Please do not edit it manually. +*/ +package org.apache.tiles.web.jsp.taglib; + +import java.io.IOException; + +import javax.servlet.jsp.JspException; +import javax.servlet.jsp.tagext.SimpleTagSupport; + +import org.apache.tiles.autotag.core.runtime.ModelBody; +import org.apache.tiles.autotag.core.runtime.AutotagRuntime; + +/** + *

+ * Put an attribute in enclosing attribute container tag. + *

+ *

+ * Enclosing attribute container tag can be : + *

    + *
  • <initContainer>
  • + *
  • <definition>
  • + *
  • <insertAttribute>
  • + *
  • <insertDefinition>
  • + *
  • <putListAttribute>
  • + *
+ * (or any other tag which implements the PutAttributeTagParent interface. + * Exception is thrown if no appropriate tag can be found. + *

+ *

+ * Put tag can have following atributes : + *

    + *
  • name : Name of the attribute
  • + *
  • value : value to put as attribute
  • + *
  • type : value type. Possible type are : string (value is used as direct + * string), template (value is used as a page url to insert), definition (value + * is used as a definition name to insert), object (value is used as it is)
  • + *
  • role : Role to check when 'insertAttribute' will be called.
  • + *
+ *

+ *

+ * Value can also come from tag body. Tag body is taken into account only if + * value is not set by one of the tag attributes. In this case Attribute type is + * "string", unless tag body define another type. + *

+ */ +public class PutAttributeTag extends SimpleTagSupport { + + /** + * The template model. + */ + private org.apache.tiles.template.PutAttributeModel model = new org.apache.tiles.template.PutAttributeModel(); + + /** + * The name of the attribute to put. + */ + private java.lang.String name; + + /** + * The value of the attribute. Use this parameter, or expression, or body. + */ + private java.lang.Object value; + + /** + * The expression to calculate the value from. Use this parameter, or value, or + * body. + */ + private java.lang.String expression; + + /** + * A comma-separated list of roles. If present, the attribute will be rendered + * only if the current user belongs to one of the roles. + */ + private java.lang.String role; + + /** + * The type (renderer) of the attribute. + */ + private java.lang.String type; + + /** + * If true the attribute will be cascaded to all nested attributes. + */ + private boolean cascade; + + /** + * Getter for name property. + * + * @return The name of the attribute to put. + */ + public java.lang.String getName() { + return name; + } + + /** + * Setter for name property. + * + * @param name The name of the attribute to put. + */ + public void setName(java.lang.String name) { + this.name = name; + } + + /** + * Getter for value property. + * + * @return The value of the attribute. Use this parameter, or expression, or + * body. + */ + public java.lang.Object getValue() { + return value; + } + + /** + * Setter for value property. + * + * @param value The value of the attribute. Use this parameter, or expression, + * or body. + */ + public void setValue(java.lang.Object value) { + this.value = value; + } + + /** + * Getter for expression property. + * + * @return The expression to calculate the value from. Use this parameter, or + * value, or body. + */ + public java.lang.String getExpression() { + return expression; + } + + /** + * Setter for expression property. + * + * @param expression The expression to calculate the value from. Use this + * parameter, or value, or body. + */ + public void setExpression(java.lang.String expression) { + this.expression = expression; + } + + /** + * Getter for role property. + * + * @return A comma-separated list of roles. If present, the attribute will be + * rendered only if the current user belongs to one of the roles. + */ + public java.lang.String getRole() { + return role; + } + + /** + * Setter for role property. + * + * @param role A comma-separated list of roles. If present, the attribute will + * be rendered only if the current user belongs to one of the roles. + */ + public void setRole(java.lang.String role) { + this.role = role; + } + + /** + * Getter for type property. + * + * @return The type (renderer) of the attribute. + */ + public java.lang.String getType() { + return type; + } + + /** + * Setter for type property. + * + * @param type The type (renderer) of the attribute. + */ + public void setType(java.lang.String type) { + this.type = type; + } + + /** + * Getter for cascade property. + * + * @return If true the attribute will be cascaded to all nested attributes. + */ + public boolean isCascade() { + return cascade; + } + + /** + * Setter for cascade property. + * + * @param cascade If true the attribute will be cascaded to all nested + * attributes. + */ + public void setCascade(boolean cascade) { + this.cascade = cascade; + } + + @Override + public void doTag() throws JspException, IOException { + AutotagRuntime runtime = new org.apache.tiles.request.jsp.autotag.JspAutotagRuntime(); + if (runtime instanceof SimpleTagSupport) { + SimpleTagSupport tag = (SimpleTagSupport) runtime; + tag.setJspContext(getJspContext()); + tag.setJspBody(getJspBody()); + tag.setParent(getParent()); + tag.doTag(); + } + org.apache.tiles.request.Request request = runtime.createRequest(); + ModelBody modelBody = runtime.createModelBody(); + model.execute(name, value, expression, role, type, cascade, request, modelBody); + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/web/jsp/taglib/PutListAttributeTag.java b/plugins/tiles/src/main/java/org/apache/tiles/web/jsp/taglib/PutListAttributeTag.java new file mode 100644 index 000000000..1e96972c7 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/web/jsp/taglib/PutListAttributeTag.java @@ -0,0 +1,164 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +/* +* This file was automatically generated by Autotag. Please do not edit it manually. +*/ +package org.apache.tiles.web.jsp.taglib; + +import java.io.IOException; + +import javax.servlet.jsp.JspException; +import javax.servlet.jsp.tagext.SimpleTagSupport; + +import org.apache.tiles.autotag.core.runtime.ModelBody; +import org.apache.tiles.autotag.core.runtime.AutotagRuntime; + +/** + *

+ * Declare a list that will be pass as attribute to tile. + *

+ *

+ * Declare a list that will be pass as attribute to tile. List elements are + * added using the tags 'addAttribute' or 'addListAttribute'. This tag can only + * be used inside 'insertTemplate', 'insertDefinition', 'definition' tags. + *

+ */ +public class PutListAttributeTag extends SimpleTagSupport { + + /** + * The template model. + */ + private org.apache.tiles.template.PutListAttributeModel model = new org.apache.tiles.template.PutListAttributeModel(); + + /** + * The name of the attribute to put. + */ + private java.lang.String name; + + /** + * A comma-separated list of roles. If present, the attribute will be rendered + * only if the current user belongs to one of the roles. + */ + private java.lang.String role; + + /** + * If true, the list attribute will use, as first elements, the list contained + * in the list attribute, put with the same name, of the containing definition. + */ + private boolean inherit; + + /** + * If true the attribute will be cascaded to all nested attributes. + */ + private boolean cascade; + + /** + * Getter for name property. + * + * @return The name of the attribute to put. + */ + public java.lang.String getName() { + return name; + } + + /** + * Setter for name property. + * + * @param name The name of the attribute to put. + */ + public void setName(java.lang.String name) { + this.name = name; + } + + /** + * Getter for role property. + * + * @return A comma-separated list of roles. If present, the attribute will be + * rendered only if the current user belongs to one of the roles. + */ + public java.lang.String getRole() { + return role; + } + + /** + * Setter for role property. + * + * @param role A comma-separated list of roles. If present, the attribute will + * be rendered only if the current user belongs to one of the roles. + */ + public void setRole(java.lang.String role) { + this.role = role; + } + + /** + * Getter for inherit property. + * + * @return If true, the list attribute will use, as first elements, the list + * contained in the list attribute, put with the same name, of the + * containing definition. + */ + public boolean isInherit() { + return inherit; + } + + /** + * Setter for inherit property. + * + * @param inherit If true, the list attribute will use, as first elements, the + * list contained in the list attribute, put with the same name, + * of the containing definition. + */ + public void setInherit(boolean inherit) { + this.inherit = inherit; + } + + /** + * Getter for cascade property. + * + * @return If true the attribute will be cascaded to all nested attributes. + */ + public boolean isCascade() { + return cascade; + } + + /** + * Setter for cascade property. + * + * @param cascade If true the attribute will be cascaded to all nested + * attributes. + */ + public void setCascade(boolean cascade) { + this.cascade = cascade; + } + + @Override + public void doTag() throws JspException, IOException { + AutotagRuntime runtime = new org.apache.tiles.request.jsp.autotag.JspAutotagRuntime(); + if (runtime instanceof SimpleTagSupport) { + SimpleTagSupport tag = (SimpleTagSupport) runtime; + tag.setJspContext(getJspContext()); + tag.setJspBody(getJspBody()); + tag.setParent(getParent()); + tag.doTag(); + } + org.apache.tiles.request.Request request = runtime.createRequest(); + ModelBody modelBody = runtime.createModelBody(); + model.execute(name, role, inherit, cascade, request, modelBody); + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/web/jsp/taglib/SetCurrentContainerTag.java b/plugins/tiles/src/main/java/org/apache/tiles/web/jsp/taglib/SetCurrentContainerTag.java new file mode 100644 index 000000000..370f3b418 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/web/jsp/taglib/SetCurrentContainerTag.java @@ -0,0 +1,80 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +/* +* This file was automatically generated by Autotag. Please do not edit it manually. +*/ +package org.apache.tiles.web.jsp.taglib; + +import java.io.IOException; + +import javax.servlet.jsp.JspException; +import javax.servlet.jsp.tagext.SimpleTagSupport; + +import org.apache.tiles.autotag.core.runtime.AutotagRuntime; + +/** + * Selects a container to be used as the "current" container. + */ +public class SetCurrentContainerTag extends SimpleTagSupport { + + /** + * The template model. + */ + private org.apache.tiles.template.SetCurrentContainerModel model = new org.apache.tiles.template.SetCurrentContainerModel(); + + /** + * The key of the container to be used as "current". If null, the default one + * will be used. + */ + private java.lang.String containerKey; + + /** + * Getter for containerKey property. + * + * @return The key of the container to be used as "current". If null, the + * default one will be used. + */ + public java.lang.String getContainerKey() { + return containerKey; + } + + /** + * Setter for containerKey property. + * + * @param containerKey The key of the container to be used as "current". If + * null, the default one will be used. + */ + public void setContainerKey(java.lang.String containerKey) { + this.containerKey = containerKey; + } + + @Override + public void doTag() throws JspException, IOException { + AutotagRuntime runtime = new org.apache.tiles.request.jsp.autotag.JspAutotagRuntime(); + if (runtime instanceof SimpleTagSupport) { + SimpleTagSupport tag = (SimpleTagSupport) runtime; + tag.setJspContext(getJspContext()); + tag.setJspBody(getJspBody()); + tag.setParent(getParent()); + tag.doTag(); + } + org.apache.tiles.request.Request request = runtime.createRequest(); + model.execute(containerKey, request); + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/web/jsp/taglib/UseAttributeTag.java b/plugins/tiles/src/main/java/org/apache/tiles/web/jsp/taglib/UseAttributeTag.java new file mode 100644 index 000000000..e2740e56c --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/web/jsp/taglib/UseAttributeTag.java @@ -0,0 +1,214 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.web.jsp.taglib; + +import org.apache.tiles.autotag.core.runtime.AutotagRuntime; +import org.apache.tiles.request.Request; +import org.apache.tiles.request.jsp.autotag.JspAutotagRuntime; +import org.apache.tiles.template.ImportAttributeModel; + +import javax.servlet.jsp.JspException; +import javax.servlet.jsp.tagext.SimpleTagSupport; +import javax.servlet.jsp.tagext.TagData; +import javax.servlet.jsp.tagext.TagExtraInfo; +import javax.servlet.jsp.tagext.VariableInfo; +import java.io.IOException; + +/** + * Exposes am attribute as a scripting variable within the page. + * + * @since Tiles 1.0 + */ +public class UseAttributeTag extends SimpleTagSupport { + + /** + * The template model. + */ + private final ImportAttributeModel model = new ImportAttributeModel(); + + /** + * The id of the imported scripting variable. + */ + private String id; + + /** + * The scope name. + */ + private String scopeName = null; + + /** + * The name of the attribute. + */ + private String name = null; + + /** + * Flag that, if true, ignores exceptions. + */ + private boolean ignore = false; + + /** + * Class name of object. + */ + private String classname = null; + + /** + * Returns the id of the imported scripting variable. + * + * @return The id of the imported scripting variable. + * @since 2.2.0 + */ + public String getId() { + return id; + } + + /** + * Sets the id of the imported scripting variable. + * + * @param id The id of the imported scripting variable. + * @since 2.2.0 + */ + public void setId(String id) { + this.id = id; + } + + /** + * Set the scope. + * + * @param scope Scope. + */ + public void setScope(String scope) { + this.scopeName = scope; + } + + /** + * Get scope. + * + * @return Scope. + */ + public String getScope() { + return scopeName; + } + + /** + * Get the name. + * + * @return Name. + */ + public String getName() { + return name; + } + + /** + * Set the name. + * + * @param name The new name + */ + public void setName(String name) { + this.name = name; + } + + /** + * Set ignore flag. + * + * @param ignore default: false: Exception is thrown when attribute is not + * found, set to true to ignore missing attributes silently + */ + public void setIgnore(boolean ignore) { + this.ignore = ignore; + } + + /** + * Get ignore flag. + * + * @return default: false: Exception is thrown when attribute is not found, set + * to true to ignore missing attributes silently + */ + public boolean isIgnore() { + return ignore; + } + + /** + * Get class name. + * + * @return class name + */ + public String getClassname() { + return classname; + + } + + /** + * Set the class name. + * + * @param name The new class name. + */ + public void setClassname(String name) { + this.classname = name; + } + + /** + * {@inheritDoc} + */ + @Override + public void doTag() throws JspException, IOException { + AutotagRuntime runtime = new JspAutotagRuntime(); + SimpleTagSupport tag = (SimpleTagSupport) runtime; + tag.setJspContext(getJspContext()); + tag.setJspBody(getJspBody()); + tag.setParent(getParent()); + tag.doTag(); + Request request = runtime.createRequest(); + model.execute(name, scopeName, id, ignore, request); + } + + /** + * Returns the scripting variable to use. + * + * @return The scripting variable. + */ + public String getScriptingVariable() { + return id == null ? getName() : id; + } + + /** + * Implementation of TagExtraInfo which identifies the scripting object(s) to be + * made visible. + */ + public static class Tei extends TagExtraInfo { + + /** + * {@inheritDoc} + */ + @Override + public VariableInfo[] getVariableInfo(TagData data) { + String classname = data.getAttributeString("classname"); + if (classname == null) { + classname = "java.lang.Object"; + } + + String id = data.getAttributeString("id"); + if (id == null) { + id = data.getAttributeString("name"); + } + + return new VariableInfo[] { new VariableInfo(id, classname, true, VariableInfo.AT_END) }; + + } + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/web/jsp/taglib/package-info.java b/plugins/tiles/src/main/java/org/apache/tiles/web/jsp/taglib/package-info.java new file mode 100644 index 000000000..0c9e72cd0 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/web/jsp/taglib/package-info.java @@ -0,0 +1,23 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +/** + * The "tiles-jsp" tag library contains tags that are useful to create + * templates, subpages other reusable view parts using the "tiles-core" package. + */ +package org.apache.tiles.web.jsp.taglib; diff --git a/plugins/tiles/src/main/java/org/apache/tiles/web/startup/AbstractTilesListener.java b/plugins/tiles/src/main/java/org/apache/tiles/web/startup/AbstractTilesListener.java new file mode 100644 index 000000000..465431b06 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/web/startup/AbstractTilesListener.java @@ -0,0 +1,69 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.web.startup; + +import org.apache.tiles.core.startup.TilesInitializer; +import org.apache.tiles.request.servlet.ServletApplicationContext; + +import javax.servlet.ServletContext; +import javax.servlet.ServletContextEvent; +import javax.servlet.ServletContextListener; + +/** + * Listener for the initialization of the Tiles container. + */ +public abstract class AbstractTilesListener implements ServletContextListener { + + /** + * The initializer object. + * + * @since 2.1.2 + */ + protected TilesInitializer initializer; + + /** + * Initialize the TilesContainer and place it + * into service. + * + * @param event The intercepted event. + */ + public void contextInitialized(ServletContextEvent event) { + ServletContext servletContext = event.getServletContext(); + initializer = createTilesInitializer(); + initializer.initialize(new ServletApplicationContext(servletContext)); + } + + /** + * Destroys the initializer. + * + * @param event The intercepted event. + */ + public void contextDestroyed(ServletContextEvent event) { + initializer.destroy(); + } + + /** + * Creates a new instance of {@link TilesInitializer}. Implement it to use a + * different initializer. + * + * @return The Tiles servlet-based initializer. + * @since 2.2.0 + */ + protected abstract TilesInitializer createTilesInitializer(); +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/web/startup/package-info.java b/plugins/tiles/src/main/java/org/apache/tiles/web/startup/package-info.java new file mode 100644 index 000000000..6dc2fd3d2 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/web/startup/package-info.java @@ -0,0 +1,24 @@ +/* + * $Id: package-info.java 1049711 2010-12-15 21:12:00Z apetrelli $ + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +/** + * Classes to start the Tiles engine up in a web environment. + */ +package org.apache.tiles.web.startup; diff --git a/plugins/tiles/src/main/java/org/apache/tiles/web/util/AttributeContextMutator.java b/plugins/tiles/src/main/java/org/apache/tiles/web/util/AttributeContextMutator.java new file mode 100644 index 000000000..aa99ca099 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/web/util/AttributeContextMutator.java @@ -0,0 +1,42 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.web.util; + +import org.apache.tiles.api.AttributeContext; + +import javax.servlet.ServletRequest; + +/** + * It represents an object able to manipulate a AttributeContext. + * In other words, it is able to add, replace and remove attributes from the + * AttributeContext. + * + * @since Tiles 2.0 + */ +public interface AttributeContextMutator { + + /** + * Mutate a AttributeContext. + * + * @param context The attribute context to mutate. + * @param request The current servlet request. + */ + void mutate(AttributeContext context, ServletRequest request); + +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/web/util/TilesDispatchServlet.java b/plugins/tiles/src/main/java/org/apache/tiles/web/util/TilesDispatchServlet.java new file mode 100644 index 000000000..d456848c8 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/web/util/TilesDispatchServlet.java @@ -0,0 +1,148 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.web.util; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.apache.tiles.api.AttributeContext; +import org.apache.tiles.api.TilesContainer; +import org.apache.tiles.api.access.TilesAccess; +import org.apache.tiles.request.ApplicationContext; +import org.apache.tiles.request.Request; +import org.apache.tiles.request.reflect.ClassUtil; +import org.apache.tiles.request.servlet.ServletRequest; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +/** + * Tiles dispatching servlet. Used to invoke + * a definition directly. + */ +public class TilesDispatchServlet extends HttpServlet { + + /** + * Init parameter to define the key of the container to use. + * + * @since 2.1.2 + */ + public static final String CONTAINER_KEY_INIT_PARAMETER = + "org.apache.tiles.web.util.TilesDispatchServlet.CONTAINER_KEY"; + + /** + * The logging object. + */ + private static final Logger LOG = LogManager.getLogger(TilesDispatchServlet.class); + + /** + * The key under which the container is stored. + */ + private String containerKey; + + /** + * The object that will mutate the attribute context so that it uses + * different attributes. + */ + private org.apache.tiles.web.util.AttributeContextMutator mutator; + + + /** + * {@inheritDoc} + */ + @Override + public void init() throws ServletException { + super.init(); + + containerKey = getServletConfig().getInitParameter( + CONTAINER_KEY_INIT_PARAMETER); + + String temp = getInitParameter("mutator"); + if (temp != null) { + try { + mutator = (org.apache.tiles.web.util.AttributeContextMutator) ClassUtil.instantiate(temp); + } catch (Exception e) { + throw new ServletException("Unable to instantiate specified context mutator.", e); + } + } else { + mutator = new DefaultMutator(); + } + } + + /** + * {@inheritDoc} + */ + @Override + protected void doGet(HttpServletRequest req, HttpServletResponse res) { + + ApplicationContext applicationContext = org.apache.tiles.request.servlet.ServletUtil + .getApplicationContext(getServletContext()); + Request request = new ServletRequest(applicationContext, + req, res); + TilesContainer container = TilesAccess.getContainer(applicationContext, + containerKey); + mutator.mutate(container.getAttributeContext(request), req); + String definition = getDefinitionName(req); + if (LOG.isDebugEnabled()) { + LOG.info("Dispatching to tile '{}'", definition); + } + container.render(definition, request); + } + + /** + * Returns the called definition name for the given request. + * + * @param request The request to parse. + * @return The definition name to render. + */ + protected String getDefinitionName(HttpServletRequest request) { + String path = (String) request.getAttribute("javax.servlet.include.servlet_path"); + if (path == null) { + path = request.getServletPath(); + } + + int start = path.startsWith("/") ? 1 : 0; + int end = path.endsWith(".tiles") ? path.indexOf(".tiles") : path.length(); + + return path.substring(start, end); + } + + /** + * {@inheritDoc} + */ + @Override + protected void doPost(HttpServletRequest req, HttpServletResponse res) { + LOG.info("Tiles dispatch request received. Redirecting POST to GET."); + doGet(req, res); + } + + /** + * Default no-op mutator. + */ + static class DefaultMutator implements AttributeContextMutator { + + /** + * {@inheritDoc} + */ + public void mutate(AttributeContext context, javax.servlet.ServletRequest request) { + // noop; + } + } +} diff --git a/plugins/tiles/src/main/java/org/apache/tiles/web/util/package-info.java b/plugins/tiles/src/main/java/org/apache/tiles/web/util/package-info.java new file mode 100644 index 000000000..4a373d94f --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/tiles/web/util/package-info.java @@ -0,0 +1,24 @@ +/* + * $Id: package-info.java 1049711 2010-12-15 21:12:00Z apetrelli $ + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +/** + * Utility classes to use Tiles in a servlet environment. + */ +package org.apache.tiles.web.util; diff --git a/plugins/tiles/src/main/resources/META-INF/template-suite.xml b/plugins/tiles/src/main/resources/META-INF/template-suite.xml new file mode 100644 index 000000000..3d0a48ec5 --- /dev/null +++ b/plugins/tiles/src/main/resources/META-INF/template-suite.xml @@ -0,0 +1,1188 @@ + + + tiles + This tag library provides Tiles tags. + + + org.apache.tiles.template.InsertDefinitionModel + + org.apache.tiles.template.InsertDefinitionModel + insertDefinition + InsertDefinition + <p> +Insert a definition. +</p> +<p> +Insert a definition with the possibility to override and specify parameters +(called attributes). A definition can be seen as a (partially or totally) +filled template that can override or complete attribute values. +&lt;tiles:insertDefinition&gt; allows to define these attributes +and pass them to the inserted jsp page, called template. Attributes are +defined using nested tag &lt;tiles:putAttribute&gt; or +&lt;tiles:putListAttribute&gt;. +</p> +<p> +You must specify name tag attribute, for inserting a definition from definitions factory. +</p> +<p> +Example : +</p> + +<pre> + &lt;tiles:insertDefinition name=&quot;.my.tiles.defininition flush=&quot;true&quot;&gt; + &lt;tiles:putAttribute name=&quot;title&quot; value=&quot;My first page&quot; /&gt; + &lt;tiles:putAttribute name=&quot;header&quot; value=&quot;/common/header.jsp&quot; /&gt; + &lt;tiles:putAttribute name=&quot;footer&quot; value=&quot;/common/footer.jsp&quot; /&gt; + &lt;tiles:putAttribute name=&quot;menu&quot; value=&quot;/basic/menu.jsp&quot; /&gt; + &lt;tiles:putAttribute name=&quot;body&quot; value=&quot;/basic/helloBody.jsp&quot; /&gt; + &lt;/tiles:insertDefinition&gt; +</pre> + + execute + Executes the operation. + + + definitionName + + definitionName + name + The name of the definition to render. + java.lang.String + true + false + + + + template + + template + template + If specified, this template will be used instead of the one used by the definition. + java.lang.String + false + false + + + + templateType + + templateType + templateType + The type of the template attribute. + java.lang.String + false + false + + + + templateExpression + + templateExpression + templateExpression + The expression to evaluate to get the value of the template. + java.lang.String + false + false + + + + role + + role + role + A comma-separated list of roles. If present, the definition +will be rendered only if the current user belongs to one of the roles. + java.lang.String + false + false + + + + preparer + + preparer + preparer + The preparer to use to invoke before the definition is +rendered. If specified, it overrides the preparer specified in the definition itself. + java.lang.String + false + false + + + + flush + + flush + flush + If true, the response will be flushed after the insert. + boolean + false + false + + + + request + + request + request + The request. + org.apache.tiles.request.Request + false + true + + + + modelBody + + modelBody + modelBody + The body. + org.apache.tiles.autotag.core.runtime.ModelBody + false + false + + + + + + + + org.apache.tiles.template.ImportAttributeModel + + org.apache.tiles.template.ImportAttributeModel + importAttribute + ImportAttribute + <p> +Import attribute(s) in specified context. +</p> +<p> +Import attribute(s) to requested scope. Attribute name and scope are +optional. If not specified, all attributes are imported in page scope. Once +imported, an attribute can be used as any other beans from jsp contexts. +</p> + + execute + Executes the model. + + + name + + name + name + The name of the attribute to import. If it is null, all the attributes will be imported. + java.lang.String + false + false + + + + scope + + scope + scope + The scope into which the attribute(s) will be imported. If +null, the import will go in page scope. + java.lang.String + false + false + + + + toName + + toName + toName + The name of the attribute into which the attribute will be +imported. To be used in conjunction to name. If null, the value of name will be used. + java.lang.String + false + false + + + + ignore + + ignore + ignore + If true, if the attribute is not present, the problem will be ignored. + boolean + false + false + + + + request + + request + request + The request. + org.apache.tiles.request.Request + false + true + + + + + + + + org.apache.tiles.template.SetCurrentContainerModel + + org.apache.tiles.template.SetCurrentContainerModel + setCurrentContainer + SetCurrentContainer + Selects a container to be used as the "current" container. + + execute + Executes the model. + + + containerKey + + containerKey + containerKey + The key of the container to be used as "current". If null, the default one will be used. + java.lang.String + false + false + + + + request + + request + request + The request. + org.apache.tiles.request.Request + false + true + + + + + + + + org.apache.tiles.template.AddListAttributeModel + + org.apache.tiles.template.AddListAttributeModel + addListAttribute + AddListAttribute + <p> +Declare a list that will be pass as an attribute. +</p> +<p> +Declare a list that will be pass as an attribute . List elements are added +using the tag 'addAttribute' or 'addListAttribute'. This tag can only be used +inside 'insertTemplate', 'insertDefinition' or 'definition' tag. +</p> + + execute + Executes the model. + + + role + + role + role + The comma-separated list of roles that can use the list attribute. + java.lang.String + false + false + + + + request + + request + request + The request. + org.apache.tiles.request.Request + false + true + + + + modelBody + + modelBody + modelBody + The body. + org.apache.tiles.autotag.core.runtime.ModelBody + false + false + + + + + + + + org.apache.tiles.template.GetAsStringModel + + org.apache.tiles.template.GetAsStringModel + getAsString + GetAsString + <p> + Render the value of the specified template attribute to the current Writer +</p> + +<p> +Retrieve the value of the specified template attribute property, and render +it to the current Writer as a String. The usual toString() conversions is applied on found value. +</p> + + execute + Executes the operation. + + + ignore + + ignore + ignore + If true, if an exception happens during +rendering, of if the attribute is null, the problem will be ignored. + boolean + false + false + + + + preparer + + preparer + preparer + The preparer to invoke before rendering the attribute. + java.lang.String + false + false + + + + role + + role + role + A comma-separated list of roles. If present, the attribute +will be rendered only if the current user belongs to one of the roles. + java.lang.String + false + false + + + + defaultValue + + defaultValue + defaultValue + The default value of the attribute. To use only if +the attribute was not computed. + java.lang.Object + false + false + + + + defaultValueRole + + defaultValueRole + defaultValueRole + The default comma-separated list of roles. To use +only if the attribute was not computed. + java.lang.String + false + false + + + + defaultValueType + + defaultValueType + defaultValueType + The default type of the attribute. To use only if +the attribute was not computed. + java.lang.String + false + false + + + + name + + name + name + The name of the attribute. + java.lang.String + true + false + + + + value + + value + value + The attribute to use immediately, if not null. + org.apache.tiles.api.Attribute + false + false + + + + request + + request + request + The request. + org.apache.tiles.request.Request + false + true + + + + modelBody + + modelBody + modelBody + The body. + org.apache.tiles.autotag.core.runtime.ModelBody + false + false + + + + + + + + org.apache.tiles.template.InsertAttributeModel + + org.apache.tiles.template.InsertAttributeModel + insertAttribute + InsertAttribute + <p> +Inserts the value of an attribute into the page. +</p> +<p> +This tag can be flexibly used to insert the value of an attribute into a +page. As in other usages in Tiles, every attribute can be determined to have +a "type", either set explicitly when it was defined, or "computed". If the +type is not explicit, then if the attribute value is a valid definition, it +will be inserted as such. Otherwise, if it begins with a "/" character, it +will be treated as a "template". Finally, if it has not otherwise been +assigned a type, it will be treated as a String and included without any special handling. +</p> + +<p> +Example : +</p> + +<pre> + &lt;tiles:insertAttribute name=&quot;body&quot; /&gt; +</pre> + + execute + Executes the operation. + + + ignore + + ignore + ignore + If true, if an exception happens during +rendering, of if the attribute is null, the problem will be ignored. + boolean + false + false + + + + preparer + + preparer + preparer + The preparer to invoke before rendering the attribute. + java.lang.String + false + false + + + + role + + role + role + A comma-separated list of roles. If present, the attribute +will be rendered only if the current user belongs to one of the roles. + java.lang.String + false + false + + + + defaultValue + + defaultValue + defaultValue + The default value of the attribute. To use only if +the attribute was not computed. + java.lang.Object + false + false + + + + defaultValueRole + + defaultValueRole + defaultValueRole + The default comma-separated list of roles. To use +only if the attribute was not computed. + java.lang.String + false + false + + + + defaultValueType + + defaultValueType + defaultValueType + The default type of the attribute. To use only if +the attribute was not computed. + java.lang.String + false + false + + + + name + + name + name + The name of the attribute. + java.lang.String + false + false + + + + value + + value + value + The attribute to use immediately, if not null. + org.apache.tiles.api.Attribute + false + false + + + + flush + + flush + flush + If true, the response will be flushed after the insert. + boolean + false + false + + + + request + + request + request + The request. + org.apache.tiles.request.Request + false + true + + + + modelBody + + modelBody + modelBody + The body. + org.apache.tiles.autotag.core.runtime.ModelBody + false + false + + + + + + + + org.apache.tiles.template.PutAttributeModel + + org.apache.tiles.template.PutAttributeModel + putAttribute + PutAttribute + <p> +Put an attribute in enclosing attribute container tag. +</p> +<p> +Enclosing attribute container tag can be : +<ul> +<li>&lt;initContainer&gt;</li> +<li>&lt;definition&gt;</li> +<li>&lt;insertAttribute&gt;</li> +<li>&lt;insertDefinition&gt;</li> +<li>&lt;putListAttribute&gt;</li> +</ul> +(or any other tag which implements the PutAttributeTagParent +interface. Exception is thrown if no appropriate tag can be found. +</p> +<p> +Put tag can have following atributes : +<ul> +<li>name : Name of the attribute</li> +<li>value : value to put as attribute</li> +<li>type : value type. Possible type are : string (value is used as direct +string), template (value is used as a page url to insert), definition (value +is used as a definition name to insert), object (value is used as it is)</li> +<li>role : Role to check when 'insertAttribute' will be called.</li> +</ul> +</p> +<p> +Value can also come from tag body. Tag body is taken into account only if +value is not set by one of the tag attributes. In this case Attribute type is +"string", unless tag body define another type. +</p> + + execute + Executes the operation. + + + name + + name + name + The name of the attribute to put. + java.lang.String + true + false + + + + value + + value + value + The value of the attribute. Use this parameter, or expression, or body. + java.lang.Object + false + false + + + + expression + + expression + expression + The expression to calculate the value from. Use this +parameter, or value, or body. + java.lang.String + false + false + + + + role + + role + role + A comma-separated list of roles. If present, the attribute +will be rendered only if the current user belongs to one of the roles. + java.lang.String + false + false + + + + type + + type + type + The type (renderer) of the attribute. + java.lang.String + false + false + + + + cascade + + cascade + cascade + If true the attribute will be cascaded to all nested attributes. + boolean + false + false + + + + request + + request + request + The request. + org.apache.tiles.request.Request + false + true + + + + modelBody + + modelBody + modelBody + The body. + org.apache.tiles.autotag.core.runtime.ModelBody + false + false + + + + + + + + org.apache.tiles.template.DefinitionModel + + org.apache.tiles.template.DefinitionModel + definition + Definition + <p> +Create a definition at runtime. +</p> +<p> +Create a new definition at runtime. Newly created definition will be +available across the entire request. +</p> + + execute + Executes the operation. + + + name + + name + name + The name of the definition to create. If not specified, an +anonymous definition will be created. + java.lang.String + false + false + + + + template + + template + template + The template of this definition. + java.lang.String + false + false + + + + role + + role + role + A comma-separated list of roles. If present, the definition +will be rendered only if the current user belongs to one of the roles. + java.lang.String + false + false + + + + extendsParam + + extendsParam + extends + The definition name that this definition extends. + java.lang.String + false + false + + + + preparer + + preparer + preparer + The preparer to use to invoke before the definition is rendered. + java.lang.String + false + false + + + + request + + request + request + The request. + org.apache.tiles.request.Request + false + true + + + + modelBody + + modelBody + modelBody + The body. + org.apache.tiles.autotag.core.runtime.ModelBody + false + false + + + + + + + + org.apache.tiles.template.AddAttributeModel + + org.apache.tiles.template.AddAttributeModel + addAttribute + AddAttribute + <p> +Add an element to the surrounding list. Equivalent to 'putAttribute', +but for list element. +</p> + +<p> +Add an element to the surrounding list. This tag can only be used inside +'putListAttribute' or 'addListAttribute' tags. Value can come from a direct +assignment (value="aValue") +</p> + + execute + Executes the operation. + + + value + + value + value + The value of the attribute. Use this parameter, or expression, or body. + java.lang.Object + false + false + + + + expression + + expression + expression + The expression to calculate the value from. Use this +parameter, or value, or body. + java.lang.String + false + false + + + + role + + role + role + A comma-separated list of roles. If present, the attribute +will be rendered only if the current user belongs to one of the roles. + java.lang.String + false + false + + + + type + + type + type + The type (renderer) of the attribute. + java.lang.String + false + false + + + + request + + request + request + The request. + org.apache.tiles.request.Request + false + true + + + + modelBody + + modelBody + modelBody + The body. + org.apache.tiles.autotag.core.runtime.ModelBody + false + false + + + + + + + + org.apache.tiles.template.PutListAttributeModel + + org.apache.tiles.template.PutListAttributeModel + putListAttribute + PutListAttribute + <p> +Declare a list that will be pass as attribute to tile. +</p> +<p> +Declare a list that will be pass as attribute to tile. List elements are +added using the tags 'addAttribute' or 'addListAttribute'. This tag can only +be used inside 'insertTemplate', 'insertDefinition', 'definition' tags. +</p> + + execute + Executes the model. + + + name + + name + name + The name of the attribute to put. + java.lang.String + true + false + + + + role + + role + role + A comma-separated list of roles. If present, the attribute +will be rendered only if the current user belongs to one of the roles. + java.lang.String + false + false + + + + inherit + + inherit + inherit + If true, the list attribute will use, as first elements, the +list contained in the list attribute, put with the same name, of the containing definition. + boolean + false + false + + + + cascade + + cascade + cascade + If true the attribute will be cascaded to all nested attributes. + boolean + false + false + + + + request + + request + request + The request. + org.apache.tiles.request.Request + false + true + + + + modelBody + + modelBody + modelBody + The body. + org.apache.tiles.autotag.core.runtime.ModelBody + false + false + + + + + + + + org.apache.tiles.template.InsertTemplateModel + + org.apache.tiles.template.InsertTemplateModel + insertTemplate + InsertTemplate + <p> +Insert a template. +</p> +<p> +Insert a template with the possibility to pass parameters (called +attributes). A template can be seen as a procedure that can take parameters +or attributes. &lt;tiles:insertTemplate&gt; allows to define +these attributes and pass them to the inserted jsp page, called template. +Attributes are defined using nested tag +&lt;tiles:putAttribute&gt; or +&lt;tiles:putListAttribute&gt;. +</p> +<p> +You must specify template attribute, for inserting a template +</p> + +<p> +Example : +</p> + +<pre> + &lt;tiles:insertTemplate template=&quot;/basic/myLayout.jsp&quot; flush=&quot;true&quot;&gt; + &lt;tiles:putAttribute name=&quot;title&quot; value=&quot;My first page&quot; /&gt; + &lt;tiles:putAttribute name=&quot;header&quot; value=&quot;/common/header.jsp&quot; /&gt; + &lt;tiles:putAttribute name=&quot;footer&quot; value=&quot;/common/footer.jsp&quot; /&gt; + &lt;tiles:putAttribute name=&quot;menu&quot; value=&quot;/basic/menu.jsp&quot; /&gt; + &lt;tiles:putAttribute name=&quot;body&quot; value=&quot;/basic/helloBody.jsp&quot; /&gt; + &lt;/tiles:insertTemplate&gt; +</pre> + + execute + Executes the operation. + + + template + + template + template + The template to render. + java.lang.String + true + false + + + + templateType + + templateType + templateType + The type of the template attribute. + java.lang.String + false + false + + + + templateExpression + + templateExpression + templateExpression + The expression to evaluate to get the value of the template. + java.lang.String + false + false + + + + role + + role + role + A comma-separated list of roles. If present, the template +will be rendered only if the current user belongs to one of the roles. + java.lang.String + false + false + + + + preparer + + preparer + preparer + The preparer to use to invoke before the definition is +rendered. If specified, it overrides the preparer specified in the +definition itself. + java.lang.String + false + false + + + + flush + + flush + flush + If true, the response will be flushed after the insert. + boolean + false + false + + + + request + + request + request + The request. + org.apache.tiles.request.Request + false + true + + + + modelBody + + modelBody + modelBody + The body. + org.apache.tiles.autotag.core.runtime.ModelBody + false + false + + + + + + + + \ No newline at end of file diff --git a/plugins/tiles/src/main/resources/META-INF/tld/tiles-extras-jsp.tld b/plugins/tiles/src/main/resources/META-INF/tld/tiles-extras-jsp.tld new file mode 100644 index 000000000..4ba058ebe --- /dev/null +++ b/plugins/tiles/src/main/resources/META-INF/tld/tiles-extras-jsp.tld @@ -0,0 +1,105 @@ + + + + + This tag library provides Tiles tags.

+ ]]> +
+ 1.2 + tilesx + http://tiles.apache.org/tags-tiles-extras + + + Use attribute value inside page.

+

Declare a Java variable, and an attribute in the specified scope, using its attribute + value.

+

Java variable and attribute will have the name specified by 'id', or the original name + if not specified.

+ ]]> +
+ useAttribute + org.apache.tiles.web.jsp.taglib.UseAttributeTag + org.apache.tiles.web.jsp.taglib.UseAttributeTag$Tei + empty + + + Declared attribute and variable name.

+ ]]> +
+ id + false + true +
+ + + Class of the declared variable.

+ ]]> +
+ classname + false + true +
+ + + Scope of the declared attribute. Default to 'page'.

+ ]]> +
+ scope + false + false +
+ + + Attribute name.

+ ]]> +
+ name + true + true +
+ + + + If this attribute is set to true, and the attribute specified by the name does not exist, + simply return without error. The default value is false, which will cause a runtime + exception to be thrown. +

+ ]]> +
+ ignore + false + true + boolean +
+
+
+ diff --git a/plugins/tiles/src/main/resources/META-INF/tld/tiles-jsp.tld b/plugins/tiles/src/main/resources/META-INF/tld/tiles-jsp.tld new file mode 100644 index 000000000..defe3ef55 --- /dev/null +++ b/plugins/tiles/src/main/resources/META-INF/tld/tiles-jsp.tld @@ -0,0 +1,922 @@ + + + + + + + + 1.2 + tiles + http://tiles.apache.org/tags-tiles + + + + Insert a definition. +

+

+ Insert a definition with the possibility to override and specify parameters + (called attributes). A definition can be seen as a (partially or totally) + filled template that can override or complete attribute values. + <tiles:insertDefinition> allows to define these attributes + and pass them to the inserted jsp page, called template. Attributes are + defined using nested tag <tiles:putAttribute> or + <tiles:putListAttribute>. +

+

+ You must specify name tag attribute, for inserting a definition from definitions factory. +

+

+ Example : +

+ +
+          <tiles:insertDefinition name=".my.tiles.defininition flush="true">
+              <tiles:putAttribute name="title" value="My first page" />
+              <tiles:putAttribute name="header" value="/common/header.jsp" />
+              <tiles:putAttribute name="footer" value="/common/footer.jsp" />
+              <tiles:putAttribute name="menu" value="/basic/menu.jsp" />
+              <tiles:putAttribute name="body" value="/basic/helloBody.jsp" />
+          </tiles:insertDefinition>
+      
+ ]]> +
+ insertDefinition + org.apache.tiles.web.jsp.taglib.InsertDefinitionTag + scriptless + + + + + name + true + true + java.lang.String + + + + + + template + false + true + java.lang.String + + + + + + templateType + false + true + java.lang.String + + + + + + templateExpression + false + true + java.lang.String + + + + + + role + false + true + java.lang.String + + + + + + preparer + false + true + java.lang.String + + + + + + flush + false + true + boolean + +
+ + + + Import attribute(s) in specified context. +

+

+ Import attribute(s) to requested scope. Attribute name and scope are + optional. If not specified, all attributes are imported in page scope. Once + imported, an attribute can be used as any other beans from jsp contexts. +

+ ]]> +
+ importAttribute + org.apache.tiles.web.jsp.taglib.ImportAttributeTag + empty + + + + + name + false + true + java.lang.String + + + + + + scope + false + true + java.lang.String + + + + + + toName + false + true + java.lang.String + + + + + + ignore + false + true + boolean + +
+ + + + + setCurrentContainer + org.apache.tiles.web.jsp.taglib.SetCurrentContainerTag + empty + + + + + containerKey + false + true + java.lang.String + + + + + + Declare a list that will be pass as an attribute. +

+

+ Declare a list that will be pass as an attribute . List elements are added + using the tag 'addAttribute' or 'addListAttribute'. This tag can only be used + inside 'insertTemplate', 'insertDefinition' or 'definition' tag. +

+ ]]> +
+ addListAttribute + org.apache.tiles.web.jsp.taglib.AddListAttributeTag + scriptless + + + + + role + false + true + java.lang.String + +
+ + + + Render the value of the specified template attribute to the current Writer +

+ +

+ Retrieve the value of the specified template attribute property, and render + it to the current Writer as a String. The usual toString() conversions is applied on found value. +

+ ]]> +
+ getAsString + org.apache.tiles.web.jsp.taglib.GetAsStringTag + scriptless + + + + + ignore + false + true + boolean + + + + + + preparer + false + true + java.lang.String + + + + + + role + false + true + java.lang.String + + + + + + defaultValue + false + true + java.lang.Object + + + + + + defaultValueRole + false + true + java.lang.String + + + + + + defaultValueType + false + true + java.lang.String + + + + + + name + true + true + java.lang.String + + + + + + value + false + true + org.apache.tiles.api.Attribute + +
+ + + + Inserts the value of an attribute into the page. +

+

+ This tag can be flexibly used to insert the value of an attribute into a + page. As in other usages in Tiles, every attribute can be determined to have + a "type", either set explicitly when it was defined, or "computed". If the + type is not explicit, then if the attribute value is a valid definition, it + will be inserted as such. Otherwise, if it begins with a "/" character, it + will be treated as a "template". Finally, if it has not otherwise been + assigned a type, it will be treated as a String and included without any special handling. +

+ +

+ Example : +

+ +
+          <tiles:insertAttribute name="body" />
+      
+ ]]> +
+ insertAttribute + org.apache.tiles.web.jsp.taglib.InsertAttributeTag + scriptless + + + + + ignore + false + true + boolean + + + + + + preparer + false + true + java.lang.String + + + + + + role + false + true + java.lang.String + + + + + + defaultValue + false + true + java.lang.Object + + + + + + defaultValueRole + false + true + java.lang.String + + + + + + defaultValueType + false + true + java.lang.String + + + + + + name + false + true + java.lang.String + + + + + + value + false + true + org.apache.tiles.api.Attribute + + + + + + flush + false + true + boolean + +
+ + + + Put an attribute in enclosing attribute container tag. +

+

+ Enclosing attribute container tag can be : +

    +
  • <initContainer>
  • +
  • <definition>
  • +
  • <insertAttribute>
  • +
  • <insertDefinition>
  • +
  • <putListAttribute>
  • +
+ (or any other tag which implements the PutAttributeTagParent + interface. Exception is thrown if no appropriate tag can be found. +

+

+ Put tag can have following atributes : +

    +
  • name : Name of the attribute
  • +
  • value : value to put as attribute
  • +
  • type : value type. Possible type are : string (value is used as direct + string), template (value is used as a page url to insert), definition (value + is used as a definition name to insert), object (value is used as it is)
  • +
  • role : Role to check when 'insertAttribute' will be called.
  • +
+

+

+ Value can also come from tag body. Tag body is taken into account only if + value is not set by one of the tag attributes. In this case Attribute type is + "string", unless tag body define another type. +

+ ]]> +
+ putAttribute + org.apache.tiles.web.jsp.taglib.PutAttributeTag + scriptless + + + + + name + true + true + java.lang.String + + + + + + value + false + true + java.lang.Object + + + + + + expression + false + true + java.lang.String + + + + + + role + false + true + java.lang.String + + + + + + type + false + true + java.lang.String + + + + + + cascade + false + true + boolean + +
+ + + + Create a definition at runtime. +

+

+ Create a new definition at runtime. Newly created definition will be + available across the entire request. +

+ ]]> +
+ definition + org.apache.tiles.web.jsp.taglib.DefinitionTag + scriptless + + + + + name + false + true + java.lang.String + + + + + + template + false + true + java.lang.String + + + + + + role + false + true + java.lang.String + + + + + + extends + false + true + java.lang.String + + + + + + preparer + false + true + java.lang.String + +
+ + + + Add an element to the surrounding list. Equivalent to 'putAttribute', + but for list element. +

+ +

+ Add an element to the surrounding list. This tag can only be used inside + 'putListAttribute' or 'addListAttribute' tags. Value can come from a direct + assignment (value="aValue") +

+ ]]> +
+ addAttribute + org.apache.tiles.web.jsp.taglib.AddAttributeTag + scriptless + + + + + value + false + true + java.lang.Object + + + + + + expression + false + true + java.lang.String + + + + + + role + false + true + java.lang.String + + + + + + type + false + true + java.lang.String + +
+ + + + Declare a list that will be pass as attribute to tile. +

+

+ Declare a list that will be pass as attribute to tile. List elements are + added using the tags 'addAttribute' or 'addListAttribute'. This tag can only + be used inside 'insertTemplate', 'insertDefinition', 'definition' tags. +

+ ]]> +
+ putListAttribute + org.apache.tiles.web.jsp.taglib.PutListAttributeTag + scriptless + + + + + name + true + true + java.lang.String + + + + + + role + false + true + java.lang.String + + + + + + inherit + false + true + boolean + + + + + + cascade + false + true + boolean + +
+ + + + Insert a template. +

+

+ Insert a template with the possibility to pass parameters (called + attributes). A template can be seen as a procedure that can take parameters + or attributes. <tiles:insertTemplate> allows to define + these attributes and pass them to the inserted jsp page, called template. + Attributes are defined using nested tag + <tiles:putAttribute> or + <tiles:putListAttribute>. +

+

+ You must specify template attribute, for inserting a template +

+ +

+ Example : +

+ +
+          <tiles:insertTemplate template="/basic/myLayout.jsp" flush="true">
+              <tiles:putAttribute name="title" value="My first page" />
+              <tiles:putAttribute name="header" value="/common/header.jsp" />
+              <tiles:putAttribute name="footer" value="/common/footer.jsp" />
+              <tiles:putAttribute name="menu" value="/basic/menu.jsp" />
+              <tiles:putAttribute name="body" value="/basic/helloBody.jsp" />
+          </tiles:insertTemplate>
+      
+ ]]> +
+ insertTemplate + org.apache.tiles.web.jsp.taglib.InsertTemplateTag + scriptless + + + + + template + true + true + java.lang.String + + + + + + templateType + false + true + java.lang.String + + + + + + templateExpression + false + true + java.lang.String + + + + + + role + false + true + java.lang.String + + + + + + preparer + false + true + java.lang.String + + + + + + flush + false + true + boolean + +
+
diff --git a/plugins/tiles/src/main/resources/META-INF/velocity.properties b/plugins/tiles/src/main/resources/META-INF/velocity.properties new file mode 100644 index 000000000..4887c6cc3 --- /dev/null +++ b/plugins/tiles/src/main/resources/META-INF/velocity.properties @@ -0,0 +1,30 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# +# This file was automatically generated by Autotag. Please do not edit it manually. + +userdirective=org.apache.tiles.velocity.template.InsertDefinitionDirective,\ +org.apache.tiles.velocity.template.ImportAttributeDirective,\ +org.apache.tiles.velocity.template.SetCurrentContainerDirective,\ +org.apache.tiles.velocity.template.AddListAttributeDirective,\ +org.apache.tiles.velocity.template.GetAsStringDirective,\ +org.apache.tiles.velocity.template.InsertAttributeDirective,\ +org.apache.tiles.velocity.template.PutAttributeDirective,\ +org.apache.tiles.velocity.template.DefinitionDirective,\ +org.apache.tiles.velocity.template.AddAttributeDirective,\ +org.apache.tiles.velocity.template.PutListAttributeDirective,\ +org.apache.tiles.velocity.template.InsertTemplateDirective diff --git a/plugins/tiles/src/main/resources/org/apache/tiles/autotag/freemarker/fmModel.vm b/plugins/tiles/src/main/resources/org/apache/tiles/autotag/freemarker/fmModel.vm new file mode 100644 index 000000000..c307110dd --- /dev/null +++ b/plugins/tiles/src/main/resources/org/apache/tiles/autotag/freemarker/fmModel.vm @@ -0,0 +1,78 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +/* + * This file was automatically generated by Autotag. Please do not edit it manually. + */ +package ${packageName}; + +import java.io.IOException; +import java.util.Map; + +#if(${clazz.hasBody()}) +import org.apache.tiles.autotag.core.runtime.ModelBody; +#end +import org.apache.tiles.autotag.core.runtime.AutotagRuntime; + +import freemarker.core.Environment; +import freemarker.template.TemplateDirectiveBody; +import freemarker.template.TemplateDirectiveModel; +import freemarker.template.TemplateException; +import freemarker.template.TemplateModel; + +/** +#foreach($line in $stringTool.splitOnNewlines(${clazz.documentation})) + * ${line} +#end + */ +public class ${clazz.tagClassPrefix}FMModel implements TemplateDirectiveModel { + + /** + * The template model. + */ + private ${clazz.name} model; + + /** + * Constructor. + * + * @param model + * The template model. + */ + public ${clazz.tagClassPrefix}FMModel(${clazz.name} model) { + this.model = model; + } + + @Override + public void execute(Environment env, @SuppressWarnings("rawtypes") Map params, TemplateModel[] loopVars, + TemplateDirectiveBody body) throws TemplateException, IOException { + AutotagRuntime<${requestClass}> runtime = new ${runtimeClass}(); + if (runtime instanceof TemplateDirectiveModel) { + ((TemplateDirectiveModel) runtime).execute(env, params, loopVars, body); + } + ${requestClass} request = runtime.createRequest(); +#if(${clazz.hasBody()}) + ModelBody modelBody = runtime.createModelBody(); +#end + model.execute( +#foreach($parameter in ${clazz.parameters}) + runtime.getParameter("${parameter.exportedName}", ${stringTool.getClassToCast(${parameter.type})}.class, $stringTool.getDefaultValue(${parameter.type}, ${parameter.defaultValue})), +#end + request#if(${clazz.hasBody()}), modelBody#end + ); + } +} diff --git a/plugins/tiles/src/main/resources/org/apache/tiles/autotag/freemarker/repository.vm b/plugins/tiles/src/main/resources/org/apache/tiles/autotag/freemarker/repository.vm new file mode 100644 index 000000000..a854aa4ac --- /dev/null +++ b/plugins/tiles/src/main/resources/org/apache/tiles/autotag/freemarker/repository.vm @@ -0,0 +1,57 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +/* + * This file was automatically generated by Autotag. Please do not edit it manually. + */ +package ${packageName}; + +/** +#foreach($line in $stringTool.splitOnNewlines(${suite.documentation})) + * $line +#end + */ +public class $stringTool.capitalizeFirstLetter(${suite.name})FMModelRepository { + +#foreach($clazz in ${suite.getTemplateClasses()}) + /** + * The "${clazz.tagName}" directive. + */ + private ${clazz.tagClassPrefix}FMModel ${clazz.tagName}; + +#end + /** + * Constructor. + */ + public TilesFMModelRepository() { +#foreach($clazz in ${suite.getTemplateClasses()}) + ${clazz.tagName} = new ${clazz.tagClassPrefix}FMModel(new ${clazz.name}()); +#end + } +#foreach($clazz in ${suite.getTemplateClasses()}) + + /** + * Returns the "${clazz.tagName}" directive. + * + * @return The "${clazz.tagName}" directive. + */ + public ${clazz.tagClassPrefix}FMModel get$stringTool.capitalizeFirstLetter(${clazz.tagName})() { + return ${clazz.tagName}; + } +#end +} diff --git a/plugins/tiles/src/main/resources/org/apache/tiles/autotag/jsp/bodyTag.vm b/plugins/tiles/src/main/resources/org/apache/tiles/autotag/jsp/bodyTag.vm new file mode 100644 index 000000000..e48be526c --- /dev/null +++ b/plugins/tiles/src/main/resources/org/apache/tiles/autotag/jsp/bodyTag.vm @@ -0,0 +1,102 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + /* + * This file was automatically generated by Autotag. Please do not edit it manually. + */ +package ${packageName}; + +import java.io.IOException; + +import javax.servlet.jsp.JspException; +import javax.servlet.jsp.tagext.SimpleTagSupport; + +#if(${clazz.hasBody()}) +import org.apache.tiles.autotag.core.runtime.ModelBody; +#end +import org.apache.tiles.autotag.core.runtime.AutotagRuntime; + +/** +#foreach($line in $stringTool.splitOnNewlines(${clazz.documentation})) + * ${line} +#end + */ +public class ${clazz.tagClassPrefix}Tag extends SimpleTagSupport { + + /** + * The template model. + */ + private ${clazz.name} model = new ${clazz.name}(); + +#foreach($parameter in ${clazz.parameters}) + /** +#foreach($line in $stringTool.splitOnNewlines(${parameter.documentation})) + * ${line} +#end + */ + private ${parameter.type} ${parameter.name}; + +#end +#foreach($parameter in ${clazz.parameters}) + /** + * Getter for ${parameter.exportedName} property. + * + * @return +#foreach($line in $stringTool.splitOnNewlines(${parameter.documentation})) + * ${line} +#end + */ + public ${parameter.type} #if(${parameter.type} == 'boolean')is#{else}get#end${parameter.getterSetterSuffix}() { + return ${parameter.name}; + } + + /** + * Setter for ${parameter.exportedName} property. + * + * @param ${parameter.name} +#foreach($line in $stringTool.splitOnNewlines(${parameter.documentation})) + * ${line} +#end + */ + public void set${parameter.getterSetterSuffix}(${parameter.type} ${parameter.name}) { + this.${parameter.name} = ${parameter.name}; + } + +#end + @Override + public void doTag() throws JspException, IOException { + AutotagRuntime<${requestClass}> runtime = new ${runtimeClass}(); + if (runtime instanceof SimpleTagSupport) { + SimpleTagSupport tag = (SimpleTagSupport) runtime; + tag.setJspContext(getJspContext()); + tag.setJspBody(getJspBody()); + tag.setParent(getParent()); + tag.doTag(); + } + ${requestClass} request = runtime.createRequest(); +#if(${clazz.hasBody()}) + ModelBody modelBody = runtime.createModelBody(); +#end + model.execute( +#foreach($parameter in ${clazz.parameters}) + ${parameter.name}, +#end + request#if(${clazz.hasBody()}), modelBody#end + ); + } +} diff --git a/plugins/tiles/src/main/resources/org/apache/tiles/autotag/jsp/tld.vm b/plugins/tiles/src/main/resources/org/apache/tiles/autotag/jsp/tld.vm new file mode 100644 index 000000000..2faecf662 --- /dev/null +++ b/plugins/tiles/src/main/resources/org/apache/tiles/autotag/jsp/tld.vm @@ -0,0 +1,66 @@ + + + + + + + + 1.2 + ${suite.name} + ${parameters.taglibURI} +#foreach($clazz in ${suite.getTemplateClasses()}) + + + + + ${clazz.tagName} + ${packageName}.${clazz.tagClassPrefix}Tag + #if(${clazz.hasBody()})scriptless#{else}empty#end +#foreach($parameter in ${clazz.parameters}) + + + + + ${parameter.exportedName} + ${parameter.required} + true + ${parameter.type} + +#end + +#end + diff --git a/plugins/tiles/src/main/resources/org/apache/tiles/autotag/velocity.properties b/plugins/tiles/src/main/resources/org/apache/tiles/autotag/velocity.properties new file mode 100644 index 000000000..821c6d762 --- /dev/null +++ b/plugins/tiles/src/main/resources/org/apache/tiles/autotag/velocity.properties @@ -0,0 +1,101 @@ + # Licensed to the Apache Software Foundation (ASF) under one + # or more contributor license agreements. See the NOTICE file + # distributed with this work for additional information + # regarding copyright ownership. The ASF licenses this file + # to you under the Apache License, Version 2.0 (the + # "License"); you may not use this file except in compliance + # with the License. You may obtain a copy of the License at + # + # http://www.apache.org/licenses/LICENSE-2.0 + # + # Unless required by applicable law or agreed to in writing, + # software distributed under the License is distributed on an + # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + # KIND, either express or implied. See the License for the + # specific language governing permissions and limitations + # under the License. +# ---------------------------------------------------------------------------- +# These are the default properties for the +# Velocity Runtime. These values are used when +# Runtime.init() is called, and when Runtime.init(properties) +# fails to find the specificed properties file. +# ---------------------------------------------------------------------------- + + +# ---------------------------------------------------------------------------- +# R U N T I M E L O G +# ---------------------------------------------------------------------------- +# Velocity uses the Servlet APIs logging facilites. + +# ---------------------------------------------------------------------------- +# This controls if Runtime.error(), info() and warn() messages include the +# whole stack trace. The last property controls whether invalid references +# are logged. +# ---------------------------------------------------------------------------- + +runtime.log.invalid.reference = true + + +# ---------------------------------------------------------------------------- +# T E M P L A T E E N C O D I N G +# ---------------------------------------------------------------------------- + +input.encoding=ISO-8859-1 +output.encoding=ISO-8859-1 + + +# ---------------------------------------------------------------------------- +# I N C L U D E P R O P E R T I E S +# ---------------------------------------------------------------------------- +# These are the properties that governed the way #include'd content +# is governed. +# ---------------------------------------------------------------------------- + +directive.include.output.errormsg.start = + + +# ---------------------------------------------------------------------------- +# P A R S E P R O P E R T I E S +# ---------------------------------------------------------------------------- + +directive.parse.max.depth = 10 + + +# ---------------------------------------------------------------------------- +# VELOCIMACRO PROPERTIES +# ---------------------------------------------------------------------------- +# global : name of default global library. It is expected to be in the regular +# template path. You may remove it (either the file or this property) if +# you wish with no harm. +# ---------------------------------------------------------------------------- +# dev-changes by Marino +resource.loader=class, string + +class.resource.loader.class=org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader + +velocimacro.library.autoreload = false + +velocimacro.permissions.allow.inline = true +velocimacro.permissions.allow.inline.to.replace.global = false +velocimacro.permissions.allow.inline.local.scope = false + +velocimacro.context.localscope = false + +# ---------------------------------------------------------------------------- +# INTERPOLATION +# ---------------------------------------------------------------------------- +# turn off and on interpolation of references and directives in string +# literals. ON by default :) +# ---------------------------------------------------------------------------- +runtime.interpolate.string.literals = true + + +# ---------------------------------------------------------------------------- +# RESOURCE MANAGEMENT +# ---------------------------------------------------------------------------- +# Allows alternative ResourceManager and ResourceCache implementations +# to be plugged in. +# ---------------------------------------------------------------------------- +resource.manager.class = org.apache.velocity.runtime.resource.ResourceManagerImpl +resource.manager.cache.class = org.apache.velocity.runtime.resource.ResourceCacheImpl diff --git a/plugins/tiles/src/main/resources/org/apache/tiles/autotag/velocity/velocityDirective.vm b/plugins/tiles/src/main/resources/org/apache/tiles/autotag/velocity/velocityDirective.vm new file mode 100644 index 000000000..0528affab --- /dev/null +++ b/plugins/tiles/src/main/resources/org/apache/tiles/autotag/velocity/velocityDirective.vm @@ -0,0 +1,76 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + /* + * This file was automatically generated by Autotag. Please do not edit it manually. + */ +package ${packageName}; + +import java.io.IOException; +import java.io.Writer; + +#if(${clazz.hasBody()}) +import org.apache.tiles.autotag.core.runtime.ModelBody; +#end +import org.apache.tiles.autotag.core.runtime.AutotagRuntime; +import org.apache.velocity.context.InternalContextAdapter; +import org.apache.velocity.runtime.directive.Directive; +import org.apache.velocity.runtime.parser.node.Node; + +/** +#foreach($line in $stringTool.splitOnNewlines(${clazz.documentation})) + * ${line} +#end + */ +public class ${clazz.tagClassPrefix}Directive extends Directive { + + /** + * The template model. + */ + private ${clazz.name} model = new ${clazz.name}(); + + @Override + public String getName() { + return "${suite.name}_${clazz.tagName}"; + } + + @Override + public int getType() { + return #if(${clazz.hasBody()})BLOCK#{else}LINE#{end}; + } + + @Override + public boolean render(InternalContextAdapter context, Writer writer, Node node) + throws IOException { + AutotagRuntime<${requestClass}> runtime = new ${runtimeClass}(); + if (runtime instanceof Directive) { + ((Directive) runtime).render(context, writer, node); + } + ${requestClass} request = runtime.createRequest(); +#if(${clazz.hasBody()}) + ModelBody modelBody = runtime.createModelBody(); +#end + model.execute( +#foreach($parameter in ${clazz.parameters}) + runtime.getParameter("${parameter.exportedName}", ${stringTool.getClassToCast(${parameter.type})}.class, $stringTool.getDefaultValue(${parameter.type}, ${parameter.defaultValue})), +#end + request#if(${clazz.hasBody()}), modelBody#end + ); + return true; + } +} diff --git a/plugins/tiles/src/main/resources/org/apache/tiles/autotag/velocity/velocityProperties.vm b/plugins/tiles/src/main/resources/org/apache/tiles/autotag/velocity/velocityProperties.vm new file mode 100644 index 000000000..6360d64f4 --- /dev/null +++ b/plugins/tiles/src/main/resources/org/apache/tiles/autotag/velocity/velocityProperties.vm @@ -0,0 +1,21 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# +# This file was automatically generated by Autotag. Please do not edit it manually. + +userdirective=#foreach($clazz in ${suite.getTemplateClasses()})#if($foreach.count > 1),\ + #{end}${packageName}.${clazz.tagClassPrefix}Directive#end \ No newline at end of file diff --git a/plugins/tiles/src/main/resources/org/apache/tiles/resources/tiles-config_3_0.dtd b/plugins/tiles/src/main/resources/org/apache/tiles/resources/tiles-config_3_0.dtd new file mode 100644 index 000000000..dab8d7857 --- /dev/null +++ b/plugins/tiles/src/main/resources/org/apache/tiles/resources/tiles-config_3_0.dtd @@ -0,0 +1,245 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/tiles/src/main/resources/tools.xml b/plugins/tiles/src/main/resources/tools.xml new file mode 100644 index 000000000..65d673763 --- /dev/null +++ b/plugins/tiles/src/main/resources/tools.xml @@ -0,0 +1,24 @@ + + + + + + + diff --git a/plugins/tiles/src/test/java/org/apache/struts2/tiles/StrutsTilesAnnotationProcessorTest.java b/plugins/tiles/src/test/java/org/apache/struts2/tiles/StrutsTilesAnnotationProcessorTest.java index bad09f4b4..ca11f3bff 100644 --- a/plugins/tiles/src/test/java/org/apache/struts2/tiles/StrutsTilesAnnotationProcessorTest.java +++ b/plugins/tiles/src/test/java/org/apache/struts2/tiles/StrutsTilesAnnotationProcessorTest.java @@ -22,9 +22,9 @@ import java.util.List; import java.util.Set; import org.apache.struts2.tiles.annotation.TilesDefinition; -import org.apache.tiles.Attribute; -import org.apache.tiles.Definition; -import org.apache.tiles.Expression; +import org.apache.tiles.api.Attribute; +import org.apache.tiles.api.Definition; +import org.apache.tiles.api.Expression; import org.junit.Test; import org.junit.Assert; diff --git a/plugins/tiles/src/test/java/org/apache/tiles/api/AttributeTest.java b/plugins/tiles/src/test/java/org/apache/tiles/api/AttributeTest.java new file mode 100644 index 000000000..703dde92b --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/api/AttributeTest.java @@ -0,0 +1,275 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.api; + +import org.apache.tiles.request.Request; +import org.junit.Test; + +import java.util.HashSet; +import java.util.LinkedHashSet; +import java.util.Objects; +import java.util.Set; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + +/** + * Tests {@link Attribute}. + */ +public class AttributeTest { + + /** + * Tests {@link Attribute#createTemplateAttribute(String)}. + */ + @Test + public void testCreateTemplateAttribute1() { + Attribute attribute = Attribute.createTemplateAttribute("/my/template.jsp"); + assertEquals("/my/template.jsp", attribute.getValue()); + assertEquals("template", attribute.getRenderer()); + } + + /** + * Tests {@link Attribute#Attribute()}. + */ + @Test + public void testAttribute() { + Attribute attribute = new Attribute(); + assertNull(attribute.getValue()); + } + + /** + * Tests {@link Attribute#Attribute(Object)}. + */ + @Test + public void testAttributeObject() { + Attribute attribute = new Attribute("my.value"); + assertEquals("my.value", attribute.getValue()); + assertNull(attribute.getRenderer()); + } + + /** + * Tests {@link Attribute#Attribute(Object, String)}. + */ + @Test + public void testAttributeObjectString() { + Attribute attribute = new Attribute("my.value", "role1,role2"); + assertEquals("my.value", attribute.getValue()); + assertNull(attribute.getRenderer()); + Set roles = new HashSet<>(); + roles.add("role1"); + roles.add("role2"); + assertEquals(roles, attribute.getRoles()); + } + + /** + * Tests {@link Attribute#Attribute(Object, Expression, String, String)}. + */ + @Test + public void testAttributeComplete() { + Expression expression = new Expression("my.expression", "MYLANG"); + Attribute attribute = new Attribute("my.value", expression, "role1,role2", "myrenderer"); + assertEquals("my.value", attribute.getValue()); + assertEquals("myrenderer", attribute.getRenderer()); + Set roles = new HashSet<>(); + roles.add("role1"); + roles.add("role2"); + assertEquals(roles, attribute.getRoles()); + assertEquals("my.expression", attribute.getExpressionObject().getExpression()); + assertEquals("MYLANG", attribute.getExpressionObject().getLanguage()); + } + + /** + * Tests {@link Attribute#Attribute(Attribute)}. + */ + @Test + public void testAttributeCopy() { + Expression expression = new Expression("my.expression", "MYLANG"); + Attribute attribute = new Attribute("my.value", expression, "role1,role2", "myrenderer"); + attribute = new Attribute(attribute); + assertEquals("my.value", attribute.getValue()); + assertEquals("myrenderer", attribute.getRenderer()); + Set roles = new HashSet<>(); + roles.add("role1"); + roles.add("role2"); + assertEquals(roles, attribute.getRoles()); + assertEquals("my.expression", attribute.getExpressionObject().getExpression()); + assertEquals("MYLANG", attribute.getExpressionObject().getLanguage()); + + attribute = new Attribute("my.value", null, "role1,role2", "myrenderer"); + attribute = new Attribute(attribute); + assertEquals("my.value", attribute.getValue()); + assertEquals("myrenderer", attribute.getRenderer()); + roles = new HashSet<>(); + roles.add("role1"); + roles.add("role2"); + assertEquals(roles, attribute.getRoles()); + assertNull(attribute.getExpressionObject()); + } + + /** + * Tests {@link Attribute#equals(Object)}. + */ + @Test + public void testEquals() { + Expression expression = new Expression("my.expression", "MYLANG"); + Attribute attribute = new Attribute("my.value", expression, "role1,role2", "myrenderer"); + Attribute attribute2 = new Attribute(attribute); + assertEquals(attribute, attribute2); + attribute2.setRenderer("anotherRenderer"); + assertNotEquals(attribute, attribute2); + attribute2 = new Attribute(attribute); + attribute2.setRole("otherrole"); + assertNotEquals(attribute, attribute2); + attribute2 = new Attribute(attribute); + attribute2.setExpressionObject(new Expression("another.expression", "MYLANG")); + assertNotEquals(attribute, attribute2); + attribute2 = new Attribute(attribute); + attribute2.setValue("anothervalue"); + assertNotEquals(attribute, attribute2); + } + + /** + * Tests {@link Attribute#getRole()} and {@link Attribute#setRole(String)}. + */ + @Test + public void testGetRole() { + Attribute attribute = new Attribute("my.value"); + assertNull(attribute.getRole()); + Set roles = new LinkedHashSet<>(); + attribute.setRoles(roles); + assertNull(attribute.getRole()); + roles.add("role1"); + roles.add("role2"); + assertEquals("role1,role2", attribute.getRole()); + } + + /** + * Tests {@link Attribute#hashCode()}. + */ + @Test + public void testHashCode() { + Expression expression = new Expression("my.expression", "MYLANG"); + Attribute attribute = new Attribute("my.value", expression, "role1,role2", "myrenderer"); + Set roles = new HashSet<>(); + roles.add("role1"); + roles.add("role2"); + assertEquals( + Objects.hashCode("my.value") + + Objects.hashCode(expression) + Objects.hashCode(roles) + + Objects.hashCode("myrenderer"), attribute.hashCode() + ); + } + + /** + * Tests {@link Attribute#toString()}. + */ + @Test + public void testToString() { + Expression expression = new Expression("my.expression", "MYLANG"); + Attribute attribute = new Attribute("my.value", expression, "role1,role2", "myrenderer"); + assertEquals("my.value", attribute.toString()); + attribute.setValue(null); + assertNotNull(attribute.toString()); + } + + @Test + public void testInherit() { + Attribute attribute = new Attribute(null, null, null, null); + Attribute parentAttribute = new Attribute("value", Expression + .createExpression("expression", "language"), "role", "renderer"); + attribute.inherit(parentAttribute); + assertEquals("value", attribute.getValue()); + assertEquals("expression", attribute.getExpressionObject().getExpression()); + assertEquals("language", attribute.getExpressionObject().getLanguage()); + assertEquals("role", attribute.getRole()); + assertEquals("renderer", attribute.getRenderer()); + Expression expression = new Expression(null, "MYLANG"); + attribute = new Attribute(null, expression, null, null); + attribute.setRoles(new HashSet<>()); + attribute.inherit(parentAttribute); + assertEquals("value", attribute.getValue()); + assertEquals("expression", attribute.getExpressionObject().getExpression()); + assertEquals("language", attribute.getExpressionObject().getLanguage()); + assertEquals("role", attribute.getRole()); + assertEquals("renderer", attribute.getRenderer()); + } + + /** + * Tests {@link Attribute#clone()}. + */ + @Test + public void testClone() { + Expression expression = new Expression("my.expression", "MYLANG"); + Attribute attribute = new Attribute("my.value", expression, "role1,role2", "myrenderer"); + attribute = attribute.copy(); + assertEquals("my.value", attribute.getValue()); + assertEquals("myrenderer", attribute.getRenderer()); + Set roles = new HashSet<>(); + roles.add("role1"); + roles.add("role2"); + assertEquals(roles, attribute.getRoles()); + assertEquals("my.expression", attribute.getExpressionObject().getExpression()); + assertEquals("MYLANG", attribute.getExpressionObject().getLanguage()); + } + + /** + * Tests {@link Attribute#createTemplateAttribute(String, String, String, String)}. + */ + @Test + public void testCreateTemplateAttribute() { + Attribute attribute = Attribute.createTemplateAttribute("myTemplate", "MYLANG:myExpression", "myType", "myRole"); + assertEquals("myTemplate", attribute.getValue()); + assertEquals("MYLANG", attribute.getExpressionObject().getLanguage()); + assertEquals("myExpression", attribute.getExpressionObject().getExpression()); + assertEquals("myType", attribute.getRenderer()); + Set roles = attribute.getRoles(); + assertEquals(1, roles.size()); + assertTrue(roles.contains("myRole")); + } + + @Test + public void testIsPermitted() { + Attribute attribute = new Attribute("myvalue"); + Request requestContext = createMock(Request.class); + expect(requestContext.isUserInRole("first")).andReturn(Boolean.TRUE) + .anyTimes(); + expect(requestContext.isUserInRole("second")).andReturn(Boolean.FALSE) + .anyTimes(); + replay(requestContext); + assertTrue(attribute.isPermitted(requestContext)); + Set roles = new HashSet<>(); + roles.add("first"); + attribute.setRoles(roles); + assertTrue("The role is not permitted", attribute.isPermitted( + requestContext)); + roles.clear(); + roles.add("second"); + assertFalse("The role is not permitted", attribute.isPermitted( + requestContext)); + verify(requestContext); + } +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/api/BasicAttributeContextTest.java b/plugins/tiles/src/test/java/org/apache/tiles/api/BasicAttributeContextTest.java new file mode 100644 index 000000000..8b60953b5 --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/api/BasicAttributeContextTest.java @@ -0,0 +1,681 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.api; + +import org.junit.Test; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + +/** + * Tests BasicAttributeContext. + * + * @version $Rev$ $Date$ + */ +public class BasicAttributeContextTest { + + /** + * Tests {@link BasicAttributeContext#BasicAttributeContext()}. + */ + @Test + public void testBasicAttributeContext() { + AttributeContext context = new BasicAttributeContext(); + assertNull("There are some spurious attributes", context + .getLocalAttributeNames()); + assertNull("There are some spurious attributes", context + .getCascadedAttributeNames()); + } + + /** + * Tests {@link BasicAttributeContext#BasicAttributeContext(Map)}. + */ + @Test + public void testBasicAttributeContextMapOfStringAttribute() { + Map name2attrib = new HashMap<>(); + Attribute attribute = new Attribute("Value 1"); + name2attrib.put("name1", attribute); + attribute = new Attribute("Value 2"); + name2attrib.put("name2", attribute); + AttributeContext context = new BasicAttributeContext(name2attrib); + attribute = context.getAttribute("name1"); + assertNotNull("Attribute name1 not found", attribute); + assertEquals("Attribute name1 has not been set correctly", "Value 1", + attribute.getValue()); + attribute = context.getAttribute("name2"); + assertNotNull("Attribute name2 not found", attribute); + assertEquals("Attribute name2 has not been set correctly", "Value 2", + attribute.getValue()); + } + + /** + * Tests + * {@link BasicAttributeContext#BasicAttributeContext(AttributeContext)}. + */ + @Test + public void testBasicAttributeContextAttributeContext() { + Set localAttributes = new LinkedHashSet<>(); + Set cascadedAttributes = new LinkedHashSet<>(); + localAttributes.add("local1"); + localAttributes.add("local2"); + cascadedAttributes.add("cascaded1"); + cascadedAttributes.add("cascaded2"); + AttributeContext toCopy = createMock(AttributeContext.class); + expect(toCopy.getLocalAttributeNames()).andReturn(localAttributes); + expect(toCopy.getLocalAttribute("local1")).andReturn( + new Attribute("value1")).anyTimes(); + expect(toCopy.getLocalAttribute("local2")).andReturn( + new Attribute("value2")).anyTimes(); + expect(toCopy.getCascadedAttributeNames()) + .andReturn(cascadedAttributes); + expect(toCopy.getCascadedAttribute("cascaded1")).andReturn( + new Attribute("value3")).anyTimes(); + expect(toCopy.getCascadedAttribute("cascaded2")).andReturn( + new Attribute("value4")).anyTimes(); + Attribute templateAttribute = new Attribute("/template.jsp", Expression + .createExpression("expression", null), "role1,role2", + "template"); + expect(toCopy.getTemplateAttribute()).andReturn(templateAttribute); + Set roles = new HashSet<>(); + roles.add("role1"); + roles.add("role2"); + expect(toCopy.getPreparer()).andReturn("my.preparer.Preparer"); + replay(toCopy); + BasicAttributeContext context = new BasicAttributeContext(toCopy); + assertEquals("The template has not been set correctly", + "/template.jsp", context.getTemplateAttribute().getValue()); + assertEquals("The template expression has not been set correctly", + "expression", context.getTemplateAttribute() + .getExpressionObject().getExpression()); + assertEquals("The roles are not the same", roles, context + .getTemplateAttribute().getRoles()); + assertEquals("The preparer has not been set correctly", + "my.preparer.Preparer", context.getPreparer()); + Attribute attribute = context.getLocalAttribute("local1"); + assertNotNull("Attribute local1 not found", attribute); + assertEquals("Attribute local1 has not been set correctly", "value1", + attribute.getValue()); + attribute = context.getLocalAttribute("local2"); + assertNotNull("Attribute local2 not found", attribute); + assertEquals("Attribute local2 has not been set correctly", "value2", + attribute.getValue()); + attribute = context.getCascadedAttribute("cascaded1"); + assertNotNull("Attribute cascaded1 not found", attribute); + assertEquals("Attribute cascaded1 has not been set correctly", + "value3", attribute.getValue()); + attribute = context.getCascadedAttribute("cascaded2"); + assertNotNull("Attribute cascaded2 not found", attribute); + assertEquals("Attribute cascaded2 has not been set correctly", + "value4", attribute.getValue()); + } + + /** + * Tests + * {@link BasicAttributeContext#BasicAttributeContext(BasicAttributeContext)} + * . + */ + @Test + public void testBasicAttributeContextBasicAttributeContext() { + BasicAttributeContext toCopy = new BasicAttributeContext(); + toCopy.putAttribute("name1", new Attribute("value1"), false); + toCopy.putAttribute("name2", new Attribute("value2"), true); + Attribute templateAttribute = Attribute + .createTemplateAttribute("/template.jsp"); + Set roles = new HashSet<>(); + roles.add("role1"); + roles.add("role2"); + templateAttribute.setRoles(roles); + toCopy.setTemplateAttribute(templateAttribute); + toCopy.setPreparer("my.preparer.Preparer"); + AttributeContext context = new BasicAttributeContext(toCopy); + assertEquals("The template has not been set correctly", + "/template.jsp", context.getTemplateAttribute().getValue()); + assertEquals("The roles are not the same", roles, context + .getTemplateAttribute().getRoles()); + assertEquals("The preparer has not been set correctly", + "my.preparer.Preparer", context.getPreparer()); + Attribute attribute = context.getLocalAttribute("name1"); + assertNotNull("Attribute name1 not found", attribute); + assertEquals("Attribute name1 has not been set correctly", "value1", + attribute.getValue()); + attribute = context.getCascadedAttribute("name2"); + assertNotNull("Attribute name2 not found", attribute); + assertEquals("Attribute name2 has not been set correctly", "value2", + attribute.getValue()); + } + + /** + * Tests + * {@link BasicAttributeContext#inheritCascadedAttributes(AttributeContext)} + * . + */ + @Test + public void testInheritCascadedAttributes() { + AttributeContext toCopy = new BasicAttributeContext(); + toCopy.putAttribute("name1", new Attribute("value1"), false); + toCopy.putAttribute("name2", new Attribute("value2"), true); + AttributeContext context = new BasicAttributeContext(); + context.inheritCascadedAttributes(toCopy); + Attribute attribute = context.getLocalAttribute("name1"); + assertNull("Attribute name1 found", attribute); + attribute = context.getCascadedAttribute("name2"); + assertNotNull("Attribute name2 not found", attribute); + assertEquals("Attribute name2 has not been set correctly", "value2", + attribute.getValue()); + } + + /** + * Tests {@link BasicAttributeContext#inherit(BasicAttributeContext)} + * testing inheritance between {@link ListAttribute} instances. + */ + @Test + public void testInheritListAttribute() { + AttributeContext toCopy = new BasicAttributeContext(); + ListAttribute parentListAttribute = new ListAttribute(); + Attribute first = new Attribute("first"); + Attribute second = new Attribute("second"); + parentListAttribute.add(first); + toCopy.putAttribute("list", parentListAttribute); + AttributeContext context = new BasicAttributeContext(); + ListAttribute listAttribute = new ListAttribute(); + listAttribute.setInherit(true); + listAttribute.add(second); + context.putAttribute("list", listAttribute); + context.inherit(toCopy); + ListAttribute result = (ListAttribute) context.getAttribute("list"); + assertNotNull("The attribute must exist", result); + List value = result.getValue(); + assertNotNull("The list must exist", value); + assertEquals("The size is not correct", 2, value.size()); + assertEquals("The first element is not correct", first, value.get(0)); + assertEquals("The second element is not correct", second, value + .get(1)); + + context = new BasicAttributeContext(); + listAttribute = new ListAttribute(); + listAttribute.add(second); + context.putAttribute("list", listAttribute); + context.inherit(toCopy); + result = (ListAttribute) context.getAttribute("list"); + assertNotNull("The attribute must exist", result); + value = result.getValue(); + assertNotNull("The list must exist", value); + assertEquals("The size is not correct", 1, value.size()); + assertEquals("The second element is not correct", second, value + .get(0)); + } + + /** + * Tests + * {@link BasicAttributeContext#inheritCascadedAttributes(AttributeContext)} + * . + */ + @Test + public void testInherit() { + AttributeContext toCopy = new BasicAttributeContext(); + Attribute parentTemplateAttribute = new Attribute(); + parentTemplateAttribute.setValue("/parent/template.jsp"); + toCopy.setTemplateAttribute(parentTemplateAttribute); + toCopy.putAttribute("name1", new Attribute("value1"), true); + toCopy.putAttribute("name2", new Attribute("value2"), true); + toCopy.putAttribute("name3", new Attribute("value3"), false); + toCopy.putAttribute("name4", new Attribute("value4"), false); + AttributeContext context = new BasicAttributeContext(); + Attribute templateAttribute = new Attribute(); + templateAttribute.setRole("role1,role2"); + context.setTemplateAttribute(templateAttribute); + context.putAttribute("name1", new Attribute("newValue1"), true); + context.putAttribute("name3", new Attribute("newValue3"), false); + context.inherit(toCopy); + Attribute attribute = context.getTemplateAttribute(); + assertEquals("/parent/template.jsp", attribute.getValue()); + assertTrue(attribute.getRoles().contains("role1")); + assertTrue(attribute.getRoles().contains("role2")); + attribute = context.getCascadedAttribute("name1"); + assertNotNull("Attribute name1 not found", attribute); + assertEquals("Attribute name1 has not been set correctly", "newValue1", + attribute.getValue()); + attribute = context.getCascadedAttribute("name2"); + assertNotNull("Attribute name2 not found", attribute); + assertEquals("Attribute name2 has not been set correctly", "value2", + attribute.getValue()); + attribute = context.getLocalAttribute("name3"); + assertNotNull("Attribute name3 not found", attribute); + assertEquals("Attribute name3 has not been set correctly", "newValue3", + attribute.getValue()); + attribute = context.getLocalAttribute("name4"); + assertNotNull("Attribute name4 not found", attribute); + assertEquals("Attribute name4 has not been set correctly", "value4", + attribute.getValue()); + + toCopy = new BasicAttributeContext(); + toCopy.putAttribute("name1", new Attribute("value1"), true); + toCopy.putAttribute("name2", new Attribute("value2"), true); + toCopy.putAttribute("name3", new Attribute("value3"), false); + toCopy.putAttribute("name4", new Attribute("value4"), false); + context = new BasicAttributeContext(); + context.inherit(toCopy); + attribute = context.getCascadedAttribute("name1"); + assertNotNull("Attribute name1 not found", attribute); + assertEquals("Attribute name1 has not been set correctly", "value1", + attribute.getValue()); + attribute = context.getCascadedAttribute("name2"); + assertNotNull("Attribute name2 not found", attribute); + assertEquals("Attribute name2 has not been set correctly", "value2", + attribute.getValue()); + attribute = context.getLocalAttribute("name3"); + assertNotNull("Attribute name3 not found", attribute); + assertEquals("Attribute name3 has not been set correctly", "value3", + attribute.getValue()); + attribute = context.getLocalAttribute("name4"); + assertNotNull("Attribute name4 not found", attribute); + assertEquals("Attribute name4 has not been set correctly", "value4", + attribute.getValue()); + } + + /** + * Tests + * {@link BasicAttributeContext#inherit(AttributeContext)} + * . + */ + @Test + public void testInheritAttributeContext() { + AttributeContext toCopy = createMock(AttributeContext.class); + Attribute templateAttribute = Attribute.createTemplateAttribute("/my/template.jsp"); + expect(toCopy.getTemplateAttribute()).andReturn(templateAttribute); + expect(toCopy.getPreparer()).andReturn("my.preparer"); + Set cascadedNames = new HashSet<>(); + cascadedNames.add("name1"); + cascadedNames.add("name2"); + expect(toCopy.getCascadedAttributeNames()).andReturn(cascadedNames); + expect(toCopy.getCascadedAttribute("name1")).andReturn(new Attribute("value1")); + expect(toCopy.getCascadedAttribute("name2")).andReturn(new Attribute("value2")); + Set names = new HashSet<>(); + names.add("name3"); + names.add("name4"); + expect(toCopy.getLocalAttributeNames()).andReturn(names); + expect(toCopy.getLocalAttribute("name3")).andReturn(new Attribute("value3")); + expect(toCopy.getLocalAttribute("name4")).andReturn(new Attribute("value4")); + + replay(toCopy); + AttributeContext context = new BasicAttributeContext(); + context.putAttribute("name1", new Attribute("newValue1"), true); + context.putAttribute("name3", new Attribute("newValue3"), false); + context.inherit(toCopy); + Attribute attribute = context.getCascadedAttribute("name1"); + assertEquals("/my/template.jsp", context.getTemplateAttribute().getValue()); + assertEquals("my.preparer", context.getPreparer()); + assertNotNull("Attribute name1 not found", attribute); + assertEquals("Attribute name1 has not been set correctly", "newValue1", + attribute.getValue()); + attribute = context.getCascadedAttribute("name2"); + assertNotNull("Attribute name2 not found", attribute); + assertEquals("Attribute name2 has not been set correctly", "value2", + attribute.getValue()); + attribute = context.getLocalAttribute("name3"); + assertNotNull("Attribute name3 not found", attribute); + assertEquals("Attribute name3 has not been set correctly", "newValue3", + attribute.getValue()); + attribute = context.getLocalAttribute("name4"); + assertNotNull("Attribute name4 not found", attribute); + assertEquals("Attribute name4 has not been set correctly", "value4", + attribute.getValue()); + verify(toCopy); + } + + /** + * Tests {@link BasicAttributeContext#inherit(AttributeContext)} + * testing inheritance between {@link ListAttribute} instances. + */ + @Test + public void testInheritAttributeContextListAttribute() { + AttributeContext toCopy = createMock(AttributeContext.class); + Attribute templateAttribute = Attribute.createTemplateAttribute("/my/template.jsp"); + expect(toCopy.getTemplateAttribute()).andReturn(templateAttribute).times(2); + expect(toCopy.getPreparer()).andReturn("my.preparer").times(2); + ListAttribute parentListAttribute = new ListAttribute(); + Attribute first = new Attribute("first"); + Attribute second = new Attribute("second"); + Attribute third = new Attribute("third"); + Attribute fourth = new Attribute("fourth"); + parentListAttribute.add(first); + ListAttribute parentListAttribute2 = new ListAttribute(); + parentListAttribute2.add(third); + Set names = new HashSet<>(); + names.add("list"); + Set cascadedNames = new HashSet<>(); + cascadedNames.add("list2"); + expect(toCopy.getCascadedAttributeNames()).andReturn(cascadedNames).times(2); + expect(toCopy.getCascadedAttribute("list2")).andReturn(parentListAttribute2).times(2); + expect(toCopy.getLocalAttributeNames()).andReturn(names).times(2); + expect(toCopy.getLocalAttribute("list")).andReturn(parentListAttribute).times(2); + + replay(toCopy); + AttributeContext context = new BasicAttributeContext(); + ListAttribute listAttribute = new ListAttribute(); + listAttribute.setInherit(true); + listAttribute.add(second); + context.putAttribute("list", listAttribute, false); + ListAttribute listAttribute2 = new ListAttribute(); + listAttribute2.setInherit(true); + listAttribute2.add(fourth); + context.putAttribute("list2", listAttribute2, true); + context.inherit(toCopy); + ListAttribute result = (ListAttribute) context.getAttribute("list"); + assertNotNull("The attribute must exist", result); + List value = result.getValue(); + assertNotNull("The list must exist", value); + assertEquals("The size is not correct", 2, value.size()); + assertEquals("The first element is not correct", first, value.get(0)); + assertEquals("The second element is not correct", second, value + .get(1)); + result = (ListAttribute) context.getAttribute("list2"); + assertNotNull("The attribute must exist", result); + value = result.getValue(); + assertNotNull("The list must exist", value); + assertEquals("The size is not correct", 2, value.size()); + assertEquals("The first element is not correct", third, value.get(0)); + assertEquals("The second element is not correct", fourth, value + .get(1)); + + context = new BasicAttributeContext(); + listAttribute = new ListAttribute(); + listAttribute.add(second); + context.putAttribute("list", listAttribute); + context.inherit(toCopy); + result = (ListAttribute) context.getAttribute("list"); + assertNotNull("The attribute must exist", result); + value = result.getValue(); + assertNotNull("The list must exist", value); + assertEquals("The size is not correct", 1, value.size()); + assertEquals("The second element is not correct", second, value + .get(0)); + verify(toCopy); + } + + /** + * Tests {@link BasicAttributeContext#addAll(Map)}. + */ + @Test + public void testAddAll() { + AttributeContext context = new BasicAttributeContext(); + Map name2attrib = new HashMap<>(); + Attribute attribute = new Attribute("Value 1"); + name2attrib.put("name1", attribute); + attribute = new Attribute("Value 2"); + name2attrib.put("name2", attribute); + context.addAll(name2attrib); + attribute = context.getAttribute("name1"); + assertNotNull("Attribute name1 not found", attribute); + assertEquals("Attribute name1 has not been set correctly", "Value 1", + attribute.getValue()); + attribute = context.getAttribute("name2"); + assertNotNull("Attribute name2 not found", attribute); + assertEquals("Attribute name2 has not been set correctly", "Value 2", + attribute.getValue()); + + context.addAll(null); + attribute = context.getAttribute("name1"); + assertNotNull("Attribute name1 not found", attribute); + assertEquals("Attribute name1 has not been set correctly", "Value 1", + attribute.getValue()); + attribute = context.getAttribute("name2"); + assertNotNull("Attribute name2 not found", attribute); + assertEquals("Attribute name2 has not been set correctly", "Value 2", + attribute.getValue()); + + name2attrib = new HashMap<>(); + name2attrib.put("name3", new Attribute("Value 3")); + context.addAll(name2attrib); + attribute = context.getAttribute("name1"); + assertNotNull("Attribute name1 not found", attribute); + assertEquals("Attribute name1 has not been set correctly", "Value 1", + attribute.getValue()); + attribute = context.getAttribute("name2"); + assertNotNull("Attribute name2 not found", attribute); + assertEquals("Attribute name2 has not been set correctly", "Value 2", + attribute.getValue()); + attribute = context.getAttribute("name3"); + assertNotNull("Attribute name3 not found", attribute); + assertEquals("Attribute name3 has not been set correctly", "Value 3", + attribute.getValue()); + } + + /** + * Tests {@link BasicAttributeContext#getAttribute(String)}. + */ + @Test + public void testGetAttribute() { + AttributeContext context = new BasicAttributeContext(); + context.putAttribute("name1", new Attribute("value1"), false); + context.putAttribute("name2", new Attribute("value2"), true); + context.putAttribute("name3", new Attribute("value3a"), true); + context.putAttribute("name3", new Attribute("value3"), false); + Attribute attribute = context.getAttribute("name1"); + assertNotNull("Attribute name1 not found", attribute); + assertEquals("Attribute name1 has not been set correctly", "value1", + attribute.getValue()); + attribute = context.getAttribute("name2"); + assertNotNull("Attribute name2 not found", attribute); + assertEquals("Attribute name2 has not been set correctly", "value2", + attribute.getValue()); + attribute = context.getAttribute("name3"); + assertNotNull("Attribute name3 not found", attribute); + assertEquals("Attribute name3 has not been set correctly", "value3", + attribute.getValue()); + } + + /** + * Tests {@link BasicAttributeContext#getLocalAttribute(String)}. + */ + @Test + public void testGetLocalAttribute() { + AttributeContext context = new BasicAttributeContext(); + context.putAttribute("name1", new Attribute("value1"), false); + context.putAttribute("name2", new Attribute("value2"), true); + context.putAttribute("name3", new Attribute("value3a"), true); + context.putAttribute("name3", new Attribute("value3"), false); + Attribute attribute = context.getLocalAttribute("name1"); + assertNotNull("Attribute name1 not found", attribute); + assertEquals("Attribute name1 has not been set correctly", "value1", + attribute.getValue()); + attribute = context.getLocalAttribute("name2"); + assertNull("Attribute name2 found", attribute); + attribute = context.getLocalAttribute("name3"); + assertNotNull("Attribute name3 not found", attribute); + assertEquals("Attribute name3 has not been set correctly", "value3", + attribute.getValue()); + } + + /** + * Tests {@link BasicAttributeContext#getCascadedAttribute(String)}. + */ + @Test + public void testGetCascadedAttribute() { + AttributeContext context = new BasicAttributeContext(); + context.putAttribute("name1", new Attribute("value1"), false); + context.putAttribute("name2", new Attribute("value2"), true); + context.putAttribute("name3", new Attribute("value3a"), true); + context.putAttribute("name3", new Attribute("value3"), false); + Attribute attribute = context.getCascadedAttribute("name1"); + assertNull("Attribute name1 found", attribute); + attribute = context.getCascadedAttribute("name2"); + assertNotNull("Attribute name2 not found", attribute); + assertEquals("Attribute name2 has not been set correctly", "value2", + attribute.getValue()); + attribute = context.getCascadedAttribute("name3"); + assertNotNull("Attribute name3 not found", attribute); + assertEquals("Attribute name3 has not been set correctly", "value3a", + attribute.getValue()); + } + + /** + * Tests {@link BasicAttributeContext#getLocalAttributeNames()}. + */ + @Test + public void testGetLocalAttributeNames() { + AttributeContext context = new BasicAttributeContext(); + context.putAttribute("name1", new Attribute("value1"), false); + context.putAttribute("name2", new Attribute("value2"), true); + context.putAttribute("name3", new Attribute("value3a"), true); + context.putAttribute("name3", new Attribute("value3"), false); + Set names = context.getLocalAttributeNames(); + assertTrue("Attribute name1 is not present", names.contains("name1")); + assertFalse("Attribute name2 is present", names.contains("name2")); + assertTrue("Attribute name3 is not present", names.contains("name3")); + } + + /** + * Tests {@link BasicAttributeContext#getCascadedAttributeNames()}. + */ + @Test + public void testGetCascadedAttributeNames() { + AttributeContext context = new BasicAttributeContext(); + context.putAttribute("name1", new Attribute("value1"), false); + context.putAttribute("name2", new Attribute("value2"), true); + context.putAttribute("name3", new Attribute("value3a"), true); + context.putAttribute("name3", new Attribute("value3"), false); + Set names = context.getCascadedAttributeNames(); + assertFalse("Attribute name1 is present", names.contains("name1")); + assertTrue("Attribute name2 is not present", names.contains("name2")); + assertTrue("Attribute name3 is not present", names.contains("name3")); + } + + /** + * Tests {@link BasicAttributeContext#putAttribute(String, Attribute)}. + */ + @Test + public void testPutAttributeStringAttribute() { + AttributeContext context = new BasicAttributeContext(); + context.putAttribute("name1", new Attribute("value1")); + Attribute attribute = context.getLocalAttribute("name1"); + assertNotNull("Attribute name1 not found", attribute); + assertEquals("Attribute name1 has not been set correctly", "value1", + attribute.getValue()); + attribute = context.getCascadedAttribute("name1"); + assertNull("Attribute name1 found", attribute); + } + + /** + * Tests + * {@link BasicAttributeContext#putAttribute(String, Attribute, boolean)}. + */ + @Test + public void testPutAttributeStringAttributeBoolean() { + AttributeContext context = new BasicAttributeContext(); + context.putAttribute("name1", new Attribute("value1"), false); + context.putAttribute("name2", new Attribute("value2"), true); + Attribute attribute = context.getLocalAttribute("name1"); + assertNotNull("Attribute name1 not found", attribute); + assertEquals("Attribute name1 has not been set correctly", "value1", + attribute.getValue()); + attribute = context.getCascadedAttribute("name1"); + assertNull("Attribute name1 found", attribute); + attribute = context.getCascadedAttribute("name2"); + assertNotNull("Attribute name2 not found", attribute); + assertEquals("Attribute name2 has not been set correctly", "value2", + attribute.getValue()); + attribute = context.getLocalAttribute("name2"); + assertNull("Attribute name2 found", attribute); + } + + /** + * Tests {@link BasicAttributeContext#clear()}. + */ + @Test + public void testClear() { + AttributeContext context = new BasicAttributeContext(); + context.putAttribute("name1", new Attribute("value1"), false); + context.putAttribute("name2", new Attribute("value2"), true); + context.clear(); + Set names = context.getLocalAttributeNames(); + assertTrue("There are local attributes", names == null + || names.isEmpty()); + names = context.getCascadedAttributeNames(); + assertTrue("There are cascaded attributes", names == null + || names.isEmpty()); + } + + /** + * Tests {@link BasicAttributeContext#equals(Object)}. + */ + @Test + public void testEquals() { + BasicAttributeContext attributeContext = new BasicAttributeContext(); + attributeContext.setPreparer("my.preparer"); + attributeContext.setTemplateAttribute(Attribute.createTemplateAttribute("/my/template.jsp")); + attributeContext.putAttribute("attribute1", new Attribute("value1"), true); + attributeContext.putAttribute("attribute2", new Attribute("value2"), true); + attributeContext.putAttribute("attribute3", new Attribute("value3"), false); + BasicAttributeContext toCompare = new BasicAttributeContext(attributeContext); + assertEquals(toCompare, attributeContext); + toCompare = new BasicAttributeContext(attributeContext); + toCompare.putAttribute("attribute4", new Attribute("value4"), true); + assertNotEquals(toCompare, attributeContext); + toCompare = new BasicAttributeContext(attributeContext); + toCompare.putAttribute("attribute4", new Attribute("value4"), false); + assertNotEquals(toCompare, attributeContext); + toCompare = new BasicAttributeContext(attributeContext); + toCompare.setPreparer("another.preparer"); + assertNotEquals(toCompare, attributeContext); + toCompare = new BasicAttributeContext(attributeContext); + toCompare.setTemplateAttribute(Attribute.createTemplateAttribute("/another/template.jsp")); + assertNotEquals(toCompare, attributeContext); + } + + /** + * Tests {@link BasicAttributeContext#hashCode()}. + */ + @Test + public void testHashCode() { + BasicAttributeContext attributeContext = new BasicAttributeContext(); + attributeContext.setPreparer("my.preparer"); + Attribute templateAttribute = Attribute.createTemplateAttribute("/my/template.jsp"); + attributeContext.setTemplateAttribute(templateAttribute); + Attribute attribute1 = new Attribute("value1"); + Attribute attribute2 = new Attribute("value2"); + Attribute attribute3 = new Attribute("value3"); + attributeContext.putAttribute("attribute1", attribute1, true); + attributeContext.putAttribute("attribute2", attribute2, true); + attributeContext.putAttribute("attribute3", attribute3, false); + Map cascadedAttributes = new HashMap<>(); + cascadedAttributes.put("attribute1", attribute1); + cascadedAttributes.put("attribute2", attribute2); + Map attributes = new HashMap<>(); + attributes.put("attribute3", attribute3); + assertEquals(templateAttribute.hashCode() + "my.preparer".hashCode() + + attributes.hashCode() + cascadedAttributes.hashCode(), + attributeContext.hashCode()); + } + +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/api/ExpressionTest.java b/plugins/tiles/src/test/java/org/apache/tiles/api/ExpressionTest.java new file mode 100644 index 000000000..6c2d618b1 --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/api/ExpressionTest.java @@ -0,0 +1,108 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tiles.api; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertNull; + +/** + * Tests {@link Expression}. + */ +public class ExpressionTest { + + @Test + public void testHashCode() { + Expression expression = new Expression("hello", "there"); + assertEquals("hello".hashCode() + "there".hashCode(), expression.hashCode()); + } + + @Test + public void testExpressionStringString() { + Expression expression = new Expression("hello", "there"); + assertEquals("hello", expression.getExpression()); + assertEquals("there", expression.getLanguage()); + } + + @Test + public void testExpressionString() { + Expression expression = new Expression("hello"); + assertEquals("hello", expression.getExpression()); + assertNull(expression.getLanguage()); + } + + @Test + public void testExpressionExpression() { + Expression expression = new Expression("hello", "there"); + Expression expression2 = new Expression(expression); + assertEquals("hello", expression2.getExpression()); + assertEquals("there", expression2.getLanguage()); + } + + @Test + public void testCreateExpressionFromDescribedExpression() { + Expression expression = Expression.createExpressionFromDescribedExpression("hello"); + assertEquals("hello", expression.getExpression()); + assertNull(expression.getLanguage()); + expression = Expression.createExpressionFromDescribedExpression("there:hello"); + assertEquals("hello", expression.getExpression()); + assertEquals("there", expression.getLanguage()); + expression = Expression.createExpressionFromDescribedExpression("there_:hello"); + assertEquals("there_:hello", expression.getExpression()); + assertNull(expression.getLanguage()); + assertNull(Expression.createExpressionFromDescribedExpression(null)); + } + + @Test + public void testCreateExpression() { + Expression expression = Expression.createExpression("hello", "there"); + assertEquals("hello", expression.getExpression()); + assertEquals("there", expression.getLanguage()); + expression = Expression.createExpression("hello", null); + assertEquals("hello", expression.getExpression()); + assertNull(expression.getLanguage()); + expression = Expression.createExpression(null, "there"); + assertNull(expression); + } + + @Test + public void testEqualsObject() { + Expression expression = new Expression("hello", "there"); + Expression expression2 = new Expression("hello", "there"); + assertEquals(expression, expression2); + expression2 = new Expression("hello", "there2"); + assertNotEquals(expression, expression2); + expression2 = new Expression("hello"); + assertNotEquals(expression, expression2); + expression = new Expression("hello"); + assertEquals(expression, expression2); + } + + @Test + public void testToString() { + Expression expression = new Expression("hello", "there"); + assertEquals("there:hello", expression.toString()); + expression = new Expression("hello"); + assertEquals("DEFAULT:hello", expression.toString()); + } + +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/api/ListAttributeTest.java b/plugins/tiles/src/test/java/org/apache/tiles/api/ListAttributeTest.java new file mode 100644 index 000000000..baa41fd7a --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/api/ListAttributeTest.java @@ -0,0 +1,109 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tiles.api; + +import org.junit.Test; + +import java.util.ArrayList; +import java.util.List; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertTrue; + +/** + * Tests {@link ListAttribute}. + */ +public class ListAttributeTest { + + @Test + public void testHashCode() { + ListAttribute attribute = new ListAttribute(); + List list = new ArrayList<>(); + list.add(new Attribute("value1")); + list.add(new Attribute("value2")); + attribute.setValue(list); + attribute.setInherit(true); + assertEquals(list.hashCode() + Boolean.TRUE.hashCode(), attribute.hashCode()); + } + + @Test + public void testEqualsObject() { + ListAttribute attribute = new ListAttribute(); + List list = new ArrayList<>(); + list.add(new Attribute("value1")); + list.add(new Attribute("value2")); + attribute.setValue(list); + attribute.setInherit(true); + ListAttribute toCheck = new ListAttribute(attribute); + assertEquals(attribute, toCheck); + toCheck = new ListAttribute(attribute); + toCheck.setInherit(false); + assertNotEquals(attribute, toCheck); + toCheck = new ListAttribute(attribute); + toCheck.add(new Attribute("value3")); + assertNotEquals(attribute, toCheck); + } + + @Test + public void testListAttributeListAttribute() { + ListAttribute attribute = new ListAttribute(); + List list = new ArrayList<>(); + list.add(new Attribute("value1")); + list.add(new Attribute("value2")); + list.add(null); + attribute.setValue(list); + attribute.setInherit(true); + ListAttribute toCheck = new ListAttribute(attribute); + assertEquals(attribute, toCheck); + } + + @Test + public void testSetValue() { + ListAttribute attribute = new ListAttribute(); + List list = new ArrayList<>(); + list.add(new Attribute("value1")); + list.add(new Attribute("value2")); + attribute.setValue(list); + assertEquals(list, attribute.getValue()); + } + + @Test + public void testSetInherit() { + ListAttribute attribute = new ListAttribute(); + attribute.setInherit(true); + assertTrue(attribute.isInherit()); + attribute.setInherit(false); + assertFalse(attribute.isInherit()); + } + + @Test + public void testClone() { + ListAttribute attribute = new ListAttribute(); + List list = new ArrayList<>(); + list.add(new Attribute("value1")); + list.add(new Attribute("value2")); + attribute.setValue(list); + attribute.setInherit(true); + ListAttribute toCheck = attribute.copy(); + assertEquals(attribute, toCheck); + } +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/api/NoSuchContainerExceptionTest.java b/plugins/tiles/src/test/java/org/apache/tiles/api/NoSuchContainerExceptionTest.java new file mode 100644 index 000000000..7634873b8 --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/api/NoSuchContainerExceptionTest.java @@ -0,0 +1,39 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tiles.api; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; + +/** + * Tests {@link NoSuchContainerException}. + */ +public class NoSuchContainerExceptionTest { + + @Test + public void testNoSuchContainerExceptionString() { + NoSuchContainerException exception = new NoSuchContainerException("my message"); + assertEquals("my message", exception.getMessage()); + assertNull(exception.getCause()); + } + +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/api/TestDefinition.java b/plugins/tiles/src/test/java/org/apache/tiles/api/TestDefinition.java new file mode 100644 index 000000000..520fd997c --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/api/TestDefinition.java @@ -0,0 +1,248 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tiles.api; + +import org.junit.Test; + +import java.util.HashMap; +import java.util.Map; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +/** + * Tests the Definition class. + */ +public class TestDefinition { + + /** + * Tests {@link Definition#Definition(Definition)}. + */ + @Test + public void testDefinitionCopy() { + Definition definition = new Definition(); + definition.setName("myDefinition"); + definition.setExtends("myExtends"); + Attribute attribute1 = new Attribute("value1"); + definition.putAttribute("name1", attribute1); + Attribute attribute2 = new Attribute("value2"); + definition.putAttribute("name2", attribute2); + Definition toCheck = new Definition(definition); + assertEquals("myDefinition", toCheck.getName()); + assertEquals("myExtends", toCheck.getExtends()); + assertEquals(attribute1, toCheck.getAttribute("name1")); + assertEquals(attribute2, toCheck.getAttribute("name2")); + } + + /** + * Tests {@link Definition#Definition(Definition)}. + */ + @Test + public void testDefinitionComplete() { + Map attributeMap = new HashMap<>(); + Attribute attribute1 = new Attribute("value1"); + Attribute attribute2 = new Attribute("value2"); + attributeMap.put("name1", attribute1); + attributeMap.put("name2", attribute2); + Attribute templateAttribute = Attribute.createTemplateAttribute("/my/template.jsp"); + Definition definition = new Definition("myDefinition", + templateAttribute, attributeMap); + assertEquals("myDefinition", definition.getName()); + assertEquals(templateAttribute, definition.getTemplateAttribute()); + assertEquals(attribute1, definition.getAttribute("name1")); + assertEquals(attribute2, definition.getAttribute("name2")); + } + + /** + * Verifies the put Attribute functionality. Attributes are added or replaced in the definition. + */ + @Test + public void testPutAttribute() { + Definition def = new Definition(); + def.setName("test1"); + def.setTemplateAttribute(Attribute + .createTemplateAttribute("/page1.jsp")); + Attribute attr1 = new Attribute("test.definition.name", null, null, "definition"); + def.putAttribute("attr1", attr1); + + attr1 = def.getAttribute("attr1"); + assertNotNull("Null attribute.", attr1); + assertEquals("Wrong attribute type", "definition", attr1.getRenderer()); + } + + /** + * Tests the {@link Definition#inherit(BasicAttributeContext)} method. + */ + @Test + public void testInherit() { + Definition toCopy = new Definition(); + toCopy.putAttribute("name1", new Attribute("value1"), true); + toCopy.putAttribute("name2", new Attribute("value2"), true); + toCopy.putAttribute("name3", new Attribute("value3"), false); + toCopy.putAttribute("name4", new Attribute("value4"), false); + Definition context = new Definition(); + toCopy.putAttribute("name1", new Attribute("newValue1"), true); + toCopy.putAttribute("name3", new Attribute("newValue3"), false); + context.inherit(toCopy); + Attribute attribute = context.getCascadedAttribute("name1"); + assertNotNull("Attribute name1 not found", attribute); + assertEquals("Attribute name1 has not been set correctly", "newValue1", + attribute.getValue()); + attribute = context.getCascadedAttribute("name2"); + assertNotNull("Attribute name2 not found", attribute); + assertEquals("Attribute name2 has not been set correctly", "value2", + attribute.getValue()); + attribute = context.getLocalAttribute("name3"); + assertNotNull("Attribute name3 not found", attribute); + assertEquals("Attribute name3 has not been set correctly", "newValue3", + attribute.getValue()); + attribute = context.getLocalAttribute("name4"); + assertNotNull("Attribute name4 not found", attribute); + assertEquals("Attribute name4 has not been set correctly", "value4", + attribute.getValue()); + + toCopy = new Definition(); + toCopy.setPreparer("ExtendedPreparer"); + Attribute templateAttribute = new Attribute("extendedTemplate.jsp", + Expression.createExpression("expression", "language"), + "extendedRole", "template"); + toCopy.setTemplateAttribute(templateAttribute); + context = new Definition(); + context.inherit(toCopy); + assertEquals("Preparer not inherited", "ExtendedPreparer", context + .getPreparer()); + assertNotNull("Roles not inherited", context.getTemplateAttribute() + .getRoles()); + assertEquals("Roles not inherited", context.getTemplateAttribute() + .getRoles().size(), 1); + assertTrue("Roles not inherited", context.getTemplateAttribute() + .getRoles().contains( + "extendedRole")); + assertEquals("Template not inherited", "extendedTemplate.jsp", context + .getTemplateAttribute().getValue()); + assertEquals("Template expression not inherited", "expression", context + .getTemplateAttribute().getExpressionObject().getExpression()); + assertEquals("Template expression language not inherited", "language", + context.getTemplateAttribute().getExpressionObject() + .getLanguage()); + context = new Definition(); + context.setPreparer("LocalPreparer"); + templateAttribute = new Attribute("localTemplate.jsp", Expression + .createExpression("localExpression", "localLanguage"), + "localRole", "template"); + context.setTemplateAttribute(templateAttribute); + assertEquals("Preparer inherited", "LocalPreparer", context + .getPreparer()); + assertNotNull("Roles not correct", context.getTemplateAttribute() + .getRoles()); + assertEquals("Roles not correct", context.getTemplateAttribute() + .getRoles().size(), 1); + assertTrue("Roles inherited", context.getTemplateAttribute().getRoles() + .contains("localRole")); + assertEquals("Template inherited", "localTemplate.jsp", context + .getTemplateAttribute().getValue()); + assertEquals("Template expression inherited", "localExpression", + context.getTemplateAttribute().getExpressionObject() + .getExpression()); + assertEquals("Template expression language not inherited", + "localLanguage", context.getTemplateAttribute() + .getExpressionObject().getLanguage()); + } + + /** + * Tests {@link Definition#toString()}. + */ + @Test + public void testToString() { + Definition definition = new Definition(); + definition.setName("myDefinitionName"); + assertEquals( + "{name=myDefinitionName, template=, role=, preparerInstance=null, attributes=null}", + definition.toString()); + definition.setTemplateAttribute(Attribute.createTemplateAttribute("myTemplate")); + assertEquals( + "{name=myDefinitionName, template=myTemplate, role=null, preparerInstance=null, attributes=null}", + definition.toString()); + definition.putAttribute("myAttributeName", new Attribute("myAttributeValue")); + assertEquals( + "{name=myDefinitionName, template=myTemplate, role=null, preparerInstance=null, " + + "attributes={myAttributeName=myAttributeValue}}", + definition.toString()); + } + + /** + * Tests {@link Definition#equals(Object)}. + */ + @Test + public void testEquals() { + Definition definition = new Definition(); + definition.setName("myDefinition"); + definition.setExtends("myExtends"); + Attribute attribute1 = new Attribute("value1"); + definition.putAttribute("name1", attribute1); + Attribute attribute2 = new Attribute("value2"); + definition.putAttribute("name2", attribute2); + Definition toCheck = new Definition(definition); + assertEquals(definition, toCheck); + toCheck = new Definition(definition); + toCheck.setName("anotherDefinition"); + assertNotEquals(definition, toCheck); + toCheck = new Definition(definition); + toCheck.setExtends("anotherExtends"); + assertNotEquals(definition, toCheck); + toCheck = new Definition(definition); + toCheck.putAttribute("name1", new Attribute("anotherAttribute")); + assertNotEquals(definition, toCheck); + } + + /** + * Tests {@link Definition#hashCode()}. + */ + @Test + public void testHashCode() { + Definition definition = new Definition(); + definition.setName("myDefinition"); + definition.setExtends("myExtends"); + Attribute attribute1 = new Attribute("value1"); + definition.putAttribute("name1", attribute1); + Attribute attribute2 = new Attribute("value2"); + definition.putAttribute("name2", attribute2); + BasicAttributeContext attributeContext = new BasicAttributeContext(); + attributeContext.putAttribute("name1", attribute1); + attributeContext.putAttribute("name2", attribute2); + assertEquals("myDefinition".hashCode() + "myExtends".hashCode() + + attributeContext.hashCode(), definition.hashCode()); + } + + /** + * Tests {@link Definition#isExtending()}. + */ + @Test + public void testIsExtending() { + Definition definition = new Definition(); + definition.setName("myDefinition"); + assertFalse(definition.isExtending()); + definition.setExtends("myExtends"); + assertTrue(definition.isExtending()); + } +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/api/TilesContainerWrapperTest.java b/plugins/tiles/src/test/java/org/apache/tiles/api/TilesContainerWrapperTest.java new file mode 100644 index 000000000..c4a3bb919 --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/api/TilesContainerWrapperTest.java @@ -0,0 +1,232 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.api; + +import org.apache.tiles.request.ApplicationContext; +import org.apache.tiles.request.Request; +import org.junit.Before; +import org.junit.Test; + +import java.io.IOException; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertTrue; + +/** + * Tests {@link TilesContainerWrapper}. + */ +public class TilesContainerWrapperTest { + + /** + * The container. + */ + private TilesContainer container; + + /** + * The wrapper to test. + */ + private TilesContainerWrapper wrapper; + + /** + * Sets up the test. + */ + @Before + public void setUp() { + container = createMock(TilesContainer.class); + wrapper = new TilesContainerWrapper(container); + } + + /** + * Tests {@link TilesContainerWrapper#TilesContainerWrapper(TilesContainer)}. + */ + @Test(expected = NullPointerException.class) + public void testTilesContainerWrapperNPE() { + new TilesContainerWrapper(null); + } + + @Test + public void testEndContext() { + Request request = createMock(Request.class); + + container.endContext(request); + + replay(container, request); + wrapper.endContext(request); + verify(container, request); + } + + /** + * Test method for {@link TilesContainerWrapper#evaluate(Attribute, Request)}. + */ + @Test + public void testEvaluate() { + Request request = createMock(Request.class); + Attribute attribute = createMock(Attribute.class); + + expect(container.evaluate(attribute, request)).andReturn(1); + + replay(container, request, attribute); + assertEquals(new Integer(1), wrapper.evaluate(attribute, request)); + verify(container, request, attribute); + } + + @Test + public void testGetApplicationContext() { + ApplicationContext applicationContext = createMock(ApplicationContext.class); + + expect(container.getApplicationContext()).andReturn(applicationContext); + + replay(container, applicationContext); + assertSame(applicationContext, wrapper.getApplicationContext()); + verify(container, applicationContext); + } + + /** + * Test method for {@link TilesContainerWrapper#getAttributeContext(Request)}. + */ + @Test + public void testGetAttributeContext() { + Request request = createMock(Request.class); + AttributeContext attribute = createMock(AttributeContext.class); + + expect(container.getAttributeContext(request)).andReturn(attribute); + + replay(container, request, attribute); + assertSame(attribute, wrapper.getAttributeContext(request)); + verify(container, request, attribute); + } + + /** + * Test method for {@link TilesContainerWrapper#getDefinition(String, Request)}. + */ + @Test + public void testGetDefinition() { + Request request = createMock(Request.class); + Definition definition = createMock(Definition.class); + + expect(container.getDefinition("definition", request)).andReturn(definition); + + replay(container, request, definition); + assertSame(definition, wrapper.getDefinition("definition", request)); + verify(container, request, definition); + } + + /** + * Test method for {@link TilesContainerWrapper#isValidDefinition(String, Request)}. + */ + @Test + public void testIsValidDefinition() { + Request request = createMock(Request.class); + + expect(container.isValidDefinition("definition", request)).andReturn(true); + + replay(container, request); + assertTrue(wrapper.isValidDefinition("definition", request)); + verify(container, request); + } + + /** + * Test method for {@link TilesContainerWrapper#prepare(String, Request)}. + */ + @Test + public void testPrepare() { + Request request = createMock(Request.class); + + container.prepare("preparer", request); + + replay(container, request); + wrapper.prepare("preparer", request); + verify(container, request); + } + + /** + * Test method for {@link TilesContainerWrapper#render(String, Request)}. + */ + @Test + public void testRenderStringRequest() { + Request request = createMock(Request.class); + + container.render("definition", request); + + replay(container, request); + wrapper.render("definition", request); + verify(container, request); + } + + /** + * Test method for {@link TilesContainerWrapper#render(Definition, Request)}. + */ + @Test + public void testRenderDefinitionRequest() { + Request request = createMock(Request.class); + Definition definition = createMock(Definition.class); + + container.render(definition, request); + + replay(container, request, definition); + wrapper.render(definition, request); + verify(container, request, definition); + } + + /** + * Test method for {@link TilesContainerWrapper#render(Attribute, Request)}. + * + * @throws IOException If something goes wrong. + */ + @Test + public void testRenderAttributeRequest() throws IOException { + Request request = createMock(Request.class); + Attribute attribute = createMock(Attribute.class); + + container.render(attribute, request); + + replay(container, request, attribute); + wrapper.render(attribute, request); + verify(container, request, attribute); + } + + @Test + public void testRenderContext() { + Request request = createMock(Request.class); + + container.renderContext(request); + + replay(container, request); + wrapper.renderContext(request); + verify(container, request); + } + + @Test + public void testStartContext() { + Request request = createMock(Request.class); + AttributeContext attribute = createMock(AttributeContext.class); + + expect(container.startContext(request)).andReturn(attribute); + + replay(container, request, attribute); + assertSame(attribute, wrapper.startContext(request)); + verify(container, request, attribute); + } + +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/api/TilesExceptionTest.java b/plugins/tiles/src/test/java/org/apache/tiles/api/TilesExceptionTest.java new file mode 100644 index 000000000..cb6b8012b --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/api/TilesExceptionTest.java @@ -0,0 +1,62 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tiles.api; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; + +/** + * Tests {@link TilesException}. + */ +public class TilesExceptionTest { + + @Test + public void testTilesException() { + TilesException exception = new TilesException(); + assertNull(exception.getMessage()); + assertNull(exception.getCause()); + } + + @Test + public void testTilesExceptionString() { + TilesException exception = new TilesException("my message"); + assertEquals("my message", exception.getMessage()); + assertNull(exception.getCause()); + } + + @Test + public void testTilesExceptionThrowable() { + Throwable cause = new Throwable(); + TilesException exception = new TilesException(cause); + assertEquals(cause.toString(), exception.getMessage()); + assertEquals(cause, exception.getCause()); + } + + @Test + public void testTilesExceptionStringThrowable() { + Throwable cause = new Throwable(); + TilesException exception = new TilesException("my message", cause); + assertEquals("my message", exception.getMessage()); + assertEquals(cause, exception.getCause()); + } + +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/api/access/TilesAccessTest.java b/plugins/tiles/src/test/java/org/apache/tiles/api/access/TilesAccessTest.java new file mode 100644 index 000000000..93726132b --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/api/access/TilesAccessTest.java @@ -0,0 +1,206 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.api.access; + +import org.apache.tiles.api.NoSuchContainerException; +import org.apache.tiles.api.TilesContainer; +import org.apache.tiles.request.ApplicationContext; +import org.apache.tiles.request.Request; +import org.junit.Test; + +import java.util.HashMap; +import java.util.Map; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import static org.junit.Assert.assertEquals; + +/** + * Tests {@link TilesAccess}. + */ +public class TilesAccessTest { + + @Test + public void testSetContainer() { + ApplicationContext context = createMock(ApplicationContext.class); + TilesContainer container = createMock(TilesContainer.class); + Map attribs = new HashMap<>(); + expect(context.getApplicationScope()).andReturn(attribs); + replay(context, container); + TilesAccess.setContainer(context, container, null); + assertEquals(attribs.size(), 1); + assertEquals(attribs.get(TilesAccess.CONTAINER_ATTRIBUTE), container); + verify(context, container); + } + + @Test + public void testSetContainerWithKey() { + ApplicationContext context = createMock(ApplicationContext.class); + TilesContainer container = createMock(TilesContainer.class); + Map attribs = new HashMap<>(); + expect(context.getApplicationScope()).andReturn(attribs).anyTimes(); + replay(context, container); + TilesAccess.setContainer(context, container, "myKey"); + assertEquals(1, attribs.size()); + assertEquals(container, attribs.get("myKey")); + + TilesAccess.setContainer(context, null, "myKey"); + assertEquals(0, attribs.size()); + + TilesAccess.setContainer(context, container, null); + assertEquals(1, attribs.size()); + assertEquals(container, attribs.get(TilesAccess.CONTAINER_ATTRIBUTE)); + verify(context, container); + } + + @Test + public void testGetContainer() { + ApplicationContext context = createMock(ApplicationContext.class); + TilesContainer container = createMock(TilesContainer.class); + Map attribs = new HashMap<>(); + expect(context.getApplicationScope()).andReturn(attribs).anyTimes(); + + replay(context, container); + attribs.put(TilesAccess.CONTAINER_ATTRIBUTE, container); + assertEquals(container, TilesAccess.getContainer(context)); + verify(context, container); + } + + @Test + public void testGetContainerWithKey() { + ApplicationContext context = createMock(ApplicationContext.class); + TilesContainer container = createMock(TilesContainer.class); + Map attribs = new HashMap<>(); + expect(context.getApplicationScope()).andReturn(attribs).anyTimes(); + + replay(context, container); + attribs.put(TilesAccess.CONTAINER_ATTRIBUTE, container); + attribs.put("myKey", container); + assertEquals(container, TilesAccess.getContainer(context, null)); + assertEquals(container, TilesAccess.getContainer(context, "myKey")); + verify(context, container); + } + + @Test + public void testSetCurrentContainer() { + Request request = createMock(Request.class); + ApplicationContext context = createMock(ApplicationContext.class); + TilesContainer container = createMock(TilesContainer.class); + Map attribs = new HashMap<>(); + attribs.put("myKey", container); + Map requestScope = new HashMap<>(); + + expect(context.getApplicationScope()).andReturn(attribs).anyTimes(); + expect(request.getContext("request")).andReturn(requestScope); + expect(request.getApplicationContext()).andReturn(context); + replay(request, context, container); + TilesAccess.setCurrentContainer(request, "myKey"); + assertEquals(container, requestScope.get(TilesAccess.CURRENT_CONTAINER_ATTRIBUTE_NAME)); + verify(request, context, container); + } + + @Test(expected = NoSuchContainerException.class) + public void testSetCurrentContainerException() { + Request request = createMock(Request.class); + ApplicationContext context = createMock(ApplicationContext.class); + Map attribs = new HashMap<>(); + + expect(request.getApplicationContext()).andReturn(context); + expect(context.getApplicationScope()).andReturn(attribs).anyTimes(); + replay(request, context); + try { + TilesAccess.setCurrentContainer(request, "myKey"); + } finally { + verify(request, context); + } + } + + @Test + public void testSetCurrentContainerWithContainer() { + Request request = createMock(Request.class); + ApplicationContext context = createMock(ApplicationContext.class); + TilesContainer container = createMock(TilesContainer.class); + Map attribs = new HashMap<>(); + attribs.put("myKey", container); + Map requestScope = new HashMap<>(); + + expect(context.getApplicationScope()).andReturn(attribs).anyTimes(); + expect(request.getContext("request")).andReturn(requestScope); + + replay(request, context, container); + TilesAccess.setCurrentContainer(request, container); + assertEquals(container, requestScope.get(TilesAccess.CURRENT_CONTAINER_ATTRIBUTE_NAME)); + verify(request, context, container); + } + + @Test(expected = NullPointerException.class) + public void testSetCurrentContainerWithContainerException() { + Request request = createMock(Request.class); + ApplicationContext context = createMock(ApplicationContext.class); + Map attribs = new HashMap<>(); + + expect(context.getApplicationScope()).andReturn(attribs).anyTimes(); + + replay(request, context); + try { + TilesAccess.setCurrentContainer(request, (TilesContainer) null); + } finally { + verify(request, context); + } + } + + @Test + public void testGetCurrentContainer() { + Request request = createMock(Request.class); + ApplicationContext context = createMock(ApplicationContext.class); + TilesContainer container = createMock(TilesContainer.class); + Map attribs = new HashMap<>(); + attribs.put("myKey", container); + Map requestScope = new HashMap<>(); + requestScope.put(TilesAccess.CURRENT_CONTAINER_ATTRIBUTE_NAME, container); + + expect(request.getApplicationContext()).andReturn(context); + expect(context.getApplicationScope()).andReturn(attribs).anyTimes(); + expect(request.getContext("request")).andReturn(requestScope); + + replay(request, context, container); + assertEquals(container, TilesAccess.getCurrentContainer(request)); + verify(request, context, container); + } + + @Test + public void testGetCurrentContainerDefault() { + Request request = createMock(Request.class); + ApplicationContext context = createMock(ApplicationContext.class); + TilesContainer container = createMock(TilesContainer.class); + Map attribs = new HashMap<>(); + attribs.put(TilesAccess.CONTAINER_ATTRIBUTE, container); + Map requestScope = new HashMap<>(); + + expect(request.getApplicationContext()).andReturn(context); + expect(context.getApplicationScope()).andReturn(attribs).anyTimes(); + expect(request.getContext("request")).andReturn(requestScope); + + replay(request, context, container); + assertEquals(container, TilesAccess.getCurrentContainer(request)); + verify(request, context, container); + } +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/api/preparer/PreparerExceptionTest.java b/plugins/tiles/src/test/java/org/apache/tiles/api/preparer/PreparerExceptionTest.java new file mode 100644 index 000000000..35cbc3bbb --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/api/preparer/PreparerExceptionTest.java @@ -0,0 +1,74 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tiles.api.preparer; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; + +/** + * Tests {@link PreparerException}. + */ +public class PreparerExceptionTest { + + /** + * Test method for {@link PreparerException#PreparerException()}. + */ + @Test + public void testPreparerException() { + PreparerException exception = new PreparerException(); + assertNull(exception.getMessage()); + assertNull(exception.getCause()); + } + + /** + * Test method for {@link PreparerException#PreparerException(String)}. + */ + @Test + public void testPreparerExceptionString() { + PreparerException exception = new PreparerException("my message"); + assertEquals("my message", exception.getMessage()); + assertNull(exception.getCause()); + } + + /** + * Test method for {@link PreparerException#PreparerException(Throwable)}. + */ + @Test + public void testPreparerExceptionThrowable() { + Throwable cause = new Throwable(); + PreparerException exception = new PreparerException(cause); + assertEquals(cause.toString(), exception.getMessage()); + assertEquals(cause, exception.getCause()); + } + + /** + * Test method for {@link PreparerException#PreparerException(String, Throwable)}. + */ + @Test + public void testPreparerExceptionStringThrowable() { + Throwable cause = new Throwable(); + PreparerException exception = new PreparerException("my message", cause); + assertEquals("my message", exception.getMessage()); + assertEquals(cause, exception.getCause()); + } + +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/autotag/freemarker/FMModelGeneratorTest.java b/plugins/tiles/src/test/java/org/apache/tiles/autotag/freemarker/FMModelGeneratorTest.java new file mode 100644 index 000000000..599e7f472 --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/autotag/freemarker/FMModelGeneratorTest.java @@ -0,0 +1,139 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.autotag.freemarker; + +import static org.junit.Assert.*; + +import java.io.File; +import java.io.FileInputStream; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.List; +import java.util.Properties; + +import org.apache.commons.io.FileUtils; +import org.apache.commons.io.IOUtils; +import org.apache.tiles.autotag.core.runtime.ModelBody; +import org.apache.tiles.autotag.model.TemplateClass; +import org.apache.tiles.autotag.model.TemplateMethod; +import org.apache.tiles.autotag.model.TemplateParameter; +import org.apache.tiles.autotag.model.TemplateSuite; +import org.apache.velocity.app.VelocityEngine; +import org.junit.Test; + +/** + * Tests TagClassGenerator. + */ +public class FMModelGeneratorTest { + + public static final String REQUEST_CLASS = "org.apache.tiles.autotag.freemarker.test.Request"; + + /** + * Test method for TagClassGenerator#generate(File, String, TemplateSuite, + * TemplateClass, java.util.Map). + * + * @throws Exception If something goes wrong. + */ + @Test + public void testGenerate() throws Exception { + Properties props = new Properties(); + InputStream propsStream = getClass().getResourceAsStream("/org/apache/tiles/autotag/velocity.properties"); + props.load(propsStream); + propsStream.close(); + VelocityEngine velocityEngine = new VelocityEngine(props); + + FMModelGenerator generator = new FMModelGenerator(velocityEngine); + File file = File.createTempFile("autotag", null); + file.delete(); + file.mkdir(); + file.deleteOnExit(); + TemplateSuite suite = new TemplateSuite("tldtest", "Test for TLD docs."); + + List params = new ArrayList(); + TemplateParameter param = new TemplateParameter("one", "one", "java.lang.String", null, true, false); + param.setDocumentation("Parameter one."); + params.add(param); + param = new TemplateParameter("two", "two", "int", null, false, false); + param.setDocumentation("Parameter two."); + params.add(param); + param = new TemplateParameter("three", "three", "boolean", null, false, false); + param.setDocumentation("Parameter three."); + params.add(param); + param = new TemplateParameter("request", "request", REQUEST_CLASS, null, false, true); + param.setDocumentation("The request."); + params.add(param); + param = new TemplateParameter("modelBody", "modelBody", ModelBody.class.getName(), null, false, false); + param.setDocumentation("The body."); + params.add(param); + TemplateMethod executeMethod = new TemplateMethod("execute", params); + + TemplateClass clazz = new TemplateClass("org.apache.tiles.autotag.template.DoStuffTemplate", "doStuff", + "DoStuff", executeMethod); + clazz.setDocumentation("Documentation of the DoStuff class."); + + generator.generate(file, "org.apache.tiles.autotag.freemarker.test", suite, clazz, null, + "org.apache.tiles.autotag.freemarker.test.Runtime", REQUEST_CLASS); + + InputStream expected = getClass() + .getResourceAsStream("/org/apache/tiles/autotag/freemarker/test/DoStuffFMModel.javat"); + File effectiveFile = new File(file, "/org/apache/tiles/autotag/freemarker/test/DoStuffFMModel.java"); + assertTrue(effectiveFile.exists()); + InputStream effective = new FileInputStream(effectiveFile); + assertTrue(IOUtils.contentEquals(effective, expected)); + effective.close(); + expected.close(); + + suite.addTemplateClass(clazz); + params = new ArrayList(); + param = new TemplateParameter("one", "one", "java.lang.Double", null, true, false); + param.setDocumentation("Parameter one."); + params.add(param); + param = new TemplateParameter("two", "two", "float", null, false, false); + param.setDocumentation("Parameter two."); + params.add(param); + param = new TemplateParameter("three", "three", "java.util.Date", null, false, false); + param.setDocumentation("Parameter three."); + params.add(param); + param = new TemplateParameter("request", "request", REQUEST_CLASS, null, false, true); + param.setDocumentation("The request."); + params.add(param); + executeMethod = new TemplateMethod("execute", params); + + clazz = new TemplateClass("org.apache.tiles.autotag.template.DoStuffNoBodyTemplate", "doStuffNoBody", + "DoStuffNoBody", executeMethod); + clazz.setDocumentation("Documentation of the DoStuffNoBody class."); + + suite.addTemplateClass(clazz); + + generator.generate(file, "org.apache.tiles.autotag.freemarker.test", suite, clazz, null, + "org.apache.tiles.autotag.freemarker.test.Runtime", REQUEST_CLASS); + + expected = getClass() + .getResourceAsStream("/org/apache/tiles/autotag/freemarker/test/DoStuffNoBodyFMModel.javat"); + effectiveFile = new File(file, "/org/apache/tiles/autotag/freemarker/test/DoStuffNoBodyFMModel.java"); + assertTrue(effectiveFile.exists()); + effective = new FileInputStream(effectiveFile); + assertTrue(IOUtils.contentEquals(effective, expected)); + effective.close(); + expected.close(); + + FileUtils.deleteDirectory(file); + } + +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/autotag/freemarker/FMModelRepositoryGeneratorTest.java b/plugins/tiles/src/test/java/org/apache/tiles/autotag/freemarker/FMModelRepositoryGeneratorTest.java new file mode 100644 index 000000000..ac3b449c4 --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/autotag/freemarker/FMModelRepositoryGeneratorTest.java @@ -0,0 +1,126 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.autotag.freemarker; + +import static org.junit.Assert.*; + +import java.io.File; +import java.io.FileInputStream; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.List; +import java.util.Properties; + +import org.apache.commons.io.FileUtils; +import org.apache.commons.io.IOUtils; +import org.apache.tiles.autotag.core.runtime.ModelBody; +import org.apache.tiles.autotag.model.TemplateClass; +import org.apache.tiles.autotag.model.TemplateMethod; +import org.apache.tiles.autotag.model.TemplateParameter; +import org.apache.tiles.autotag.model.TemplateSuite; +import org.apache.velocity.app.VelocityEngine; +import org.junit.Test; + +/** + * Tests TLDGenerator. + */ +public class FMModelRepositoryGeneratorTest { + + public static final String REQUEST_CLASS = "org.apache.tiles.autotag.freemarker.test.Request"; + + /** + * Test method for + * {@link FMModelRepositoryGenerator#generate(File, String, TemplateSuite, java.util.Map)}. + * + * @throws Exception If something goes wrong. + */ + @Test + public void testGenerate() throws Exception { + Properties props = new Properties(); + InputStream propsStream = getClass().getResourceAsStream("/org/apache/tiles/autotag/velocity.properties"); + props.load(propsStream); + propsStream.close(); + VelocityEngine velocityEngine = new VelocityEngine(props); + + FMModelRepositoryGenerator generator = new FMModelRepositoryGenerator(velocityEngine); + File file = File.createTempFile("autotag", null); + file.delete(); + file.mkdir(); + file.deleteOnExit(); + TemplateSuite suite = new TemplateSuite("tldtest", "Test for TLD docs."); + + List params = new ArrayList(); + TemplateParameter param = new TemplateParameter("one", "one", "java.lang.String", null, true, false); + param.setDocumentation("Parameter one."); + params.add(param); + param = new TemplateParameter("two", "two", "int", null, false, false); + param.setDocumentation("Parameter two."); + params.add(param); + param = new TemplateParameter("three", "three", "long", null, false, false); + param.setDocumentation("Parameter three."); + params.add(param); + param = new TemplateParameter("request", "request", REQUEST_CLASS, null, false, true); + param.setDocumentation("The request."); + params.add(param); + param = new TemplateParameter("modelBody", "modelBody", ModelBody.class.getName(), null, false, false); + param.setDocumentation("The body."); + params.add(param); + TemplateMethod executeMethod = new TemplateMethod("execute", params); + + TemplateClass clazz = new TemplateClass("org.apache.tiles.autotag.template.DoStuffTemplate", "doStuff", + "DoStuff", executeMethod); + clazz.setDocumentation("Documentation of the DoStuff class"); + + suite.addTemplateClass(clazz); + params = new ArrayList(); + param = new TemplateParameter("one", "one", "java.lang.Double", null, true, false); + param.setDocumentation("Parameter one."); + params.add(param); + param = new TemplateParameter("two", "two", "float", null, false, false); + param.setDocumentation("Parameter two."); + params.add(param); + param = new TemplateParameter("three", "three", "java.util.Date", null, false, false); + param.setDocumentation("Parameter three."); + params.add(param); + param = new TemplateParameter("request", "request", REQUEST_CLASS, null, false, true); + param.setDocumentation("The request."); + params.add(param); + executeMethod = new TemplateMethod("execute", params); + + clazz = new TemplateClass("org.apache.tiles.autotag.template.DoStuffNoBodyTemplate", "doStuffNoBody", + "DoStuffNoBody", executeMethod); + clazz.setDocumentation("Documentation of the DoStuffNoBody class"); + + suite.addTemplateClass(clazz); + + generator.generate(file, "org.apache.tiles.autotag.freemarker.test", suite, null); + + InputStream expected = getClass() + .getResourceAsStream("/org/apache/tiles/autotag/freemarker/test/TldtestFMModelRepository.javat"); + File effectiveFile = new File(file, "/org/apache/tiles/autotag/freemarker/test/TldtestFMModelRepository.java"); + assertTrue(effectiveFile.exists()); + InputStream effective = new FileInputStream(effectiveFile); + assertTrue(IOUtils.contentEquals(effective, expected)); + effective.close(); + expected.close(); + + FileUtils.deleteDirectory(file); + } + +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/autotag/freemarker/FMTemplateGeneratorFactoryTest.java b/plugins/tiles/src/test/java/org/apache/tiles/autotag/freemarker/FMTemplateGeneratorFactoryTest.java new file mode 100644 index 000000000..c8f91af82 --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/autotag/freemarker/FMTemplateGeneratorFactoryTest.java @@ -0,0 +1,58 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.autotag.freemarker; + +import static org.easymock.EasyMock.*; +import static org.junit.Assert.*; + +import java.io.File; + +import org.apache.tiles.autotag.generate.TemplateGenerator; +import org.apache.tiles.autotag.generate.TemplateGeneratorBuilder; +import org.apache.velocity.app.VelocityEngine; +import org.junit.Test; + +/** + * Tests FMTemplateGeneratorFactory. + */ +public class FMTemplateGeneratorFactoryTest { + + /** + * Test method forFMTemplateGeneratorFactory#createTemplateGenerator(). + */ + @Test + public void testCreateTemplateGenerator() { + File classesOutputDirectory = createMock(File.class); + VelocityEngine velocityEngine = createMock(VelocityEngine.class); + TemplateGeneratorBuilder builder = createMock(TemplateGeneratorBuilder.class); + TemplateGenerator generator = createMock(TemplateGenerator.class); + + expect(builder.setClassesOutputDirectory(classesOutputDirectory)).andReturn(builder); + expect(builder.addClassesTemplateSuiteGenerator(isA(FMModelRepositoryGenerator.class))).andReturn(builder); + expect(builder.addClassesTemplateClassGenerator(isA(FMModelGenerator.class))).andReturn(builder); + expect(builder.build()).andReturn(generator); + + replay(classesOutputDirectory, velocityEngine, builder, generator); + FMTemplateGeneratorFactory factory = new FMTemplateGeneratorFactory(classesOutputDirectory, velocityEngine, + builder); + assertSame(generator, factory.createTemplateGenerator()); + verify(classesOutputDirectory, velocityEngine, builder, generator); + } + +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/autotag/jsp/JspTemplateGeneratorFactoryTest.java b/plugins/tiles/src/test/java/org/apache/tiles/autotag/jsp/JspTemplateGeneratorFactoryTest.java new file mode 100644 index 000000000..a753756c9 --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/autotag/jsp/JspTemplateGeneratorFactoryTest.java @@ -0,0 +1,61 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.autotag.jsp; + +import static org.easymock.EasyMock.*; +import static org.junit.Assert.*; + +import java.io.File; + +import org.apache.tiles.autotag.generate.TemplateGenerator; +import org.apache.tiles.autotag.generate.TemplateGeneratorBuilder; +import org.apache.velocity.app.VelocityEngine; +import org.junit.Test; + +/** + * Tests JspTemplateGeneratorFactory. + */ +public class JspTemplateGeneratorFactoryTest { + + /** + * Test method JspTemplateGeneratorFactory#createTemplateGenerator(). + */ + @Test + public void testCreateTemplateGenerator() { + File classesOutputDirectory = createMock(File.class); + File resourcesOutputDirectory = createMock(File.class); + VelocityEngine velocityEngine = createMock(VelocityEngine.class); + TemplateGeneratorBuilder builder = createMock(TemplateGeneratorBuilder.class); + TemplateGenerator generator = createMock(TemplateGenerator.class); + + expect(builder.setClassesOutputDirectory(classesOutputDirectory)).andReturn(builder); + expect(builder.setResourcesOutputDirectory(resourcesOutputDirectory)).andReturn(builder); + expect(builder.addResourcesTemplateSuiteGenerator(isA(TLDGenerator.class))).andReturn(builder); + expect(builder.addClassesTemplateClassGenerator(isA(TagClassGenerator.class))).andReturn(builder); + expect(builder.build()).andReturn(generator); + + replay(classesOutputDirectory, resourcesOutputDirectory, velocityEngine, builder, generator); + JspTemplateGeneratorFactory factory = new JspTemplateGeneratorFactory( + classesOutputDirectory, resourcesOutputDirectory, + velocityEngine, builder); + assertSame(generator, factory.createTemplateGenerator()); + verify(classesOutputDirectory, resourcesOutputDirectory, velocityEngine, builder, generator); + } + +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/autotag/jsp/TLDGeneratorTest.java b/plugins/tiles/src/test/java/org/apache/tiles/autotag/jsp/TLDGeneratorTest.java new file mode 100644 index 000000000..0fbe25c07 --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/autotag/jsp/TLDGeneratorTest.java @@ -0,0 +1,129 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.autotag.jsp; + +import static org.junit.Assert.*; + +import java.io.File; +import java.io.FileInputStream; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Properties; + +import org.apache.commons.io.FileUtils; +import org.apache.commons.io.IOUtils; +import org.apache.tiles.autotag.core.runtime.ModelBody; +import org.apache.tiles.autotag.model.TemplateClass; +import org.apache.tiles.autotag.model.TemplateMethod; +import org.apache.tiles.autotag.model.TemplateParameter; +import org.apache.tiles.autotag.model.TemplateSuite; +import org.apache.velocity.app.VelocityEngine; +import org.junit.Test; + +/** + * Tests TLDGenerator. + * + * @version $Rev: 1349964 $ $Date: 2012-06-13 13:18:51 -0400 (Wed, 13 Jun 2012) $ + */ +public class TLDGeneratorTest { + + public static final String REQUEST_CLASS = "org.apache.tiles.autotag.jsp.test.Request"; + + /** + * Test method for TLDGenerator#generate(File, String, TemplateSuite, Map). + * @throws Exception If something goes wrong. + */ + @Test + public void testGenerate() throws Exception { + Properties props = new Properties(); + InputStream propsStream = getClass().getResourceAsStream("/org/apache/tiles/autotag/velocity.properties"); + props.load(propsStream); + propsStream.close(); + VelocityEngine velocityEngine = new VelocityEngine(props); + + TLDGenerator generator = new TLDGenerator(velocityEngine); + File file = File.createTempFile("autotag", null); + file.delete(); + file.mkdir(); + file.deleteOnExit(); + TemplateSuite suite = new TemplateSuite("tldtest", "Test for TLD docs."); + Map parameters = new HashMap(); + parameters.put("taglibURI", "http://www.initrode.net/tags/test"); + + List params = new ArrayList(); + TemplateParameter param = new TemplateParameter("one", "one", "java.lang.String", null, true, false); + param.setDocumentation("Parameter one."); + params.add(param); + param = new TemplateParameter("two", "two", "int", null, false, false); + param.setDocumentation("Parameter two."); + params.add(param); + param = new TemplateParameter("three", "three", "long", null, false, false); + param.setDocumentation("Parameter three."); + params.add(param); + param = new TemplateParameter("request", "request", REQUEST_CLASS, null, false, true); + param.setDocumentation("The request."); + params.add(param); + param = new TemplateParameter("modelBody", "modelBody", ModelBody.class.getName(), null, false, false); + param.setDocumentation("The body."); + params.add(param); + TemplateMethod executeMethod = new TemplateMethod("execute", params); + + TemplateClass clazz = new TemplateClass("org.apache.tiles.autotag.template.DoStuffTemplate", + "doStuff", "DoStuff", executeMethod); + clazz.setDocumentation("Documentation of the DoStuff class"); + + suite.addTemplateClass(clazz); + params = new ArrayList(); + param = new TemplateParameter("one", "one", "java.lang.Double", null, true, false); + param.setDocumentation("Parameter one."); + params.add(param); + param = new TemplateParameter("two", "two", "float", null, false, false); + param.setDocumentation("Parameter two."); + params.add(param); + param = new TemplateParameter("three", "three", "java.util.Date", null, false, false); + param.setDocumentation("Parameter three."); + params.add(param); + param = new TemplateParameter("request", "request", REQUEST_CLASS, null, false ,true); + param.setDocumentation("The request."); + params.add(param); + executeMethod = new TemplateMethod("execute", params); + + clazz = new TemplateClass("org.apache.tiles.autotag.template.DoStuffNoBodyTemplate", + "doStuffNoBody", "DoStuffNoBody", executeMethod); + clazz.setDocumentation("Documentation of the DoStuffNoBody class"); + + suite.addTemplateClass(clazz); + + generator.generate(file, "org.apache.tiles.autotag.jsp.test", suite, parameters); + + InputStream expected = getClass().getResourceAsStream("/tldtest-jsp.tld"); + File effectiveFile = new File(file, "META-INF/tld/tldtest-jsp.tld"); + assertTrue(effectiveFile.exists()); + InputStream effective = new FileInputStream(effectiveFile); + assertTrue(IOUtils.contentEquals(effective, expected)); + effective.close(); + expected.close(); + + FileUtils.deleteDirectory(file); + } + +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/autotag/jsp/TagClassGeneratorTest.java b/plugins/tiles/src/test/java/org/apache/tiles/autotag/jsp/TagClassGeneratorTest.java new file mode 100644 index 000000000..834ef8ebd --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/autotag/jsp/TagClassGeneratorTest.java @@ -0,0 +1,139 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.autotag.jsp; + +import static org.junit.Assert.*; + +import java.io.File; +import java.io.FileInputStream; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Properties; + +import org.apache.commons.io.FileUtils; +import org.apache.commons.io.IOUtils; +import org.apache.tiles.autotag.core.runtime.ModelBody; +import org.apache.tiles.autotag.model.TemplateClass; +import org.apache.tiles.autotag.model.TemplateMethod; +import org.apache.tiles.autotag.model.TemplateParameter; +import org.apache.tiles.autotag.model.TemplateSuite; +import org.apache.velocity.app.VelocityEngine; +import org.junit.Test; + +/** + * Tests TagClassGenerator. + */ +public class TagClassGeneratorTest { + + public static final String REQUEST_CLASS = "org.apache.tiles.autotag.jsp.test.Request"; + + /** + * Test method for TagClassGenerator#generate(File, String, TemplateSuite, TemplateClass, Map). + * @throws Exception If something goes wrong. + */ + @Test + public void testGenerate() throws Exception { + Properties props = new Properties(); + InputStream propsStream = getClass().getResourceAsStream("/org/apache/tiles/autotag/velocity.properties"); + props.load(propsStream); + propsStream.close(); + VelocityEngine velocityEngine = new VelocityEngine(props); + + TagClassGenerator generator = new TagClassGenerator(velocityEngine); + File file = File.createTempFile("autotag", null); + file.delete(); + file.mkdir(); + file.deleteOnExit(); + TemplateSuite suite = new TemplateSuite("tldtest", "Test for TLD docs."); + Map parameters = new HashMap(); + parameters.put("taglibURI", "http://www.initrode.net/tags/test"); + + List params = new ArrayList(); + TemplateParameter param = new TemplateParameter("one", "one", "java.lang.String", null, true, false); + param.setDocumentation("Parameter one."); + params.add(param); + param = new TemplateParameter("two", "two", "int", null, false, false); + param.setDocumentation("Parameter two."); + params.add(param); + param = new TemplateParameter("three", "three", "boolean", null, false, false); + param.setDocumentation("Parameter three."); + params.add(param); + param = new TemplateParameter("request", "request", REQUEST_CLASS, null, false, true); + param.setDocumentation("The request."); + params.add(param); + param = new TemplateParameter("modelBody", "modelBody", ModelBody.class.getName(), null, false, false); + param.setDocumentation("The body."); + params.add(param); + TemplateMethod executeMethod = new TemplateMethod("execute", params); + + TemplateClass clazz = new TemplateClass("org.apache.tiles.autotag.template.DoStuffTemplate", + "doStuff", "DoStuff", executeMethod); + clazz.setDocumentation("Documentation of the DoStuff class."); + + generator.generate(file, "org.apache.tiles.autotag.jsp.test", suite, clazz, parameters, + "org.apache.tiles.autotag.jsp.test.Runtime", REQUEST_CLASS); + + InputStream expected = getClass().getResourceAsStream("/org/apache/tiles/autotag/jsp/test/DoStuffTag.java"); + File effectiveFile = new File(file, "/org/apache/tiles/autotag/jsp/test/DoStuffTag.java"); + assertTrue(effectiveFile.exists()); + InputStream effective = new FileInputStream(effectiveFile); + assertTrue(IOUtils.contentEquals(effective, expected)); + effective.close(); + expected.close(); + + suite.addTemplateClass(clazz); + params = new ArrayList(); + param = new TemplateParameter("one", "one", "java.lang.Double", null, true, false); + param.setDocumentation("Parameter one."); + params.add(param); + param = new TemplateParameter("two", "two", "float", null, false, false); + param.setDocumentation("Parameter two."); + params.add(param); + param = new TemplateParameter("three", "three", "java.util.Date", null, false, false); + param.setDocumentation("Parameter three."); + params.add(param); + param = new TemplateParameter("request", "request", REQUEST_CLASS, null, false, true); + param.setDocumentation("The request."); + params.add(param); + executeMethod = new TemplateMethod("execute", params); + + clazz = new TemplateClass("org.apache.tiles.autotag.template.DoStuffNoBodyTemplate", + "doStuffNoBody", "DoStuffNoBody", executeMethod); + clazz.setDocumentation("Documentation of the DoStuffNoBody class."); + + suite.addTemplateClass(clazz); + + generator.generate(file, "org.apache.tiles.autotag.jsp.test", suite, clazz, parameters, + "org.apache.tiles.autotag.jsp.test.Runtime", REQUEST_CLASS); + + expected = getClass().getResourceAsStream("/org/apache/tiles/autotag/jsp/test/DoStuffNoBodyTag.java"); + effectiveFile = new File(file, "/org/apache/tiles/autotag/jsp/test/DoStuffNoBodyTag.java"); + assertTrue(effectiveFile.exists()); + effective = new FileInputStream(effectiveFile); + assertTrue(IOUtils.contentEquals(effective, expected)); + effective.close(); + expected.close(); + + FileUtils.deleteDirectory(file); + } + +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/autotag/model/TemplateClassTest.java b/plugins/tiles/src/test/java/org/apache/tiles/autotag/model/TemplateClassTest.java new file mode 100644 index 000000000..1b875c37d --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/autotag/model/TemplateClassTest.java @@ -0,0 +1,153 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.autotag.model; + +import org.junit.Test; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Iterator; +import java.util.List; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertTrue; + +public class TemplateClassTest { + + /** + * Test method for {@link TemplateClass#TemplateClass(String)}. + */ + @Test + public void testTemplateConstructor1() { + TemplateClass templateClass = new TemplateClass("name"); + assertEquals("name", templateClass.getName()); + assertNull(templateClass.getTagName()); + assertNull(templateClass.getTagClassPrefix()); + assertNull(templateClass.getExecuteMethod()); + Collection params = templateClass.getParameters(); + assertTrue(params.isEmpty()); + } + + /** + * Test method for {@link TemplateClass#TemplateClass(String, String, String, TemplateMethod)}. + */ + @Test + public void testTemplateConstructor2() { + TemplateMethod method = createMock(TemplateMethod.class); + + replay(method); + TemplateClass templateClass = new TemplateClass("name", "tagName", "tagClassPrefix", method); + assertEquals("name", templateClass.getName()); + assertEquals("tagName", templateClass.getTagName()); + assertEquals("tagClassPrefix", templateClass.getTagClassPrefix()); + assertEquals(method, templateClass.getExecuteMethod()); + verify(method); + } + + /** + * Test method for {@link TemplateClass#getSimpleName()}. + */ + @Test + public void testGetSimpleName() { + TemplateClass templateClass = new TemplateClass("name"); + assertEquals("name", templateClass.getSimpleName()); + templateClass = new TemplateClass("org.whatever.Hello"); + assertEquals("Hello", templateClass.getSimpleName()); + } + + /** + * Test method for {@link TemplateClass#setDocumentation(String)}. + */ + @Test + public void testSetDocumentation() { + TemplateClass templateClass = new TemplateClass("name"); + templateClass.setDocumentation("docs"); + assertEquals("docs", templateClass.getDocumentation()); + } + + /** + * Test method for {@link TemplateClass#getParameters()}. + */ + @Test + public void testGetParameters() { + TemplateParameter param1 = createMock(TemplateParameter.class); + TemplateParameter param2 = createMock(TemplateParameter.class); + TemplateParameter param3 = createMock(TemplateParameter.class); + TemplateParameter param4 = createMock(TemplateParameter.class); + TemplateMethod method = createMock(TemplateMethod.class); + List params = new ArrayList<>(); + + expect(method.getParameters()).andReturn(params); + expect(param1.isRequest()).andReturn(true); + expect(param2.isRequest()).andReturn(false); + expect(param2.isBody()).andReturn(true); + expect(param3.isRequest()).andReturn(false); + expect(param3.isBody()).andReturn(false); + expect(param4.isRequest()).andReturn(false); + expect(param4.isBody()).andReturn(false); + expect(param3.getName()).andReturn("param1"); + expect(param4.getName()).andReturn("param2"); + + replay(param1, param2, param3, param4, method); + params.add(param1); + params.add(param2); + params.add(param3); + params.add(param4); + + TemplateClass templateClass = new TemplateClass("name", "tagName", "tagClassPrefix", method); + Collection returnedParams = templateClass.getParameters(); + Iterator paramIt = returnedParams.iterator(); + assertSame(param3, paramIt.next()); + assertSame(param4, paramIt.next()); + assertFalse(paramIt.hasNext()); + verify(param1, param2, param3, param4, method); + } + + /** + * Test method for {@link TemplateClass#hasBody()}. + */ + @Test + public void testHasBody() { + TemplateMethod method = createMock(TemplateMethod.class); + expect(method.hasBody()).andReturn(true); + + replay(method); + TemplateClass templateClass = new TemplateClass("name", "tagName", "tagClassPrefix", method); + assertTrue(templateClass.hasBody()); + verify(method); + } + + /** + * Test method for {@link TemplateClass#toString()}. + */ + @Test + public void testToString() { + TemplateMethod method = new TemplateMethod("method", new ArrayList<>()); + TemplateClass templateClass = new TemplateClass("name", "tagName", "tagClassPrefix", method); + assertEquals("TemplateClass [name=name, tagName=tagName, tagClassPrefix=tagClassPrefix, " + "documentation=null, executeMethod=TemplateMethod " + "[name=method, documentation=null, parameters={}]]", templateClass.toString()); + } + +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/autotag/model/TemplateMethodTest.java b/plugins/tiles/src/test/java/org/apache/tiles/autotag/model/TemplateMethodTest.java new file mode 100644 index 000000000..e6ad8b181 --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/autotag/model/TemplateMethodTest.java @@ -0,0 +1,132 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.autotag.model; + +import org.junit.Test; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertTrue; + +/** + * Tests {@link TemplateMethod}. + */ +public class TemplateMethodTest { + + /** + * Tests {@link TemplateMethod#TemplateMethod(String, Iterable)}. + */ + @Test + public void testTemplateMethod() { + TemplateParameter param1 = createMock(TemplateParameter.class); + TemplateParameter param2 = createMock(TemplateParameter.class); + + expect(param1.getName()).andReturn("param1"); + expect(param2.getName()).andReturn("param2"); + + replay(param1, param2); + List parameters = new ArrayList<>(); + parameters.add(param1); + parameters.add(param2); + + TemplateMethod method = new TemplateMethod("method", parameters); + assertEquals("method", method.getName()); + Iterator params = method.getParameters().iterator(); + assertSame(param1, params.next()); + assertSame(param2, params.next()); + assertFalse(params.hasNext()); + assertSame(param1, method.getParameterByName("param1")); + assertSame(param2, method.getParameterByName("param2")); + verify(param1, param2); + } + + /** + * Tests {@link TemplateMethod#setDocumentation(String)}. + */ + @Test + public void testSetDocumentation() { + TemplateMethod method = new TemplateMethod("method", new ArrayList<>()); + method.setDocumentation("docs"); + assertEquals("docs", method.getDocumentation()); + } + + /** + * Tests {@link TemplateMethod#hasBody()}. + */ + @Test + public void testHasBody() { + TemplateParameter param1 = createMock(TemplateParameter.class); + TemplateParameter param2 = createMock(TemplateParameter.class); + + expect(param1.getName()).andReturn("param1"); + expect(param2.getName()).andReturn("param2"); + expect(param1.isBody()).andReturn(true); + + replay(param1, param2); + List parameters = new ArrayList<>(); + parameters.add(param1); + parameters.add(param2); + + TemplateMethod method = new TemplateMethod("method", parameters); + assertTrue(method.hasBody()); + verify(param1, param2); + } + + /** + * Tests {@link TemplateMethod#hasBody()}. + */ + @Test + public void testHasBody2() { + TemplateParameter param1 = createMock(TemplateParameter.class); + TemplateParameter param2 = createMock(TemplateParameter.class); + + expect(param1.getName()).andReturn("param1"); + expect(param2.getName()).andReturn("param2"); + expect(param1.isBody()).andReturn(false); + expect(param2.isBody()).andReturn(false); + + replay(param1, param2); + List parameters = new ArrayList<>(); + parameters.add(param1); + parameters.add(param2); + + TemplateMethod method = new TemplateMethod("method", parameters); + assertFalse(method.hasBody()); + verify(param1, param2); + } + + /** + * Tests {@link TemplateMethod#toString()}. + */ + @Test + public void testToString() { + TemplateMethod method = new TemplateMethod("method", new ArrayList<>()); + assertEquals("TemplateMethod [name=method, documentation=null, parameters={}]", method.toString()); + } + +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/autotag/model/TemplateParameterTest.java b/plugins/tiles/src/test/java/org/apache/tiles/autotag/model/TemplateParameterTest.java new file mode 100644 index 000000000..efa486950 --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/autotag/model/TemplateParameterTest.java @@ -0,0 +1,88 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.autotag.model; + +import org.apache.tiles.autotag.core.runtime.ModelBody; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +/** + * Tests {@link TemplateParameter}. + */ +public class TemplateParameterTest { + + @Test + public void testTemplateParameter() { + TemplateParameter parameter = new TemplateParameter("name", "exportedName", "type", "defaultValue", true, false); + assertEquals("name", parameter.getName()); + assertEquals("exportedName", parameter.getExportedName()); + assertEquals("type", parameter.getType()); + assertEquals("defaultValue", parameter.getDefaultValue()); + assertTrue(parameter.isRequired()); + assertEquals("ExportedName", parameter.getGetterSetterSuffix()); + assertFalse(parameter.isBody()); + assertFalse(parameter.isRequest()); + + parameter = new TemplateParameter("name", "exportedName", "my.Request", "defaultValue", false, true); + assertEquals("name", parameter.getName()); + assertEquals("exportedName", parameter.getExportedName()); + assertEquals("my.Request", parameter.getType()); + assertEquals("defaultValue", parameter.getDefaultValue()); + assertFalse(parameter.isRequired()); + assertEquals("ExportedName", parameter.getGetterSetterSuffix()); + assertFalse(parameter.isBody()); + assertTrue(parameter.isRequest()); + + parameter = new TemplateParameter("name", "exportedName", ModelBody.class.getName(), "defaultValue", false, false); + assertEquals("name", parameter.getName()); + assertEquals("exportedName", parameter.getExportedName()); + assertEquals(ModelBody.class.getName(), parameter.getType()); + assertEquals("defaultValue", parameter.getDefaultValue()); + assertFalse(parameter.isRequired()); + assertEquals("ExportedName", parameter.getGetterSetterSuffix()); + assertTrue(parameter.isBody()); + assertFalse(parameter.isRequest()); + } + + /** + * Tests {@link TemplateParameter#setDocumentation(String)}. + */ + @Test + public void testSetDocumentation() { + TemplateParameter parameter = new TemplateParameter("name", "exportedName", "type", "defaultValue", true, false); + parameter.setDocumentation("docs"); + assertEquals("docs", parameter.getDocumentation()); + } + + /** + * Tests {@link TemplateParameter#toString()}. + */ + @Test + public void testToString() { + TemplateParameter parameter = new TemplateParameter("name", "exportedName", "type", "defaultValue", true, false); + assertEquals( + "TemplateParameter [name=name, exportedName=exportedName, " + + "documentation=null, type=type, defaultValue=defaultValue, required=true, request=false]", + parameter.toString()); + } + +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/autotag/model/TemplateSuiteTest.java b/plugins/tiles/src/test/java/org/apache/tiles/autotag/model/TemplateSuiteTest.java new file mode 100644 index 000000000..cdb5c5216 --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/autotag/model/TemplateSuiteTest.java @@ -0,0 +1,112 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.autotag.model; + +import org.junit.Test; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertTrue; + +/** + * Tests {@link TemplateSuite}. + */ +public class TemplateSuiteTest { + + /** + * Test method for {@link TemplateSuite#TemplateSuite(String, String)}. + */ + @Test + public void testTemplateSuiteConstructor1() { + TemplateSuite suite = new TemplateSuite("name", "docs"); + assertEquals("name", suite.getName()); + assertEquals("docs", suite.getDocumentation()); + assertTrue(suite.getTemplateClasses().isEmpty()); + } + + /** + * Test method for {@link TemplateSuite#TemplateSuite(String, String, Iterable)}. + */ + @Test + public void testTemplateSuiteConstructor2() { + TemplateClass class1 = createMock(TemplateClass.class); + TemplateClass class2 = createMock(TemplateClass.class); + expect(class1.getName()).andReturn("class1"); + expect(class2.getName()).andReturn("class2"); + + replay(class1, class2); + List classes = new ArrayList<>(); + classes.add(class1); + classes.add(class2); + TemplateSuite suite = new TemplateSuite("name", "docs", classes); + assertEquals("name", suite.getName()); + assertEquals("docs", suite.getDocumentation()); + Iterator clazzes = suite.getTemplateClasses().iterator(); + assertSame(class1, clazzes.next()); + assertSame(class2, clazzes.next()); + assertFalse(clazzes.hasNext()); + assertSame(class1, suite.getTemplateClassByName("class1")); + assertSame(class2, suite.getTemplateClassByName("class2")); + verify(class1, class2); + } + + /** + * Test method for {@link TemplateSuite#addTemplateClass(TemplateClass)}. + */ + @Test + public void testAddTemplateClass() { + TemplateClass class1 = createMock(TemplateClass.class); + TemplateClass class2 = createMock(TemplateClass.class); + expect(class1.getName()).andReturn("class1"); + expect(class2.getName()).andReturn("class2"); + + replay(class1, class2); + TemplateSuite suite = new TemplateSuite("name", "docs"); + assertEquals("name", suite.getName()); + assertEquals("docs", suite.getDocumentation()); + assertTrue(suite.getTemplateClasses().isEmpty()); + suite.addTemplateClass(class1); + suite.addTemplateClass(class2); + Iterator clazzes = suite.getTemplateClasses().iterator(); + assertSame(class1, clazzes.next()); + assertSame(class2, clazzes.next()); + assertFalse(clazzes.hasNext()); + assertSame(class1, suite.getTemplateClassByName("class1")); + assertSame(class2, suite.getTemplateClassByName("class2")); + verify(class1, class2); + } + + /** + * Test method for {@link TemplateSuite#toString()}. + */ + @Test + public void testToString() { + TemplateSuite suite = new TemplateSuite("name", "docs"); + assertEquals("TemplateSuite [name=name, documentation=docs, templateClasses={}]", suite.toString()); + } +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/autotag/runtime/AbstractModelBodyTest.java b/plugins/tiles/src/test/java/org/apache/tiles/autotag/runtime/AbstractModelBodyTest.java new file mode 100644 index 000000000..3bfe89ff5 --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/autotag/runtime/AbstractModelBodyTest.java @@ -0,0 +1,157 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.autotag.runtime; + +import org.apache.tiles.autotag.core.runtime.AbstractModelBody; +import org.apache.tiles.autotag.core.runtime.util.NullWriter; +import org.junit.Test; + +import java.io.IOException; +import java.io.StringWriter; +import java.io.Writer; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.createMockBuilder; +import static org.easymock.EasyMock.expectLastCall; +import static org.easymock.EasyMock.isA; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; + +/** + * Tests {@link AbstractModelBody}. + */ +public class AbstractModelBodyTest { + + /** + * Test method for {@link AbstractModelBody#evaluate()}. + * + * @throws IOException If something goes wrong. + */ + @Test + public void testEvaluate() throws IOException { + Writer writer = createMock(Writer.class); + AbstractModelBody modelBody = createMockBuilder(AbstractModelBody.class).withConstructor(writer).createMock(); + + modelBody.evaluate(writer); + + replay(writer, modelBody); + modelBody.evaluate(); + verify(writer, modelBody); + } + + /** + * Test method for {@link AbstractModelBody#evaluateAsString()}. + * + * @throws IOException If something goes wrong. + */ + @Test + public void testEvaluateAsString() throws IOException { + AbstractModelBody modelBody = new MockModelBody(null, "return me"); + assertEquals("return me", modelBody.evaluateAsString()); + + modelBody = new MockModelBody(null, "\n \n"); + assertNull(modelBody.evaluateAsString()); + } + + /** + * Test method for {@link AbstractModelBody#evaluateAsString()}. + * + * @throws IOException If something goes wrong. + */ + @Test(expected = IOException.class) + public void testEvaluateAsStringException() throws IOException { + Writer writer = createMock(Writer.class); + AbstractModelBody modelBody = createMockBuilder(AbstractModelBody.class).withConstructor(writer).createMock(); + + modelBody.evaluate(isA(StringWriter.class)); + expectLastCall().andThrow(new IOException()); + + replay(writer, modelBody); + try { + modelBody.evaluateAsString(); + } finally { + verify(writer, modelBody); + } + } + + /** + * Test method for {@link AbstractModelBody#evaluateWithoutWriting()}. + * + * @throws IOException If something goes wrong. + */ + @Test + public void testEvaluateWithoutWriting() throws IOException { + Writer writer = createMock(Writer.class); + AbstractModelBody modelBody = createMockBuilder(AbstractModelBody.class).withConstructor(writer).createMock(); + + modelBody.evaluate(isA(NullWriter.class)); + + replay(writer, modelBody); + modelBody.evaluateWithoutWriting(); + verify(writer, modelBody); + } + + /** + * Test method for {@link AbstractModelBody#evaluateWithoutWriting()}. + * + * @throws IOException If something goes wrong. + */ + @Test(expected = IOException.class) + public void testEvaluateWithoutWritingException() throws IOException { + Writer writer = createMock(Writer.class); + AbstractModelBody modelBody = createMockBuilder(AbstractModelBody.class).withConstructor(writer).createMock(); + + modelBody.evaluate(isA(NullWriter.class)); + expectLastCall().andThrow(new IOException()); + + replay(writer, modelBody); + try { + modelBody.evaluateWithoutWriting(); + } finally { + verify(writer, modelBody); + } + } + + public static class MockModelBody extends AbstractModelBody { + + /** + * The result to return. + */ + private final String toReturn; + + /** + * Constructor. + * + * @param defaultWriter The default writer. + * @param toReturn The result to return. + */ + public MockModelBody(Writer defaultWriter, String toReturn) { + super(defaultWriter); + this.toReturn = toReturn; + } + + @Override + public void evaluate(Writer writer) throws IOException { + writer.write(toReturn); + } + + } +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/autotag/runtime/util/NullWriterTest.java b/plugins/tiles/src/test/java/org/apache/tiles/autotag/runtime/util/NullWriterTest.java new file mode 100644 index 000000000..00f6b452c --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/autotag/runtime/util/NullWriterTest.java @@ -0,0 +1,71 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.autotag.runtime.util; + +import org.apache.tiles.autotag.core.runtime.util.NullWriter; +import org.junit.Before; +import org.junit.Test; + +/** + * Tests {@link NullWriter}. + */ +public class NullWriterTest { + + /** + * A dummy size. + */ + private static final int DUMMY_SIZE = 15; + /** + * The object to test. + */ + private NullWriter writer; + + /** + * Sets up the test. + */ + @Before + public void setUp() { + writer = new NullWriter(); + } + + /** + * Test method for {@link NullWriter#write(char[], int, int)}. + */ + @Test + public void testWriteCharArrayIntInt() { + writer.write("Hello there".toCharArray(), 0, DUMMY_SIZE); + } + + /** + * Test method for {@link NullWriter#flush()}. + */ + @Test + public void testFlush() { + writer.flush(); + } + + /** + * Test method for {@link NullWriter#close()}. + */ + @Test + public void testClose() { + writer.close(); + } + +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/autotag/velocity/VelocityDirectiveGeneratorTest.java b/plugins/tiles/src/test/java/org/apache/tiles/autotag/velocity/VelocityDirectiveGeneratorTest.java new file mode 100644 index 000000000..b9854bf1c --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/autotag/velocity/VelocityDirectiveGeneratorTest.java @@ -0,0 +1,139 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.autotag.velocity; + +import static org.junit.Assert.*; + +import java.io.File; +import java.io.FileInputStream; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.List; +import java.util.Properties; + +import org.apache.commons.io.FileUtils; +import org.apache.commons.io.IOUtils; +import org.apache.tiles.autotag.core.runtime.ModelBody; +import org.apache.tiles.autotag.model.TemplateClass; +import org.apache.tiles.autotag.model.TemplateMethod; +import org.apache.tiles.autotag.model.TemplateParameter; +import org.apache.tiles.autotag.model.TemplateSuite; +import org.apache.velocity.app.VelocityEngine; +import org.junit.Test; + +/** + * Tests VelocityDirectiveGenerator. + */ +public class VelocityDirectiveGeneratorTest { + + public static final String REQUEST_CLASS = "org.apache.tiles.autotag.velocity.Request"; + + /** + * Test method for VelocityDirectiveGenerator#generate(File, String, + * TemplateSuite, TemplateClass, java.util.Map). + * + * @throws Exception If something goes wrong. + */ + @Test + public void testGenerate() throws Exception { + Properties props = new Properties(); + InputStream propsStream = getClass().getResourceAsStream("/org/apache/tiles/autotag/velocity.properties"); + props.load(propsStream); + propsStream.close(); + VelocityEngine velocityEngine = new VelocityEngine(props); + + VelocityDirectiveGenerator generator = new VelocityDirectiveGenerator(velocityEngine); + File file = File.createTempFile("autotag", null); + file.delete(); + file.mkdir(); + file.deleteOnExit(); + TemplateSuite suite = new TemplateSuite("tldtest", "Test for TLD docs."); + + List params = new ArrayList(); + TemplateParameter param = new TemplateParameter("one", "one", "java.lang.String", null, true, false); + param.setDocumentation("Parameter one."); + params.add(param); + param = new TemplateParameter("two", "two", "int", null, false, false); + param.setDocumentation("Parameter two."); + params.add(param); + param = new TemplateParameter("three", "three", "boolean", null, false, false); + param.setDocumentation("Parameter three."); + params.add(param); + param = new TemplateParameter("request", "request", REQUEST_CLASS, null, false, true); + param.setDocumentation("The request."); + params.add(param); + param = new TemplateParameter("modelBody", "modelBody", ModelBody.class.getName(), null, false, false); + param.setDocumentation("The body."); + params.add(param); + TemplateMethod executeMethod = new TemplateMethod("execute", params); + + TemplateClass clazz = new TemplateClass("org.apache.tiles.autotag.template.DoStuffTemplate", "doStuff", + "DoStuff", executeMethod); + clazz.setDocumentation("Documentation of the DoStuff class."); + + generator.generate(file, "org.apache.tiles.autotag.velocity.test", suite, clazz, null, + "org.apache.tiles.autotag.velocity.test.Runtime", REQUEST_CLASS); + + InputStream expected = getClass() + .getResourceAsStream("/org/apache/tiles/autotag/velocity/test/DoStuffDirective.javat"); + File effectiveFile = new File(file, "/org/apache/tiles/autotag/velocity/test/DoStuffDirective.java"); + assertTrue(effectiveFile.exists()); + InputStream effective = new FileInputStream(effectiveFile); + assertTrue(IOUtils.contentEquals(effective, expected)); + effective.close(); + expected.close(); + + suite.addTemplateClass(clazz); + params = new ArrayList(); + param = new TemplateParameter("one", "one", "java.lang.Double", null, true, false); + param.setDocumentation("Parameter one."); + params.add(param); + param = new TemplateParameter("two", "two", "float", null, false, false); + param.setDocumentation("Parameter two."); + params.add(param); + param = new TemplateParameter("three", "three", "java.util.Date", null, false, false); + param.setDocumentation("Parameter three."); + params.add(param); + param = new TemplateParameter("request", "request", REQUEST_CLASS, null, false, true); + param.setDocumentation("The request."); + params.add(param); + executeMethod = new TemplateMethod("execute", params); + + clazz = new TemplateClass("org.apache.tiles.autotag.template.DoStuffNoBodyTemplate", "doStuffNoBody", + "DoStuffNoBody", executeMethod); + clazz.setDocumentation("Documentation of the DoStuffNoBody class."); + + suite.addTemplateClass(clazz); + + generator.generate(file, "org.apache.tiles.autotag.velocity.test", suite, clazz, null, + "org.apache.tiles.autotag.velocity.test.Runtime", REQUEST_CLASS); + + expected = getClass() + .getResourceAsStream("/org/apache/tiles/autotag/velocity/test/DoStuffNoBodyDirective.javat"); + effectiveFile = new File(file, "/org/apache/tiles/autotag/velocity/test/DoStuffNoBodyDirective.java"); + assertTrue(effectiveFile.exists()); + effective = new FileInputStream(effectiveFile); + assertTrue(IOUtils.contentEquals(effective, expected)); + effective.close(); + expected.close(); + + FileUtils.deleteDirectory(file); + } + +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/autotag/velocity/VelocityPropertiesGeneratorTest.java b/plugins/tiles/src/test/java/org/apache/tiles/autotag/velocity/VelocityPropertiesGeneratorTest.java new file mode 100644 index 000000000..1ea2b37fc --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/autotag/velocity/VelocityPropertiesGeneratorTest.java @@ -0,0 +1,125 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.autotag.velocity; + +import static org.junit.Assert.*; + +import java.io.File; +import java.io.FileInputStream; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.List; +import java.util.Properties; + +import org.apache.commons.io.FileUtils; +import org.apache.commons.io.IOUtils; +import org.apache.tiles.autotag.core.runtime.ModelBody; +import org.apache.tiles.autotag.model.TemplateClass; +import org.apache.tiles.autotag.model.TemplateMethod; +import org.apache.tiles.autotag.model.TemplateParameter; +import org.apache.tiles.autotag.model.TemplateSuite; +import org.apache.velocity.app.VelocityEngine; +import org.junit.Test; + +/** + * Tests VelocityPropertiesGenerator. + */ +public class VelocityPropertiesGeneratorTest { + + public static final String REQUEST_CLASS = "org.apache.tiles.autotag.velocity.Request"; + + /** + * Test method for org.apache.tiles.autotag.velocity.VelocityPropertiesGenerator + * #generate(File, String, TemplateSuite, java.util.Map). + * + * @throws Exception If something goes wrong. + */ + @Test + public void testGenerate() throws Exception { + Properties props = new Properties(); + InputStream propsStream = getClass().getResourceAsStream("/org/apache/tiles/autotag/velocity.properties"); + props.load(propsStream); + propsStream.close(); + VelocityEngine velocityEngine = new VelocityEngine(props); + + VelocityPropertiesGenerator generator = new VelocityPropertiesGenerator(velocityEngine); + File file = File.createTempFile("autotag", null); + file.delete(); + file.mkdir(); + file.deleteOnExit(); + TemplateSuite suite = new TemplateSuite("tldtest", "Test for TLD docs."); + + List params = new ArrayList(); + TemplateParameter param = new TemplateParameter("one", "one", "java.lang.String", null, true, false); + param.setDocumentation("Parameter one."); + params.add(param); + param = new TemplateParameter("two", "two", "int", null, false, false); + param.setDocumentation("Parameter two."); + params.add(param); + param = new TemplateParameter("three", "three", "long", null, false, false); + param.setDocumentation("Parameter three."); + params.add(param); + param = new TemplateParameter("request", "request", REQUEST_CLASS, null, false, true); + param.setDocumentation("The request."); + params.add(param); + param = new TemplateParameter("modelBody", "modelBody", ModelBody.class.getName(), null, false, false); + param.setDocumentation("The body."); + params.add(param); + TemplateMethod executeMethod = new TemplateMethod("execute", params); + + TemplateClass clazz = new TemplateClass("org.apache.tiles.autotag.template.DoStuffTemplate", "doStuff", + "DoStuff", executeMethod); + clazz.setDocumentation("Documentation of the DoStuff class"); + + suite.addTemplateClass(clazz); + params = new ArrayList(); + param = new TemplateParameter("one", "one", "java.lang.Double", null, true, false); + param.setDocumentation("Parameter one."); + params.add(param); + param = new TemplateParameter("two", "two", "float", null, false, false); + param.setDocumentation("Parameter two."); + params.add(param); + param = new TemplateParameter("three", "three", "java.util.Date", null, false, false); + param.setDocumentation("Parameter three."); + params.add(param); + param = new TemplateParameter("request", "request", REQUEST_CLASS, null, false, true); + param.setDocumentation("The request."); + params.add(param); + executeMethod = new TemplateMethod("execute", params); + + clazz = new TemplateClass("org.apache.tiles.autotag.template.DoStuffNoBodyTemplate", "doStuffNoBody", + "DoStuffNoBody", executeMethod); + clazz.setDocumentation("Documentation of the DoStuffNoBody class"); + + suite.addTemplateClass(clazz); + + generator.generate(file, "org.apache.tiles.autotag.velocity.test", suite, null); + + InputStream expected = getClass().getResourceAsStream("/velocity.properties.test"); + File effectiveFile = new File(file, "META-INF/velocity.properties"); + assertTrue(effectiveFile.exists()); + InputStream effective = new FileInputStream(effectiveFile); + assertTrue(IOUtils.contentEquals(effective, expected)); + effective.close(); + expected.close(); + + FileUtils.deleteDirectory(file); + } + +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/autotag/velocity/VelocityTemplateGeneratorFactoryTest.java b/plugins/tiles/src/test/java/org/apache/tiles/autotag/velocity/VelocityTemplateGeneratorFactoryTest.java new file mode 100644 index 000000000..e0924178a --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/autotag/velocity/VelocityTemplateGeneratorFactoryTest.java @@ -0,0 +1,60 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.autotag.velocity; + +import static org.easymock.EasyMock.*; +import static org.junit.Assert.*; + +import java.io.File; + +import org.apache.tiles.autotag.generate.TemplateGenerator; +import org.apache.tiles.autotag.generate.TemplateGeneratorBuilder; +import org.apache.velocity.app.VelocityEngine; +import org.junit.Test; + +/** + * Tests JspTemplateGeneratorFactory. + */ +public class VelocityTemplateGeneratorFactoryTest { + + /** + * Test method for VelocityTemplateGeneratorFactory#createTemplateGenerator(). + */ + @Test + public void testCreateTemplateGenerator() { + File classesOutputDirectory = createMock(File.class); + File resourcesOutputDirectory = createMock(File.class); + VelocityEngine velocityEngine = createMock(VelocityEngine.class); + TemplateGeneratorBuilder builder = createMock(TemplateGeneratorBuilder.class); + TemplateGenerator generator = createMock(TemplateGenerator.class); + + expect(builder.setClassesOutputDirectory(classesOutputDirectory)).andReturn(builder); + expect(builder.setResourcesOutputDirectory(resourcesOutputDirectory)).andReturn(builder); + expect(builder.addResourcesTemplateSuiteGenerator(isA(VelocityPropertiesGenerator.class))).andReturn(builder); + expect(builder.addClassesTemplateClassGenerator(isA(VelocityDirectiveGenerator.class))).andReturn(builder); + expect(builder.build()).andReturn(generator); + + replay(classesOutputDirectory, resourcesOutputDirectory, velocityEngine, builder, generator); + VelocityTemplateGeneratorFactory factory = new VelocityTemplateGeneratorFactory(classesOutputDirectory, + resourcesOutputDirectory, velocityEngine, builder); + assertSame(generator, factory.createTemplateGenerator()); + verify(classesOutputDirectory, resourcesOutputDirectory, velocityEngine, builder, generator); + } + +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/core/definition/DefinitionsFactoryExceptionTest.java b/plugins/tiles/src/test/java/org/apache/tiles/core/definition/DefinitionsFactoryExceptionTest.java new file mode 100644 index 000000000..c9f4d5bd2 --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/core/definition/DefinitionsFactoryExceptionTest.java @@ -0,0 +1,74 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tiles.core.definition; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; + +/** + * Tests {@link DefinitionsFactoryException}. + */ +public class DefinitionsFactoryExceptionTest { + + /** + * Test method for {@link DefinitionsFactoryException#DefinitionsFactoryException()}. + */ + @Test + public void testDefinitionsFactoryException() { + DefinitionsFactoryException exception = new DefinitionsFactoryException(); + assertNull(exception.getMessage()); + assertNull(exception.getCause()); + } + + /** + * Test method for {@link DefinitionsFactoryException#DefinitionsFactoryException(String)}. + */ + @Test + public void testDefinitionsFactoryExceptionString() { + DefinitionsFactoryException exception = new DefinitionsFactoryException("my message"); + assertEquals("my message", exception.getMessage()); + assertNull(exception.getCause()); + } + + /** + * Test method for {@link DefinitionsFactoryException#DefinitionsFactoryException(Throwable)}. + */ + @Test + public void testDefinitionsFactoryExceptionThrowable() { + Throwable cause = new Throwable(); + DefinitionsFactoryException exception = new DefinitionsFactoryException(cause); + assertEquals(cause.toString(), exception.getMessage()); + assertEquals(cause, exception.getCause()); + } + + /** + * Test method for {@link DefinitionsFactoryException#DefinitionsFactoryException(String, Throwable)}. + */ + @Test + public void testDefinitionsFactoryExceptionStringThrowable() { + Throwable cause = new Throwable(); + DefinitionsFactoryException exception = new DefinitionsFactoryException("my message", cause); + assertEquals("my message", exception.getMessage()); + assertEquals(cause, exception.getCause()); + } + +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/core/definition/MockDefinitionsReader.java b/plugins/tiles/src/test/java/org/apache/tiles/core/definition/MockDefinitionsReader.java new file mode 100644 index 000000000..865e2230f --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/core/definition/MockDefinitionsReader.java @@ -0,0 +1,44 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.core.definition; + +import org.apache.tiles.api.Definition; + +import java.util.LinkedHashMap; +import java.util.Map; + +/** + * Mock Definitions Reader implementation. Stubs out all functionality. + */ +public class MockDefinitionsReader implements DefinitionsReader { + + /** + * Reads {@link Definition} objects from a source. + * Implementations should publish what type of source object is expected. + * + * @param source The source from which definitions will be read. + * @return a Map of Definition objects read from + * the source. + * @throws org.apache.tiles.core.definition.DefinitionsFactoryException if the source is invalid or + * an error occurs when reading definitions. + */ + public Map read(Object source) { + return new LinkedHashMap<>(); + } +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/core/definition/NoSuchDefinitionExceptionTest.java b/plugins/tiles/src/test/java/org/apache/tiles/core/definition/NoSuchDefinitionExceptionTest.java new file mode 100644 index 000000000..9e2c2faab --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/core/definition/NoSuchDefinitionExceptionTest.java @@ -0,0 +1,42 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tiles.core.definition; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; + +/** + * Tests {@link NoSuchDefinitionException}. + */ +public class NoSuchDefinitionExceptionTest { + + /** + * Test method for {@link NoSuchDefinitionException#NoSuchDefinitionException(String)}. + */ + @Test + public void testNoSuchDefinitionExceptionString() { + NoSuchDefinitionException exception = new NoSuchDefinitionException("my message"); + assertEquals("my message", exception.getMessage()); + assertNull(exception.getCause()); + } + +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/core/definition/UnresolvingLocaleDefinitionsFactoryTest.java b/plugins/tiles/src/test/java/org/apache/tiles/core/definition/UnresolvingLocaleDefinitionsFactoryTest.java new file mode 100644 index 000000000..1d136589f --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/core/definition/UnresolvingLocaleDefinitionsFactoryTest.java @@ -0,0 +1,63 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tiles.core.definition; + +import org.apache.tiles.api.Definition; +import org.apache.tiles.core.definition.dao.DefinitionDAO; +import org.apache.tiles.core.locale.LocaleResolver; +import org.apache.tiles.request.Request; +import org.junit.Test; + +import java.util.Locale; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import static org.junit.Assert.assertEquals; + +/** + * Tests {@link UnresolvingLocaleDefinitionsFactory}. + */ +public class UnresolvingLocaleDefinitionsFactoryTest { + + /** + * Test method for {@link UnresolvingLocaleDefinitionsFactory#getDefinition(String, Request)}. + */ + @Test + public void testGetDefinition() { + DefinitionDAO dao = createMock(DefinitionDAO.class); + LocaleResolver localeResolver = createMock(LocaleResolver.class); + UnresolvingLocaleDefinitionsFactory factory = new UnresolvingLocaleDefinitionsFactory(); + Request request = createMock(Request.class); + Definition definition = createMock(Definition.class); + Locale locale = Locale.ITALY; + + expect(localeResolver.resolveLocale(request)).andReturn(locale); + expect(dao.getDefinition("myDefinition", locale)).andReturn(definition); + + replay(dao, localeResolver, request, definition); + factory.setDefinitionDAO(dao); + factory.setLocaleResolver(localeResolver); + assertEquals(definition, factory.getDefinition("myDefinition", request)); + verify(dao, localeResolver, request, definition); + } + +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/core/definition/dao/BaseLocaleUrlDefinitionDAOTest.java b/plugins/tiles/src/test/java/org/apache/tiles/core/definition/dao/BaseLocaleUrlDefinitionDAOTest.java new file mode 100644 index 000000000..77dc4fba9 --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/core/definition/dao/BaseLocaleUrlDefinitionDAOTest.java @@ -0,0 +1,156 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.core.definition.dao; + +import org.apache.tiles.api.Attribute; +import org.apache.tiles.api.Definition; +import org.apache.tiles.core.definition.DefinitionsReader; +import org.apache.tiles.core.definition.RefreshMonitor; +import org.apache.tiles.core.definition.digester.DigesterDefinitionsReader; +import org.apache.tiles.request.ApplicationContext; +import org.apache.tiles.request.ApplicationResource; +import org.apache.tiles.request.Request; +import org.apache.tiles.request.locale.PostfixedApplicationResource; +import org.junit.Before; +import org.junit.Test; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.createMockBuilder; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +/** + * Tests {@link BaseLocaleUrlDefinitionDAO}. + */ +public class BaseLocaleUrlDefinitionDAOTest { + + private static final class MutableApplicationResource extends PostfixedApplicationResource { + private long lastModified = System.currentTimeMillis(); + private String xml = "\n" + + "\n\n" + "" + + "" + + "" + "" // + + ""; + + private MutableApplicationResource(String localePath) { + super(localePath); + } + + public void modify(String xml) { + lastModified = System.currentTimeMillis(); + this.xml = xml; + } + + @Override + public long getLastModified() { + return lastModified; + } + + @Override + public InputStream getInputStream() throws IOException { + return new ByteArrayInputStream(xml.getBytes(StandardCharsets.ISO_8859_1)); + } + } + + /** + * The time (in milliseconds) to wait to be sure that the system updates the + * modify date of a file. + */ + private static final int SLEEP_MILLIS = 2000; + + private BaseLocaleUrlDefinitionDAO dao; + private MutableApplicationResource resource; + + @Before + public void setUp() throws IOException { + resource = new MutableApplicationResource("org/apache/tiles/core/config/temp-defs.xml"); + + ApplicationContext applicationContext = createMock(ApplicationContext.class); + expect(applicationContext.getResource("org/apache/tiles/core/config/temp-defs.xml")).andReturn(resource).anyTimes(); + replay(applicationContext); + dao = createMockBuilder(BaseLocaleUrlDefinitionDAO.class).withConstructor(applicationContext).createMock(); + } + + /** + * Test method for {@link org.apache.tiles.core.definition.dao.BaseLocaleUrlDefinitionDAO#refreshRequired()}. + * + * @throws InterruptedException If something goes wrong. + */ + @Test + public void testRefreshRequired() throws InterruptedException { + // Set up multiple data sources. + Map attribs = new HashMap<>(); + attribs.put("testparm", new Attribute("testval")); + Definition rewriteTest = new Definition("rewrite.test", Attribute.createTemplateAttribute("/test.jsp"), attribs); + expect(dao.getDefinition("rewrite.test", null)).andReturn(rewriteTest); + + replay(dao); + + List sources = new ArrayList<>(); + sources.add(resource); + dao.setSources(sources); + DefinitionsReader reader = new DigesterDefinitionsReader(); + dao.setReader(reader); + + Request context = createMock(Request.class); + expect(context.getContext("session")).andReturn(new HashMap<>()).anyTimes(); + expect(context.getRequestLocale()).andReturn(null).anyTimes(); + replay(context); + + Definition definition = dao.getDefinition("rewrite.test", null); + assertNotNull("rewrite.test definition not found.", definition); + assertEquals("Incorrect initial template value", "/test.jsp", definition.getTemplateAttribute().getValue()); + + RefreshMonitor reloadable = dao; + dao.loadDefinitionsFromResource(resource); + assertFalse("Factory should be fresh.", reloadable.refreshRequired()); + + // Make sure the system actually updates the timestamp. + Thread.sleep(SLEEP_MILLIS); + + // Set up multiple data sources. + resource.modify("\n" + "\n\n" + "" + + "" + + "" + "" // + + ""); + + assertTrue("Factory should be stale.", reloadable.refreshRequired()); + + verify(context, dao); + } + +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/core/definition/dao/CachingLocaleUrlDefinitionDAOTest.java b/plugins/tiles/src/test/java/org/apache/tiles/core/definition/dao/CachingLocaleUrlDefinitionDAOTest.java new file mode 100644 index 000000000..048577321 --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/core/definition/dao/CachingLocaleUrlDefinitionDAOTest.java @@ -0,0 +1,371 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tiles.core.definition.dao; + +import junit.framework.TestCase; +import org.apache.tiles.api.Attribute; +import org.apache.tiles.api.Definition; +import org.apache.tiles.api.ListAttribute; +import org.apache.tiles.core.definition.DefinitionsReader; +import org.apache.tiles.core.definition.MockDefinitionsReader; +import org.apache.tiles.core.definition.digester.DigesterDefinitionsReader; +import org.apache.tiles.core.definition.pattern.BasicPatternDefinitionResolver; +import org.apache.tiles.core.definition.pattern.PatternDefinitionResolver; +import org.apache.tiles.core.definition.pattern.wildcard.WildcardDefinitionPatternMatcherFactory; +import org.apache.tiles.request.ApplicationContext; +import org.apache.tiles.request.ApplicationResource; +import org.apache.tiles.request.locale.URLApplicationResource; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Objects; +import java.util.Set; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.reset; +import static org.easymock.EasyMock.verify; + +/** + * Tests {@link CachingLocaleUrlDefinitionDAO}. + * + * @version $Rev$ $Date$ + */ +public class CachingLocaleUrlDefinitionDAOTest extends TestCase { + + /** + * The object to test. + */ + private CachingLocaleUrlDefinitionDAO definitionDao; + + private ApplicationContext applicationContext; + + private ApplicationResource url1; + + private ApplicationResource url2; + + private ApplicationResource url3; + + private ApplicationResource urlWildcard; + + private ApplicationResource url21; + + private ApplicationResource setupUrl(String filename, Locale... locales) { + ApplicationResource url = new URLApplicationResource( + "org/apache/tiles/core/config/" + filename + ".xml", + Objects.requireNonNull(this.getClass().getClassLoader().getResource("org/apache/tiles/core/config/" + filename + ".xml")) + ); + assertNotNull("Could not load " + filename + " file.", url); + expect(applicationContext.getResource(url.getLocalePath())).andReturn(url).anyTimes(); + expect(applicationContext.getResource(url, Locale.ROOT)).andReturn(url).anyTimes(); + Map localeResources = new HashMap(); + for (Locale locale : locales) { + ApplicationResource urlLocale = new URLApplicationResource( + "org/apache/tiles/core/config/" + filename + "_" + locale.toString() + ".xml", + Objects.requireNonNull(this.getClass().getClassLoader().getResource("org/apache/tiles/core/config/" + filename + "_" + locale + ".xml")) + ); + assertNotNull("Could not load " + filename + "_" + locale + " file.", urlLocale); + localeResources.put(locale, urlLocale); + } + for (Locale locale : new Locale[]{Locale.CANADA_FRENCH, Locale.FRENCH, Locale.US, Locale.ENGLISH, + Locale.CHINA, Locale.CHINESE, Locale.ITALY, Locale.ITALIAN}) { + ApplicationResource urlLocale = localeResources.get(locale); + expect(applicationContext.getResource(url, locale)).andReturn(urlLocale).anyTimes(); + } + return url; + } + + /** + * {@inheritDoc} + */ + @Override + protected void setUp() throws Exception { + super.setUp(); + applicationContext = createMock(ApplicationContext.class); + url1 = setupUrl("defs1", Locale.FRENCH, Locale.CANADA_FRENCH, Locale.US); + url2 = setupUrl("defs2"); + url3 = setupUrl("defs3"); + urlWildcard = setupUrl("defs-wildcard"); + url21 = setupUrl("tiles-defs-2.1", Locale.ITALIAN); + replay(applicationContext); + definitionDao = new CachingLocaleUrlDefinitionDAO(applicationContext); + WildcardDefinitionPatternMatcherFactory definitionPatternMatcherFactory = + new WildcardDefinitionPatternMatcherFactory(); + PatternDefinitionResolver definitionResolver = new BasicPatternDefinitionResolver<>( + definitionPatternMatcherFactory, + definitionPatternMatcherFactory); + definitionDao.setPatternDefinitionResolver(definitionResolver); + } + + public void testGetDefinition() { + List sourceURLs = new ArrayList<>(); + sourceURLs.add(url1); + sourceURLs.add(url2); + sourceURLs.add(url3); + definitionDao.setSources(sourceURLs); + DefinitionsReader reader = new DigesterDefinitionsReader(); + definitionDao.setReader(reader); + + assertNotNull("test.def1 definition not found.", definitionDao + .getDefinition("test.def1", null)); + assertNotNull("test.def2 definition not found.", definitionDao + .getDefinition("test.def2", null)); + assertNotNull("test.def3 definition not found.", definitionDao + .getDefinition("test.def3", null)); + assertNotNull("test.common definition not found.", definitionDao + .getDefinition("test.common", null)); + assertNotNull("test.common definition in US locale not found.", + definitionDao.getDefinition("test.common", Locale.US)); + assertNotNull("test.common definition in FRENCH locale not found.", + definitionDao.getDefinition("test.common", Locale.FRENCH)); + assertNotNull("test.common definition in CHINA locale not found.", + definitionDao.getDefinition("test.common", Locale.CHINA)); + assertNotNull( + "test.common.french definition in FRENCH locale not found.", + definitionDao.getDefinition("test.common.french", + Locale.FRENCH)); + assertNotNull( + "test.common.french definition in CANADA_FRENCH locale not found.", + definitionDao.getDefinition("test.common.french", + Locale.CANADA_FRENCH)); + assertNotNull("test.def.toextend definition not found.", definitionDao + .getDefinition("test.def.toextend", null)); + assertNotNull("test.def.overridden definition not found.", + definitionDao.getDefinition("test.def.overridden", null)); + assertNotNull( + "test.def.overridden definition in FRENCH locale not found.", + definitionDao.getDefinition("test.def.overridden", + Locale.FRENCH)); + + assertEquals("Incorrect default country value", "default", + definitionDao.getDefinition("test.def1", null).getAttribute( + "country").getValue()); + assertEquals("Incorrect US country value", "US", definitionDao + .getDefinition("test.def1", Locale.US).getAttribute("country") + .getValue()); + assertEquals("Incorrect France country value", "France", definitionDao + .getDefinition("test.def1", Locale.FRENCH).getAttribute( + "country").getValue()); + assertEquals("Incorrect Chinese country value (should be default)", + "default", definitionDao.getDefinition("test.def1", + Locale.CHINA).getAttribute("country").getValue()); + assertEquals("Incorrect default country value", "default", + definitionDao.getDefinition("test.def.overridden", null) + .getAttribute("country").getValue()); + assertEquals("Incorrect default title value", + "Definition to be overridden", definitionDao.getDefinition( + "test.def.overridden", null).getAttribute("title") + .getValue()); + assertEquals("Incorrect France country value", "France", definitionDao + .getDefinition("test.def.overridden", Locale.FRENCH) + .getAttribute("country").getValue()); + assertNull("Definition in French not found", definitionDao + .getDefinition("test.def.overridden", Locale.FRENCH) + .getAttribute("title")); + } + + public void testGetDefinitions() { + List sourceURLs = new ArrayList<>(); + sourceURLs.add(url1); + sourceURLs.add(url2); + sourceURLs.add(url3); + definitionDao.setSources(sourceURLs); + DefinitionsReader reader = new DigesterDefinitionsReader(); + definitionDao.setReader(reader); + + Map defaultDefinitions = definitionDao + .getDefinitions(null); + Map usDefinitions = definitionDao + .getDefinitions(Locale.US); + Map frenchDefinitions = definitionDao + .getDefinitions(Locale.FRENCH); + Map chinaDefinitions = definitionDao + .getDefinitions(Locale.CHINA); + Map canadaFrenchDefinitions = definitionDao + .getDefinitions(Locale.CANADA_FRENCH); + + assertNotNull("test.def1 definition not found.", defaultDefinitions + .get("test.def1")); + assertNotNull("test.def2 definition not found.", defaultDefinitions + .get("test.def2")); + assertNotNull("test.def3 definition not found.", defaultDefinitions + .get("test.def3")); + assertNotNull("test.common definition not found.", defaultDefinitions + .get("test.common")); + assertNotNull("test.common definition in US locale not found.", + usDefinitions.get("test.common")); + assertNotNull("test.common definition in FRENCH locale not found.", + frenchDefinitions.get("test.common")); + assertNotNull("test.common definition in CHINA locale not found.", + chinaDefinitions.get("test.common")); + assertNotNull( + "test.common.french definition in FRENCH locale not found.", + frenchDefinitions.get("test.common.french")); + assertNotNull( + "test.common.french definition in CANADA_FRENCH locale not found.", + canadaFrenchDefinitions.get("test.common.french")); + assertNotNull("test.def.toextend definition not found.", + defaultDefinitions.get("test.def.toextend")); + assertNotNull("test.def.overridden definition not found.", + defaultDefinitions.get("test.def.overridden")); + assertNotNull( + "test.def.overridden definition in FRENCH locale not found.", + frenchDefinitions.get("test.def.overridden")); + + assertEquals("Incorrect default country value", "default", + defaultDefinitions.get("test.def1").getAttribute("country") + .getValue()); + assertEquals("Incorrect US country value", "US", usDefinitions.get( + "test.def1").getAttribute("country").getValue()); + assertEquals("Incorrect France country value", "France", + frenchDefinitions.get("test.def1").getAttribute("country") + .getValue()); + assertEquals("Incorrect Chinese country value (should be default)", + "default", chinaDefinitions.get("test.def1").getAttribute( + "country").getValue()); + assertEquals("Incorrect default country value", "default", + defaultDefinitions.get("test.def.overridden").getAttribute( + "country").getValue()); + assertEquals("Incorrect default title value", + "Definition to be overridden", defaultDefinitions.get( + "test.def.overridden").getAttribute("title").getValue()); + assertEquals("Incorrect France country value", "France", + frenchDefinitions.get("test.def.overridden").getAttribute( + "country").getValue()); + assertNull("Definition in French not found", frenchDefinitions.get( + "test.def.overridden").getAttribute("title")); + } + + public void testSetSourceURLs() { + List sourceURLs = new ArrayList<>(); + sourceURLs.add(url1); + sourceURLs.add(url2); + sourceURLs.add(url3); + definitionDao.setSources(sourceURLs); + assertEquals("The source URLs are not set correctly", sourceURLs, + definitionDao.sources); + } + + public void testSetReader() { + DefinitionsReader reader = createMock(DefinitionsReader.class); + definitionDao.setReader(reader); + assertEquals("There reader has not been set correctly", reader, + definitionDao.reader); + } + + public void testInit() { + ApplicationContext applicationContext = createMock(ApplicationContext.class); + Set urlSet = new HashSet<>(); + urlSet.add(url1); + expect(applicationContext.getResources("/WEB-INF/tiles.xml")) + .andReturn(urlSet); + replay(applicationContext); + DefinitionsReader reader = new DigesterDefinitionsReader(); + definitionDao.setReader(reader); + List sourceURLs = new ArrayList<>(); + sourceURLs.add(url1); + definitionDao.setSources(sourceURLs); + assertEquals("The reader is not of the correct class", + DigesterDefinitionsReader.class, definitionDao.reader + .getClass()); + assertEquals("The source URLs are not correct", sourceURLs, + definitionDao.sources); + reset(applicationContext); + + definitionDao.setReader(new MockDefinitionsReader()); + assertEquals("The reader is not of the correct class", + MockDefinitionsReader.class, definitionDao.reader.getClass()); + sourceURLs = new ArrayList<>(); + sourceURLs.add(url1); + sourceURLs.add(url2); + sourceURLs.add(url3); + definitionDao.setSources(sourceURLs); + assertEquals("The source URLs are not correct", sourceURLs, + definitionDao.sources); + } + + /** + * Tests wildcard mappings. + */ + public void testWildcardMapping() { + List urls = new ArrayList<>(); + urls.add(urlWildcard); + definitionDao.setSources(urls); + definitionDao.setReader(new DigesterDefinitionsReader()); + + Definition definition = definitionDao.getDefinition("test.defName.subLayered", Locale.ITALY); + assertEquals("The template is not correct", "/testName.jsp", definition + .getTemplateAttribute().getValue()); + assertEquals("The header attribute is not correct", + "/common/headerLayered.jsp", definition.getAttribute("header") + .getValue()); + definition = definitionDao.getDefinition("test.defName.subLayered", Locale.ITALIAN); + assertEquals("The template is not correct", "/testName.jsp", definition + .getTemplateAttribute().getValue()); + assertEquals("The header attribute is not correct", + "/common/headerLayered.jsp", definition.getAttribute("header") + .getValue()); + definition = definitionDao.getDefinition("test.defName.subLayered", null); + assertEquals("The template is not correct", "/testName.jsp", definition + .getTemplateAttribute().getValue()); + assertEquals("The header attribute is not correct", + "/common/headerLayered.jsp", definition.getAttribute("header") + .getValue()); + definition = definitionDao.getDefinition("test.defName.noAttribute", null); + assertEquals("/testName.jsp", definition.getTemplateAttribute().getValue()); + assertNull(definition.getLocalAttributeNames()); + definition = definitionDao.getDefinition("test.def3", null); + assertNotNull("The simple definition is null", definition); + + definition = definitionDao.getDefinition("test.extended.defName.subLayered", null); + assertEquals("test.defName.subLayered", definition.getExtends()); + assertNull(definition.getTemplateAttribute().getValue()); + assertEquals(1, definition.getLocalAttributeNames().size()); + assertEquals("Overridden Title", definition.getAttribute("title").getValue()); + } + + /** + * Tests + * {@link ResolvingLocaleUrlDefinitionDAO#getDefinition(String, Locale)} + * when loading multiple files for a locale. + */ + public void testListAttributeLocaleInheritance() { + List urls = new ArrayList<>(); + urls.add(url21); + definitionDao.setSources(urls); + ApplicationContext applicationContext = createMock(ApplicationContext.class); + definitionDao.setReader(new DigesterDefinitionsReader()); + replay(applicationContext); + + Definition definition = definitionDao.getDefinition( + "test.inherit.list", Locale.ITALIAN); + ListAttribute listAttribute = (ListAttribute) definition + .getAttribute("list"); + List attributes = listAttribute.getValue(); + // It is right not to resolve inheritance in this DAO. + assertEquals(1, attributes.size()); + verify(applicationContext); + } +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/core/definition/dao/ResolvingLocaleUrlDefinitionDAOTest.java b/plugins/tiles/src/test/java/org/apache/tiles/core/definition/dao/ResolvingLocaleUrlDefinitionDAOTest.java new file mode 100644 index 000000000..727617b69 --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/core/definition/dao/ResolvingLocaleUrlDefinitionDAOTest.java @@ -0,0 +1,391 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tiles.core.definition.dao; + +import org.apache.tiles.api.Attribute; +import org.apache.tiles.api.Definition; +import org.apache.tiles.api.ListAttribute; +import org.apache.tiles.core.definition.DefinitionsReader; +import org.apache.tiles.core.definition.MockDefinitionsReader; +import org.apache.tiles.core.definition.NoSuchDefinitionException; +import org.apache.tiles.core.definition.digester.DigesterDefinitionsReader; +import org.apache.tiles.core.definition.pattern.BasicPatternDefinitionResolver; +import org.apache.tiles.core.definition.pattern.PatternDefinitionResolver; +import org.apache.tiles.core.definition.pattern.wildcard.WildcardDefinitionPatternMatcherFactory; +import org.apache.tiles.request.ApplicationContext; +import org.apache.tiles.request.ApplicationResource; +import org.apache.tiles.request.locale.URLApplicationResource; +import org.junit.Before; +import org.junit.Test; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Objects; +import java.util.Set; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.reset; +import static org.easymock.EasyMock.verify; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; + +/** + * Tests {@link ResolvingLocaleUrlDefinitionDAO}. + */ +public class ResolvingLocaleUrlDefinitionDAOTest { + + /** + * The number of attribute names. + */ + private static final int ATTRIBUTE_NAMES_COUNT = 6; + + /** + * The object to test. + */ + private ResolvingLocaleUrlDefinitionDAO definitionDao; + + private ApplicationContext applicationContext; + + private ApplicationResource url1; + private ApplicationResource url2; + private ApplicationResource url3; + private ApplicationResource urlWildcard; + private ApplicationResource url21; + private ApplicationResource url513; + + private ApplicationResource setupUrl(String filename, Locale... locales) { + ApplicationResource url = new URLApplicationResource( + "org/apache/tiles/core/config/" + filename + ".xml", + Objects.requireNonNull(this.getClass().getClassLoader().getResource("org/apache/tiles/core/config/" + filename + ".xml")) + ); + assertNotNull("Could not load " + filename + " file.", url); + expect(applicationContext.getResource(url.getLocalePath())).andReturn(url).anyTimes(); + expect(applicationContext.getResource(url, Locale.ROOT)).andReturn(url).anyTimes(); + Map localeResources = new HashMap<>(); + for (Locale locale : locales) { + ApplicationResource urlLocale = new URLApplicationResource( + "org/apache/tiles/core/config/" + filename + "_" + locale + ".xml", + Objects.requireNonNull(this.getClass().getClassLoader().getResource("org/apache/tiles/core/config/" + filename + "_" + locale.toString() + ".xml")) + ); + assertNotNull("Could not load " + filename + "_" + locale + " file.", urlLocale); + localeResources.put(locale, urlLocale); + } + Locale[] supportedLocales = { + Locale.CANADA_FRENCH, + Locale.FRENCH, + Locale.US, + Locale.ENGLISH, + Locale.CHINA, + Locale.CHINESE, + Locale.ITALY, + Locale.ITALIAN, + new Locale("es"), + new Locale("es", "CO"), + new Locale("en", "CA") + }; + for (Locale locale : supportedLocales) { + ApplicationResource urlLocale = localeResources.get(locale); + expect(applicationContext.getResource(url, locale)).andReturn(urlLocale).anyTimes(); + } + return url; + } + + @Before + public void setUp() throws IOException { + // Set up multiple data sources. + applicationContext = createMock(ApplicationContext.class); + url1 = setupUrl("defs1", Locale.FRENCH, Locale.CANADA_FRENCH, Locale.US); + url2 = setupUrl("defs2"); + url3 = setupUrl("defs3"); + urlWildcard = setupUrl("defs-wildcard"); + url21 = setupUrl("tiles-defs-2.1", Locale.ITALIAN); + url513 = setupUrl("defs-tiles-513"); + replay(applicationContext); + + definitionDao = new ResolvingLocaleUrlDefinitionDAO(applicationContext); + WildcardDefinitionPatternMatcherFactory definitionPatternMatcherFactory = new WildcardDefinitionPatternMatcherFactory(); + PatternDefinitionResolver definitionResolver = new BasicPatternDefinitionResolver<>( + definitionPatternMatcherFactory, definitionPatternMatcherFactory); + definitionDao.setPatternDefinitionResolver(definitionResolver); + } + + @Test + public void testGetDefinition() { + List sourceURLs = new ArrayList<>(); + sourceURLs.add(url1); + sourceURLs.add(url2); + sourceURLs.add(url3); + definitionDao.setSources(sourceURLs); + DefinitionsReader reader = new DigesterDefinitionsReader(); + definitionDao.setReader(reader); + + assertNotNull("test.def1 definition not found.", definitionDao.getDefinition("test.def1", null)); + assertNotNull("test.def2 definition not found.", definitionDao.getDefinition("test.def2", null)); + assertNotNull("test.def3 definition not found.", definitionDao.getDefinition("test.def3", null)); + assertNotNull("test.common definition not found.", definitionDao.getDefinition("test.common", null)); + assertNotNull("test.common definition in US locale not found.", + definitionDao.getDefinition("test.common", Locale.US)); + assertNotNull("test.common definition in FRENCH locale not found.", + definitionDao.getDefinition("test.common", Locale.FRENCH)); + assertNotNull("test.common definition in CHINA locale not found.", + definitionDao.getDefinition("test.common", Locale.CHINA)); + assertNotNull("test.common.french definition in FRENCH locale not found.", + definitionDao.getDefinition("test.common.french", Locale.FRENCH)); + assertNotNull("test.common.french definition in CANADA_FRENCH locale not found.", + definitionDao.getDefinition("test.common.french", Locale.CANADA_FRENCH)); + assertNotNull("test.def.toextend definition not found.", definitionDao.getDefinition("test.def.toextend", null)); + assertNotNull("test.def.overridden definition not found.", + definitionDao.getDefinition("test.def.overridden", null)); + assertNotNull("test.def.overridden definition in FRENCH locale not found.", + definitionDao.getDefinition("test.def.overridden", Locale.FRENCH)); + + assertEquals("Incorrect default country value", "default", definitionDao.getDefinition("test.def1", null) + .getAttribute("country").getValue()); + assertEquals("Incorrect US country value", "US", definitionDao.getDefinition("test.def1", Locale.US) + .getAttribute("country").getValue()); + assertEquals("Incorrect France country value", "France", definitionDao + .getDefinition("test.def1", Locale.FRENCH).getAttribute("country").getValue()); + assertEquals("Incorrect Chinese country value (should be default)", "default", + definitionDao.getDefinition("test.def1", Locale.CHINA).getAttribute("country").getValue()); + assertEquals("Incorrect default country value", "default", + definitionDao.getDefinition("test.def.overridden", null).getAttribute("country").getValue()); + assertEquals("Incorrect default title value", "Definition to be overridden", + definitionDao.getDefinition("test.def.overridden", null).getAttribute("title").getValue()); + assertEquals("Incorrect France country value", "France", + definitionDao.getDefinition("test.def.overridden", Locale.FRENCH).getAttribute("country").getValue()); + assertEquals("Incorrect France title value", "Definition to be extended", + definitionDao.getDefinition("test.def.overridden", Locale.FRENCH).getAttribute("title").getValue()); + } + + @Test + public void testGetDefinitions() { + List sourceURLs = new ArrayList<>(); + sourceURLs.add(url1); + sourceURLs.add(url2); + sourceURLs.add(url3); + definitionDao.setSources(sourceURLs); + DefinitionsReader reader = new DigesterDefinitionsReader(); + definitionDao.setReader(reader); + + Map defaultDefinitions = definitionDao.getDefinitions(null); + Map usDefinitions = definitionDao.getDefinitions(Locale.US); + Map frenchDefinitions = definitionDao.getDefinitions(Locale.FRENCH); + Map chinaDefinitions = definitionDao.getDefinitions(Locale.CHINA); + Map canadaFrendDefinitions = definitionDao.getDefinitions(Locale.CANADA_FRENCH); + + assertNotNull("test.def1 definition not found.", defaultDefinitions.get("test.def1")); + assertNotNull("test.def2 definition not found.", defaultDefinitions.get("test.def2")); + assertNotNull("test.def3 definition not found.", defaultDefinitions.get("test.def3")); + assertNotNull("test.common definition not found.", defaultDefinitions.get("test.common")); + assertNotNull("test.common definition in US locale not found.", usDefinitions.get("test.common")); + assertNotNull("test.common definition in FRENCH locale not found.", frenchDefinitions.get("test.common")); + assertNotNull("test.common definition in CHINA locale not found.", chinaDefinitions.get("test.common")); + assertNotNull("test.common.french definition in FRENCH locale not found.", + canadaFrendDefinitions.get("test.common.french")); + assertNotNull("test.common.french definition in CANADA_FRENCH locale not found.", + canadaFrendDefinitions.get("test.common.french")); + assertNotNull("test.def.toextend definition not found.", defaultDefinitions.get("test.def.toextend")); + assertNotNull("test.def.overridden definition not found.", defaultDefinitions.get("test.def.overridden")); + assertNotNull("test.def.overridden definition in FRENCH locale not found.", + frenchDefinitions.get("test.def.overridden")); + + assertEquals("Incorrect default country value", "default", + defaultDefinitions.get("test.def1").getAttribute("country").getValue()); + assertEquals("Incorrect US country value", "US", usDefinitions.get("test.def1").getAttribute("country") + .getValue()); + assertEquals("Incorrect France country value", "France", + frenchDefinitions.get("test.def1").getAttribute("country").getValue()); + assertEquals("Incorrect Chinese country value (should be default)", "default", chinaDefinitions + .get("test.def1").getAttribute("country").getValue()); + assertEquals("Incorrect default country value", "default", defaultDefinitions.get("test.def.overridden") + .getAttribute("country").getValue()); + assertEquals("Incorrect default title value", "Definition to be overridden", + defaultDefinitions.get("test.def.overridden").getAttribute("title").getValue()); + assertEquals("Incorrect France country value", "France", frenchDefinitions.get("test.def.overridden") + .getAttribute("country").getValue()); + assertEquals("Incorrect France title value", "Definition to be extended", + frenchDefinitions.get("test.def.overridden").getAttribute("title").getValue()); + } + + @Test + public void testSetSourceURLs() { + List sourceURLs = new ArrayList<>(); + sourceURLs.add(url1); + sourceURLs.add(url2); + sourceURLs.add(url3); + definitionDao.setSources(sourceURLs); + assertEquals("The source URLs are not set correctly", sourceURLs, definitionDao.sources); + } + + @Test + public void testSetReader() { + DefinitionsReader reader = createMock(DefinitionsReader.class); + definitionDao.setReader(reader); + assertEquals("There reader has not been set correctly", reader, definitionDao.reader); + } + + /** + * Tests {@link ResolvingLocaleUrlDefinitionDAO#resolveInheritance(Definition, Map, Locale, Set)}. + */ + @Test(expected = NoSuchDefinitionException.class) + public void testResolveInheritanceNoParent() { + Definition definition = new Definition("mydef", null, null); + definition.setExtends("otherDef"); + definitionDao.resolveInheritance(definition, new HashMap<>(), Locale.ITALY, + new HashSet<>()); + } + + /** + * Tests execution. + */ + @Test + public void testInit() { + ApplicationContext applicationContext = createMock(ApplicationContext.class); + Set urlSet = new HashSet<>(); + urlSet.add(url1); + expect(applicationContext.getResources("/WEB-INF/tiles.xml")).andReturn(urlSet); + replay(applicationContext); + DefinitionsReader reader = new DigesterDefinitionsReader(); + definitionDao.setReader(reader); + List sourceURLs = new ArrayList<>(); + sourceURLs.add(url1); + definitionDao.setSources(sourceURLs); + assertEquals("The reader is not of the correct class", DigesterDefinitionsReader.class, + definitionDao.reader.getClass()); + assertEquals("The source URLs are not correct", sourceURLs, definitionDao.sources); + reset(applicationContext); + + applicationContext = createMock(ApplicationContext.class); + replay(applicationContext); + definitionDao.setReader(new MockDefinitionsReader()); + assertEquals("The reader is not of the correct class", MockDefinitionsReader.class, + definitionDao.reader.getClass()); + sourceURLs = new ArrayList<>(); + sourceURLs.add(url1); + sourceURLs.add(url2); + sourceURLs.add(url3); + definitionDao.setSources(sourceURLs); + assertEquals("The source URLs are not correct", sourceURLs, definitionDao.sources); + verify(applicationContext); + } + + /** + * Tests wildcard mappings. + */ + @Test + public void testWildcardMapping() { + List urls = new ArrayList<>(); + urls.add(urlWildcard); + definitionDao.setSources(urls); + definitionDao.setReader(new DigesterDefinitionsReader()); + + Definition definition = definitionDao.getDefinition("test.defName.subLayered", Locale.ITALY); + assertEquals("The template is not correct", "/testName.jsp", definition.getTemplateAttribute().getValue()); + assertEquals("The header attribute is not correct", "/common/headerLayered.jsp", + definition.getAttribute("header").getValue()); + definition = definitionDao.getDefinition("test.defName.subLayered", Locale.ITALIAN); + assertEquals("The template is not correct", "/testName.jsp", definition.getTemplateAttribute().getValue()); + assertEquals("The header attribute is not correct", "/common/headerLayered.jsp", + definition.getAttribute("header").getValue()); + definition = definitionDao.getDefinition("test.defName.subLayered", null); + assertEquals("The template is not correct", "/testName.jsp", definition.getTemplateAttribute().getValue()); + assertEquals("The header attribute is not correct", "/common/headerLayered.jsp", + definition.getAttribute("header").getValue()); + definition = definitionDao.getDefinition("test.defName.noAttribute", null); + assertEquals("/testName.jsp", definition.getTemplateAttribute().getValue()); + assertNull(definition.getLocalAttributeNames()); + definition = definitionDao.getDefinition("test.def3", null); + assertNotNull("The simple definition is null", definition); + + definition = definitionDao.getDefinition("test.extended.defName.subLayered", null); + assertEquals("test.defName.subLayered", definition.getExtends()); + assertEquals(ATTRIBUTE_NAMES_COUNT, definition.getLocalAttributeNames().size()); + assertEquals("The template is not correct", "/testName.jsp", definition.getTemplateAttribute().getValue()); + assertEquals("Overridden Title", definition.getAttribute("title").getValue()); + assertEquals("The header attribute is not correct", "/common/headerLayered.jsp", + definition.getAttribute("header").getValue()); + } + + /** + * Tests + * {@link ResolvingLocaleUrlDefinitionDAO#getDefinition(String, Locale)} + * when loading multiple files for a locale. + */ + @Test + public void testListAttributeLocaleInheritance() { + List urls = new ArrayList<>(); + urls.add(url21); + definitionDao.setSources(urls); + ApplicationContext applicationContext = createMock(ApplicationContext.class); + definitionDao.setReader(new DigesterDefinitionsReader()); + replay(applicationContext); + + Definition definition = definitionDao.getDefinition("test.inherit.list", Locale.ITALIAN); + ListAttribute listAttribute = (ListAttribute) definition.getAttribute("list"); + List attributes = listAttribute.getValue(); + assertEquals(2, attributes.size()); + verify(applicationContext); + } + + @Test + public void testTiles512() { + List urls = new ArrayList<>(); + urls.add(url21); + definitionDao.setSources(urls); + ApplicationContext applicationContext = createMock(ApplicationContext.class); + definitionDao.setReader(new DigesterDefinitionsReader()); + replay(applicationContext); + + Definition definition = definitionDao.getDefinition("test.inherit.othertype", Locale.ITALIAN); + assertEquals("/layout.ftl", definition.getTemplateAttribute().getValue()); + assertEquals("freemarker", definition.getTemplateAttribute().getRenderer()); + } + + @Test + public void testTiles513() { + List urls = new ArrayList<>(); + urls.add(url513); + definitionDao.setSources(urls); + ApplicationContext applicationContext = createMock(ApplicationContext.class); + definitionDao.setReader(new DigesterDefinitionsReader()); + replay(applicationContext); + + Definition definition = definitionDao.getDefinition("test.anonymous", null); + definitionDao.getDefinition("test.anonymous", new Locale("es", "CO")); + definitionDao.getDefinition("test.anonymous", new Locale("en", "CA")); + Attribute attribute = definition.getAttribute("header"); + Definition child = definitionDao.getDefinition((String) attribute.getValue(), null); + assertNotNull(child); + attribute = definition.getAttribute("menu"); + child = definitionDao.getDefinition((String) attribute.getValue(), null); + assertNotNull(child); + attribute = definition.getAttribute("footer"); + child = definitionDao.getDefinition((String) attribute.getValue(), null); + assertNotNull(child); + } +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/core/definition/digester/DigesterDefinitionsReaderExceptionTest.java b/plugins/tiles/src/test/java/org/apache/tiles/core/definition/digester/DigesterDefinitionsReaderExceptionTest.java new file mode 100644 index 000000000..55403cbbb --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/core/definition/digester/DigesterDefinitionsReaderExceptionTest.java @@ -0,0 +1,41 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.core.definition.digester; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; + +/** + * Tests {@link DigesterDefinitionsReaderException}. + */ +public class DigesterDefinitionsReaderExceptionTest { + + /** + * Test method for {@link DigesterDefinitionsReaderException#DigesterDefinitionsReaderException(String)}. + */ + @Test + public void testDigesterDefinitionsReaderExceptionString() { + DigesterDefinitionsReaderException exception = new DigesterDefinitionsReaderException("my message"); + assertEquals("my message", exception.getMessage()); + assertNull(exception.getCause()); + } + +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/core/definition/digester/TestDigesterDefinitionsReader.java b/plugins/tiles/src/test/java/org/apache/tiles/core/definition/digester/TestDigesterDefinitionsReader.java new file mode 100644 index 000000000..f8a5ee0a3 --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/core/definition/digester/TestDigesterDefinitionsReader.java @@ -0,0 +1,279 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tiles.core.definition.digester; + +import org.apache.tiles.api.Attribute; +import org.apache.tiles.api.Definition; +import org.apache.tiles.api.ListAttribute; +import org.apache.tiles.core.definition.DefinitionsFactoryException; +import org.junit.Before; +import org.junit.Test; + +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; +import java.util.List; +import java.util.Map; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +/** + * Tests the org.apache.tiles.definition.digester.DigesterDefinitionsReader class. + */ +public class TestDigesterDefinitionsReader { + + private DigesterDefinitionsReader reader; + + @Before + public void setUp() { + reader = new DigesterDefinitionsReader(); + } + + /** + * Tests the read method under normal conditions. + * + * @throws IOException If something goes wrong. + */ + @Test + public void testRead() throws IOException { + URL configFile = this.getClass().getClassLoader().getResource("org/apache/tiles/core/config/tiles-defs.xml"); + assertNotNull("Config file not found", configFile); + + InputStream source = configFile.openStream(); + Map definitions = reader.read(source); + + assertNotNull("Definitions not returned.", definitions); + assertNotNull("Couldn't find doc.mainLayout tile.", definitions.get("doc.mainLayout")); + assertNotNull("Couldn't Find title attribute.", definitions.get("doc.mainLayout").getAttribute("title").getValue()); + assertEquals("Incorrect Find title attribute.", "Tiles Library Documentation", definitions.get("doc.mainLayout").getAttribute("title").getValue()); + + Definition def = definitions.get("doc.role.test"); + assertNotNull("Couldn't find doc.role.test tile.", def); + Attribute attribute = def.getAttribute("title"); + assertNotNull("Couldn't Find title attribute.", attribute.getValue()); + assertEquals("Role 'myrole' expected", attribute.getRole(), "myrole"); + + def = definitions.get("doc.listattribute.test"); + assertNotNull("Couldn't find doc.listattribute.test tile.", def); + attribute = def.getAttribute("items"); + assertNotNull("Couldn't Find items attribute.", attribute); + assertTrue("The class of the attribute is not right", attribute instanceof ListAttribute); + assertTrue("The class of value of the attribute is not right", attribute.getValue() instanceof List); + } + + + /** + * Tests the read method under normal conditions for the new features in 2.1 + * version of the DTD. + * + * @throws IOException If something goes wrong. + */ + @Test + public void testRead21Version() throws IOException { + URL configFile = this.getClass().getClassLoader().getResource("org/apache/tiles/core/config/tiles-defs-2.1.xml"); + assertNotNull("Config file not found", configFile); + + InputStream source = configFile.openStream(); + Map definitions = reader.read(source); + + assertNotNull("Definitions not returned.", definitions); + Definition def = definitions.get("doc.cascaded.test"); + + assertNotNull("Couldn't find doc.role.test tile.", def); + Attribute attribute = def.getLocalAttribute("title"); + assertNotNull("Couldn't Find title local attribute.", attribute); + attribute = def.getCascadedAttribute("title2"); + assertNotNull("Couldn't Find title2 cascaded attribute.", attribute); + attribute = def.getLocalAttribute("items1"); + assertNotNull("Couldn't Find items1 local attribute.", attribute); + attribute = def.getCascadedAttribute("items2"); + assertNotNull("Couldn't Find items2 cascaded attribute.", attribute); + + def = definitions.get("test.nesting.definitions"); + assertNotNull("Couldn't find test.nesting.definitions tile.", def); + assertEquals("/layout.jsp", def.getTemplateAttribute().getValue()); + assertEquals("template", def.getTemplateAttribute().getRenderer()); + attribute = def.getAttribute("body"); + assertNotNull("Couldn't Find body attribute.", attribute); + assertEquals("Attribute not of 'definition' type", "definition", attribute.getRenderer()); + assertNotNull("Attribute value null", attribute.getValue()); + String defName = attribute.getValue().toString(); + def = definitions.get(defName); + assertNotNull("Couldn't find " + defName + " tile.", def); + + def = definitions.get("test.nesting.list.definitions"); + assertNotNull("Couldn't find test.nesting.list.definitions tile.", def); + attribute = def.getAttribute("list"); + assertNotNull("Couldn't Find list attribute.", attribute); + assertTrue("Attribute not of valid type", attribute instanceof ListAttribute); + ListAttribute listAttribute = (ListAttribute) attribute; + List list = listAttribute.getValue(); + assertEquals("The list is not of correct size", 1, list.size()); + attribute = list.get(0); + assertNotNull("Couldn't Find element attribute.", attribute); + assertEquals("Attribute not of 'definition' type", "definition", attribute.getRenderer()); + assertNotNull("Attribute value null", attribute.getValue()); + defName = attribute.getValue().toString(); + def = definitions.get(defName); + assertNotNull("Couldn't find " + defName + " tile.", def); + + defName = "test.inherit.list.base"; + def = definitions.get(defName); + assertNotNull("Couldn't find " + defName + " tile.", def); + defName = "test.inherit.list"; + def = definitions.get(defName); + assertNotNull("Couldn't find " + defName + " tile.", def); + listAttribute = (ListAttribute) def.getAttribute("list"); + assertTrue("This definition does not inherit its list attribute", listAttribute.isInherit()); + defName = "test.noinherit.list"; + def = definitions.get(defName); + listAttribute = (ListAttribute) def.getAttribute("list"); + assertFalse("This definition inherits its list attribute", listAttribute.isInherit()); + + defName = "test.new.attributes"; + def = definitions.get(defName); + assertNotNull("Couldn't find " + defName + " tile.", def); + Attribute templateAttribute = def.getTemplateAttribute(); + assertEquals(templateAttribute.getExpressionObject().getExpression(), "${my.expression}"); + assertEquals("mytype", templateAttribute.getRenderer()); + attribute = def.getAttribute("body"); + assertNotNull("Couldn't Find body attribute.", attribute); + assertEquals("${my.attribute.expression}", attribute.getExpressionObject().getExpression()); + } + + /** + * Tests read with bad input source. + */ + @Test + public void testBadSource() { + try { + reader.read("Bad Input"); + fail("Should've thrown an exception."); + } catch (DefinitionsFactoryException e) { + assertTrue(true); + } catch (Exception e) { + fail("Exception reading configuration." + e); + } + } + + /** + * Tests read with bad XML source. + */ + @Test + public void testBadXml() { + try { + URL configFile = this.getClass().getClassLoader().getResource( + "org/apache/tiles/config/malformed-defs.xml"); + assertNotNull("Config file not found", configFile); + + InputStream source = configFile.openStream(); + reader.read(source); + fail("Should've thrown an exception."); + } catch (DefinitionsFactoryException e) { + assertTrue(true); + } catch (Exception e) { + fail("Exception reading configuration." + e); + } + } + + /** + * Tests the validating input parameter. + *

+ * This test case enables Digester's validating property then passes in a + * configuration file with invalid XML. + */ + @Test + public void testValidatingParameter() { + // Testing with default (validation ON). + try { + URL configFile = this.getClass().getClassLoader().getResource( + "org/apache/tiles/config/invalid-defs.xml"); + assertNotNull("Config file not found", configFile); + + InputStream source = configFile.openStream(); + reader.setValidating(true); + reader.read(source); + fail("Should've thrown an exception."); + } catch (DefinitionsFactoryException e) { + assertTrue(true); + } catch (Exception e) { + fail("Exception reading configuration." + e); + } + + // Testing with validation OFF. + try { + setUp(); + URL configFile = this.getClass().getClassLoader().getResource( + "org/apache/tiles/config/invalid-defs.xml"); + assertNotNull("Config file not found", configFile); + + InputStream source = configFile.openStream(); + reader.read(source); + } catch (DefinitionsFactoryException e) { + fail("Should not have thrown an exception." + e); + } catch (Exception e) { + fail("Exception reading configuration." + e); + } + } + + /** + * Regression test for bug TILES-352. + * + * @throws IOException If something goes wrong. + */ + @Test + public void testRegressionTiles352() throws IOException { + URL configFile = this.getClass().getClassLoader().getResource( + "org/apache/tiles/config/defs_regression_TILES-352.xml"); + assertNotNull("Config file not found", configFile); + + InputStream source = configFile.openStream(); + Map name2defs = reader.read(source); + source.close(); + Definition root = name2defs.get("root"); + Attribute attribute = root.getAttribute("body"); + Definition child = name2defs.get(attribute.getValue()); + ListAttribute listAttribute = (ListAttribute) child.getAttribute("list"); + List list = listAttribute.getValue(); + assertEquals((list.get(0)).getValue(), "This is a value"); + } + + /** + * Tests {@link DigesterDefinitionsReader#read(Object)}. + */ + @Test + public void testReadNoSource() { + assertNull(reader.read(null)); + } + + /** + * Tests {@link DigesterDefinitionsReader#addDefinition(Definition)}. + */ + @Test(expected = DigesterDefinitionsReaderException.class) + public void testAddDefinitionNoName() { + Definition def = new Definition(); + reader.addDefinition(def); + } +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/core/definition/pattern/AbstractPatternDefinitionResolverTest.java b/plugins/tiles/src/test/java/org/apache/tiles/core/definition/pattern/AbstractPatternDefinitionResolverTest.java new file mode 100644 index 000000000..db9c00f6e --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/core/definition/pattern/AbstractPatternDefinitionResolverTest.java @@ -0,0 +1,119 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tiles.core.definition.pattern; + +import org.apache.tiles.api.Definition; +import org.junit.Test; + +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; + +/** + * Tests {@link AbstractPatternDefinitionResolver}. + */ +public class AbstractPatternDefinitionResolverTest { + + private DefinitionPatternMatcher firstMatcher; + private DefinitionPatternMatcher thirdMatcher; + + private final PatternDefinitionResolver resolver = new AbstractPatternDefinitionResolver() { + @Override + protected Map addDefinitionsAsPatternMatchers(List matchers, Map defsMap) { + if (defsMap.containsKey("first")) { + matchers.add(firstMatcher); + } + if (defsMap.containsKey("third")) { + matchers.add(thirdMatcher); + } + Map retValue = new HashMap<>(defsMap); + retValue.remove("first"); + retValue.remove("third"); + return retValue; + } + }; + + /** + * Test method for + * {@link BasicPatternDefinitionResolver#resolveDefinition(String, Object)}. + */ + @Test + public void testResolveDefinition() { + testResolveDefinitionImpl(); + } + + /** + * Test method for + * {@link BasicPatternDefinitionResolver#clearPatternPaths(Object)}. + */ + @Test + public void testClearPatternPaths() { + testResolveDefinitionImpl(); + resolver.clearPatternPaths(1); + resolver.clearPatternPaths(2); + testResolveDefinitionImpl(); + } + + private void testResolveDefinitionImpl() { + + firstMatcher = createMock(DefinitionPatternMatcher.class); + thirdMatcher = createMock(DefinitionPatternMatcher.class); + + Definition firstDefinition = new Definition("first", null, null); + Definition secondDefinition = new Definition("second", null, null); + Definition thirdDefinition = new Definition("third", null, null); + + Definition firstTransformedDefinition = new Definition("firstTransformed", null, null); + Definition thirdTransformedDefinition = new Definition("thirdTransformed", null, null); + + expect(firstMatcher.createDefinition("firstTransformed")).andReturn(firstTransformedDefinition); + expect(firstMatcher.createDefinition("secondTransformed")).andReturn(null); + expect(firstMatcher.createDefinition("thirdTransformed")).andReturn(null); + expect(thirdMatcher.createDefinition("thirdTransformed")).andReturn(thirdTransformedDefinition).times(2); + expect(thirdMatcher.createDefinition("firstTransformed")).andReturn(null); + expect(thirdMatcher.createDefinition("secondTransformed")).andReturn(null).times(2); + + replay(firstMatcher, thirdMatcher); + + Map localeDefsMap = new LinkedHashMap<>(); + localeDefsMap.put("first", firstDefinition); + localeDefsMap.put("second", secondDefinition); + localeDefsMap.put("third", thirdDefinition); + resolver.storeDefinitionPatterns(localeDefsMap, 1); + localeDefsMap = new LinkedHashMap<>(); + localeDefsMap.put("third", thirdDefinition); + resolver.storeDefinitionPatterns(localeDefsMap, 2); + assertEquals(firstTransformedDefinition, resolver.resolveDefinition("firstTransformed", 1)); + assertNull(resolver.resolveDefinition("secondTransformed", 1)); + assertEquals(thirdTransformedDefinition, resolver.resolveDefinition("thirdTransformed", 1)); + assertNull(resolver.resolveDefinition("firstTransformed", 2)); + assertNull(resolver.resolveDefinition("secondTransformed", 2)); + assertEquals(thirdTransformedDefinition, resolver.resolveDefinition("thirdTransformed", 2)); + verify(firstMatcher, thirdMatcher); + } +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/core/definition/pattern/BasicPatternDefinitionResolverTest.java b/plugins/tiles/src/test/java/org/apache/tiles/core/definition/pattern/BasicPatternDefinitionResolverTest.java new file mode 100644 index 000000000..7cd651b98 --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/core/definition/pattern/BasicPatternDefinitionResolverTest.java @@ -0,0 +1,78 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tiles.core.definition.pattern; + +import org.apache.tiles.api.Definition; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import static org.junit.Assert.assertEquals; + +/** + * Tests {@link BasicPatternDefinitionResolver}. + */ +public class BasicPatternDefinitionResolverTest { + + /** + * Test method for + * {@link BasicPatternDefinitionResolver#addDefinitionsAsPatternMatchers(List, Map)}. + */ + @Test + public void testAddDefinitionsAsPatternMatchers() { + DefinitionPatternMatcherFactory factory = createMock(DefinitionPatternMatcherFactory.class); + PatternRecognizer recognizer = createMock(PatternRecognizer.class); + DefinitionPatternMatcher firstMatcher = createMock(DefinitionPatternMatcher.class); + DefinitionPatternMatcher thirdMatcher = createMock(DefinitionPatternMatcher.class); + + expect(recognizer.isPatternRecognized("first")).andReturn(true); + expect(recognizer.isPatternRecognized("second")).andReturn(false); + expect(recognizer.isPatternRecognized("third")).andReturn(true); + + Definition firstDefinition = new Definition("first", null, null); + Definition secondDefinition = new Definition("second", null, null); + Definition thirdDefinition = new Definition("third", null, null); + + expect(factory.createDefinitionPatternMatcher("first", firstDefinition)) + .andReturn(firstMatcher); + expect(factory.createDefinitionPatternMatcher("third", thirdDefinition)) + .andReturn(thirdMatcher); + + replay(factory, recognizer, firstMatcher, thirdMatcher); + BasicPatternDefinitionResolver resolver = new BasicPatternDefinitionResolver<>(factory, recognizer); + Map localeDefsMap = new LinkedHashMap<>(); + localeDefsMap.put("first", firstDefinition); + localeDefsMap.put("second", secondDefinition); + localeDefsMap.put("third", thirdDefinition); + List matchers = new ArrayList<>(); + resolver.addDefinitionsAsPatternMatchers(matchers, localeDefsMap); + assertEquals(2, matchers.size()); + assertEquals(firstMatcher, matchers.get(0)); + assertEquals(thirdMatcher, matchers.get(1)); + verify(factory, recognizer, firstMatcher, thirdMatcher); + } +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/core/definition/pattern/PatternUtilTest.java b/plugins/tiles/src/test/java/org/apache/tiles/core/definition/pattern/PatternUtilTest.java new file mode 100644 index 000000000..8dea7b4af --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/core/definition/pattern/PatternUtilTest.java @@ -0,0 +1,316 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.core.definition.pattern; + +import org.apache.tiles.api.Attribute; +import org.apache.tiles.api.Definition; +import org.apache.tiles.api.Expression; +import org.apache.tiles.api.ListAttribute; +import org.junit.Test; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + +public class PatternUtilTest { + + /** + * The size of the list in the main list attribute. + */ + private static final int LIST_ATTRIBUTE_SIZE = 3; + + /** + * Test method for + * {@link PatternUtil#replacePlaceholders(Definition, String, Object[])}. + */ + @Test + public void testReplacePlaceholders() { + Map attributes = new HashMap<>(); + attributes.put("attrib1", new Attribute("value{2}")); + attributes.put("attrib2", new Attribute("value{2}{3}")); + attributes.put("attrib3", new Attribute(null, Expression + .createExpression("expr{1}", "EL"), null, null)); + Definition definition = new Definition("definitionName", new Attribute( + "template{1}"), attributes); + definition.setExtends("{2}ext"); + definition.setPreparer("{3}prep"); + Definition nudef = PatternUtil.replacePlaceholders(definition, "nudef", + "value0", "value1", "value2", "value3"); + assertEquals("nudef", nudef.getName()); + assertEquals("value2ext", nudef.getExtends()); + assertEquals("value3prep", nudef.getPreparer()); + Attribute attribute = nudef.getTemplateAttribute(); + assertEquals("templatevalue1", attribute.getValue()); + attribute = nudef.getAttribute("attrib1"); + assertEquals("valuevalue2", attribute.getValue()); + attribute = nudef.getAttribute("attrib2"); + assertEquals("valuevalue2value3", attribute.getValue()); + attribute = nudef.getAttribute("attrib3"); + assertEquals("exprvalue1", attribute.getExpressionObject().getExpression()); + } + + /** + * Test method for + * {@link PatternUtil#replacePlaceholders(Definition, String, Object[])}. + */ + @Test + public void testReplacePlaceholdersNullTemplate() { + Map attributes = new HashMap<>(); + attributes.put("attrib1", new Attribute("value{2}")); + attributes.put("attrib2", new Attribute("value{2}{3}")); + Definition definition = new Definition("definitionName", null, attributes); + Definition nudef = PatternUtil.replacePlaceholders(definition, "nudef", + "value0", "value1", "value2", "value3"); + assertEquals("nudef", nudef.getName()); + assertNull(nudef.getTemplateAttribute()); + Attribute attribute = nudef.getAttribute("attrib1"); + assertEquals("valuevalue2", attribute.getValue()); + attribute = nudef.getAttribute("attrib2"); + assertEquals("valuevalue2value3", attribute.getValue()); + } + + /** + * Test method for + * {@link PatternUtil#replacePlaceholders(Definition, String, Object[])}. + */ + @Test + public void testReplacePlaceholdersCascadedAttributes() { + Definition definition = new Definition("definitionName", new Attribute( + "template{1}"), null); + definition.putAttribute("attrib1", new Attribute("value{2}"), true); + definition.putAttribute("attrib2", new Attribute("value{2}{3}"), true); + Definition nudef = PatternUtil.replacePlaceholders(definition, "nudef", + "value0", "value1", "value2", "value3"); + assertEquals("nudef", nudef.getName()); + Attribute attribute = nudef.getTemplateAttribute(); + assertEquals("templatevalue1", attribute.getValue()); + attribute = nudef.getAttribute("attrib1"); + assertEquals("valuevalue2", attribute.getValue()); + attribute = nudef.getAttribute("attrib2"); + assertEquals("valuevalue2value3", attribute.getValue()); + } + + /** + * Test method for + * {@link PatternUtil#replacePlaceholders(Definition, String, Object[])}. + */ + @Test + public void testReplacePlaceholdersListAttribute() { + Map attributes = new HashMap<>(); + ListAttribute listAttribute = new ListAttribute(); + ListAttribute internalListAttribute = new ListAttribute(); + listAttribute.setInherit(true); + attributes.put("myList", listAttribute); + listAttribute.add(new Attribute("value{2}")); + listAttribute.add(new Attribute("value{2}{3}")); + listAttribute.add(internalListAttribute); + internalListAttribute.add(new Attribute("secondvalue{2}")); + internalListAttribute.add(new Attribute("secondvalue{2}{3}")); + Definition definition = new Definition("definitionName", new Attribute( + "template{1}"), attributes); + Definition nudef = PatternUtil.replacePlaceholders(definition, "nudef", + "value0", "value1", "value2", "value3"); + assertEquals("nudef", nudef.getName()); + Attribute attribute = nudef.getTemplateAttribute(); + assertEquals("templatevalue1", attribute.getValue()); + ListAttribute nuListAttribute = (ListAttribute) nudef.getAttribute("myList"); + assertTrue(nuListAttribute.isInherit()); + List list = nuListAttribute.getValue(); + assertEquals(LIST_ATTRIBUTE_SIZE, list.size()); + attribute = list.get(0); + assertEquals("valuevalue2", attribute.getValue()); + attribute = list.get(1); + assertEquals("valuevalue2value3", attribute.getValue()); + ListAttribute evaluatedListAttribute = (ListAttribute) list.get(2); + assertFalse(evaluatedListAttribute.isInherit()); + list = evaluatedListAttribute.getValue(); + assertEquals(2, list.size()); + attribute = list.get(0); + assertEquals("secondvaluevalue2", attribute.getValue()); + attribute = list.get(1); + assertEquals("secondvaluevalue2value3", attribute.getValue()); + } + + + /** + * Tests {@link PatternUtil#createExtractedMap(Map, Set)}. + */ + @Test + public void testCreateExtractedMap() { + Map map = new HashMap<>(); + map.put(0, "value0"); + map.put(1, "value1"); + map.put(2, "value2"); + Set set = new HashSet<>(); + set.add(1); + set.add(2); + Map extractedMap = PatternUtil.createExtractedMap(map, set); + assertEquals(2, extractedMap.size()); + assertEquals("value1", extractedMap.get(1)); + assertEquals("value2", extractedMap.get(2)); + } + + /** + * Test method for + * {@link PatternUtil#replacePlaceholders(Definition, String, Object[])}. + * See TILES-502 + */ + @Test + public void testReplacePlaceholdersEL_0() { + Map attributes = new HashMap<>(); + Attribute attribute = new Attribute("some-{1}-${requestScope.someVariable}.jsp"); + attribute.setExpressionObject(new Expression((String)attribute.getValue())); + attributes.put("something", attribute); + Definition definition = new Definition("definitionName", new Attribute("template"), attributes); + Definition nudef = PatternUtil.replacePlaceholders(definition, "nudef", "value0", "value1", "value2", "value3"); + assertEquals("nudef", nudef.getName()); + + assertEquals( + "some-value1-${requestScope.someVariable}.jsp", + nudef.getAttribute("something").getValue()); + + assertEquals( + "some-value1-${requestScope.someVariable}.jsp", + nudef.getAttribute("something").getExpressionObject().getExpression()); + } + + /** + * Test method for + * {@link PatternUtil#replacePlaceholders(Definition, String, Object[])}. + * See TILES-574 + */ + @Test + public void testReplacePlaceholdersEL_1() { + Map attributes = new HashMap<>(); + Attribute attribute = new Attribute("some-{1}-${requestScope.someVariable}-other-{2}.jsp"); + attribute.setExpressionObject(new Expression((String)attribute.getValue())); + attributes.put("something", attribute); + Definition definition = new Definition("definitionName", new Attribute("template"), attributes); + Definition nudef = PatternUtil.replacePlaceholders(definition, "nudef", "value0", "value1", "value2", "value3"); + assertEquals("nudef", nudef.getName()); + + assertEquals( + "some-value1-${requestScope.someVariable}-other-value2.jsp", + nudef.getAttribute("something").getValue()); + + assertEquals( + "some-value1-${requestScope.someVariable}-other-value2.jsp", + nudef.getAttribute("something").getExpressionObject().getExpression()); + } + + /** + * Test method for + * {@link PatternUtil#replacePlaceholders(Definition, String, Object[])}. + * See TILES-574 + */ + @Test + public void testReplacePlaceholdersEL_2() { + Map attributes = new HashMap<>(); + Attribute attribute = new Attribute("some-${requestScope.someVariable}-other-{1}-${requestScope.someOtherVariable}.jsp"); + attribute.setExpressionObject(new Expression((String)attribute.getValue())); + attributes.put("something", attribute); + Definition definition = new Definition("definitionName", new Attribute("template"), attributes); + Definition nudef = PatternUtil.replacePlaceholders(definition, "nudef", "value0", "value1", "value2", "value3"); + assertEquals("nudef", nudef.getName()); + + assertEquals( + "some-${requestScope.someVariable}-other-value1-${requestScope.someOtherVariable}.jsp", + nudef.getAttribute("something").getValue()); + + assertEquals( + "some-${requestScope.someVariable}-other-value1-${requestScope.someOtherVariable}.jsp", + nudef.getAttribute("something").getExpressionObject().getExpression()); + } + + /** + * Test method for + * {@link PatternUtil#replacePlaceholders(Definition, String, Object[])}. + */ + @Test + public void testReplacePlaceholdersEL_conditional() { + Map attributes = new HashMap<>(); + Attribute attribute = new Attribute("{1}/some-other-{2}-${requestScope.someBoolean ? 'a' : 'b'}.jsp"); + attribute.setExpressionObject(new Expression((String)attribute.getValue())); + attributes.put("something", attribute); + Definition definition = new Definition("definitionName", new Attribute("template"), attributes); + Definition nudef = PatternUtil.replacePlaceholders(definition, "nudef", "value0", "value1", "value2", "value3"); + assertEquals("nudef", nudef.getName()); + + assertEquals( + "value1/some-other-value2-${requestScope.someBoolean ? 'a' : 'b'}.jsp", + nudef.getAttribute("something").getValue()); + + assertEquals( + "value1/some-other-value2-${requestScope.someBoolean ? 'a' : 'b'}.jsp", + nudef.getAttribute("something").getExpressionObject().getExpression()); + } + + /** + * Test method for + * {@link PatternUtil#replacePlaceholders(Definition, String, Object[])}. + */ + @Test + public void testReplacePlaceholdersEL_twice() { + Map attributes = new HashMap<>(); + Attribute attribute = new Attribute("some-${requestScope.firstVariable}-${requestScope.secondVariable}.jsp"); + attribute.setExpressionObject(new Expression((String)attribute.getValue())); + attributes.put("something", attribute); + Definition definition = new Definition("definitionName", new Attribute("template"), attributes); + Definition nudef = PatternUtil.replacePlaceholders(definition, "nudef", "value0", "value1", "value2", "value3"); + assertEquals("nudef", nudef.getName()); + + assertEquals( + "some-${requestScope.firstVariable}-${requestScope.secondVariable}.jsp", + nudef.getAttribute("something").getValue()); + + assertEquals( + "some-${requestScope.firstVariable}-${requestScope.secondVariable}.jsp", + nudef.getAttribute("something").getExpressionObject().getExpression()); + } + + /** + * Test method for + * {@link PatternUtil#replacePlaceholders(Definition, String, Object[])}. + */ + @Test + public void testReplacePlaceholdersEL_options() { + Map attributes = new HashMap<>(); + Attribute attribute = new Attribute("{1}/{options[my_fallback}}/some-other-{2}-${requestScope.someVariable}.jsp"); + attribute.setExpressionObject(new Expression((String)attribute.getValue())); + attributes.put("something", attribute); + Definition definition = new Definition("definitionName", new Attribute("template"), attributes); + Definition nudef = PatternUtil.replacePlaceholders(definition, "nudef", "value0", "value1", "value2", "value3"); + assertEquals("nudef", nudef.getName()); + + assertEquals( + "value1/{options[my_fallback}}/some-other-value2-${requestScope.someVariable}.jsp", + nudef.getAttribute("something").getValue()); + + assertEquals( + "value1/{options[my_fallback}}/some-other-value2-${requestScope.someVariable}.jsp", + nudef.getAttribute("something").getExpressionObject().getExpression()); + } +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/core/definition/pattern/PrefixedPatternDefinitionResolverTest.java b/plugins/tiles/src/test/java/org/apache/tiles/core/definition/pattern/PrefixedPatternDefinitionResolverTest.java new file mode 100644 index 000000000..bdeaca258 --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/core/definition/pattern/PrefixedPatternDefinitionResolverTest.java @@ -0,0 +1,77 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tiles.core.definition.pattern; + +import org.apache.tiles.api.Attribute; +import org.apache.tiles.api.Definition; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import static org.junit.Assert.assertEquals; + +/** + * Tests {@link PrefixedPatternDefinitionResolver}. + */ +public class PrefixedPatternDefinitionResolverTest { + + /** + * Test method for {@link PrefixedPatternDefinitionResolver#addDefinitionsAsPatternMatchers(List, Map)}. + */ + @Test + public void testAddDefinitionsAsPatternMatchers() { + DefinitionPatternMatcherFactory factory1 = createMock(DefinitionPatternMatcherFactory.class); + DefinitionPatternMatcherFactory factory2 = createMock(DefinitionPatternMatcherFactory.class); + DefinitionPatternMatcher matcher1 = createMock(DefinitionPatternMatcher.class); + DefinitionPatternMatcher matcher2 = createMock(DefinitionPatternMatcher.class); + Definition definition1 = new Definition("DF1:definition1", null, null); + Definition definition2 = new Definition("DF2:definition2", null, null); + Definition definition3 = new Definition("noLanguageHere", null, null); + + expect(factory1.createDefinitionPatternMatcher("definition1", definition1)).andReturn(matcher1); + expect(factory2.createDefinitionPatternMatcher("definition2", definition2)).andReturn(matcher2); + + replay(factory1, factory2, matcher1, matcher2); + + PrefixedPatternDefinitionResolver resolver = new PrefixedPatternDefinitionResolver<>(); + resolver.registerDefinitionPatternMatcherFactory("DF1", factory1); + resolver.registerDefinitionPatternMatcherFactory("DF2", factory2); + List matchers = new ArrayList<>(); + Map definitions = new LinkedHashMap<>(); + definitions.put("DF1:definition1", definition1); + definitions.put("DF2:definition2", definition2); + definitions.put("noLanguageHere", definition3); + + resolver.addDefinitionsAsPatternMatchers(matchers, definitions); + + assertEquals(2, matchers.size()); + assertEquals(matcher1, matchers.get(0)); + assertEquals(matcher2, matchers.get(1)); + + verify(factory1, factory2, matcher1, matcher2); + } +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/core/definition/pattern/regexp/RegexpDefinitionPatternMatcherFactoryTest.java b/plugins/tiles/src/test/java/org/apache/tiles/core/definition/pattern/regexp/RegexpDefinitionPatternMatcherFactoryTest.java new file mode 100644 index 000000000..35e9826cb --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/core/definition/pattern/regexp/RegexpDefinitionPatternMatcherFactoryTest.java @@ -0,0 +1,49 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.core.definition.pattern.regexp; + +import org.apache.tiles.api.Definition; +import org.junit.Before; +import org.junit.Test; + +import static org.junit.Assert.assertTrue; + +/** + * Tests {@link RegexpDefinitionPatternMatcherFactory}. + */ +public class RegexpDefinitionPatternMatcherFactoryTest { + + /** + * The object to test. + */ + private RegexpDefinitionPatternMatcherFactory factory; + + /** + * Sets up the object to test. + */ + @Before + public void setUp() { + factory = new RegexpDefinitionPatternMatcherFactory(); + } + + @Test + public void testCreateDefinitionPatternMatcher() { + assertTrue(factory.createDefinitionPatternMatcher("myPattern", new Definition()) instanceof RegexpDefinitionPatternMatcher); + } +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/core/definition/pattern/regexp/RegexpDefinitionPatternMatcherTest.java b/plugins/tiles/src/test/java/org/apache/tiles/core/definition/pattern/regexp/RegexpDefinitionPatternMatcherTest.java new file mode 100644 index 000000000..291918fc2 --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/core/definition/pattern/regexp/RegexpDefinitionPatternMatcherTest.java @@ -0,0 +1,47 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.core.definition.pattern.regexp; + +import org.apache.tiles.api.Attribute; +import org.apache.tiles.api.Definition; +import org.apache.tiles.core.definition.pattern.DefinitionPatternMatcher; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +/** + * Tests {@link RegexpDefinitionPatternMatcher}. + */ +public class RegexpDefinitionPatternMatcherTest { + + @Test + public void testResolveDefinition() { + Definition def = new Definition(); + def.setName("testDef(.*)\\.message(.*)"); + def.setTemplateAttribute(Attribute.createTemplateAttribute("/test{1}.jsp")); + def.putAttribute("body", new Attribute("message{2}")); + DefinitionPatternMatcher patternMatcher = new RegexpDefinitionPatternMatcher("testDef(.*)\\.message(.*)", def); + Definition result = patternMatcher.createDefinition("testDefOne.messageTwo"); + assertNotNull(result); + assertEquals("testDefOne.messageTwo", result.getName()); + assertEquals("/testOne.jsp", result.getTemplateAttribute().getValue()); + assertEquals("messageTwo", result.getAttribute("body").getValue()); + } +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/core/definition/pattern/wildcard/WildcardDefinitionPatternMatcherFactoryTest.java b/plugins/tiles/src/test/java/org/apache/tiles/core/definition/pattern/wildcard/WildcardDefinitionPatternMatcherFactoryTest.java new file mode 100644 index 000000000..dc98f2033 --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/core/definition/pattern/wildcard/WildcardDefinitionPatternMatcherFactoryTest.java @@ -0,0 +1,61 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tiles.core.definition.pattern.wildcard; + +import org.apache.tiles.api.Definition; +import org.junit.Before; +import org.junit.Test; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +/** + * Tests {@link WildcardDefinitionPatternMatcherFactory}. + */ +public class WildcardDefinitionPatternMatcherFactoryTest { + + /** + * The object to test. + */ + private WildcardDefinitionPatternMatcherFactory factory; + + /** + * Sets up the object to test. + */ + @Before + public void setUp() { + factory = new WildcardDefinitionPatternMatcherFactory(); + } + + @Test + public void testCreateDefinitionPatternMatcher() { + assertTrue(factory.createDefinitionPatternMatcher("myPattern", new Definition()) instanceof WildcardDefinitionPatternMatcher); + } + + /** + * Test method for {@link WildcardDefinitionPatternMatcherFactory#isPatternRecognized(String)}. + */ + @Test + public void testIsPatternRecognized() { + assertTrue(factory.isPatternRecognized("my*pattern")); + assertFalse(factory.isPatternRecognized("mypattern")); + } + +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/core/definition/pattern/wildcard/WildcardDefinitionPatternMatcherTest.java b/plugins/tiles/src/test/java/org/apache/tiles/core/definition/pattern/wildcard/WildcardDefinitionPatternMatcherTest.java new file mode 100644 index 000000000..90eea7eb6 --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/core/definition/pattern/wildcard/WildcardDefinitionPatternMatcherTest.java @@ -0,0 +1,53 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tiles.core.definition.pattern.wildcard; + + +import org.apache.tiles.api.Attribute; +import org.apache.tiles.api.Definition; +import org.apache.tiles.core.definition.pattern.DefinitionPatternMatcher; +import org.apache.tiles.core.util.WildcardHelper; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +/** + * Tests {@link WildcardDefinitionPatternMatcher}. + */ +public class WildcardDefinitionPatternMatcherTest { + + /** + * Test method for {@link WildcardDefinitionPatternMatcher#createDefinition(String)}. + */ + @Test + public void testResolveDefinition() { + Definition def = new Definition(); + def.setName("testDef*.message*"); + def.setTemplateAttribute(Attribute.createTemplateAttribute("/test{1}.jsp")); + def.putAttribute("body", new Attribute("message{2}")); + DefinitionPatternMatcher patternMatcher = new WildcardDefinitionPatternMatcher("testDef*.message*", def, new WildcardHelper()); + Definition result = patternMatcher.createDefinition("testDefOne.messageTwo"); + assertNotNull(result); + assertEquals("testDefOne.messageTwo", result.getName()); + assertEquals("/testOne.jsp", result.getTemplateAttribute().getValue()); + assertEquals("messageTwo", result.getAttribute("body").getValue()); + } +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/core/evaluator/BasicAttributeEvaluatorFactoryTest.java b/plugins/tiles/src/test/java/org/apache/tiles/core/evaluator/BasicAttributeEvaluatorFactoryTest.java new file mode 100644 index 000000000..ccba2299b --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/core/evaluator/BasicAttributeEvaluatorFactoryTest.java @@ -0,0 +1,85 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tiles.core.evaluator; + +import org.apache.tiles.api.Attribute; +import org.apache.tiles.api.Expression; +import org.junit.Test; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import static org.junit.Assert.assertSame; + +/** + * Tests {@link BasicAttributeEvaluatorFactory}. + */ +public class BasicAttributeEvaluatorFactoryTest { + + /** + * Test method for {@link BasicAttributeEvaluatorFactory#getAttributeEvaluator(String)}. + */ + @Test + public void testGetAttributeEvaluatorString() { + AttributeEvaluator defaultEvaluator = createMock(AttributeEvaluator.class); + AttributeEvaluator evaluator1 = createMock(AttributeEvaluator.class); + AttributeEvaluator evaluator2 = createMock(AttributeEvaluator.class); + replay(defaultEvaluator, evaluator1, evaluator2); + BasicAttributeEvaluatorFactory factory = new BasicAttributeEvaluatorFactory(defaultEvaluator); + factory.registerAttributeEvaluator("LANG1", evaluator1); + factory.registerAttributeEvaluator("LANG2", evaluator2); + assertSame(evaluator1, factory.getAttributeEvaluator("LANG1")); + assertSame(evaluator2, factory.getAttributeEvaluator("LANG2")); + assertSame(defaultEvaluator, factory.getAttributeEvaluator("LANG3")); + verify(defaultEvaluator, evaluator1, evaluator2); + } + + /** + * Test method for {@link BasicAttributeEvaluatorFactory#getAttributeEvaluator(Attribute)}. + */ + @Test + public void testGetAttributeEvaluatorAttribute() { + AttributeEvaluator defaultEvaluator = createMock(AttributeEvaluator.class); + AttributeEvaluator evaluator1 = createMock(AttributeEvaluator.class); + AttributeEvaluator evaluator2 = createMock(AttributeEvaluator.class); + replay(defaultEvaluator, evaluator1, evaluator2); + BasicAttributeEvaluatorFactory factory = new BasicAttributeEvaluatorFactory(defaultEvaluator); + factory.registerAttributeEvaluator("LANG1", evaluator1); + factory.registerAttributeEvaluator("LANG2", evaluator2); + assertSame(evaluator1, factory + .getAttributeEvaluator(createExpressionAttribute("LANG1"))); + assertSame(evaluator2, factory + .getAttributeEvaluator(createExpressionAttribute("LANG2"))); + assertSame(defaultEvaluator, factory + .getAttributeEvaluator(createExpressionAttribute("LANG3"))); + verify(defaultEvaluator, evaluator1, evaluator2); + } + + /** + * Creates a sample attribute with an expression. + * + * @param language The expression language. + * @return The attribute. + */ + private Attribute createExpressionAttribute(String language) { + return new Attribute(null, Expression.createExpression("myExpression", language), null, "string"); + } + +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/core/evaluator/EvaluatorExceptionTest.java b/plugins/tiles/src/test/java/org/apache/tiles/core/evaluator/EvaluatorExceptionTest.java new file mode 100644 index 000000000..d3fc07215 --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/core/evaluator/EvaluatorExceptionTest.java @@ -0,0 +1,53 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tiles.core.evaluator; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +/** + * Tests {@link EvaluationException}. + */ +public class EvaluatorExceptionTest { + + /** + * Test method for {@link EvaluationException#EvaluationException(Throwable)}. + */ + @Test + public void testEvaluationExceptionThrowable() { + Throwable cause = new Throwable(); + EvaluationException exception = new EvaluationException(cause); + assertEquals(cause.toString(), exception.getMessage()); + assertEquals(cause, exception.getCause()); + } + + /** + * Test method for {@link EvaluationException#EvaluationException(String, Throwable)}. + */ + @Test + public void testEvaluationExceptionStringThrowable() { + Throwable cause = new Throwable(); + EvaluationException exception = new EvaluationException("my message", cause); + assertEquals("my message", exception.getMessage()); + assertEquals(cause, exception.getCause()); + } + +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/core/evaluator/impl/DirectAttributeEvaluatorTest.java b/plugins/tiles/src/test/java/org/apache/tiles/core/evaluator/impl/DirectAttributeEvaluatorTest.java new file mode 100644 index 000000000..1af84a7d0 --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/core/evaluator/impl/DirectAttributeEvaluatorTest.java @@ -0,0 +1,84 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.core.evaluator.impl; + +import org.apache.tiles.api.Attribute; +import org.apache.tiles.api.Expression; +import org.junit.Before; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +/** + * Tests {@link DirectAttributeEvaluator}. + */ +public class DirectAttributeEvaluatorTest { + + /** + * The evaluator to test. + */ + private DirectAttributeEvaluator evaluator; + + /** + * Sets up the test. + */ + @Before + public void setUp() { + evaluator = new DirectAttributeEvaluator(); + } + + /** + * Tests + * {@link DirectAttributeEvaluator#evaluate(Attribute, org.apache.tiles.request.Request)}. + */ + @Test + public void testEvaluate() { + String expression = "This is an expression"; + Attribute attribute = new Attribute(null, Expression.createExpression(expression, null), null, null); + Object result = evaluator.evaluate(attribute, null); + assertEquals("The expression has not been evaluated correctly", result, expression); + expression = "${attributeName}"; + attribute.setExpressionObject(new Expression(expression)); + result = evaluator.evaluate(attribute, null); + assertEquals("The expression has not been evaluated correctly", result, expression); + } + + /** + * Tests + * {@link DirectAttributeEvaluator#evaluate(Attribute, org.apache.tiles.request.Request)}. + */ + @Test(expected = IllegalArgumentException.class) + public void testEvaluateNullAttribute() { + evaluator.evaluate((Attribute) null, null); + } + + /** + * Tests + * {@link DirectAttributeEvaluator#evaluate(String, org.apache.tiles.request.Request)}. + */ + @Test + public void testEvaluateString() { + String expression = "This is an expression"; + Object result = evaluator.evaluate(expression, null); + assertEquals("The expression has not been evaluated correctly", result, expression); + expression = "${attributeName}"; + result = evaluator.evaluate(expression, null); + assertEquals("The expression has not been evaluated correctly", result, expression); + } +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/core/factory/BasicPreparerFactoryTest.java b/plugins/tiles/src/test/java/org/apache/tiles/core/factory/BasicPreparerFactoryTest.java new file mode 100644 index 000000000..0e5ffed61 --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/core/factory/BasicPreparerFactoryTest.java @@ -0,0 +1,72 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.core.factory; + +import junit.framework.TestCase; +import org.apache.tiles.api.AttributeContext; +import org.apache.tiles.api.preparer.ViewPreparer; +import org.apache.tiles.core.prepare.factory.BasicPreparerFactory; +import org.apache.tiles.request.Request; + +/** + * Tests the basic preparer factory. + */ +public class BasicPreparerFactoryTest extends TestCase { + + /** + * The preparer factory. + */ + private BasicPreparerFactory factory; + + /** + * {@inheritDoc} + */ + @Override + public void setUp() { + factory = new BasicPreparerFactory(); + } + + /** + * Tests getting a preparer. + */ + public void testGetPreparer() { + String name = MockViewPreparer.class.getName(); + ViewPreparer p = factory.getPreparer(name, null); + assertNotNull(p); + assertTrue(p instanceof MockViewPreparer); + + name = "org.doesnotexist.Class"; + p = factory.getPreparer(name, null); + assertNull(p); + } + + /** + * Mock view preparer. + * + * @version $Rev$ $Date$ + */ + public static class MockViewPreparer implements ViewPreparer { + + /** + * {@inheritDoc} + */ + public void execute(Request tilesContext, AttributeContext attributeContext) { + } + } +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/core/factory/BasicTilesContainerFactoryTest.java b/plugins/tiles/src/test/java/org/apache/tiles/core/factory/BasicTilesContainerFactoryTest.java new file mode 100644 index 000000000..788584650 --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/core/factory/BasicTilesContainerFactoryTest.java @@ -0,0 +1,252 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.core.factory; + +import junit.framework.TestCase; +import org.apache.tiles.api.TilesContainer; +import org.apache.tiles.core.definition.DefinitionsFactory; +import org.apache.tiles.core.definition.DefinitionsReader; +import org.apache.tiles.core.definition.UnresolvingLocaleDefinitionsFactory; +import org.apache.tiles.core.definition.digester.DigesterDefinitionsReader; +import org.apache.tiles.core.evaluator.AttributeEvaluatorFactory; +import org.apache.tiles.core.evaluator.impl.DirectAttributeEvaluator; +import org.apache.tiles.core.impl.BasicTilesContainer; +import org.apache.tiles.core.locale.LocaleResolver; +import org.apache.tiles.core.locale.impl.DefaultLocaleResolver; +import org.apache.tiles.core.prepare.factory.BasicPreparerFactory; +import org.apache.tiles.core.prepare.factory.PreparerFactory; +import org.apache.tiles.core.renderer.DefinitionRenderer; +import org.apache.tiles.request.ApplicationContext; +import org.apache.tiles.request.ApplicationResource; +import org.apache.tiles.request.locale.URLApplicationResource; +import org.apache.tiles.request.render.BasicRendererFactory; +import org.apache.tiles.request.render.ChainedDelegateRenderer; +import org.apache.tiles.request.render.DispatchRenderer; +import org.apache.tiles.request.render.Renderer; +import org.apache.tiles.request.render.RendererFactory; +import org.apache.tiles.request.render.StringRenderer; + +import java.util.List; +import java.util.Objects; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; + +/** + * Tests {@link BasicTilesContainerFactory}. + */ +public class BasicTilesContainerFactoryTest extends TestCase { + + /** + * The factory to test. + */ + private BasicTilesContainerFactory factory; + + /** + * The context object. + */ + private ApplicationContext applicationContext; + + /** + * The resource to load. + */ + private ApplicationResource resource; + + /** {@inheritDoc} */ + @Override + protected void setUp() throws Exception { + applicationContext = createMock(ApplicationContext.class); + resource = new URLApplicationResource( + "/org/apache/tiles/core/config/tiles-defs.xml", + Objects.requireNonNull(getClass().getResource("/org/apache/tiles/core/config/tiles-defs.xml")) + ); + expect(applicationContext.getResource("/WEB-INF/tiles.xml")).andReturn(resource); + replay(applicationContext); + factory = new BasicTilesContainerFactory(); + } + + /** + * Tests {@link BasicTilesContainerFactory#createContainer(ApplicationContext)}. + */ + public void testCreateContainer() { + TilesContainer container = factory.createContainer(applicationContext); + assertTrue("The class of the container is not correct", container instanceof BasicTilesContainer); + } + + /** + * Tests {@link BasicTilesContainerFactory#createDefinitionsFactory( + * ApplicationContext, LocaleResolver)}. + */ + public void testCreateDefinitionsFactory() { + LocaleResolver resolver = factory.createLocaleResolver(applicationContext); + DefinitionsFactory defsFactory = factory.createDefinitionsFactory(applicationContext, resolver); + assertTrue("The class of the definitions factory is not correct", + defsFactory instanceof UnresolvingLocaleDefinitionsFactory); + } + + /** + * Tests {@link BasicTilesContainerFactory#createLocaleResolver( + * ApplicationContext)}. + */ + public void testCreateLocaleResolver() { + LocaleResolver localeResolver = factory.createLocaleResolver(applicationContext); + assertTrue("The class of the locale resolver is not correct", localeResolver instanceof DefaultLocaleResolver); + } + + /** + * Tests {@link BasicTilesContainerFactory#createDefinitionsReader( + * ApplicationContext)}. + */ + public void testCreateDefinitionsReader() { + DefinitionsReader reader = factory.createDefinitionsReader(applicationContext); + assertTrue("The class of the reader is not correct", reader instanceof DigesterDefinitionsReader); + } + + /** + * Tests + * {@link BasicTilesContainerFactory#getSources(ApplicationContext)}. + */ + public void testGetSources() { + List resources = factory.getSources(applicationContext); + assertEquals("The urls list is not one-sized", 1, resources.size()); + assertEquals("The URL is not correct", resource, resources.get(0)); + } + + /** + * Tests + * {@link BasicTilesContainerFactory#createAttributeEvaluatorFactory( + * ApplicationContext, LocaleResolver)}. + */ + public void testCreateAttributeEvaluatorFactory() { + LocaleResolver resolver = factory.createLocaleResolver(applicationContext); + AttributeEvaluatorFactory attributeEvaluatorFactory = factory.createAttributeEvaluatorFactory( + applicationContext, resolver); + assertTrue("The class of the evaluator is not correct", + attributeEvaluatorFactory.getAttributeEvaluator((String) null) instanceof DirectAttributeEvaluator); + } + + /** + * Tests + * {@link BasicTilesContainerFactory#createPreparerFactory(ApplicationContext)}. + */ + public void testCreatePreparerFactory() { + PreparerFactory preparerFactory = factory.createPreparerFactory(applicationContext); + assertTrue("The class of the preparer factory is not correct", preparerFactory instanceof BasicPreparerFactory); + } + + /** + * Tests {@link BasicTilesContainerFactory#createRendererFactory( + * ApplicationContext, TilesContainer, AttributeEvaluatorFactory)}. + */ + public void testCreateRendererFactory() { + TilesContainer container = factory.createContainer(applicationContext); + LocaleResolver resolver = factory.createLocaleResolver(applicationContext); + AttributeEvaluatorFactory attributeEvaluatorFactory = factory.createAttributeEvaluatorFactory( + applicationContext, resolver); + RendererFactory rendererFactory = factory.createRendererFactory(applicationContext, container, + attributeEvaluatorFactory); + assertTrue("The class of the renderer factory is not correct", rendererFactory instanceof BasicRendererFactory); + Renderer renderer = rendererFactory.getRenderer("string"); + assertNotNull("The string renderer is null", renderer); + assertTrue("The string renderer class is not correct", renderer instanceof StringRenderer); + renderer = rendererFactory.getRenderer("template"); + assertNotNull("The template renderer is null", renderer); + assertTrue("The template renderer class is not correct", renderer instanceof DispatchRenderer); + renderer = rendererFactory.getRenderer("definition"); + assertNotNull("The definition renderer is null", renderer); + assertTrue("The definition renderer class is not correct", renderer instanceof DefinitionRenderer); + } + + /** + * Tests + * {@link BasicTilesContainerFactory#createDefaultAttributeRenderer(BasicRendererFactory, + * ApplicationContext, TilesContainer, AttributeEvaluatorFactory)}. + */ + public void testCreateDefaultAttributeRenderer() { + TilesContainer container = createMock(TilesContainer.class); + AttributeEvaluatorFactory attributeEvaluatorFactory = createMock(AttributeEvaluatorFactory.class); + BasicRendererFactory rendererFactory = createMock(BasicRendererFactory.class); + Renderer stringRenderer = createMock(Renderer.class); + Renderer templateRenderer = createMock(Renderer.class); + Renderer definitionRenderer = createMock(Renderer.class); + + expect(rendererFactory.getRenderer("string")).andReturn(stringRenderer); + expect(rendererFactory.getRenderer("template")).andReturn(templateRenderer); + expect(rendererFactory.getRenderer("definition")).andReturn(definitionRenderer); + + replay(container, attributeEvaluatorFactory, rendererFactory); + Renderer renderer = factory.createDefaultAttributeRenderer(rendererFactory, applicationContext, container, + attributeEvaluatorFactory); + assertTrue("The default renderer class is not correct", renderer instanceof ChainedDelegateRenderer); + verify(container, attributeEvaluatorFactory, rendererFactory); + } + + /** + * Tests + * {@link BasicTilesContainerFactory#createStringAttributeRenderer(BasicRendererFactory, + * ApplicationContext, TilesContainer, AttributeEvaluatorFactory)}. + */ + public void testCreateStringAttributeRenderer() { + TilesContainer container = createMock(TilesContainer.class); + AttributeEvaluatorFactory attributeEvaluatorFactory = createMock(AttributeEvaluatorFactory.class); + BasicRendererFactory rendererFactory = createMock(BasicRendererFactory.class); + + replay(container, attributeEvaluatorFactory, rendererFactory); + Renderer renderer = factory.createStringAttributeRenderer(rendererFactory, applicationContext, container, + attributeEvaluatorFactory); + assertTrue("The renderer class is not correct", renderer instanceof StringRenderer); + verify(container, attributeEvaluatorFactory, rendererFactory); + } + + /** + * Tests + * {@link BasicTilesContainerFactory#createTemplateAttributeRenderer(BasicRendererFactory, + * ApplicationContext, TilesContainer, AttributeEvaluatorFactory)}. + */ + public void testCreateTemplateAttributeRenderer() { + TilesContainer container = createMock(TilesContainer.class); + AttributeEvaluatorFactory attributeEvaluatorFactory = createMock(AttributeEvaluatorFactory.class); + BasicRendererFactory rendererFactory = createMock(BasicRendererFactory.class); + + replay(container, attributeEvaluatorFactory, rendererFactory); + Renderer renderer = factory.createTemplateAttributeRenderer(rendererFactory, applicationContext, container, + attributeEvaluatorFactory); + assertTrue("The renderer class is not correct", renderer instanceof DispatchRenderer); + verify(container, attributeEvaluatorFactory, rendererFactory); + } + + /** + * Tests + * {@link BasicTilesContainerFactory#createDefinitionAttributeRenderer(BasicRendererFactory, + * ApplicationContext, TilesContainer, AttributeEvaluatorFactory)}. + */ + public void testCreateDefinitionAttributeRenderer() { + TilesContainer container = createMock(TilesContainer.class); + AttributeEvaluatorFactory attributeEvaluatorFactory = createMock(AttributeEvaluatorFactory.class); + BasicRendererFactory rendererFactory = createMock(BasicRendererFactory.class); + + replay(container, attributeEvaluatorFactory, rendererFactory); + Renderer renderer = factory.createDefinitionAttributeRenderer(rendererFactory, applicationContext, container, + attributeEvaluatorFactory); + assertTrue("The renderer class is not correct", renderer instanceof DefinitionRenderer); + verify(container, attributeEvaluatorFactory, rendererFactory); + } +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/core/factory/NoSuchPreparerExceptionTest.java b/plugins/tiles/src/test/java/org/apache/tiles/core/factory/NoSuchPreparerExceptionTest.java new file mode 100644 index 000000000..2255f1667 --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/core/factory/NoSuchPreparerExceptionTest.java @@ -0,0 +1,43 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tiles.core.factory; + +import org.apache.tiles.core.prepare.factory.NoSuchPreparerException; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; + +/** + * Tests {@link NoSuchPreparerException}. + */ +public class NoSuchPreparerExceptionTest { + + /** + * Test method for {@link NoSuchPreparerException#NoSuchPreparerException(String)}. + */ + @Test + public void testNoSuchPreparerExceptionString() { + NoSuchPreparerException exception = new NoSuchPreparerException("my message"); + assertEquals("my message", exception.getMessage()); + assertNull(exception.getCause()); + } + +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/core/factory/TilesContainerFactoryExceptionTest.java b/plugins/tiles/src/test/java/org/apache/tiles/core/factory/TilesContainerFactoryExceptionTest.java new file mode 100644 index 000000000..bc1aaec3d --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/core/factory/TilesContainerFactoryExceptionTest.java @@ -0,0 +1,42 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tiles.core.factory; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +/** + * Tests {@link TilesContainerFactoryException}. + */ +public class TilesContainerFactoryExceptionTest { + + /** + * Test method for {@link TilesContainerFactoryException#TilesContainerFactoryException(String, Throwable)}. + */ + @Test + public void testTilesContainerFactoryExceptionStringThrowable() { + Throwable cause = new Throwable(); + TilesContainerFactoryException exception = new TilesContainerFactoryException("my message", cause); + assertEquals("my message", exception.getMessage()); + assertEquals(cause, exception.getCause()); + } + +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/core/impl/BasicTilesContainerTest.java b/plugins/tiles/src/test/java/org/apache/tiles/core/impl/BasicTilesContainerTest.java new file mode 100644 index 000000000..2e7328481 --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/core/impl/BasicTilesContainerTest.java @@ -0,0 +1,126 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.core.impl; + +import junit.framework.TestCase; +import org.apache.tiles.api.Attribute; +import org.apache.tiles.core.factory.AbstractTilesContainerFactory; +import org.apache.tiles.core.factory.BasicTilesContainerFactory; +import org.apache.tiles.request.ApplicationContext; +import org.apache.tiles.request.Request; +import org.apache.tiles.request.locale.URLApplicationResource; +import org.apache.tiles.request.render.CannotRenderException; +import org.easymock.EasyMock; + +import java.io.IOException; +import java.io.StringWriter; +import java.util.Objects; + +public class BasicTilesContainerTest extends TestCase { + + /** + * A sample integer value to check object rendering. + */ + private static final int SAMPLE_INT = 15; + + /** + * The container. + */ + private BasicTilesContainer container; + + @Override + public void setUp() { + ApplicationContext context = EasyMock.createMock(ApplicationContext.class); + URLApplicationResource resource = new URLApplicationResource( + "/WEB-INF/tiles.xml", + Objects.requireNonNull(getClass().getResource("/org/apache/tiles/core/factory/test-defs.xml")) + ); + + EasyMock.expect(context.getResource("/WEB-INF/tiles.xml")).andReturn(resource); + EasyMock.replay(context); + AbstractTilesContainerFactory factory = new BasicTilesContainerFactory(); + container = (BasicTilesContainer) factory.createContainer(context); + } + + /** + * Tests basic Tiles container initialization. + */ + public void testInitialization() { + assertNotNull(container); + } + + /** + * Tests that attributes of type "object" won't be rendered. + * + * @throws IOException If something goes wrong, but it's not a Tiles + * exception. + */ + public void testObjectAttribute() throws IOException { + Attribute attribute = new Attribute(); + Request request = EasyMock.createMock(Request.class); + EasyMock.replay(request); + boolean exceptionFound = false; + + attribute.setValue(SAMPLE_INT); + try { + container.render(attribute, request); + } catch (CannotRenderException e) { + exceptionFound = true; + } + + assertTrue("An attribute of 'object' type cannot be rendered", exceptionFound); + } + + /** + * Tests is attributes are rendered correctly according to users roles. + * + * @throws IOException If a problem arises during rendering or writing in the writer. + */ + public void testAttributeCredentials() throws IOException { + Request request = EasyMock.createMock(Request.class); + EasyMock.expect(request.isUserInRole("myrole")).andReturn(Boolean.TRUE); + StringWriter writer = new StringWriter(); + EasyMock.expect(request.getWriter()).andReturn(writer); + EasyMock.replay(request); + Attribute attribute = new Attribute("This is the value", "myrole"); + attribute.setRenderer("string"); + container.render(attribute, request); + writer.close(); + assertEquals("The attribute should have been rendered", "This is the value", writer.toString()); + EasyMock.reset(request); + request = EasyMock.createMock(Request.class); + EasyMock.expect(request.isUserInRole("myrole")).andReturn(Boolean.FALSE); + EasyMock.replay(request); + writer = new StringWriter(); + container.render(attribute, request); + writer.close(); + assertNotSame("The attribute should have not been rendered", "This is the value", writer.toString()); + } + + /** + * Tests {@link BasicTilesContainer#evaluate(Attribute, Request)}. + */ + public void testEvaluate() { + Request request = EasyMock.createMock(Request.class); + EasyMock.replay(request); + Attribute attribute = new Attribute("This is the value"); + Object value = container.evaluate(attribute, request); + assertEquals("The attribute has not been evaluated correctly", "This is the value", value); + } +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/core/impl/BasicTilesContainerUnitTest.java b/plugins/tiles/src/test/java/org/apache/tiles/core/impl/BasicTilesContainerUnitTest.java new file mode 100644 index 000000000..7f4c9d0c4 --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/core/impl/BasicTilesContainerUnitTest.java @@ -0,0 +1,836 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.core.impl; + +import org.apache.tiles.api.Attribute; +import org.apache.tiles.api.AttributeContext; +import org.apache.tiles.api.BasicAttributeContext; +import org.apache.tiles.api.Definition; +import org.apache.tiles.api.preparer.ViewPreparer; +import org.apache.tiles.core.definition.DefinitionsFactory; +import org.apache.tiles.core.definition.NoSuchDefinitionException; +import org.apache.tiles.core.evaluator.AttributeEvaluator; +import org.apache.tiles.core.evaluator.AttributeEvaluatorFactory; +import org.apache.tiles.core.prepare.factory.NoSuchPreparerException; +import org.apache.tiles.core.prepare.factory.PreparerFactory; +import org.apache.tiles.request.ApplicationContext; +import org.apache.tiles.request.Request; +import org.apache.tiles.request.render.CannotRenderException; +import org.apache.tiles.request.render.NoSuchRendererException; +import org.apache.tiles.request.render.Renderer; +import org.apache.tiles.request.render.RendererFactory; +import org.junit.Before; +import org.junit.Test; + +import java.io.IOException; +import java.util.Deque; +import java.util.LinkedList; +import java.util.Map; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.eq; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.expectLastCall; +import static org.easymock.EasyMock.isA; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + +/** + * Tests {@link BasicTilesContainer}. + */ +public class BasicTilesContainerUnitTest { + + /** + * Name used to store attribute context stack. + */ + private static final String ATTRIBUTE_CONTEXT_STACK = + "org.apache.tiles.AttributeContext.STACK"; + + /** + * The application context. + */ + private ApplicationContext applicationContext; + + /** + * The definitions factory. + */ + private DefinitionsFactory definitionsFactory; + + /** + * The preparer factory. + */ + private PreparerFactory preparerFactory; + + /** + * The renderer factory. + */ + private RendererFactory rendererFactory; + + /** + * The evaluator factory. + */ + private AttributeEvaluatorFactory attributeEvaluatorFactory; + + /** + * The container to test. + */ + private BasicTilesContainer container; + + /** + * Sets up the test. + */ + @Before + public void setUp() { + applicationContext = createMock(ApplicationContext.class); + definitionsFactory = createMock(DefinitionsFactory.class); + preparerFactory = createMock(PreparerFactory.class); + rendererFactory = createMock(RendererFactory.class); + attributeEvaluatorFactory = createMock(AttributeEvaluatorFactory.class); + container = new BasicTilesContainer(); + container.setApplicationContext(applicationContext); + container.setAttributeEvaluatorFactory(attributeEvaluatorFactory); + container.setDefinitionsFactory(definitionsFactory); + container.setPreparerFactory(preparerFactory); + container.setRendererFactory(rendererFactory); + } + + /** + * Test method for {@link BasicTilesContainer#startContext(Request)}. + */ + @Test + public void testStartContext() { + Request request = createMock(Request.class); + Map requestScope = createMock(Map.class); + Deque deque = createMock(Deque.class); + AttributeContext attributeContext = createMock(AttributeContext.class); + + expect(request.getContext("request")).andReturn(requestScope); + expect(requestScope.get(ATTRIBUTE_CONTEXT_STACK)).andReturn(deque); + expect(deque.isEmpty()).andReturn(false); + expect(deque.peek()).andReturn(attributeContext); + expect(attributeContext.getCascadedAttributeNames()).andReturn(null); + deque.push(isA(BasicAttributeContext.class)); + + replay(applicationContext, attributeEvaluatorFactory, + definitionsFactory, preparerFactory, rendererFactory, request, + requestScope, deque, attributeContext); + assertTrue(container.startContext(request) instanceof BasicAttributeContext); + verify(applicationContext, attributeEvaluatorFactory, + definitionsFactory, preparerFactory, rendererFactory, request, + requestScope, deque, attributeContext); + } + + /** + * Test method for {@link BasicTilesContainer#endContext(Request)}. + */ + @Test + public void testEndContext() { + Request request = createMock(Request.class); + Map requestScope = createMock(Map.class); + Deque deque = createMock(Deque.class); + AttributeContext attributeContext = createMock(AttributeContext.class); + + expect(request.getContext("request")).andReturn(requestScope); + expect(requestScope.get(ATTRIBUTE_CONTEXT_STACK)).andReturn(deque); + expect(deque.pop()).andReturn(attributeContext); + + replay(applicationContext, attributeEvaluatorFactory, + definitionsFactory, preparerFactory, rendererFactory, request, + requestScope, deque, attributeContext); + container.endContext(request); + verify(applicationContext, attributeEvaluatorFactory, + definitionsFactory, preparerFactory, rendererFactory, request, + requestScope, deque, attributeContext); + } + + /** + * Test method for {@link BasicTilesContainer#renderContext(Request)}. + * + * @throws IOException If something goes wrong. + */ + @Test + public void testRenderContext() throws IOException { + Request request = createMock(Request.class); + Map requestScope = createMock(Map.class); + Deque deque = createMock(Deque.class); + AttributeContext attributeContext = createMock(AttributeContext.class); + ViewPreparer preparer = createMock(ViewPreparer.class); + Attribute templateAttribute = createMock(Attribute.class); + Renderer renderer = createMock(Renderer.class); + AttributeEvaluator evaluator = createMock(AttributeEvaluator.class); + + expect(request.getContext("request")).andReturn(requestScope); + expect(requestScope.get(ATTRIBUTE_CONTEXT_STACK)).andReturn(deque); + expect(deque.isEmpty()).andReturn(false); + expect(deque.peek()).andReturn(attributeContext); + expect(attributeContext.getPreparer()).andReturn(null); + expect(attributeContext.getTemplateAttribute()).andReturn(templateAttribute); + expect(templateAttribute.getRenderer()).andReturn("renderer"); + expect(rendererFactory.getRenderer("renderer")).andReturn(renderer); + expect(attributeEvaluatorFactory.getAttributeEvaluator(templateAttribute)).andReturn(evaluator); + expect(evaluator.evaluate(templateAttribute, request)).andReturn("/mytemplate.jsp"); + expect(templateAttribute.isPermitted(request)).andReturn(true); + renderer.render("/mytemplate.jsp", request); + + replay(applicationContext, attributeEvaluatorFactory, evaluator, + definitionsFactory, preparerFactory, rendererFactory, request, + requestScope, deque, attributeContext, preparer, templateAttribute, renderer); + container.renderContext(request); + verify(applicationContext, attributeEvaluatorFactory, evaluator, + definitionsFactory, preparerFactory, rendererFactory, request, + requestScope, deque, attributeContext, preparer, templateAttribute, renderer); + } + + /** + * Test method for {@link BasicTilesContainer#getApplicationContext()}. + */ + @Test + public void testGetApplicationContext() { + replay(applicationContext, attributeEvaluatorFactory, + definitionsFactory, preparerFactory, rendererFactory); + assertEquals(applicationContext, container.getApplicationContext()); + verify(applicationContext, attributeEvaluatorFactory, + definitionsFactory, preparerFactory, rendererFactory); + } + + /** + * Test method for {@link BasicTilesContainer#getAttributeContext(Request)}. + */ + @Test + public void testGetAttributeContext() { + Request request = createMock(Request.class); + Map requestScope = createMock(Map.class); + Deque deque = createMock(Deque.class); + AttributeContext attributeContext = createMock(AttributeContext.class); + + expect(request.getContext("request")).andReturn(requestScope); + expect(requestScope.get(ATTRIBUTE_CONTEXT_STACK)).andReturn(deque); + expect(deque.isEmpty()).andReturn(false); + expect(deque.peek()).andReturn(attributeContext); + + replay(applicationContext, attributeEvaluatorFactory, + definitionsFactory, preparerFactory, rendererFactory, request, + requestScope, deque, attributeContext); + assertEquals(attributeContext, container.getAttributeContext(request)); + verify(applicationContext, attributeEvaluatorFactory, + definitionsFactory, preparerFactory, rendererFactory, request, + requestScope, deque, attributeContext); + } + + /** + * Test method for {@link BasicTilesContainer#getAttributeContext(Request)}. + */ + @Test + public void testGetAttributeContextNew() { + Request request = createMock(Request.class); + Map requestScope = createMock(Map.class); + Deque deque = createMock(Deque.class); + AttributeContext attributeContext = createMock(AttributeContext.class); + + expect(request.getContext("request")).andReturn(requestScope).times(2); + expect(requestScope.get(ATTRIBUTE_CONTEXT_STACK)).andReturn(deque).times(2); + expect(deque.isEmpty()).andReturn(true); + deque.push(isA(BasicAttributeContext.class)); + + replay(applicationContext, attributeEvaluatorFactory, + definitionsFactory, preparerFactory, rendererFactory, request, + requestScope, deque, attributeContext); + assertTrue(container.getAttributeContext(request) instanceof BasicAttributeContext); + verify(applicationContext, attributeEvaluatorFactory, + definitionsFactory, preparerFactory, rendererFactory, request, + requestScope, deque, attributeContext); + } + + /** + * Test method for {@link BasicTilesContainer#prepare(String, Request)}. + */ + @Test + public void testPrepare() { + Request request = createMock(Request.class); + Map requestScope = createMock(Map.class); + Deque deque = createMock(Deque.class); + AttributeContext attributeContext = createMock(AttributeContext.class); + ViewPreparer preparer = createMock(ViewPreparer.class); + + expect(preparerFactory.getPreparer("preparer", request)).andReturn(preparer); + expect(request.getContext("request")).andReturn(requestScope); + expect(requestScope.get(ATTRIBUTE_CONTEXT_STACK)).andReturn(deque); + expect(deque.isEmpty()).andReturn(false); + expect(deque.peek()).andReturn(attributeContext); + preparer.execute(request, attributeContext); + + replay(applicationContext, attributeEvaluatorFactory, + definitionsFactory, preparerFactory, rendererFactory, request, + requestScope, deque, attributeContext, preparer); + container.prepare("preparer", request); + verify(applicationContext, attributeEvaluatorFactory, + definitionsFactory, preparerFactory, rendererFactory, request, + requestScope, deque, attributeContext, preparer); + } + + /** + * Test method for {@link BasicTilesContainer#prepare(String, Request)}. + */ + @Test(expected = NoSuchPreparerException.class) + public void testPrepareException() { + Request request = createMock(Request.class); + Map requestScope = createMock(Map.class); + Deque deque = createMock(Deque.class); + AttributeContext attributeContext = createMock(AttributeContext.class); + + expect(preparerFactory.getPreparer("preparer", request)).andReturn(null); + + replay(applicationContext, attributeEvaluatorFactory, + definitionsFactory, preparerFactory, rendererFactory, request, + requestScope, deque, attributeContext); + try { + container.prepare("preparer", request); + } finally { + verify(applicationContext, attributeEvaluatorFactory, + definitionsFactory, preparerFactory, rendererFactory, + request, requestScope, deque, attributeContext); + } + } + + @Test + public void testRenderStringRequest() throws IOException { + Request request = createMock(Request.class); + Map requestScope = createMock(Map.class); + Deque deque = createMock(Deque.class); + AttributeContext attributeContext = createMock(AttributeContext.class); + ViewPreparer preparer = createMock(ViewPreparer.class); + Renderer renderer = createMock(Renderer.class); + Definition definition = createMock(Definition.class); + AttributeEvaluator evaluator = createMock(AttributeEvaluator.class); + + Attribute templateAttribute = Attribute.createTemplateAttribute("/my/template.jsp"); + + expect(definitionsFactory.getDefinition("definition", request)).andReturn(definition); + expect(request.getContext("request")).andReturn(requestScope).times(3); + expect(requestScope.get(ATTRIBUTE_CONTEXT_STACK)).andReturn(deque).times(3); + expect(deque.isEmpty()).andReturn(false); + expect(deque.peek()).andReturn(attributeContext); + expect(attributeContext.getPreparer()).andReturn(null); + expect(attributeContext.getTemplateAttribute()).andReturn(templateAttribute); + expect(attributeContext.getLocalAttributeNames()).andReturn(null); + expect(attributeContext.getCascadedAttributeNames()).andReturn(null); + expect(definition.getTemplateAttribute()).andReturn(templateAttribute); + expect(rendererFactory.getRenderer("template")).andReturn(renderer); + deque.push(isA(BasicAttributeContext.class)); + expect(attributeEvaluatorFactory.getAttributeEvaluator(templateAttribute)).andReturn(evaluator); + expect(evaluator.evaluate(templateAttribute, request)).andReturn("/my/template.jsp"); + renderer.render("/my/template.jsp", request); + expect(deque.pop()).andReturn(null); + + replay(applicationContext, attributeEvaluatorFactory, evaluator, + definitionsFactory, preparerFactory, rendererFactory, request, + requestScope, deque, attributeContext, preparer, renderer, definition); + container.render("definition", request); + verify(applicationContext, attributeEvaluatorFactory, evaluator, + definitionsFactory, preparerFactory, rendererFactory, request, + requestScope, deque, attributeContext, preparer, renderer, definition); + } + + @Test(expected = NoSuchDefinitionException.class) + public void testRenderStringRequestException() { + Request request = createMock(Request.class); + + expect(definitionsFactory.getDefinition("definition", request)).andReturn(null); + + replay(applicationContext, attributeEvaluatorFactory, + definitionsFactory, preparerFactory, rendererFactory, request); + try { + container.render("definition", request); + } finally { + verify(applicationContext, attributeEvaluatorFactory, + definitionsFactory, preparerFactory, rendererFactory); + } + } + + @Test + public void testRenderAttributeRequest() throws IOException { + Request request = createMock(Request.class); + Attribute templateAttribute = createMock(Attribute.class); + Renderer renderer = createMock(Renderer.class); + AttributeEvaluator evaluator = createMock(AttributeEvaluator.class); + + expect(templateAttribute.getRenderer()).andReturn("renderer"); + expect(rendererFactory.getRenderer("renderer")).andReturn(renderer); + expect(attributeEvaluatorFactory.getAttributeEvaluator(templateAttribute)).andReturn(evaluator); + expect(evaluator.evaluate(templateAttribute, request)).andReturn("/mytemplate.jsp"); + expect(templateAttribute.isPermitted(request)).andReturn(true); + renderer.render("/mytemplate.jsp", request); + + replay(applicationContext, attributeEvaluatorFactory, evaluator, + definitionsFactory, preparerFactory, rendererFactory, request, + templateAttribute, renderer); + container.render(templateAttribute, request); + verify(applicationContext, attributeEvaluatorFactory, evaluator, + definitionsFactory, preparerFactory, rendererFactory, request, + templateAttribute, renderer); + } + + @Test(expected = CannotRenderException.class) + public void testRenderAttributeRequestException1() throws IOException { + Request request = createMock(Request.class); + + replay(applicationContext, attributeEvaluatorFactory, + definitionsFactory, preparerFactory, rendererFactory, request); + try { + container.render((Attribute) null, request); + } finally { + verify(applicationContext, attributeEvaluatorFactory, + definitionsFactory, preparerFactory, rendererFactory, + request); + } + } + + @Test(expected = NoSuchRendererException.class) + public void testRenderAttributeRequestException2() throws IOException { + Request request = createMock(Request.class); + Attribute templateAttribute = createMock(Attribute.class); + AttributeEvaluator evaluator = createMock(AttributeEvaluator.class); + + expect(templateAttribute.getRenderer()).andReturn("renderer"); + expect(templateAttribute.isPermitted(request)).andReturn(true); + expect(rendererFactory.getRenderer("renderer")).andThrow(new NoSuchRendererException("Boom!")); + + replay(applicationContext, attributeEvaluatorFactory, evaluator, + definitionsFactory, preparerFactory, rendererFactory, request, + templateAttribute); + try { + container.render(templateAttribute, request); + } finally { + verify(applicationContext, attributeEvaluatorFactory, evaluator, + definitionsFactory, preparerFactory, rendererFactory, + request, templateAttribute); + } + } + + @Test(expected = CannotRenderException.class) + public void testRenderAttributeRequestException3() throws IOException { + Request request = createMock(Request.class); + Attribute templateAttribute = createMock(Attribute.class); + AttributeEvaluator evaluator = createMock(AttributeEvaluator.class); + Renderer renderer = createMock(Renderer.class); + + expect(templateAttribute.getRenderer()).andReturn("renderer"); + expect(templateAttribute.isPermitted(request)).andReturn(true); + expect(rendererFactory.getRenderer("renderer")).andReturn(renderer); + expect(attributeEvaluatorFactory.getAttributeEvaluator(templateAttribute)).andReturn(evaluator); + expect(evaluator.evaluate(templateAttribute, request)).andReturn(1); + + replay(applicationContext, attributeEvaluatorFactory, evaluator, + definitionsFactory, preparerFactory, rendererFactory, request, + templateAttribute); + try { + container.render(templateAttribute, request); + } finally { + verify(applicationContext, attributeEvaluatorFactory, evaluator, + definitionsFactory, preparerFactory, rendererFactory, + request, templateAttribute); + } + } + + @Test(expected = NoSuchRendererException.class) + public void testRenderAttributeRequestException() throws IOException { + Request request = createMock(Request.class); + Attribute templateAttribute = createMock(Attribute.class); + AttributeEvaluator evaluator = createMock(AttributeEvaluator.class); + + expect(templateAttribute.getRenderer()).andReturn("renderer"); + expect(templateAttribute.isPermitted(request)).andReturn(true); + expect(rendererFactory.getRenderer("renderer")).andThrow(new NoSuchRendererException("Boom!")); + + replay(applicationContext, attributeEvaluatorFactory, evaluator, + definitionsFactory, preparerFactory, rendererFactory, request, + templateAttribute); + try { + container.render(templateAttribute, request); + } finally { + verify(applicationContext, attributeEvaluatorFactory, evaluator, + definitionsFactory, preparerFactory, rendererFactory, + request, templateAttribute); + } + } + + @Test + public void testEvaluate() { + Request request = createMock(Request.class); + AttributeEvaluator evaluator = createMock(AttributeEvaluator.class); + Attribute templateAttribute = createMock(Attribute.class); + + expect(attributeEvaluatorFactory.getAttributeEvaluator(templateAttribute)).andReturn(evaluator); + expect(evaluator.evaluate(templateAttribute, request)).andReturn(1); + + replay(applicationContext, attributeEvaluatorFactory, + definitionsFactory, preparerFactory, rendererFactory, request, + templateAttribute, evaluator); + assertEquals(1, container.evaluate(templateAttribute, request)); + verify(applicationContext, attributeEvaluatorFactory, + definitionsFactory, preparerFactory, rendererFactory, request, + templateAttribute, evaluator); + } + + /** + * Test method for {@link BasicTilesContainer#isValidDefinition(String, Request)}. + */ + @Test + public void testIsValidDefinition() { + Request request = createMock(Request.class); + Definition definition = createMock(Definition.class); + + expect(definitionsFactory.getDefinition("definition", request)).andReturn(definition); + + replay(applicationContext, attributeEvaluatorFactory, + definitionsFactory, preparerFactory, rendererFactory, request, definition); + assertTrue(container.isValidDefinition("definition", request)); + verify(applicationContext, attributeEvaluatorFactory, + definitionsFactory, preparerFactory, rendererFactory, request, definition); + } + + /** + * Test method for {@link BasicTilesContainer#isValidDefinition(String, Request)}. + */ + @Test + public void testIsValidDefinitionNull() { + Request request = createMock(Request.class); + + expect(definitionsFactory.getDefinition("definition", request)).andReturn(null); + + replay(applicationContext, attributeEvaluatorFactory, + definitionsFactory, preparerFactory, rendererFactory, request); + assertFalse(container.isValidDefinition("definition", request)); + verify(applicationContext, attributeEvaluatorFactory, + definitionsFactory, preparerFactory, rendererFactory, request); + } + + /** + * Test method for {@link BasicTilesContainer#isValidDefinition(String, Request)}. + */ + @Test + public void testIsValidDefinitionException() { + Request request = createMock(Request.class); + + expect(definitionsFactory.getDefinition("definition", request)) + .andThrow(new NoSuchDefinitionException("Boom!")); + + replay(applicationContext, attributeEvaluatorFactory, + definitionsFactory, preparerFactory, rendererFactory, request); + assertFalse(container.isValidDefinition("definition", request)); + verify(applicationContext, attributeEvaluatorFactory, + definitionsFactory, preparerFactory, rendererFactory, request); + } + + /** + * Test method for {@link BasicTilesContainer#getDefinition(String, Request)}. + */ + @Test + public void testGetDefinition() { + Request request = createMock(Request.class); + Definition definition = createMock(Definition.class); + + expect(definitionsFactory.getDefinition("definition", request)).andReturn(definition); + + replay(applicationContext, attributeEvaluatorFactory, + definitionsFactory, preparerFactory, rendererFactory, request, definition); + assertEquals(definition, container.getDefinition("definition", request)); + verify(applicationContext, attributeEvaluatorFactory, + definitionsFactory, preparerFactory, rendererFactory, request, definition); + } + + /** + * Test method for {@link BasicTilesContainer#getContextStack(Request)}. + */ + @Test + public void testGetContextStack() { + Request request = createMock(Request.class); + Map requestScope = createMock(Map.class); + Deque deque = createMock(Deque.class); + + expect(request.getContext("request")).andReturn(requestScope); + expect(requestScope.get(ATTRIBUTE_CONTEXT_STACK)).andReturn(deque); + + replay(applicationContext, attributeEvaluatorFactory, + definitionsFactory, preparerFactory, rendererFactory, request, + requestScope, deque); + assertEquals(deque, container.getContextStack(request)); + verify(applicationContext, attributeEvaluatorFactory, + definitionsFactory, preparerFactory, rendererFactory, request, + requestScope, deque); + } + + /** + * Test method for {@link BasicTilesContainer#getContextStack(Request)}. + */ + @Test + public void testGetContextStackNew() { + Request request = createMock(Request.class); + Map requestScope = createMock(Map.class); + + expect(request.getContext("request")).andReturn(requestScope); + expect(requestScope.get(ATTRIBUTE_CONTEXT_STACK)).andReturn(null); + expect(requestScope.put(eq(ATTRIBUTE_CONTEXT_STACK), isA(LinkedList.class))).andReturn(null); + + replay(applicationContext, attributeEvaluatorFactory, + definitionsFactory, preparerFactory, rendererFactory, request, + requestScope); + assertTrue(container.getContextStack(request) instanceof LinkedList); + verify(applicationContext, attributeEvaluatorFactory, + definitionsFactory, preparerFactory, rendererFactory, request, + requestScope); + } + + @Test + public void testPushContext() { + Request request = createMock(Request.class); + Map requestScope = createMock(Map.class); + Deque deque = createMock(Deque.class); + AttributeContext attributeContext = createMock(AttributeContext.class); + + expect(request.getContext("request")).andReturn(requestScope); + expect(requestScope.get(ATTRIBUTE_CONTEXT_STACK)).andReturn(deque); + deque.push(attributeContext); + + replay(applicationContext, attributeEvaluatorFactory, + definitionsFactory, preparerFactory, rendererFactory, request, + requestScope, deque, attributeContext); + container.pushContext(attributeContext, request); + verify(applicationContext, attributeEvaluatorFactory, + definitionsFactory, preparerFactory, rendererFactory, request, + requestScope, deque, attributeContext); + } + + /** + * Test method for {@link BasicTilesContainer#popContext(Request)}. + */ + @Test + public void testPopContext() { + Request request = createMock(Request.class); + Map requestScope = createMock(Map.class); + Deque deque = createMock(Deque.class); + AttributeContext attributeContext = createMock(AttributeContext.class); + + expect(request.getContext("request")).andReturn(requestScope); + expect(requestScope.get(ATTRIBUTE_CONTEXT_STACK)).andReturn(deque); + expect(deque.pop()).andReturn(attributeContext); + + replay(applicationContext, attributeEvaluatorFactory, + definitionsFactory, preparerFactory, rendererFactory, request, + requestScope, deque, attributeContext); + assertEquals(attributeContext, container.popContext(request)); + verify(applicationContext, attributeEvaluatorFactory, + definitionsFactory, preparerFactory, rendererFactory, request, + requestScope, deque, attributeContext); + } + + /** + * Test method for {@link BasicTilesContainer#getContext(Request)}. + */ + @Test + public void testGetContext() { + Request request = createMock(Request.class); + Map requestScope = createMock(Map.class); + Deque deque = createMock(Deque.class); + AttributeContext attributeContext = createMock(AttributeContext.class); + + expect(request.getContext("request")).andReturn(requestScope); + expect(requestScope.get(ATTRIBUTE_CONTEXT_STACK)).andReturn(deque); + expect(deque.isEmpty()).andReturn(false); + expect(deque.peek()).andReturn(attributeContext); + + replay(applicationContext, attributeEvaluatorFactory, + definitionsFactory, preparerFactory, rendererFactory, request, + requestScope, deque, attributeContext); + assertEquals(attributeContext, container.getContext(request)); + verify(applicationContext, attributeEvaluatorFactory, + definitionsFactory, preparerFactory, rendererFactory, request, + requestScope, deque, attributeContext); + } + + /** + * Test method for {@link BasicTilesContainer#getContext(Request)}. + */ + @Test + public void testGetContextNull() { + Request request = createMock(Request.class); + Map requestScope = createMock(Map.class); + Deque deque = createMock(Deque.class); + + expect(request.getContext("request")).andReturn(requestScope); + expect(requestScope.get(ATTRIBUTE_CONTEXT_STACK)).andReturn(deque); + expect(deque.isEmpty()).andReturn(true); + + replay(applicationContext, attributeEvaluatorFactory, + definitionsFactory, preparerFactory, rendererFactory, request, + requestScope, deque); + assertNull(container.getContext(request)); + verify(applicationContext, attributeEvaluatorFactory, + definitionsFactory, preparerFactory, rendererFactory, request, + requestScope, deque); + } + + @Test + public void testRenderRequestDefinition() throws IOException { + Request request = createMock(Request.class); + Map requestScope = createMock(Map.class); + Deque deque = createMock(Deque.class); + AttributeContext attributeContext = createMock(AttributeContext.class); + ViewPreparer preparer = createMock(ViewPreparer.class); + Renderer renderer = createMock(Renderer.class); + Definition definition = createMock(Definition.class); + AttributeEvaluator evaluator = createMock(AttributeEvaluator.class); + + Attribute templateAttribute = Attribute.createTemplateAttribute("/my/template.jsp"); + + expect(request.getContext("request")).andReturn(requestScope).times(3); + expect(requestScope.get(ATTRIBUTE_CONTEXT_STACK)).andReturn(deque).times(3); + expect(deque.isEmpty()).andReturn(false); + expect(deque.peek()).andReturn(attributeContext); + expect(attributeContext.getPreparer()).andReturn(null); + expect(attributeContext.getTemplateAttribute()).andReturn(templateAttribute); + expect(attributeContext.getLocalAttributeNames()).andReturn(null); + expect(attributeContext.getCascadedAttributeNames()).andReturn(null); + expect(definition.getTemplateAttribute()).andReturn(templateAttribute); + expect(rendererFactory.getRenderer("template")).andReturn(renderer); + deque.push(isA(BasicAttributeContext.class)); + expect(attributeEvaluatorFactory.getAttributeEvaluator(templateAttribute)).andReturn(evaluator); + expect(evaluator.evaluate(templateAttribute, request)).andReturn("/my/template.jsp"); + renderer.render("/my/template.jsp", request); + expect(deque.pop()).andReturn(null); + + replay(applicationContext, attributeEvaluatorFactory, evaluator, + definitionsFactory, preparerFactory, rendererFactory, request, + requestScope, deque, attributeContext, preparer, renderer, definition); + container.render(definition, request); + verify(applicationContext, attributeEvaluatorFactory, evaluator, + definitionsFactory, preparerFactory, rendererFactory, request, + requestScope, deque, attributeContext, preparer, renderer, definition); + } + + @Test(expected = CannotRenderException.class) + public void testRenderRequestDefinitionException() throws IOException { + Request request = createMock(Request.class); + Map requestScope = createMock(Map.class); + Deque deque = createMock(Deque.class); + AttributeContext attributeContext = createMock(AttributeContext.class); + ViewPreparer preparer = createMock(ViewPreparer.class); + Renderer renderer = createMock(Renderer.class); + Definition definition = createMock(Definition.class); + AttributeEvaluator evaluator = createMock(AttributeEvaluator.class); + + Attribute templateAttribute = Attribute.createTemplateAttribute("/my/template.jsp"); + + expect(request.getContext("request")).andReturn(requestScope).times(3); + expect(requestScope.get(ATTRIBUTE_CONTEXT_STACK)).andReturn(deque).times(3); + expect(deque.isEmpty()).andReturn(false); + expect(deque.peek()).andReturn(attributeContext); + expect(attributeContext.getPreparer()).andReturn(null); + expect(attributeContext.getTemplateAttribute()).andReturn(templateAttribute); + expect(attributeContext.getLocalAttributeNames()).andReturn(null); + expect(attributeContext.getCascadedAttributeNames()).andReturn(null); + expect(definition.getTemplateAttribute()).andReturn(templateAttribute); + expect(rendererFactory.getRenderer("template")).andReturn(renderer); + deque.push(isA(BasicAttributeContext.class)); + expect(attributeEvaluatorFactory.getAttributeEvaluator(templateAttribute)).andReturn(evaluator); + expect(evaluator.evaluate(templateAttribute, request)).andReturn("/mytemplate.jsp"); + renderer.render("/mytemplate.jsp", request); + expectLastCall().andThrow(new IOException()); + expect(deque.pop()).andReturn(null); + + replay(applicationContext, attributeEvaluatorFactory, evaluator, + definitionsFactory, preparerFactory, rendererFactory, request, + requestScope, deque, attributeContext, preparer, renderer, definition); + try { + container.render(definition, request); + } finally { + verify(applicationContext, attributeEvaluatorFactory, evaluator, + definitionsFactory, preparerFactory, rendererFactory, + request, requestScope, deque, attributeContext, preparer, + renderer, definition); + } + } + + @Test + public void testRenderRequestAttributeContext() throws IOException { + Request request = createMock(Request.class); + Map requestScope = createMock(Map.class); + Deque deque = createMock(Deque.class); + AttributeContext attributeContext = createMock(AttributeContext.class); + ViewPreparer preparer = createMock(ViewPreparer.class); + Attribute templateAttribute = createMock(Attribute.class); + Renderer renderer = createMock(Renderer.class); + AttributeEvaluator evaluator = createMock(AttributeEvaluator.class); + + expect(attributeContext.getPreparer()).andReturn(null); + expect(attributeContext.getTemplateAttribute()).andReturn(templateAttribute); + expect(templateAttribute.getRenderer()).andReturn("renderer"); + expect(rendererFactory.getRenderer("renderer")).andReturn(renderer); + expect(attributeEvaluatorFactory.getAttributeEvaluator(templateAttribute)).andReturn(evaluator); + expect(evaluator.evaluate(templateAttribute, request)).andReturn("/mytemplate.jsp"); + expect(templateAttribute.isPermitted(request)).andReturn(true); + renderer.render("/mytemplate.jsp", request); + + replay(applicationContext, attributeEvaluatorFactory, evaluator, + definitionsFactory, preparerFactory, rendererFactory, request, + requestScope, deque, attributeContext, preparer, templateAttribute, renderer); + container.render(request, attributeContext); + verify(applicationContext, attributeEvaluatorFactory, evaluator, + definitionsFactory, preparerFactory, rendererFactory, request, + requestScope, deque, attributeContext, preparer, templateAttribute, renderer); + } + + @Test(expected = CannotRenderException.class) + public void testRenderRequestAttributeContextException() throws IOException { + Request request = createMock(Request.class); + Map requestScope = createMock(Map.class); + Deque deque = createMock(Deque.class); + AttributeContext attributeContext = createMock(AttributeContext.class); + Attribute templateAttribute = createMock(Attribute.class); + Renderer renderer = createMock(Renderer.class); + AttributeEvaluator evaluator = createMock(AttributeEvaluator.class); + + expect(attributeContext.getPreparer()).andReturn("preparer").times(2); + expect(preparerFactory.getPreparer("preparer", request)).andReturn(null); + expect(attributeContext.getTemplateAttribute()).andReturn(templateAttribute); + expect(templateAttribute.getRenderer()).andReturn("renderer"); + expect(rendererFactory.getRenderer("renderer")).andReturn(renderer); + expect(attributeEvaluatorFactory.getAttributeEvaluator(templateAttribute)).andReturn(evaluator); + expect(evaluator.evaluate(templateAttribute, request)).andReturn("/mytemplate.jsp"); + expect(templateAttribute.isPermitted(request)).andReturn(true); + renderer.render("/mytemplate.jsp", request); + expectLastCall().andThrow(new IOException()); + + replay(applicationContext, attributeEvaluatorFactory, evaluator, + definitionsFactory, preparerFactory, rendererFactory, request, + requestScope, deque, attributeContext, templateAttribute, renderer); + try { + container.render(request, attributeContext); + } finally { + verify(applicationContext, attributeEvaluatorFactory, evaluator, + definitionsFactory, preparerFactory, rendererFactory, + request, requestScope, deque, attributeContext, + templateAttribute, renderer); + } + } +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/core/impl/CannotRenderExceptionTest.java b/plugins/tiles/src/test/java/org/apache/tiles/core/impl/CannotRenderExceptionTest.java new file mode 100644 index 000000000..77fb1202b --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/core/impl/CannotRenderExceptionTest.java @@ -0,0 +1,54 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tiles.core.impl; + +import org.apache.tiles.request.render.CannotRenderException; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; + +/** + * Tests {@link CannotRenderException}. + */ +public class CannotRenderExceptionTest { + + /** + * Test method for {@link CannotRenderException#CannotRenderException(String)}. + */ + @Test + public void testCannotRenderExceptionString() { + CannotRenderException exception = new CannotRenderException("my message"); + assertEquals("my message", exception.getMessage()); + assertNull(exception.getCause()); + } + + /** + * Test method for {@link CannotRenderException#CannotRenderException(String, Throwable)}. + */ + @Test + public void testCannotRenderExceptionStringThrowable() { + Throwable cause = new Throwable(); + CannotRenderException exception = new CannotRenderException("my message", cause); + assertEquals("my message", exception.getMessage()); + assertEquals(cause, exception.getCause()); + } + +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/core/impl/DefaultLocaleResolverTest.java b/plugins/tiles/src/test/java/org/apache/tiles/core/impl/DefaultLocaleResolverTest.java new file mode 100644 index 000000000..8b678ddb1 --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/core/impl/DefaultLocaleResolverTest.java @@ -0,0 +1,58 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.core.impl; + +import org.apache.tiles.core.locale.impl.DefaultLocaleResolver; +import org.apache.tiles.request.Request; +import org.junit.Test; + +import java.util.Locale; +import java.util.Map; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import static org.junit.Assert.assertSame; + +/** + * Tests {@link DefaultLocaleResolver}. + */ +public class DefaultLocaleResolverTest { + + /** + * Test method for {@link DefaultLocaleResolver#resolveLocale(Request)}. + */ + @Test + public void testResolveLocale() { + Request request = createMock(Request.class); + Map sessionScope = createMock(Map.class); + Locale locale = Locale.ITALY; + + expect(request.getContext("session")).andReturn(sessionScope); + expect(sessionScope.get(DefaultLocaleResolver.LOCALE_KEY)).andReturn(null); + expect(request.getRequestLocale()).andReturn(locale); + + replay(request, sessionScope); + DefaultLocaleResolver resolver = new DefaultLocaleResolver(); + assertSame(locale, resolver.resolveLocale(request)); + verify(request, sessionScope); + } + +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/core/impl/InvalidTemplateExceptionTest.java b/plugins/tiles/src/test/java/org/apache/tiles/core/impl/InvalidTemplateExceptionTest.java new file mode 100644 index 000000000..60e0e0bb4 --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/core/impl/InvalidTemplateExceptionTest.java @@ -0,0 +1,53 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tiles.core.impl; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; + +/** + * Tests {@link InvalidTemplateException}. + */ +public class InvalidTemplateExceptionTest { + + /** + * Test method for {@link InvalidTemplateException#InvalidTemplateException(String)}. + */ + @Test + public void testInvalidTemplateExceptionString() { + InvalidTemplateException exception = new InvalidTemplateException("my message"); + assertEquals("my message", exception.getMessage()); + assertNull(exception.getCause()); + } + + /** + * Test method for {@link InvalidTemplateException#InvalidTemplateException(Throwable)}. + */ + @Test + public void testInvalidTemplateExceptionThrowable() { + Throwable cause = new Throwable(); + InvalidTemplateException exception = new InvalidTemplateException(cause); + assertEquals(cause.toString(), exception.getMessage()); + assertEquals(cause, exception.getCause()); + } + +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/core/impl/mgmt/CachingTilesContainerTest.java b/plugins/tiles/src/test/java/org/apache/tiles/core/impl/mgmt/CachingTilesContainerTest.java new file mode 100644 index 000000000..d32fcfa2d --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/core/impl/mgmt/CachingTilesContainerTest.java @@ -0,0 +1,305 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.core.impl.mgmt; + +import org.apache.tiles.api.Definition; +import org.apache.tiles.api.TilesContainer; +import org.apache.tiles.core.definition.NoSuchDefinitionException; +import org.apache.tiles.request.Request; +import org.junit.Before; +import org.junit.Test; + +import java.util.HashMap; +import java.util.Map; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.eq; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.isA; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertTrue; + +/** + * Tests {@link CachingTilesContainer}. + * + * @version $Rev$ $Date$ + */ +public class CachingTilesContainerTest { + + /** + * The default name of the attribute in which storing custom definitions. + */ + private static final String DEFAULT_DEFINITIONS_ATTRIBUTE_NAME = + "org.apache.tiles.impl.mgmt.DefinitionManager.DEFINITIONS"; + + /** + * The wrapped Tiles container. + */ + private TilesContainer wrapped; + + /** + * The Tiles container to test. + */ + private CachingTilesContainer container; + + /** + * Sets up the test. + */ + @Before + public void setUp() { + wrapped = createMock(TilesContainer.class); + container = new CachingTilesContainer(wrapped); + } + + @Test + public void testCachingTilesContainer() { + Request request = createMock(Request.class); + Map definitions = createMock(Map.class); + Map scope = createMock(Map.class); + Definition definition = createMock(Definition.class); + TilesContainer wrapped = createMock(TilesContainer.class); + + expect(request.getContext("request")).andReturn(scope); + expect(scope.get(DEFAULT_DEFINITIONS_ATTRIBUTE_NAME)).andReturn(definitions); + expect(definitions.get("definition")).andReturn(definition); + + replay(wrapped, request, definitions, scope, definition); + CachingTilesContainer container = new CachingTilesContainer(wrapped); + assertSame(definition, container.getDefinition("definition", request)); + verify(wrapped, request, definitions, scope, definition); + } + + @Test + public void testGetDefinition() { + Request request = createMock(Request.class); + Map definitions = createMock(Map.class); + Map scope = createMock(Map.class); + Definition definition = createMock(Definition.class); + + expect(request.getContext("request")).andReturn(scope); + expect(scope.get(DEFAULT_DEFINITIONS_ATTRIBUTE_NAME)).andReturn( + definitions); + expect(definitions.get("definition")).andReturn(definition); + + replay(wrapped, request, definitions, scope, definition); + assertSame(definition, container.getDefinition("definition", request)); + verify(wrapped, request, definitions, scope, definition); + } + + @Test + public void testGetDefinitionContainer() { + Request request = createMock(Request.class); + Map scope = createMock(Map.class); + Definition definition = createMock(Definition.class); + + expect(request.getContext("request")).andReturn(scope); + expect(scope.get(DEFAULT_DEFINITIONS_ATTRIBUTE_NAME)).andReturn( + null); + expect(wrapped.getDefinition("definition", request)).andReturn( + definition); + + replay(wrapped, request, scope, definition); + assertSame(definition, container.getDefinition("definition", request)); + verify(wrapped, request, scope, definition); + } + + @Test + public void testIsValidDefinition() { + Request request = createMock(Request.class); + Map definitions = createMock(Map.class); + Map scope = createMock(Map.class); + Definition definition = createMock(Definition.class); + + expect(request.getContext("request")).andReturn(scope); + expect(scope.get(DEFAULT_DEFINITIONS_ATTRIBUTE_NAME)).andReturn(definitions); + expect(definitions.get("definition")).andReturn(definition); + + replay(wrapped, request, definitions, scope, definition); + assertTrue(container.isValidDefinition("definition", request)); + verify(wrapped, request, definitions, scope, definition); + } + + @Test + public void testIsValidDefinitionContainer() { + Request request = createMock(Request.class); + Map definitions = createMock(Map.class); + Map scope = createMock(Map.class); + + expect(request.getContext("request")).andReturn(scope); + expect(scope.get(DEFAULT_DEFINITIONS_ATTRIBUTE_NAME)).andReturn(definitions); + expect(definitions.get("definition")).andReturn(null); + expect(wrapped.isValidDefinition("definition", request)).andReturn(true); + + replay(wrapped, request, definitions, scope); + assertTrue(container.isValidDefinition("definition", request)); + verify(wrapped, request, definitions, scope); + } + + @Test + public void testRegister() { + Request request = createMock(Request.class); + Map definitions = createMock(Map.class); + Map scope = createMock(Map.class); + Definition definition = createMock(Definition.class); + + expect(request.getContext("request")).andReturn(scope); + expect(scope.get(DEFAULT_DEFINITIONS_ATTRIBUTE_NAME)).andReturn(definitions); + expect(definition.getName()).andReturn(null); + expect(definitions.containsKey("$anonymousMutableDefinition1")).andReturn(false); + definition.setName("$anonymousMutableDefinition1"); + expect(definition.isExtending()).andReturn(true); + // trick to test resolve definition separately. + expect(definition.isExtending()).andReturn(false); + expect(definition.getName()).andReturn("$anonymousMutableDefinition1"); + expect(definitions.put("$anonymousMutableDefinition1", definition)).andReturn(null); + + replay(wrapped, request, definitions, scope, definition); + container.register(definition, request); + verify(wrapped, request, definitions, scope, definition); + } + + @Test + public void testRegisterInheritance() { + Request request = createMock(Request.class); + Map definitions = createMock(Map.class); + Map scope = createMock(Map.class); + Definition definition = createMock(Definition.class); + Definition parent = createMock(Definition.class); + Definition grandparent = createMock(Definition.class); + + expect(request.getContext("request")).andReturn(scope).anyTimes(); + expect(scope.get(DEFAULT_DEFINITIONS_ATTRIBUTE_NAME)).andReturn( + definitions).anyTimes(); + expect(definition.getName()).andReturn(null); + expect(definitions.containsKey("$anonymousMutableDefinition1")) + .andReturn(false); + definition.setName("$anonymousMutableDefinition1"); + expect(definition.isExtending()).andReturn(true); + // trick to test resolve definition separately. + expect(definition.isExtending()).andReturn(true); + expect(definition.getExtends()).andReturn("parent"); + expect(definitions.get("parent")).andReturn(parent); + expect(parent.isExtending()).andReturn(true); + expect(parent.getExtends()).andReturn("grandparent"); + expect(definition.getName()).andReturn("$anonymousMutableDefinition1"); + expect(definitions.get("grandparent")).andReturn(null); + expect(wrapped.getDefinition("grandparent", request)).andReturn( + grandparent); + parent.inherit(grandparent); + definition.inherit(parent); + expect(definitions.put("$anonymousMutableDefinition1", definition)) + .andReturn(null); + + replay(wrapped, request, definitions, scope, definition, parent, + grandparent); + container.register(definition, request); + verify(wrapped, request, definitions, scope, definition, parent, + grandparent); + } + + @Test(expected = NoSuchDefinitionException.class) + public void testRegisterInheritanceFail() { + Request request = createMock(Request.class); + Map definitions = createMock(Map.class); + Map scope = createMock(Map.class); + Definition definition = createMock(Definition.class); + + expect(request.getContext("request")).andReturn(scope).anyTimes(); + expect(scope.get(DEFAULT_DEFINITIONS_ATTRIBUTE_NAME)).andReturn( + definitions).anyTimes(); + expect(definition.getName()).andReturn(null); + expect(definitions.containsKey("$anonymousMutableDefinition1")) + .andReturn(false); + definition.setName("$anonymousMutableDefinition1"); + expect(definition.isExtending()).andReturn(true); + // trick to test resolve definition separately. + expect(definition.isExtending()).andReturn(true); + expect(definition.getExtends()).andReturn("parent"); + expect(definitions.get("parent")).andReturn(null); + expect(wrapped.getDefinition("parent", request)).andReturn(null); + expect(definition.getName()).andReturn("$anonymousMutableDefinition1"); + + replay(wrapped, request, definitions, scope, definition); + try { + container.register(definition, request); + } finally { + verify(wrapped, request, definitions, scope, definition); + } + } + + @Test + public void testRegisterCreateDefinitions() { + Request request = createMock(Request.class); + Map scope = createMock(Map.class); + Definition definition = createMock(Definition.class); + + expect(request.getContext("request")).andReturn(scope).anyTimes(); + expect(scope.get(DEFAULT_DEFINITIONS_ATTRIBUTE_NAME)).andReturn( + null); + expect(scope.put(eq(DEFAULT_DEFINITIONS_ATTRIBUTE_NAME), isA(HashMap.class))).andReturn(null); + expect(definition.getName()).andReturn(null); + definition.setName("$anonymousMutableDefinition1"); + expect(definition.isExtending()).andReturn(true); + // trick to test resolve definition separately. + expect(definition.isExtending()).andReturn(false); + expect(definition.getName()).andReturn("$anonymousMutableDefinition1"); + + replay(wrapped, request, scope, definition); + container.register(definition, request); + verify(wrapped, request, scope, definition); + } + + @Test + public void testRender() { + Request request = createMock(Request.class); + Map definitions = createMock(Map.class); + Map scope = createMock(Map.class); + Definition definition = createMock(Definition.class); + + expect(request.getContext("request")).andReturn(scope); + expect(scope.get(DEFAULT_DEFINITIONS_ATTRIBUTE_NAME)).andReturn(definitions); + expect(definitions.get("definition")).andReturn(definition); + container.render(definition, request); + + replay(wrapped, request, definitions, scope, definition); + container.render("definition", request); + verify(wrapped, request, definitions, scope, definition); + } + + @Test(expected = NoSuchDefinitionException.class) + public void testRenderFail() { + Request request = createMock(Request.class); + Map definitions = createMock(Map.class); + Map scope = createMock(Map.class); + + expect(request.getContext("request")).andReturn(scope); + expect(scope.get(DEFAULT_DEFINITIONS_ATTRIBUTE_NAME)).andReturn(definitions); + expect(definitions.get("definition")).andReturn(null); + expect(wrapped.getDefinition("definition", request)).andReturn(null); + + replay(wrapped, request, definitions, scope); + try { + container.render("definition", request); + } finally { + verify(wrapped, request, definitions, scope); + } + } +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/core/renderer/DefinitionRendererTest.java b/plugins/tiles/src/test/java/org/apache/tiles/core/renderer/DefinitionRendererTest.java new file mode 100644 index 000000000..70e6fba58 --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/core/renderer/DefinitionRendererTest.java @@ -0,0 +1,106 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.core.renderer; + +import org.apache.tiles.api.TilesContainer; +import org.apache.tiles.request.Request; +import org.apache.tiles.request.render.CannotRenderException; +import org.junit.Before; +import org.junit.Test; + +import java.io.IOException; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +/** + * Tests {@link DefinitionRenderer}. + */ +public class DefinitionRendererTest { + + /** + * The renderer. + */ + private DefinitionRenderer renderer; + + /** + * The container. + */ + private TilesContainer container; + + /** + * {@inheritDoc} + */ + @Before + public void setUp() { + container = createMock(TilesContainer.class); + renderer = new DefinitionRenderer(container); + } + + /** + * Tests + * {@link DefinitionRenderer#render(String, Request)}. + * + * @throws IOException If something goes wrong during rendition. + */ + @Test + public void testWrite() throws IOException { + Request requestContext = createMock(Request.class); + container.render("my.definition", requestContext); + replay(requestContext, container); + renderer.render("my.definition", requestContext); + verify(requestContext, container); + } + + /** + * Tests + * {@link DefinitionRenderer#render(String, Request)}. + * + * @throws IOException If something goes wrong during rendition. + */ + @Test(expected = CannotRenderException.class) + public void testRenderException() throws IOException { + Request requestContext = createMock(Request.class); + replay(requestContext, container); + try { + renderer.render(null, requestContext); + } finally { + verify(requestContext, container); + } + } + + /** + * Tests + * {@link DefinitionRenderer#isRenderable(String, Request)} + * . + */ + @Test + public void testIsRenderable() { + Request requestContext = createMock(Request.class); + expect(container.isValidDefinition("my.definition", requestContext)).andReturn(Boolean.TRUE); + replay(requestContext, container); + assertTrue(renderer.isRenderable("my.definition", requestContext)); + assertFalse(renderer.isRenderable(null, requestContext)); + verify(requestContext, container); + } +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/core/startup/AbstractTilesInitializerTest.java b/plugins/tiles/src/test/java/org/apache/tiles/core/startup/AbstractTilesInitializerTest.java new file mode 100644 index 000000000..fa7789132 --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/core/startup/AbstractTilesInitializerTest.java @@ -0,0 +1,130 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tiles.core.startup; + +import org.apache.tiles.api.TilesContainer; +import org.apache.tiles.api.access.TilesAccess; +import org.apache.tiles.core.factory.AbstractTilesContainerFactory; +import org.apache.tiles.request.ApplicationAccess; +import org.apache.tiles.request.ApplicationContext; +import org.junit.Before; +import org.junit.Test; + +import java.util.Map; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; + +/** + * Tests {@link AbstractTilesInitializer}. + * + * @version $Rev$ $Date$ + */ +public class AbstractTilesInitializerTest { + + /** + * A mock Tiles container factory. + */ + private AbstractTilesContainerFactory containerFactory; + + /** + * The object to test. + */ + private AbstractTilesInitializer initializer; + + /** + * Sets up the test. + */ + @Before + public void setUp() { + containerFactory = createMock(AbstractTilesContainerFactory.class); + initializer = new AbstractTilesInitializer() { + + @Override + protected AbstractTilesContainerFactory createContainerFactory( + ApplicationContext context) { + return containerFactory; + } + }; + } + + /** + * Test method for {@link AbstractTilesInitializer#initialize(ApplicationContext)}. + */ + @Test + public void testInitialize() { + ApplicationContext context = createMock(ApplicationContext.class); + TilesContainer container = createMock(TilesContainer.class); + Map scope = createMock(Map.class); + + expect(containerFactory.createContainer(context)).andReturn(container); + expect(context.getApplicationScope()).andReturn(scope).anyTimes(); + expect(scope.put(ApplicationAccess.APPLICATION_CONTEXT_ATTRIBUTE, + context)).andReturn(null); + expect(scope.put(TilesAccess.CONTAINER_ATTRIBUTE, container)).andReturn(null); + expect(scope.remove(TilesAccess.CONTAINER_ATTRIBUTE)).andReturn(container); + + replay(containerFactory, context, container, scope); + initializer.initialize(context); + initializer.destroy(); + verify(containerFactory, context, container, scope); + } + + /** + * Test method for {@link AbstractTilesInitializer#createTilesApplicationContext(ApplicationContext)}. + */ + @Test + public void testCreateTilesApplicationContext() { + ApplicationContext context = createMock(ApplicationContext.class); + replay(containerFactory, context); + assertEquals(context, initializer.createTilesApplicationContext(context)); + verify(containerFactory, context); + } + + /** + * Test method for {@link AbstractTilesInitializer#getContainerKey(ApplicationContext)}. + */ + @Test + public void testGetContainerKey() { + ApplicationContext context = createMock(ApplicationContext.class); + replay(containerFactory, context); + assertNull(initializer.getContainerKey(context)); + verify(containerFactory, context); + } + + /** + * Test method for {@link AbstractTilesInitializer#createContainer(ApplicationContext)}. + */ + @Test + public void testCreateContainer() { + ApplicationContext context = createMock(ApplicationContext.class); + TilesContainer container = createMock(TilesContainer.class); + + expect(containerFactory.createContainer(context)).andReturn(container); + + replay(containerFactory, context, container); + assertEquals(container, initializer.createContainer(context)); + verify(containerFactory, context, container); + } +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/core/util/CombinedBeanInfoTest.java b/plugins/tiles/src/test/java/org/apache/tiles/core/util/CombinedBeanInfoTest.java new file mode 100644 index 000000000..b1108d3bd --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/core/util/CombinedBeanInfoTest.java @@ -0,0 +1,93 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.core.util; + +import org.apache.tiles.request.ApplicationContext; +import org.apache.tiles.request.Request; +import org.apache.tiles.request.reflect.ClassUtil; +import org.junit.Before; +import org.junit.Test; + +import java.beans.FeatureDescriptor; +import java.beans.PropertyDescriptor; +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +import static org.junit.Assert.assertEquals; + +/** + * Tests {@link CombinedBeanInfo}. + */ +public class CombinedBeanInfoTest { + + /** + * The bean info to test. + */ + private CombinedBeanInfo beanInfo; + + /** + * The property descriptors. + */ + private List descriptors; + + /** + * The map of property descriptors for request. + */ + private Map requestMap; + + /** + * The map of property descriptors for application. + */ + private Map applicationMap; + + /** + * Sets up the test. + */ + @Before + public void setUp() { + beanInfo = new CombinedBeanInfo(Request.class, ApplicationContext.class); + requestMap = new LinkedHashMap<>(); + ClassUtil.collectBeanInfo(Request.class, requestMap); + applicationMap = new LinkedHashMap<>(); + ClassUtil.collectBeanInfo(ApplicationContext.class, applicationMap); + descriptors = new ArrayList<>(); + descriptors.addAll(requestMap.values()); + descriptors.addAll(applicationMap.values()); + } + + @Test + public void testGetDescriptors() { + assertEquals(descriptors, beanInfo.getDescriptors()); + } + + @Test + public void testGetMappedDescriptors() { + assertEquals(requestMap, beanInfo.getMappedDescriptors(Request.class)); + assertEquals(applicationMap, beanInfo.getMappedDescriptors(ApplicationContext.class)); + } + + @Test + public void testGetProperties() { + assertEquals(requestMap.keySet(), beanInfo.getProperties(Request.class)); + assertEquals(applicationMap.keySet(), beanInfo.getProperties(ApplicationContext.class)); + } + +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/el/ELAttributeEvaluatorTest.java b/plugins/tiles/src/test/java/org/apache/tiles/el/ELAttributeEvaluatorTest.java new file mode 100644 index 000000000..8c1c794ba --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/el/ELAttributeEvaluatorTest.java @@ -0,0 +1,189 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.el; + +import com.sun.el.ExpressionFactoryImpl; +import junit.framework.TestCase; +import org.apache.tiles.api.Attribute; +import org.apache.tiles.api.Expression; +import org.apache.tiles.request.ApplicationContext; +import org.apache.tiles.request.Request; +import org.easymock.EasyMock; + +import javax.el.ArrayELResolver; +import javax.el.BeanELResolver; +import javax.el.CompositeELResolver; +import javax.el.ELResolver; +import javax.el.ListELResolver; +import javax.el.MapELResolver; +import javax.el.ResourceBundleELResolver; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; + +/** + * Tests {@link ELAttributeEvaluator}. + */ +public class ELAttributeEvaluatorTest extends TestCase { + + /** + * The evaluator to test. + */ + private ELAttributeEvaluator evaluator; + + /** + * The request object to use. + */ + private Request request; + + /** {@inheritDoc} */ + @Override + protected void setUp() throws Exception { + super.setUp(); + evaluator = new ELAttributeEvaluator(); + Map requestScope = new HashMap<>(); + Map sessionScope = new HashMap<>(); + Map applicationScope = new HashMap<>(); + requestScope.put("object1", "value"); + sessionScope.put("object2", 1); + applicationScope.put("object3", 2.0F); + requestScope.put("paulaBean", new PaulaBean()); + request = EasyMock.createMock(Request.class); + EasyMock.expect(request.getContext("request")).andReturn(requestScope) + .anyTimes(); + EasyMock.expect(request.getContext("session")).andReturn(sessionScope) + .anyTimes(); + EasyMock.expect(request.getContext("application")).andReturn( + applicationScope).anyTimes(); + EasyMock.expect(request.getAvailableScopes()).andReturn( + Arrays.asList("request", "session", "application")).anyTimes(); + ApplicationContext applicationContext = EasyMock + .createMock(ApplicationContext.class); + EasyMock.expect(request.getApplicationContext()).andReturn( + applicationContext).anyTimes(); + EasyMock.replay(request, applicationContext); + + evaluator.setExpressionFactory(new ExpressionFactoryImpl()); + ELResolver elResolver = new CompositeELResolver() { + { + BeanELResolver beanElResolver = new BeanELResolver(false); + add(new ScopeELResolver()); + add(new TilesContextELResolver(beanElResolver)); + add(new TilesContextBeanELResolver()); + add(new ArrayELResolver(false)); + add(new ListELResolver(false)); + add(new MapELResolver(false)); + add(new ResourceBundleELResolver()); + add(beanElResolver); + } + }; + evaluator.setResolver(elResolver); + } + + /** + * Tests + * {@link ELAttributeEvaluator#evaluate(Attribute, Request)}. + */ + public void testEvaluate() { + Attribute attribute = new Attribute(); + attribute.setExpressionObject(new Expression("${requestScope.object1}")); + assertEquals("The value is not correct", "value", evaluator.evaluate( + attribute, request)); + attribute.setExpressionObject(new Expression("${sessionScope.object2}")); + assertEquals("The value is not correct", 1, evaluator + .evaluate(attribute, request)); + attribute.setExpressionObject(new Expression("${applicationScope.object3}")); + assertEquals("The value is not correct", 2.0F, evaluator + .evaluate(attribute, request)); + attribute.setExpressionObject(new Expression("${object1}")); + assertEquals("The value is not correct", "value", evaluator.evaluate( + attribute, request)); + attribute.setExpressionObject(new Expression("${object2}")); + assertEquals("The value is not correct", 1, evaluator + .evaluate(attribute, request)); + attribute.setExpressionObject(new Expression("${object3}")); + assertEquals("The value is not correct", 2.0F, evaluator + .evaluate(attribute, request)); + attribute.setExpressionObject(new Expression("${paulaBean.paula}")); + assertEquals("The value is not correct", "Brillant", evaluator + .evaluate(attribute, request)); + attribute.setExpressionObject(new Expression("String literal")); + assertEquals("The value is not correct", "String literal", evaluator + .evaluate(attribute, request)); + attribute.setValue(2); + assertEquals("The value is not correct", 2, evaluator + .evaluate(attribute, request)); + attribute.setValue("${object1}"); + assertEquals("The value has been evaluated", "${object1}", evaluator + .evaluate(attribute, request)); + } + + /** + * Tests + * {@link ELAttributeEvaluator#evaluate(String, Request)}. + */ + public void testEvaluateString() { + String expression = "${requestScope.object1}"; + assertEquals("The value is not correct", "value", evaluator.evaluate( + expression, request)); + expression = "${sessionScope.object2}"; + assertEquals("The value is not correct", 1, evaluator + .evaluate(expression, request)); + expression = "${applicationScope.object3}"; + assertEquals("The value is not correct", 2.0F, evaluator + .evaluate(expression, request)); + expression = "${object1}"; + assertEquals("The value is not correct", "value", evaluator.evaluate( + expression, request)); + expression = "${object2}"; + assertEquals("The value is not correct", 1, evaluator + .evaluate(expression, request)); + expression = "${object3}"; + assertEquals("The value is not correct", 2.0F, evaluator + .evaluate(expression, request)); + expression = "${paulaBean.paula}"; + assertEquals("The value is not correct", "Brillant", evaluator + .evaluate(expression, request)); + expression = "String literal"; + assertEquals("The value is not correct", expression, evaluator + .evaluate(expression, request)); + } + + /** + * This is The Brillant Paula Bean (sic) just like it was posted to: + * http://thedailywtf.com/Articles/The_Brillant_Paula_Bean.aspx + * I hope that there is no copyright on it. + */ + public static class PaulaBean { + + /** + * Paula is brillant, really. + */ + private final String paula = "Brillant"; + + /** + * Returns brillant. + * + * @return "Brillant". + */ + public String getPaula() { + return paula; + } + } +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/el/ELContextImplTest.java b/plugins/tiles/src/test/java/org/apache/tiles/el/ELContextImplTest.java new file mode 100644 index 000000000..b9a835318 --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/el/ELContextImplTest.java @@ -0,0 +1,120 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.el; + +import org.junit.Before; +import org.junit.Test; + +import javax.el.ELResolver; +import javax.el.FunctionMapper; +import javax.el.ValueExpression; +import javax.el.VariableMapper; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; + +/** + * Tests {@link ELContextImpl}. + */ +public class ELContextImplTest { + + /** + * The EL context to test. + */ + private ELContextImpl context; + + /** + * The EL resolver. + */ + private ELResolver resolver; + + /** + * Sets up the test. + */ + @Before + public void setUp() { + resolver = createMock(ELResolver.class); + context = new ELContextImpl(resolver); + } + + /** + * Test method for {@link ELContextImpl#getELResolver()}. + */ + @Test + public void testGetELResolver() { + replay(resolver); + assertEquals(resolver, context.getELResolver()); + verify(resolver); + } + + /** + * Test method for {@link ELContextImpl#setFunctionMapper(FunctionMapper)}. + */ + @Test + public void testSetFunctionMapper() { + FunctionMapper functionMapper = createMock(FunctionMapper.class); + + replay(resolver, functionMapper); + context.setFunctionMapper(functionMapper); + assertEquals(functionMapper, context.getFunctionMapper()); + verify(resolver, functionMapper); + } + + /** + * Test method for {@link ELContextImpl#setVariableMapper(VariableMapper)}. + */ + @Test + public void testSetVariableMapper() { + VariableMapper variableMapper = createMock(VariableMapper.class); + + replay(resolver, variableMapper); + context.setVariableMapper(variableMapper); + assertEquals(variableMapper, context.getVariableMapper()); + verify(resolver, variableMapper); + } + + /** + * Tests {@link ELContextImpl#getFunctionMapper()}. + */ + @Test + public void testNullFunctionMapper() { + replay(resolver); + FunctionMapper functionMapper = context.getFunctionMapper(); + assertNull(functionMapper.resolveFunction("whatever", "it_IT")); + verify(resolver); + } + + /** + * Tests {@link ELContextImpl#getVariableMapper()}. + */ + @Test + public void testVariableMapperImpl() { + ValueExpression expression = createMock(ValueExpression.class); + + replay(resolver, expression); + VariableMapper variableMapper = context.getVariableMapper(); + assertNull(variableMapper.resolveVariable("whatever")); + variableMapper.setVariable("var", expression); + assertEquals(expression, variableMapper.resolveVariable("var")); + verify(resolver, expression); + } +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/el/JspExpressionFactoryFactoryTest.java b/plugins/tiles/src/test/java/org/apache/tiles/el/JspExpressionFactoryFactoryTest.java new file mode 100644 index 000000000..b7092e530 --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/el/JspExpressionFactoryFactoryTest.java @@ -0,0 +1,84 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.el; + +import org.apache.tiles.request.ApplicationContext; +import org.junit.Test; + +import javax.el.ExpressionFactory; +import javax.servlet.ServletContext; +import javax.servlet.jsp.JspApplicationContext; +import javax.servlet.jsp.JspFactory; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import static org.junit.Assert.assertEquals; + +/** + * Tests {@link JspExpressionFactoryFactory}. + */ +public class JspExpressionFactoryFactoryTest { + + /** + * Test method for {@link JspExpressionFactoryFactory#getExpressionFactory()}. + */ + @Test + public void testGetExpressionFactory() { + ApplicationContext applicationContext = createMock(ApplicationContext.class); + ServletContext servletContext = createMock(ServletContext.class); + JspFactory jspFactory = createMock(JspFactory.class); + JspApplicationContext jspApplicationContext = createMock(JspApplicationContext.class); + ExpressionFactory expressionFactory = createMock(ExpressionFactory.class); + + expect(applicationContext.getContext()).andReturn(servletContext); + expect(jspFactory.getJspApplicationContext(servletContext)).andReturn(jspApplicationContext); + expect(jspApplicationContext.getExpressionFactory()).andReturn(expressionFactory); + + replay(applicationContext, servletContext, jspFactory, + jspApplicationContext, expressionFactory); + JspFactory.setDefaultFactory(jspFactory); + JspExpressionFactoryFactory factory = new JspExpressionFactoryFactory(); + factory.setApplicationContext(applicationContext); + assertEquals(expressionFactory, factory.getExpressionFactory()); + verify(applicationContext, servletContext, jspFactory, + jspApplicationContext, expressionFactory); + } + + /** + * Test method for {@link JspExpressionFactoryFactory#getExpressionFactory()}. + */ + @Test(expected = IllegalArgumentException.class) + public void testSetApplicationContextIllegal() { + ApplicationContext applicationContext = createMock(ApplicationContext.class); + Integer servletContext = 1; + + expect(applicationContext.getContext()).andReturn(servletContext); + + replay(applicationContext); + try { + JspExpressionFactoryFactory factory = new JspExpressionFactoryFactory(); + factory.setApplicationContext(applicationContext); + } finally { + verify(applicationContext); + } + } + +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/el/ScopeELResolverTest.java b/plugins/tiles/src/test/java/org/apache/tiles/el/ScopeELResolverTest.java new file mode 100644 index 000000000..bdd8d799e --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/el/ScopeELResolverTest.java @@ -0,0 +1,175 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.el; + +import org.apache.tiles.request.ApplicationContext; +import org.apache.tiles.request.Request; +import org.junit.Before; +import org.junit.Test; + +import javax.el.ELContext; +import java.beans.FeatureDescriptor; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + +/** + * Tests {@link ScopeELResolver}. + */ +public class ScopeELResolverTest { + + /** + * The resolver to test. + */ + private ScopeELResolver resolver; + + /** + * {@inheritDoc} + */ + @Before + public void setUp() { + resolver = new ScopeELResolver(); + } + + /** + * Tests {@link ScopeELResolver#getCommonPropertyType(ELContext, Object)}. + */ + @Test + public void testGetCommonPropertyType() { + ELContext elContext = createMock(ELContext.class); + + replay(elContext); + assertNull(resolver.getCommonPropertyType(elContext, 1)); + assertEquals(Map.class, resolver.getCommonPropertyType(elContext, null)); + verify(elContext); + } + + /** + * Tests {@link ScopeELResolver#getFeatureDescriptors(ELContext, Object)}. + */ + @Test + public void testGetFeatureDescriptors() { + ELContext elContext = createMock(ELContext.class); + Request request = createMock(Request.class); + + expect(elContext.getContext(Request.class)).andReturn(request); + expect(request.getAvailableScopes()).andReturn(Arrays.asList("one", "two")); + + replay(elContext, request); + assertFalse(resolver.getFeatureDescriptors(elContext, 1).hasNext()); + Iterator descriptors = resolver.getFeatureDescriptors(elContext, null); + FeatureDescriptor descriptor = descriptors.next(); + assertEquals("oneScope", descriptor.getName()); + descriptor = descriptors.next(); + assertEquals("twoScope", descriptor.getName()); + assertFalse(descriptors.hasNext()); + verify(elContext, request); + } + + /** + * Test method for + * {@link ScopeELResolver#getType(ELContext, Object, Object)}. + */ + @Test + public void testGetType() { + Request request = createMock(Request.class); + ApplicationContext applicationContext = createMock(ApplicationContext.class); + ELContext context = new ELContextImpl(resolver); + replay(request, applicationContext); + context.putContext(Request.class, request); + context.putContext(ApplicationContext.class, applicationContext); + assertNull(resolver.getType(context, 1, "whatever")); + assertEquals("The requestScope object is not a map.", Map.class, + resolver.getType(context, null, "requestScope")); + assertEquals("The sessionScope object is not a map.", Map.class, + resolver.getType(context, null, "sessionScope")); + assertEquals("The applicationScope object is not a map.", Map.class, + resolver.getType(context, null, "applicationScope")); + } + + /** + * Test method for + * {@link ScopeELResolver#getValue(ELContext, Object, Object)}. + */ + @Test + public void testGetValue() { + Map requestScope = new HashMap<>(); + requestScope.put("objectKey", "objectValue"); + Map sessionScope = new HashMap<>(); + sessionScope.put("sessionObjectKey", "sessionObjectValue"); + Map applicationScope = new HashMap<>(); + applicationScope.put("applicationObjectKey", "applicationObjectValue"); + Request request = createMock(Request.class); + expect(request.getContext("request")).andReturn(requestScope); + expect(request.getContext("session")).andReturn(sessionScope); + ApplicationContext applicationContext = createMock(ApplicationContext.class); + expect(request.getContext("application")).andReturn(applicationScope); + ELContext context = new ELContextImpl(resolver); + replay(request, applicationContext); + context.putContext(Request.class, request); + context.putContext(ApplicationContext.class, applicationContext); + assertNull(resolver.getValue(context, 1, "whatever")); + assertEquals("The requestScope map does not correspond", requestScope, + resolver.getValue(context, null, "requestScope")); + assertEquals("The sessionScope map does not correspond", sessionScope, + resolver.getValue(context, null, "sessionScope")); + assertEquals("The applicationScope map does not correspond", + applicationScope, resolver.getValue(context, null, + "applicationScope")); + } + + /** + * Tests {@link ScopeELResolver#isReadOnly(ELContext, Object, Object)}. + */ + @Test + public void testIsReadOnly() { + ELContext elContext = createMock(ELContext.class); + + replay(elContext); + assertTrue(resolver.isReadOnly(elContext, null, "whatever")); + verify(elContext); + } + + /** + * Tests {@link ScopeELResolver#isReadOnly(ELContext, Object, Object)}. + */ + @Test(expected = NullPointerException.class) + public void testIsReadOnlyNPE() { + resolver.isReadOnly(null, null, "whatever"); + } + + /** + * Tests {@link ScopeELResolver#setValue(ELContext, Object, Object, Object)}. + */ + @Test + public void testSetValue() { + // Just to complete code coverage! + resolver.setValue(null, null, null, null); + } +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/el/TilesContextBeanELResolverTest.java b/plugins/tiles/src/test/java/org/apache/tiles/el/TilesContextBeanELResolverTest.java new file mode 100644 index 000000000..5a1214ec2 --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/el/TilesContextBeanELResolverTest.java @@ -0,0 +1,299 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.el; + +import org.apache.tiles.request.ApplicationContext; +import org.apache.tiles.request.Request; +import org.junit.Before; +import org.junit.Test; + +import javax.el.ELContext; +import java.beans.FeatureDescriptor; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + +/** + * Tests {@link TilesContextBeanELResolver}. + */ +public class TilesContextBeanELResolverTest { + + /** + * The resolver to test. + */ + private TilesContextBeanELResolver resolver; + + /** + * Sets up the test. + */ + @Before + public void setUp() { + resolver = new TilesContextBeanELResolver(); + } + + /** + * Test method for + * {@link TilesContextBeanELResolver#getCommonPropertyType(ELContext, Object)}. + */ + @Test + public void testGetCommonPropertyType() { + Class clazz = resolver.getCommonPropertyType(null, null); + assertEquals("The class is not correct", String.class, clazz); + clazz = resolver.getCommonPropertyType(null, "Base object"); + assertNull("The class for non root objects must be null", clazz); + } + + /** + * Test method for + * {@link TilesContextBeanELResolver#getFeatureDescriptors(ELContext, Object)}. + */ + @Test + public void testGetFeatureDescriptors() { + Map requestScope = new HashMap<>(); + Map sessionScope = new HashMap<>(); + Map applicationScope = new HashMap<>(); + requestScope.put("object1", "value"); + sessionScope.put("object2", 1); + applicationScope.put("object3", 2.0F); + Request request = createMock(Request.class); + expect(request.getContext("request")).andReturn(requestScope) + .anyTimes(); + expect(request.getContext("session")).andReturn(sessionScope) + .anyTimes(); + ApplicationContext applicationContext = createMock(ApplicationContext.class); + expect(request.getContext("application")).andReturn( + applicationScope).anyTimes(); + expect(request.getAvailableScopes()).andReturn( + Arrays.asList("request", "session", "application")) + .anyTimes(); + replay(request, applicationContext); + + ELContext context = new ELContextImpl(resolver); + context.putContext(Request.class, request); + context.putContext(ApplicationContext.class, applicationContext); + + List expected = new ArrayList<>(); + resolver.collectBeanInfo(requestScope, expected); + resolver.collectBeanInfo(sessionScope, expected); + resolver.collectBeanInfo(applicationScope, expected); + Iterator featureIt = resolver.getFeatureDescriptors( + context, null); + Iterator expectedIt = expected.iterator(); + while (featureIt.hasNext() && expectedIt.hasNext()) { + FeatureDescriptor expectedDescriptor = expectedIt.next(); + FeatureDescriptor descriptor = featureIt.next(); + assertEquals("The feature is not the same", expectedDescriptor + .getDisplayName(), descriptor.getDisplayName()); + assertEquals("The feature is not the same", expectedDescriptor + .getName(), descriptor.getName()); + assertEquals("The feature is not the same", expectedDescriptor + .getShortDescription(), descriptor.getShortDescription()); + assertEquals("The feature is not the same", expectedDescriptor + .getValue("type"), descriptor.getValue("type")); + assertEquals("The feature is not the same", expectedDescriptor + .getValue("resolvableAtDesignTime"), descriptor + .getValue("resolvableAtDesignTime")); + assertEquals("The feature is not the same", expectedDescriptor + .isExpert(), descriptor.isExpert()); + assertEquals("The feature is not the same", expectedDescriptor + .isHidden(), descriptor.isHidden()); + assertEquals("The feature is not the same", expectedDescriptor + .isPreferred(), descriptor.isPreferred()); + } + assertTrue("The feature descriptors are not of the same size", + !featureIt.hasNext() && !expectedIt.hasNext()); + } + + /** + * Test method for + * {@link TilesContextBeanELResolver#getType(ELContext, Object, Object)}. + */ + @Test + public void testGetType() { + Map requestScope = new HashMap<>(); + Map sessionScope = new HashMap<>(); + Map applicationScope = new HashMap<>(); + requestScope.put("object1", "value"); + sessionScope.put("object2", 1); + applicationScope.put("object3", 2.0F); + Request request = createMock(Request.class); + expect(request.getContext("request")).andReturn(requestScope) + .anyTimes(); + expect(request.getContext("session")).andReturn(sessionScope) + .anyTimes(); + ApplicationContext applicationContext = createMock(ApplicationContext.class); + expect(request.getContext("application")).andReturn( + applicationScope).anyTimes(); + expect(request.getAvailableScopes()).andReturn( + Arrays.asList("request", "session", "application")) + .anyTimes(); + replay(request, applicationContext); + + ELContext context = new ELContextImpl(resolver); + context.putContext(Request.class, request); + context.putContext(ApplicationContext.class, applicationContext); + + assertEquals("The type is not correct", String.class, resolver.getType( + context, null, "object1")); + assertEquals("The type is not correct", Integer.class, resolver.getType( + context, null, "object2")); + assertEquals("The type is not correct", Float.class, resolver.getType( + context, null, "object3")); + assertNull(resolver.getType(context, 1, "whatever")); + assertNull(resolver.getType(context, null, "object4")); + verify(request, applicationContext); + } + + /** + * Test method for + * {@link TilesContextBeanELResolver#getValue(ELContext, Object, Object)}. + */ + @Test + public void testGetValue() { + Map requestScope = new HashMap<>(); + Map sessionScope = new HashMap<>(); + Map applicationScope = new HashMap<>(); + requestScope.put("object1", "value"); + sessionScope.put("object2", 1); + applicationScope.put("object3", 2.0F); + Request request = createMock(Request.class); + expect(request.getContext("request")).andReturn(requestScope) + .anyTimes(); + expect(request.getContext("session")).andReturn(sessionScope) + .anyTimes(); + ApplicationContext applicationContext = createMock(ApplicationContext.class); + expect(request.getContext("application")).andReturn( + applicationScope).anyTimes(); + expect(request.getAvailableScopes()).andReturn( + Arrays.asList("request", "session", "application")) + .anyTimes(); + replay(request, applicationContext); + + ELContext context = new ELContextImpl(resolver); + context.putContext(Request.class, request); + context.putContext(ApplicationContext.class, applicationContext); + + assertEquals("The value is not correct", "value", resolver.getValue( + context, null, "object1")); + assertEquals("The value is not correct", 1, resolver + .getValue(context, null, "object2")); + assertEquals("The value is not correct", 2.0F, resolver + .getValue(context, null, "object3")); + assertNull(resolver.getValue(context, 1, "whatever")); + } + + /** + * Test method for + * {@link TilesContextBeanELResolver#isReadOnly(ELContext, Object, Object)}. + */ + @Test + public void testIsReadOnlyELContextObjectObject() { + ELContext context = new ELContextImpl(resolver); + assertTrue("The value is not read only", resolver.isReadOnly(context, + null, null)); + } + + /** + * Test method for + * {@link TilesContextBeanELResolver#isReadOnly(ELContext, Object, Object)}. + */ + @Test(expected = NullPointerException.class) + public void testIsReadOnlyNPE() { + resolver.isReadOnly(null, null, null); + } + + /** + * Tests {@link TilesContextBeanELResolver#setValue(ELContext, Object, Object, Object)}. + */ + @Test + public void testSetValue() { + // Just to complete code coverage! + resolver.setValue(null, null, null, null); + } + + /** + * Test method for + * {@link TilesContextBeanELResolver#findObjectByProperty(ELContext, Object)}. + */ + @Test + public void testFindObjectByProperty() { + Map requestScope = new HashMap<>(); + Map sessionScope = new HashMap<>(); + Map applicationScope = new HashMap<>(); + requestScope.put("object1", "value"); + sessionScope.put("object2", 1); + applicationScope.put("object3", 2.0F); + Request request = createMock(Request.class); + expect(request.getContext("request")).andReturn(requestScope) + .anyTimes(); + expect(request.getContext("session")).andReturn(sessionScope) + .anyTimes(); + ApplicationContext applicationContext = createMock(ApplicationContext.class); + expect(request.getContext("application")).andReturn( + applicationScope).anyTimes(); + expect(request.getAvailableScopes()).andReturn( + Arrays.asList("request", "session", "application")) + .anyTimes(); + replay(request, applicationContext); + + ELContext context = new ELContextImpl(resolver); + context.putContext(Request.class, request); + context.putContext(ApplicationContext.class, applicationContext); + + assertEquals("The value is not correct", "value", resolver + .findObjectByProperty(context, "object1")); + assertEquals("The value is not correct", 1, resolver + .findObjectByProperty(context, "object2")); + assertEquals("The value is not correct", 2.0F, resolver + .findObjectByProperty(context, "object3")); + } + + /** + * Test method for + * {@link TilesContextBeanELResolver#getObject(Map, String)}. + */ + @Test + public void testGetObject() { + Map map = new HashMap<>(); + map.put("object1", "value"); + assertEquals("The value is not correct", "value", resolver.getObject( + map, "object1")); + assertNull("The value is not null", resolver.getObject(map, "object2")); + assertNull("The value is not null", resolver.getObject(null, "object1")); + } + + /** + * Tests {@link TilesContextBeanELResolver#collectBeanInfo(Map, List)}. + */ + @Test + public void testCollectBeanInfoEmpty() { + resolver.collectBeanInfo(null, null); + } +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/el/TilesContextELResolverTest.java b/plugins/tiles/src/test/java/org/apache/tiles/el/TilesContextELResolverTest.java new file mode 100644 index 000000000..c3685aaf9 --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/el/TilesContextELResolverTest.java @@ -0,0 +1,189 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.el; + +import org.apache.tiles.request.ApplicationContext; +import org.apache.tiles.request.Request; +import org.apache.tiles.request.reflect.ClassUtil; +import org.junit.Before; +import org.junit.Test; + +import javax.el.ELContext; +import javax.el.ELResolver; +import java.beans.FeatureDescriptor; +import java.beans.PropertyDescriptor; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.Map; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.expectLastCall; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + +/** + * Tests {@link TilesContextELResolver}. + */ +public class TilesContextELResolverTest { + + /** + * The bean resolver. + */ + private ELResolver beanElResolver; + + /** + * The resolver to test. + */ + private TilesContextELResolver resolver; + + /** + * Sets up the test. + */ + @Before + public void setUp() { + beanElResolver = createMock(ELResolver.class); + resolver = new TilesContextELResolver(beanElResolver); + } + + /** + * Test method for + * {@link TilesContextELResolver#getCommonPropertyType(ELContext, Object)}. + */ + @Test + public void testGetCommonPropertyTypeELContextObject() { + replay(beanElResolver); + Class clazz = resolver.getCommonPropertyType(null, null); + assertEquals("The class is not correct", String.class, clazz); + clazz = resolver.getCommonPropertyType(null, "Base object"); + assertNull("The class for non root objects must be null", clazz); + verify(beanElResolver); + } + + /** + * Test method for + * {@link TilesContextELResolver#getFeatureDescriptors(ELContext, Object)}. + */ + @Test + public void testGetFeatureDescriptorsELContextObject() { + replay(beanElResolver); + assertNull(resolver.getFeatureDescriptors(null, 1)); + Map expected = new LinkedHashMap<>(); + ClassUtil.collectBeanInfo(Request.class, expected); + ClassUtil.collectBeanInfo(ApplicationContext.class, expected); + Iterator featureIt = resolver.getFeatureDescriptors( + null, null); + Iterator expectedIt = expected.values().iterator(); + while (featureIt.hasNext() && expectedIt.hasNext()) { + assertEquals("The feature is not the same", expectedIt.next(), + featureIt.next()); + } + assertTrue("The feature descriptors are not of the same size", + !featureIt.hasNext() && !expectedIt.hasNext()); + verify(beanElResolver); + } + + /** + * Tests {@link TilesContextBeanELResolver#getType(ELContext, Object, Object)}. + */ + @SuppressWarnings({"unchecked", "rawtypes"}) + @Test + public void testGetType() { + ELContext elContext = createMock(ELContext.class); + Request request = createMock(Request.class); + ApplicationContext applicationContext = createMock(ApplicationContext.class); + + expect(elContext.getContext(Request.class)).andReturn(request); + expect(elContext.getContext(ApplicationContext.class)).andReturn(applicationContext); + expect(beanElResolver.getType(elContext, request, "responseCommitted")).andReturn((Class) Boolean.class); + expect(beanElResolver.getType(elContext, applicationContext, "initParams")).andReturn((Class) Map.class); + elContext.setPropertyResolved(true); + expectLastCall().times(2); + + replay(beanElResolver, elContext, request, applicationContext); + assertNull(resolver.getType(elContext, 1, "whatever")); + assertEquals(Boolean.class, resolver.getType(elContext, null, "responseCommitted")); + assertEquals(Map.class, resolver.getType(elContext, null, "initParams")); + verify(beanElResolver, elContext, request, applicationContext); + } + + /** + * Tests {@link TilesContextBeanELResolver#getValue(ELContext, Object, Object)}. + */ + @Test + public void testGetValue() { + ELContext elContext = createMock(ELContext.class); + Request request = createMock(Request.class); + ApplicationContext applicationContext = createMock(ApplicationContext.class); + @SuppressWarnings("rawtypes") + Map map = createMock(Map.class); + + expect(elContext.getContext(Request.class)).andReturn(request); + expect(elContext.getContext(ApplicationContext.class)).andReturn(applicationContext); + expect(beanElResolver.getValue(elContext, request, "responseCommitted")).andReturn(true); + expect(beanElResolver.getValue(elContext, applicationContext, "initParams")).andReturn(map); + elContext.setPropertyResolved(true); + expectLastCall().times(2); + + replay(beanElResolver, elContext, request, applicationContext, map); + assertNull(resolver.getValue(elContext, 1, "whatever")); + assertEquals(true, resolver.getValue(elContext, null, "responseCommitted")); + assertEquals(map, resolver.getValue(elContext, null, "initParams")); + verify(beanElResolver, elContext, request, applicationContext, map); + } + + /** + * Test method for + * {@link TilesContextELResolver#isReadOnly(ELContext, Object, Object)}. + */ + @Test + public void testIsReadOnly() { + replay(beanElResolver); + ELContext context = new ELContextImpl(resolver); + assertTrue("The value is not read only", resolver.isReadOnly(context, + null, null)); + verify(beanElResolver); + } + + /** + * Test method for + * {@link TilesContextELResolver#isReadOnly(ELContext, Object, Object)}. + */ + @Test(expected = NullPointerException.class) + public void testIsReadOnlyNPE() { + replay(beanElResolver); + try { + resolver.isReadOnly(null, null, null); + } finally { + verify(beanElResolver); + } + } + + /** + * Tests {@link TilesContextELResolver#setValue(ELContext, Object, Object, Object)}. + */ + @Test + public void testSetValue() { + // Just to complete code coverage! + resolver.setValue(null, null, null, null); + } +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/ognl/AnyScopePropertyAccessorTest.java b/plugins/tiles/src/test/java/org/apache/tiles/ognl/AnyScopePropertyAccessorTest.java new file mode 100644 index 000000000..c7f3465cc --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/ognl/AnyScopePropertyAccessorTest.java @@ -0,0 +1,152 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.ognl; + +import org.apache.tiles.request.Request; +import org.junit.Before; +import org.junit.Test; + +import java.util.Arrays; +import java.util.Map; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; + +/** + * Tests {@link AnyScopePropertyAccessor}. + */ +public class AnyScopePropertyAccessorTest { + + /** + * The accessor to test. + */ + private AnyScopePropertyAccessor accessor; + + /** + * Sets up the test. + */ + @Before + public void setUp() { + accessor = new AnyScopePropertyAccessor(); + } + + /** + * Test method for {@link AnyScopePropertyAccessor#getProperty(Map, Object, Object)}. + */ + @Test + public void testGetProperty() { + Request request = createMock(Request.class); + Map oneScope = createMock(Map.class); + Map twoScope = createMock(Map.class); + + expect(request.getAvailableScopes()).andReturn(Arrays.asList("one", "two")).anyTimes(); + expect(request.getContext("one")).andReturn(oneScope).anyTimes(); + expect(request.getContext("two")).andReturn(twoScope).anyTimes(); + expect(oneScope.containsKey("name1")).andReturn(true); + expect(oneScope.get("name1")).andReturn("value1"); + expect(oneScope.containsKey("name2")).andReturn(false); + expect(oneScope.containsKey("name3")).andReturn(false); + expect(twoScope.containsKey("name2")).andReturn(true); + expect(twoScope.get("name2")).andReturn("value2"); + expect(twoScope.containsKey("name3")).andReturn(false); + + replay(request, oneScope, twoScope); + assertEquals("value1", accessor.getProperty(null, request, "name1")); + assertEquals("value2", accessor.getProperty(null, request, "name2")); + assertNull(accessor.getProperty(null, request, "name3")); + verify(request, oneScope, twoScope); + } + + @Test + public void testGetSourceAccessor() { + Request request = createMock(Request.class); + Map oneScope = createMock(Map.class); + Map twoScope = createMock(Map.class); + + expect(request.getAvailableScopes()).andReturn(Arrays.asList("one", "two")).anyTimes(); + expect(request.getContext("one")).andReturn(oneScope).anyTimes(); + expect(request.getContext("two")).andReturn(twoScope).anyTimes(); + expect(oneScope.containsKey("name1")).andReturn(true); + expect(oneScope.containsKey("name2")).andReturn(false); + expect(oneScope.containsKey("name3")).andReturn(false); + expect(twoScope.containsKey("name2")).andReturn(true); + expect(twoScope.containsKey("name3")).andReturn(false); + + replay(request, oneScope, twoScope); + assertEquals(".getContext(\"one\").get(index)", accessor.getSourceAccessor(null, request, "name1")); + assertEquals(".getContext(\"two\").get(index)", accessor.getSourceAccessor(null, request, "name2")); + assertNull(accessor.getSourceAccessor(null, request, "name3")); + verify(request, oneScope, twoScope); + } + + @Test + public void testGetSourceSetter() { + Request request = createMock(Request.class); + Map oneScope = createMock(Map.class); + Map twoScope = createMock(Map.class); + + expect(request.getAvailableScopes()).andReturn(Arrays.asList("one", "two")).anyTimes(); + expect(request.getContext("one")).andReturn(oneScope).anyTimes(); + expect(request.getContext("two")).andReturn(twoScope).anyTimes(); + expect(oneScope.containsKey("name1")).andReturn(true); + expect(oneScope.containsKey("name2")).andReturn(false); + expect(oneScope.containsKey("name3")).andReturn(false); + expect(twoScope.containsKey("name2")).andReturn(true); + expect(twoScope.containsKey("name3")).andReturn(false); + + replay(request, oneScope, twoScope); + assertEquals(".getContext(\"one\").put(index, target)", accessor.getSourceSetter(null, request, "name1")); + assertEquals(".getContext(\"two\").put(index, target)", accessor.getSourceSetter(null, request, "name2")); + assertEquals(".getContext(\"one\").put(index, target)", accessor.getSourceSetter(null, request, "name3")); + verify(request, oneScope, twoScope); + } + + /** + * Test method for {@link AnyScopePropertyAccessor#setProperty(Map, Object, Object, Object)}. + */ + @Test + public void testSetProperty() { + Request request = createMock(Request.class); + Map oneScope = createMock(Map.class); + Map twoScope = createMock(Map.class); + + expect(request.getAvailableScopes()).andReturn(Arrays.asList("one", "two")).anyTimes(); + expect(request.getContext("one")).andReturn(oneScope).anyTimes(); + expect(request.getContext("two")).andReturn(twoScope).anyTimes(); + expect(oneScope.containsKey("name1")).andReturn(true); + expect(oneScope.put("name1", "otherValue1")).andReturn("value1"); + expect(oneScope.containsKey("name2")).andReturn(false); + expect(oneScope.containsKey("name3")).andReturn(false); + expect(twoScope.containsKey("name2")).andReturn(true); + expect(twoScope.put("name2", "otherValue2")).andReturn("value2"); + expect(twoScope.containsKey("name3")).andReturn(false); + expect(oneScope.put("name3", "otherValue3")).andReturn(null); + + replay(request, oneScope, twoScope); + accessor.setProperty(null, request, "name1", "otherValue1"); + accessor.setProperty(null, request, "name2", "otherValue2"); + accessor.setProperty(null, request, "name3", "otherValue3"); + verify(request, oneScope, twoScope); + } + +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/ognl/DelegatePropertyAccessorTest.java b/plugins/tiles/src/test/java/org/apache/tiles/ognl/DelegatePropertyAccessorTest.java new file mode 100644 index 000000000..fc5470d74 --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/ognl/DelegatePropertyAccessorTest.java @@ -0,0 +1,111 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tiles.ognl; + +import ognl.OgnlContext; +import ognl.OgnlException; +import ognl.PropertyAccessor; +import org.junit.Test; + +import java.util.Map; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import static org.junit.Assert.assertEquals; + +/** + * Tests {@link DelegatePropertyAccessor}. + */ +public class DelegatePropertyAccessorTest { + + /** + * Test method for {@link DelegatePropertyAccessor#getProperty(Map, Object, Object)}. + * + * @throws OgnlException If something goes wrong. + */ + @Test + public void testGetProperty() throws OgnlException { + PropertyAccessorDelegateFactory factory = createMock(PropertyAccessorDelegateFactory.class); + PropertyAccessor mockAccessor = createMock(PropertyAccessor.class); + Map context = createMock(Map.class); + expect(factory.getPropertyAccessor("property", 1)).andReturn(mockAccessor); + expect(mockAccessor.getProperty(context, 1, "property")).andReturn("value"); + + replay(factory, mockAccessor, context); + PropertyAccessor accessor = new DelegatePropertyAccessor<>(factory); + assertEquals("value", accessor.getProperty(context, 1, "property")); + verify(factory, mockAccessor, context); + } + + /** + * Test method for {@link DelegatePropertyAccessor#setProperty(Map, Object, Object, Object)}. + * + * @throws OgnlException If something goes wrong. + */ + @Test + public void testSetProperty() throws OgnlException { + PropertyAccessorDelegateFactory factory = createMock(PropertyAccessorDelegateFactory.class); + PropertyAccessor mockAccessor = createMock(PropertyAccessor.class); + Map context = createMock(Map.class); + expect(factory.getPropertyAccessor("property", 1)).andReturn(mockAccessor); + mockAccessor.setProperty(context, 1, "property", "value"); + + replay(factory, mockAccessor, context); + PropertyAccessor accessor = new DelegatePropertyAccessor<>(factory); + accessor.setProperty(context, 1, "property", "value"); + verify(factory, mockAccessor, context); + } + + /** + * Test method for {@link DelegatePropertyAccessor#getSourceAccessor(OgnlContext, Object, Object)}. + */ + @Test + public void testGetSourceAccessor() { + PropertyAccessorDelegateFactory factory = createMock(PropertyAccessorDelegateFactory.class); + PropertyAccessor mockAccessor = createMock(PropertyAccessor.class); + OgnlContext context = createMock(OgnlContext.class); + expect(factory.getPropertyAccessor("property", 1)).andReturn(mockAccessor); + expect(mockAccessor.getSourceAccessor(context, 1, "property")).andReturn("method"); + + replay(factory, mockAccessor, context); + PropertyAccessor accessor = new DelegatePropertyAccessor<>(factory); + assertEquals("method", accessor.getSourceAccessor(context, 1, "property")); + verify(factory, mockAccessor, context); + } + + /** + * Test method for {@link DelegatePropertyAccessor#getSourceSetter(OgnlContext, Object, Object)}. + */ + @Test + public void testGetSourceSetter() { + PropertyAccessorDelegateFactory factory = createMock(PropertyAccessorDelegateFactory.class); + PropertyAccessor mockAccessor = createMock(PropertyAccessor.class); + OgnlContext context = createMock(OgnlContext.class); + expect(factory.getPropertyAccessor("property", 1)).andReturn(mockAccessor); + expect(mockAccessor.getSourceSetter(context, 1, "property")).andReturn("method"); + + replay(factory, mockAccessor, context); + PropertyAccessor accessor = new DelegatePropertyAccessor<>(factory); + assertEquals("method", accessor.getSourceSetter(context, 1, "property")); + verify(factory, mockAccessor, context); + } +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/ognl/NestedObjectDelegatePropertyAccessorTest.java b/plugins/tiles/src/test/java/org/apache/tiles/ognl/NestedObjectDelegatePropertyAccessorTest.java new file mode 100644 index 000000000..0425d3c1c --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/ognl/NestedObjectDelegatePropertyAccessorTest.java @@ -0,0 +1,106 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.ognl; + +import ognl.OgnlContext; +import ognl.OgnlException; +import ognl.PropertyAccessor; +import org.junit.Test; + +import java.util.Map; + +import static org.easymock.EasyMock.*; +import static org.junit.Assert.assertEquals; + +/** + * Tests {@link NestedObjectDelegatePropertyAccessor}. + */ +public class NestedObjectDelegatePropertyAccessorTest { + + /** + * Test method for {@link NestedObjectDelegatePropertyAccessor#getProperty(Map, Object, Object)}. + * @throws OgnlException If something goes wrong. + */ + @Test + public void testGetProperty() throws OgnlException { + NestedObjectExtractor nestedObjectExtractor = createMock(NestedObjectExtractor.class); + PropertyAccessor propertyAccessor = createMock(PropertyAccessor.class); + Map context = createMock(Map.class); + expect(propertyAccessor.getProperty(context, "nested", "property")).andReturn("value"); + expect(nestedObjectExtractor.getNestedObject(1)).andReturn("nested"); + + replay(nestedObjectExtractor, propertyAccessor, context); + PropertyAccessor accessor = new NestedObjectDelegatePropertyAccessor<>(nestedObjectExtractor, propertyAccessor); + assertEquals("value", accessor.getProperty(context, 1, "property")); + verify(nestedObjectExtractor, propertyAccessor, context); + } + + /** + * Test method for {@link NestedObjectDelegatePropertyAccessor#setProperty(Map, Object, Object, Object)}. + * @throws OgnlException If something goes wrong. + */ + @Test + public void testSetProperty() throws OgnlException { + NestedObjectExtractor nestedObjectExtractor = createMock(NestedObjectExtractor.class); + PropertyAccessor propertyAccessor = createMock(PropertyAccessor.class); + Map context = createMock(Map.class); + propertyAccessor.setProperty(context, "nested", "property", "value"); + expect(nestedObjectExtractor.getNestedObject(1)).andReturn("nested"); + + replay(nestedObjectExtractor, propertyAccessor, context); + PropertyAccessor accessor = new NestedObjectDelegatePropertyAccessor<>(nestedObjectExtractor, propertyAccessor); + accessor.setProperty(context, 1, "property", "value"); + verify(nestedObjectExtractor, propertyAccessor, context); + } + + /** + * Test method for {@link NestedObjectDelegatePropertyAccessor#getSourceAccessor(OgnlContext, Object, Object)}. + */ + @Test + public void testGetSourceAccessor() { + NestedObjectExtractor nestedObjectExtractor = createMock(NestedObjectExtractor.class); + PropertyAccessor propertyAccessor = createMock(PropertyAccessor.class); + OgnlContext context = createMock(OgnlContext.class); + expect(propertyAccessor.getSourceAccessor(context, "nested", "property")).andReturn("method"); + expect(nestedObjectExtractor.getNestedObject(1)).andReturn("nested"); + + replay(nestedObjectExtractor, propertyAccessor, context); + PropertyAccessor accessor = new NestedObjectDelegatePropertyAccessor<>(nestedObjectExtractor, propertyAccessor); + assertEquals("method", accessor.getSourceAccessor(context, 1, "property")); + verify(nestedObjectExtractor, propertyAccessor, context); + } + + /** + * Test method for {@link NestedObjectDelegatePropertyAccessor#getSourceSetter(OgnlContext, Object, Object)}. + */ + @Test + public void testGetSourceSetter() { + NestedObjectExtractor nestedObjectExtractor = createMock(NestedObjectExtractor.class); + PropertyAccessor propertyAccessor = createMock(PropertyAccessor.class); + OgnlContext context = createMock(OgnlContext.class); + expect(propertyAccessor.getSourceSetter(context, "nested", "property")).andReturn("method"); + expect(nestedObjectExtractor.getNestedObject(1)).andReturn("nested"); + + replay(nestedObjectExtractor, propertyAccessor, context); + PropertyAccessor accessor = new NestedObjectDelegatePropertyAccessor<>(nestedObjectExtractor, propertyAccessor); + assertEquals("method", accessor.getSourceSetter(context, 1, "property")); + verify(nestedObjectExtractor, propertyAccessor, context); + } + +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/ognl/OGNLAttributeEvaluatorTest.java b/plugins/tiles/src/test/java/org/apache/tiles/ognl/OGNLAttributeEvaluatorTest.java new file mode 100644 index 000000000..fbfe2081b --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/ognl/OGNLAttributeEvaluatorTest.java @@ -0,0 +1,229 @@ +/* + * $Id$ + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.ognl; + +import ognl.OgnlException; +import ognl.OgnlRuntime; +import ognl.PropertyAccessor; +import org.apache.tiles.api.Attribute; +import org.apache.tiles.api.Expression; +import org.apache.tiles.core.evaluator.EvaluationException; +import org.apache.tiles.request.ApplicationContext; +import org.apache.tiles.request.Request; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import static org.junit.Assert.assertEquals; + +/** + * Tests {@link OGNLAttributeEvaluator}. + * + * @version $Rev$ $Date$$ + */ +public class OGNLAttributeEvaluatorTest { + + /** + * The evaluator to test. + */ + private OGNLAttributeEvaluator evaluator; + + /** + * The request object to use. + */ + private Request request; + + /** + * The application context. + */ + private ApplicationContext applicationContext; + + /** + * Sets up the test. + * + * @throws OgnlException If something goes wrong. + */ + @Before + public void setUp() throws OgnlException { + PropertyAccessor objectPropertyAccessor = OgnlRuntime.getPropertyAccessor(Object.class); + PropertyAccessor applicationContextPropertyAccessor = new NestedObjectDelegatePropertyAccessor<>( + new TilesApplicationContextNestedObjectExtractor(), + objectPropertyAccessor + ); + PropertyAccessor anyScopePropertyAccessor = new AnyScopePropertyAccessor(); + PropertyAccessor scopePropertyAccessor = new ScopePropertyAccessor(); + PropertyAccessorDelegateFactory factory = new TilesContextPropertyAccessorDelegateFactory( + objectPropertyAccessor, + applicationContextPropertyAccessor, + anyScopePropertyAccessor, + scopePropertyAccessor + ); + PropertyAccessor tilesRequestAccessor = new DelegatePropertyAccessor<>(factory); + OgnlRuntime.setPropertyAccessor(Request.class, tilesRequestAccessor); + evaluator = new OGNLAttributeEvaluator(); + Map requestScope = new HashMap<>(); + Map sessionScope = new HashMap<>(); + Map applicationScope = new HashMap<>(); + requestScope.put("object1", "value"); + sessionScope.put("object2", 1); + applicationScope.put("object3", 2.0F); + requestScope.put("paulaBean", new PaulaBean()); + request = createMock(Request.class); + expect(request.getContext("request")).andReturn(requestScope) + .anyTimes(); + expect(request.getContext("session")).andReturn(sessionScope) + .anyTimes(); + expect(request.getContext("application")).andReturn(applicationScope) + .anyTimes(); + expect(request.getAvailableScopes()).andReturn(Arrays.asList("request", "session", "application")) + .anyTimes(); + applicationContext = createMock(ApplicationContext.class); + expect(request.getApplicationContext()).andReturn(applicationContext) + .anyTimes(); + expect(applicationContext.getApplicationScope()).andReturn(applicationScope) + .anyTimes(); + replay(request, applicationContext); + } + + /** + * Tears down the test. + */ + @After + public void tearDown() { + verify(request, applicationContext); + } + + /** + * Tests + * {@link OGNLAttributeEvaluator#evaluate(Attribute, Request)}. + */ + @Test + public void testEvaluate() { + Attribute attribute = new Attribute(); + attribute.setExpressionObject(new Expression("requestScope.object1")); + assertEquals("The value is not correct", "value", evaluator.evaluate( + attribute, request)); + attribute.setExpressionObject(new Expression("sessionScope.object2")); + assertEquals("The value is not correct", 1, evaluator + .evaluate(attribute, request)); + attribute.setExpressionObject(new Expression("applicationScope.object3")); + assertEquals("The value is not correct", 2.0F, evaluator + .evaluate(attribute, request)); + attribute.setExpressionObject(new Expression("object1")); + assertEquals("The value is not correct", "value", evaluator.evaluate( + attribute, request)); + attribute.setExpressionObject(new Expression("object2")); + assertEquals("The value is not correct", 1, evaluator + .evaluate(attribute, request)); + attribute.setExpressionObject(new Expression("object3")); + assertEquals("The value is not correct", 2.0F, evaluator + .evaluate(attribute, request)); + attribute.setExpressionObject(new Expression("paulaBean.paula")); + assertEquals("The value is not correct", "Brillant", evaluator + .evaluate(attribute, request)); + attribute.setExpressionObject(new Expression("'String literal'")); + assertEquals("The value is not correct", "String literal", evaluator + .evaluate(attribute, request)); + attribute.setValue(2); + assertEquals("The value is not correct", 2, evaluator + .evaluate(attribute, request)); + attribute.setValue("object1"); + assertEquals("The value has been evaluated", "object1", evaluator + .evaluate(attribute, request)); + } + + /** + * Tests {@link OGNLAttributeEvaluator#evaluate(String, Request)}. + */ + @Test + public void testEvaluateString() { + String expression = "requestScope.object1"; + assertEquals("The value is not correct", "value", evaluator.evaluate( + expression, request)); + expression = "sessionScope.object2"; + assertEquals("The value is not correct", 1, evaluator + .evaluate(expression, request)); + expression = "applicationScope.object3"; + assertEquals("The value is not correct", 2.0F, evaluator + .evaluate(expression, request)); + expression = "object1"; + assertEquals("The value is not correct", "value", evaluator.evaluate( + expression, request)); + expression = "object2"; + assertEquals("The value is not correct", 1, evaluator + .evaluate(expression, request)); + expression = "object3"; + assertEquals("The value is not correct", 2.0F, evaluator + .evaluate(expression, request)); + expression = "paulaBean.paula"; + assertEquals("The value is not correct", "Brillant", evaluator + .evaluate(expression, request)); + expression = "'String literal'"; + assertEquals("The value is not correct", "String literal", evaluator + .evaluate(expression, request)); + } + + /** + * Tests {@link OGNLAttributeEvaluator#evaluate(String, Request)}. + */ + @Test(expected = IllegalArgumentException.class) + public void testEvaluateNull() { + evaluator.evaluate((String) null, request); + } + + /** + * Tests {@link OGNLAttributeEvaluator#evaluate(String, Request)}. + */ + @Test(expected = EvaluationException.class) + public void testEvaluateOgnlException() { + evaluator.evaluate("wrong|||!!!!yes###", request); + } + + /** + * This is The Brillant Paula Bean (sic) just like it was posted to: + * http://thedailywtf.com/Articles/The_Brillant_Paula_Bean.aspx I hope that + * there is no copyright on it. + */ + public static class PaulaBean { + + /** + * Paula is brillant, really. + */ + private final String paula = "Brillant"; + + /** + * Returns brillant. + * + * @return "Brillant". + */ + public String getPaula() { + return paula; + } + } +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/ognl/ScopePropertyAccessorTest.java b/plugins/tiles/src/test/java/org/apache/tiles/ognl/ScopePropertyAccessorTest.java new file mode 100644 index 000000000..86b29449c --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/ognl/ScopePropertyAccessorTest.java @@ -0,0 +1,91 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.ognl; + +import org.apache.tiles.request.Request; +import org.junit.Before; +import org.junit.Test; + +import java.util.Map; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; + +/** + * Tests {@link ScopePropertyAccessor}. + */ +public class ScopePropertyAccessorTest { + + /** + * The accessor to test. + */ + private ScopePropertyAccessor accessor; + + /** + * Sets up the test. + */ + @Before + public void setUp() { + accessor = new ScopePropertyAccessor(); + } + + /** + * Test method for {@link ScopePropertyAccessor#getProperty(Map, Object, Object)}. + */ + @Test + public void testGetProperty() { + Request request = createMock(Request.class); + Map oneScope = createMock(Map.class); + + expect(request.getContext("one")).andReturn(oneScope); + + replay(request); + assertEquals(oneScope, accessor.getProperty(null, request, "oneScope")); + assertNull(accessor.getProperty(null, request, "whatever")); + verify(request); + } + + @Test + public void testGetSourceAccessor() { + Request request = createMock(Request.class); + + replay(request); + assertEquals(".getContext(\"one\")", accessor.getSourceAccessor(null, request, "oneScope")); + assertNull(accessor.getSourceAccessor(null, request, "whatever")); + verify(request); + } + + @Test + public void testGetSourceSetter() { + assertNull(accessor.getSourceSetter(null, null, "whatever")); + } + + /** + * Test method for {@link ScopePropertyAccessor#setProperty(Map, Object, Object, Object)}. + */ + @Test + public void testSetProperty() { + accessor.setProperty(null, null, "whatever", "whateverValue"); + } + +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/ognl/TilesApplicationContextNestedObjectExtractorTest.java b/plugins/tiles/src/test/java/org/apache/tiles/ognl/TilesApplicationContextNestedObjectExtractorTest.java new file mode 100644 index 000000000..b791a646c --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/ognl/TilesApplicationContextNestedObjectExtractorTest.java @@ -0,0 +1,51 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tiles.ognl; + +import org.apache.tiles.request.ApplicationContext; +import org.apache.tiles.request.Request; +import org.junit.Test; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import static org.junit.Assert.assertEquals; + +/** + * Tests {@link TilesApplicationContextNestedObjectExtractor}. + */ +public class TilesApplicationContextNestedObjectExtractorTest { + + /** + * Tests {@link TilesApplicationContextNestedObjectExtractor#getNestedObject(Request)}. + */ + @Test + public void testGetNestedObject() { + Request request = createMock(Request.class); + ApplicationContext applicationContext = createMock(ApplicationContext.class); + expect(request.getApplicationContext()).andReturn(applicationContext); + + replay(request, applicationContext); + NestedObjectExtractor extractor = new TilesApplicationContextNestedObjectExtractor(); + assertEquals(applicationContext, extractor.getNestedObject(request)); + verify(request, applicationContext); + } +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/ognl/TilesContextPropertyAccessorDelegateFactoryTest.java b/plugins/tiles/src/test/java/org/apache/tiles/ognl/TilesContextPropertyAccessorDelegateFactoryTest.java new file mode 100644 index 000000000..8a70ae220 --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/ognl/TilesContextPropertyAccessorDelegateFactoryTest.java @@ -0,0 +1,189 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tiles.ognl; + +import ognl.PropertyAccessor; +import org.apache.tiles.request.ApplicationContext; +import org.apache.tiles.request.Request; +import org.junit.Test; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import static org.junit.Assert.assertEquals; + +/** + * Tests {@link TilesContextPropertyAccessorDelegateFactory}. + */ +public class TilesContextPropertyAccessorDelegateFactoryTest { + + /** + * Test method for + * {@link TilesContextPropertyAccessorDelegateFactory#getPropertyAccessor(String, Request)} + * . + */ + @Test + public void testGetPropertyAccessorRequest() { + PropertyAccessor objectPropertyAccessor = createMock(PropertyAccessor.class); + PropertyAccessor applicationContextPropertyAccessor = createMock(PropertyAccessor.class); + PropertyAccessor requestScopePropertyAccessor = createMock(PropertyAccessor.class); + PropertyAccessor sessionScopePropertyAccessor = createMock(PropertyAccessor.class); + PropertyAccessor applicationScopePropertyAccessor = createMock(PropertyAccessor.class); + Request request = createMock(Request.class); + + replay(objectPropertyAccessor, applicationContextPropertyAccessor, requestScopePropertyAccessor, + sessionScopePropertyAccessor, applicationScopePropertyAccessor, request); + PropertyAccessorDelegateFactory factory = new TilesContextPropertyAccessorDelegateFactory( + objectPropertyAccessor, applicationContextPropertyAccessor, + requestScopePropertyAccessor, sessionScopePropertyAccessor); + assertEquals(objectPropertyAccessor, factory.getPropertyAccessor("writer", request)); + + verify(objectPropertyAccessor, applicationContextPropertyAccessor, requestScopePropertyAccessor, + sessionScopePropertyAccessor, applicationScopePropertyAccessor, request); + } + + /** + * Test method for + * {@link TilesContextPropertyAccessorDelegateFactory#getPropertyAccessor(String, Request)} + * . + */ + @Test + public void testGetPropertyAccessorApplication() { + PropertyAccessor objectPropertyAccessor = createMock(PropertyAccessor.class); + PropertyAccessor applicationContextPropertyAccessor = createMock(PropertyAccessor.class); + PropertyAccessor requestScopePropertyAccessor = createMock(PropertyAccessor.class); + PropertyAccessor sessionScopePropertyAccessor = createMock(PropertyAccessor.class); + PropertyAccessor applicationScopePropertyAccessor = createMock(PropertyAccessor.class); + Request request = createMock(Request.class); + + replay(objectPropertyAccessor, applicationContextPropertyAccessor, requestScopePropertyAccessor, + sessionScopePropertyAccessor, applicationScopePropertyAccessor, request); + PropertyAccessorDelegateFactory factory = new TilesContextPropertyAccessorDelegateFactory( + objectPropertyAccessor, applicationContextPropertyAccessor, + requestScopePropertyAccessor, sessionScopePropertyAccessor); + assertEquals(applicationContextPropertyAccessor, factory.getPropertyAccessor("initParams", request)); + + verify(objectPropertyAccessor, applicationContextPropertyAccessor, requestScopePropertyAccessor, + sessionScopePropertyAccessor, applicationScopePropertyAccessor, request); + } + + /** + * Test method for + * {@link TilesContextPropertyAccessorDelegateFactory#getPropertyAccessor(String, Request)} + * . + */ + @Test + public void testGetPropertyAccessorRequestScope() { + PropertyAccessor objectPropertyAccessor = createMock(PropertyAccessor.class); + PropertyAccessor applicationContextPropertyAccessor = createMock(PropertyAccessor.class); + PropertyAccessor requestScopePropertyAccessor = createMock(PropertyAccessor.class); + PropertyAccessor sessionScopePropertyAccessor = createMock(PropertyAccessor.class); + PropertyAccessor applicationScopePropertyAccessor = createMock(PropertyAccessor.class); + Request request = createMock(Request.class); + + replay(objectPropertyAccessor, applicationContextPropertyAccessor, requestScopePropertyAccessor, + sessionScopePropertyAccessor, applicationScopePropertyAccessor, request); + PropertyAccessorDelegateFactory factory = new TilesContextPropertyAccessorDelegateFactory( + objectPropertyAccessor, applicationContextPropertyAccessor, + requestScopePropertyAccessor, sessionScopePropertyAccessor); + assertEquals(requestScopePropertyAccessor, factory.getPropertyAccessor("attribute", request)); + + verify(objectPropertyAccessor, applicationContextPropertyAccessor, requestScopePropertyAccessor, + sessionScopePropertyAccessor, applicationScopePropertyAccessor, request); + } + + /** + * Test method for + * {@link TilesContextPropertyAccessorDelegateFactory#getPropertyAccessor(String, Request)} + * . + */ + @Test + public void testGetPropertyAccessorSessionScope() { + PropertyAccessor objectPropertyAccessor = createMock(PropertyAccessor.class); + PropertyAccessor applicationContextPropertyAccessor = createMock(PropertyAccessor.class); + PropertyAccessor requestScopePropertyAccessor = createMock(PropertyAccessor.class); + PropertyAccessor sessionScopePropertyAccessor = createMock(PropertyAccessor.class); + PropertyAccessor applicationScopePropertyAccessor = createMock(PropertyAccessor.class); + Request request = createMock(Request.class); + + replay(objectPropertyAccessor, applicationContextPropertyAccessor, requestScopePropertyAccessor, + sessionScopePropertyAccessor, applicationScopePropertyAccessor, request); + PropertyAccessorDelegateFactory factory = new TilesContextPropertyAccessorDelegateFactory( + objectPropertyAccessor, applicationContextPropertyAccessor, + requestScopePropertyAccessor, sessionScopePropertyAccessor); + assertEquals(requestScopePropertyAccessor, factory.getPropertyAccessor("attribute", request)); + + verify(objectPropertyAccessor, applicationContextPropertyAccessor, requestScopePropertyAccessor, + sessionScopePropertyAccessor, applicationScopePropertyAccessor, request); + } + + /** + * Test method for + * {@link TilesContextPropertyAccessorDelegateFactory#getPropertyAccessor(String, Request)} + * . + */ + @Test + public void testGetPropertyAccessorApplicationScope() { + PropertyAccessor objectPropertyAccessor = createMock(PropertyAccessor.class); + PropertyAccessor applicationContextPropertyAccessor = createMock(PropertyAccessor.class); + PropertyAccessor requestScopePropertyAccessor = createMock(PropertyAccessor.class); + PropertyAccessor sessionScopePropertyAccessor = createMock(PropertyAccessor.class); + PropertyAccessor applicationScopePropertyAccessor = createMock(PropertyAccessor.class); + Request request = createMock(Request.class); + ApplicationContext applicationContext = createMock(ApplicationContext.class); + + replay(objectPropertyAccessor, applicationContextPropertyAccessor, requestScopePropertyAccessor, + sessionScopePropertyAccessor, applicationScopePropertyAccessor, request, applicationContext); + PropertyAccessorDelegateFactory factory = new TilesContextPropertyAccessorDelegateFactory( + objectPropertyAccessor, applicationContextPropertyAccessor, + requestScopePropertyAccessor, sessionScopePropertyAccessor); + assertEquals(requestScopePropertyAccessor, factory.getPropertyAccessor("attribute", request)); + + verify(objectPropertyAccessor, applicationContextPropertyAccessor, requestScopePropertyAccessor, + sessionScopePropertyAccessor, applicationScopePropertyAccessor, request, applicationContext); + } + + /** + * Test method for + * {@link TilesContextPropertyAccessorDelegateFactory#getPropertyAccessor(String, Request)} + * . + */ + @Test + public void testGetPropertyAccessorRequestScopeDefault() { + PropertyAccessor objectPropertyAccessor = createMock(PropertyAccessor.class); + PropertyAccessor applicationContextPropertyAccessor = createMock(PropertyAccessor.class); + PropertyAccessor requestScopePropertyAccessor = createMock(PropertyAccessor.class); + PropertyAccessor sessionScopePropertyAccessor = createMock(PropertyAccessor.class); + PropertyAccessor applicationScopePropertyAccessor = createMock(PropertyAccessor.class); + Request request = createMock(Request.class); + ApplicationContext applicationContext = createMock(ApplicationContext.class); + + replay(objectPropertyAccessor, applicationContextPropertyAccessor, requestScopePropertyAccessor, + sessionScopePropertyAccessor, applicationScopePropertyAccessor, request, applicationContext); + PropertyAccessorDelegateFactory factory = new TilesContextPropertyAccessorDelegateFactory( + objectPropertyAccessor, applicationContextPropertyAccessor, + requestScopePropertyAccessor, sessionScopePropertyAccessor); + assertEquals(requestScopePropertyAccessor, factory.getPropertyAccessor("attribute", request)); + + verify(objectPropertyAccessor, applicationContextPropertyAccessor, requestScopePropertyAccessor, + sessionScopePropertyAccessor, applicationScopePropertyAccessor, request, applicationContext); + } + +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/request/AbstractClientRequestTest.java b/plugins/tiles/src/test/java/org/apache/tiles/request/AbstractClientRequestTest.java new file mode 100644 index 000000000..338270d11 --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/request/AbstractClientRequestTest.java @@ -0,0 +1,155 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.request; + +import org.junit.Before; +import org.junit.Test; + +import java.io.IOException; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.createMockBuilder; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +/** + * Tests {@link AbstractClientRequest}. + */ +public class AbstractClientRequestTest { + + /** + * The request to test. + */ + private AbstractClientRequest request; + + /** + * The application context. + */ + private ApplicationContext applicationContext; + + /** + * The application scope. + */ + private Map applicationScope; + + /** + * Sets up the test. + */ + @Before + public void setUp() { + applicationContext = createMock(ApplicationContext.class); + applicationScope = new HashMap<>(); + request = createMockBuilder(AbstractClientRequest.class).withConstructor(applicationContext).createMock(); + + expect(applicationContext.getApplicationScope()).andReturn(applicationScope).anyTimes(); + } + + /** + * Test method for {@link AbstractClientRequest#dispatch(String)}. + * + * @throws IOException If something goes wrong. + */ + @Test + public void testDispatch() throws IOException { + Map requestScope = new HashMap<>(); + + expect(request.getContext(Request.REQUEST_SCOPE)).andReturn(requestScope).anyTimes(); + request.doForward("/my/path.html"); + request.doInclude("/my/path2.html"); + + replay(request, applicationContext); + request.dispatch("/my/path.html"); + request.dispatch("/my/path2.html"); + verify(request, applicationContext); + } + + /** + * Test method for {@link AbstractClientRequest#include(String)}. + * + * @throws IOException If something goes wrong. + */ + @Test + public void testInclude() throws IOException { + Map requestScope = new HashMap<>(); + + expect(request.getContext(Request.REQUEST_SCOPE)).andReturn(requestScope).anyTimes(); + request.doInclude("/my/path2.html"); + + replay(request, applicationContext); + request.include("/my/path2.html"); + assertTrue((Boolean) request.getContext(Request.REQUEST_SCOPE).get(AbstractRequest.FORCE_INCLUDE_ATTRIBUTE_NAME)); + verify(request, applicationContext); + } + + /** + * Test method for {@link AbstractClientRequest#getApplicationContext()}. + */ + @Test + public void testGetApplicationContext() { + replay(request, applicationContext); + assertEquals(applicationContext, request.getApplicationContext()); + verify(request, applicationContext); + } + + /** + * Test method for {@link AbstractClientRequest#getContext(String)}. + */ + @Test + public void testGetContext() { + Map scope = createMock(Map.class); + + expect(request.getContext("myScope")).andReturn(scope); + + replay(request, applicationContext, scope); + assertEquals(scope, request.getContext("myScope")); + verify(request, applicationContext, scope); + } + + /** + * Test method for {@link AbstractClientRequest#getAvailableScopes()}. + */ + @Test + public void testGetAvailableScopes() { + String[] scopes = new String[]{"one", "two", "three"}; + + expect(request.getAvailableScopes()).andReturn(Arrays.asList(scopes)); + + replay(request, applicationContext); + assertArrayEquals(scopes, request.getAvailableScopes().toArray()); + verify(request, applicationContext); + } + + /** + * Test method for {@link AbstractClientRequest#getApplicationScope()}. + */ + @Test + public void testGetApplicationScope() { + replay(request, applicationContext); + assertEquals(applicationScope, request.getApplicationScope()); + verify(request, applicationContext); + } + +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/request/AbstractRequestTest.java b/plugins/tiles/src/test/java/org/apache/tiles/request/AbstractRequestTest.java new file mode 100644 index 000000000..e0e3dd0c3 --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/request/AbstractRequestTest.java @@ -0,0 +1,54 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.request; + +import org.junit.Test; + +import java.util.HashMap; +import java.util.Map; + +import static org.easymock.EasyMock.createMockBuilder; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +/** + * Tests {@link AbstractRequest}. + */ +public class AbstractRequestTest { + + /** + * Test method for {@link AbstractRequest#setForceInclude(boolean)}. + */ + @Test + public void testSetForceInclude() { + AbstractRequest request = createMockBuilder(AbstractRequest.class).createMock(); + Map scope = new HashMap<>(); + + expect(request.getContext(Request.REQUEST_SCOPE)).andReturn(scope).anyTimes(); + + replay(request); + assertFalse(request.isForceInclude()); + request.setForceInclude(true); + assertTrue(request.isForceInclude()); + verify(request); + } +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/request/AbstractViewRequestTest.java b/plugins/tiles/src/test/java/org/apache/tiles/request/AbstractViewRequestTest.java new file mode 100644 index 000000000..bf650240d --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/request/AbstractViewRequestTest.java @@ -0,0 +1,119 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.request; + +import org.junit.Before; +import org.junit.Test; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.createMockBuilder; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import static org.junit.Assert.assertTrue; + +/** + * Tests {@link AbstractViewRequest}. + */ +public class AbstractViewRequestTest { + + /** + * The request to test. + */ + private AbstractViewRequest request; + + /** + * The internal request. + */ + private DispatchRequest wrappedRequest; + + /** + * The application context. + */ + private ApplicationContext applicationContext; + + /** + * Sets up the test. + */ + @Before + public void setUp() { + wrappedRequest = createMock(DispatchRequest.class); + request = createMockBuilder(AbstractViewRequest.class).withConstructor(wrappedRequest).createMock(); + applicationContext = createMock(ApplicationContext.class); + Map applicationScope = new HashMap<>(); + + expect(wrappedRequest.getApplicationContext()).andReturn(applicationContext).anyTimes(); + expect(applicationContext.getApplicationScope()).andReturn(applicationScope).anyTimes(); + } + + /** + * Test method for {@link AbstractViewRequest#dispatch(String)}. + * + * @throws IOException If something goes wrong. + */ + @Test + public void testDispatch() throws IOException { + Map requestScope = new HashMap<>(); + + expect(request.getContext(Request.REQUEST_SCOPE)).andReturn(requestScope); + wrappedRequest.include("/my/path.html"); + + replay(wrappedRequest, request, applicationContext); + request.dispatch("/my/path.html"); + assertTrue((Boolean) requestScope.get(AbstractRequest.FORCE_INCLUDE_ATTRIBUTE_NAME)); + verify(wrappedRequest, request, applicationContext); + } + + /** + * Test method for {@link AbstractViewRequest#include(String)}. + * + * @throws IOException If something goes wrong. + */ + @Test + public void testInclude() throws IOException { + Map requestScope = new HashMap<>(); + + expect(request.getContext(Request.REQUEST_SCOPE)).andReturn(requestScope); + wrappedRequest.include("/my/path.html"); + + replay(wrappedRequest, request, applicationContext); + request.include("/my/path.html"); + assertTrue((Boolean) requestScope.get(AbstractRequest.FORCE_INCLUDE_ATTRIBUTE_NAME)); + verify(wrappedRequest, request, applicationContext); + } + + /** + * Test method for {@link AbstractViewRequest#doInclude(String)}. + * + * @throws IOException If something goes wrong. + */ + @Test + public void testDoInclude() throws IOException { + wrappedRequest.include("/my/path.html"); + + replay(wrappedRequest, request, applicationContext); + request.doInclude("/my/path.html"); + verify(wrappedRequest, request, applicationContext); + } + +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/request/ApplicationAccessTest.java b/plugins/tiles/src/test/java/org/apache/tiles/request/ApplicationAccessTest.java new file mode 100644 index 000000000..08b5ec27f --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/request/ApplicationAccessTest.java @@ -0,0 +1,51 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.request; + +import org.junit.Test; + +import java.util.Map; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; + +/** + * Tests {@link ApplicationAccess}. + */ +public class ApplicationAccessTest { + + /** + * Test method for {@link ApplicationAccess#register(ApplicationContext)}. + */ + @Test + public void testRegister() { + ApplicationContext applicationContext = createMock(ApplicationContext.class); + Map applicationScope = createMock(Map.class); + + expect(applicationContext.getApplicationScope()).andReturn(applicationScope); + expect(applicationScope.put(ApplicationAccess.APPLICATION_CONTEXT_ATTRIBUTE, applicationContext)).andReturn(null); + + replay(applicationContext, applicationScope); + ApplicationAccess.register(applicationContext); + verify(applicationContext, applicationScope); + } + +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/request/DispatchRequestWrapperTest.java b/plugins/tiles/src/test/java/org/apache/tiles/request/DispatchRequestWrapperTest.java new file mode 100644 index 000000000..2fa6a96d0 --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/request/DispatchRequestWrapperTest.java @@ -0,0 +1,90 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.request; + +import org.junit.Test; + +import java.io.IOException; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; + +/** + * Tests {@link DispatchRequestWrapper}. + */ +public class DispatchRequestWrapperTest { + + protected DispatchRequest createMockRequest() { + return createMock(DispatchRequest.class); + } + + protected DispatchRequestWrapper createRequestWrapper(Request wrappedRequest) { + return new DispatchRequestWrapper((DispatchRequest) wrappedRequest); + } + + /** + * Test method for {@link DispatchRequestWrapper#dispatch(String)}. + * + * @throws IOException If something goes wrong. + */ + @Test + public void testDispatch() throws IOException { + DispatchRequest wrappedRequest = createMockRequest(); + + wrappedRequest.dispatch("/my/path.html"); + + replay(wrappedRequest); + DispatchRequestWrapper request = createRequestWrapper(wrappedRequest); + request.dispatch("/my/path.html"); + verify(wrappedRequest); + } + + /** + * Test method for {@link DispatchRequestWrapper#include(String)}. + * + * @throws IOException If something goes wrong. + */ + @Test + public void testInclude() throws IOException { + DispatchRequest wrappedRequest = createMockRequest(); + + wrappedRequest.include("/my/path.html"); + + replay(wrappedRequest); + DispatchRequestWrapper request = createRequestWrapper(wrappedRequest); + request.include("/my/path.html"); + verify(wrappedRequest); + } + + /** + * Test method for {@link DispatchRequestWrapper#setContentType(String)}. + */ + @Test + public void testSetContentType() { + DispatchRequest wrappedRequest = createMockRequest(); + + wrappedRequest.setContentType("text/html"); + + replay(wrappedRequest); + DispatchRequestWrapper request = createRequestWrapper(wrappedRequest); + request.setContentType("text/html"); + verify(wrappedRequest); + } +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/request/NotAvailableFeatureExceptionTest.java b/plugins/tiles/src/test/java/org/apache/tiles/request/NotAvailableFeatureExceptionTest.java new file mode 100644 index 000000000..f1d6caf51 --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/request/NotAvailableFeatureExceptionTest.java @@ -0,0 +1,41 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.request; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +/** + * Tests {@link NotAvailableFeatureException}. + */ +public class NotAvailableFeatureExceptionTest { + + /** + * Test method for {@link NotAvailableFeatureException#NotAvailableFeatureException(String, Throwable)}. + */ + @Test + public void testNotAvailableFeatureExceptionStringThrowable() { + Throwable cause = new Throwable(); + NotAvailableFeatureException exception = new NotAvailableFeatureException("my message", cause); + assertEquals("my message", exception.getMessage()); + assertEquals(cause, exception.getCause()); + } + +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/request/RequestExceptionTest.java b/plugins/tiles/src/test/java/org/apache/tiles/request/RequestExceptionTest.java new file mode 100644 index 000000000..b8a699c45 --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/request/RequestExceptionTest.java @@ -0,0 +1,53 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tiles.request; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; + +/** + * Tests {@link RequestException}. + */ +public class RequestExceptionTest { + + /** + * Test method for {@link RequestException#RequestException(String)}. + */ + @Test + public void testRequestExceptionString() { + RequestException exception = new RequestException("my message"); + assertEquals("my message", exception.getMessage()); + assertNull(exception.getCause()); + } + + /** + * Test method for {@link RequestException#RequestException(String, Throwable)}. + */ + @Test + public void testRequestExceptionStringThrowable() { + Throwable cause = new Throwable(); + RequestException exception = new RequestException("my message", cause); + assertEquals("my message", exception.getMessage()); + assertEquals(cause, exception.getCause()); + } + +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/request/collection/AddableParameterMapTest.java b/plugins/tiles/src/test/java/org/apache/tiles/request/collection/AddableParameterMapTest.java new file mode 100644 index 000000000..a06d9bb81 --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/request/collection/AddableParameterMapTest.java @@ -0,0 +1,112 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.request.collection; + +import org.apache.tiles.request.attribute.HasAddableKeys; +import org.junit.Before; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.expectLastCall; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import static org.junit.Assert.assertNull; + +/** + * Tests {@link AddableParameterMap}. + */ +public class AddableParameterMapTest { + + /** + * The object to test. + */ + private AddableParameterMap map; + + /** + * The extractor to use. + */ + private HasAddableKeys extractor; + + /** + * Sets up the test. + */ + @Before + public void setUp() { + extractor = createMock(HasAddableKeys.class); + map = new AddableParameterMap(extractor); + } + + /** + * Test method for {@link AddableParameterMap#entrySet()}. + */ + @Test + public void testEntrySet() { + Set> entrySet = map.entrySet(); + MapEntry entry1 = new MapEntry<>("one", "value1", false); + MapEntry entry2 = new MapEntry<>("two", "value2", false); + List> entries = new ArrayList<>(2); + entries.add(entry1); + entries.add(entry2); + + extractor.setValue("one", "value1"); + expectLastCall().times(2); + extractor.setValue("two", "value2"); + replay(extractor); + entrySet.add(entry1); + entrySet.addAll(entries); + verify(extractor); + } + + /** + * Test method for {@link AddableParameterMap#put(String, String)}. + */ + @Test + public void testPut() { + expect(extractor.getValue("one")).andReturn(null); + extractor.setValue("one", "value1"); + + replay(extractor); + assertNull(map.put("one", "value1")); + verify(extractor); + } + + /** + * Test method for {@link AddableParameterMap#putAll(Map)}. + */ + @Test + public void testPutAll() { + Map map = new HashMap<>(); + map.put("one", "value1"); + map.put("two", "value2"); + + extractor.setValue("one", "value1"); + extractor.setValue("two", "value2"); + + replay(extractor); + this.map.putAll(map); + verify(extractor); + } +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/request/collection/CollectionUtilTest.java b/plugins/tiles/src/test/java/org/apache/tiles/request/collection/CollectionUtilTest.java new file mode 100644 index 000000000..39f286760 --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/request/collection/CollectionUtilTest.java @@ -0,0 +1,59 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.request.collection; + +import org.junit.Test; + +import java.util.Enumeration; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import static org.junit.Assert.assertEquals; + +public class CollectionUtilTest { + + @Test + public void testKey() { + assertEquals("1", CollectionUtil.key(1)); + assertEquals("hello", CollectionUtil.key("hello")); + } + + @Test(expected = IllegalArgumentException.class) + public void testKeyException() { + CollectionUtil.key(null); + } + + @Test + public void testEnumerationSize() { + Enumeration enumeration = createMock(Enumeration.class); + + expect(enumeration.hasMoreElements()).andReturn(true); + expect(enumeration.nextElement()).andReturn(1); + expect(enumeration.hasMoreElements()).andReturn(true); + expect(enumeration.nextElement()).andReturn(1); + expect(enumeration.hasMoreElements()).andReturn(false); + + replay(enumeration); + assertEquals(2, CollectionUtil.enumerationSize(enumeration)); + verify(enumeration); + } + +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/request/collection/HeaderValuesCollectionTest.java b/plugins/tiles/src/test/java/org/apache/tiles/request/collection/HeaderValuesCollectionTest.java new file mode 100644 index 000000000..36f9bd2e0 --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/request/collection/HeaderValuesCollectionTest.java @@ -0,0 +1,398 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.request.collection; + +import org.apache.tiles.request.attribute.EnumeratedValuesExtractor; +import org.junit.Before; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Enumeration; +import java.util.Iterator; +import java.util.List; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +/** + * Tests {@link HeaderValuesMap#values()}. + */ +public class HeaderValuesCollectionTest { + + /** + * The extractor to use. + */ + private EnumeratedValuesExtractor extractor; + + /** + * The map to test. + */ + private HeaderValuesMap map; + + /** + * The collection. + */ + private Collection coll; + + /** + * Sets up the test. + */ + @Before + public void setUp() { + extractor = createMock(EnumeratedValuesExtractor.class); + map = new HeaderValuesMap(extractor); + coll = map.values(); + } + + /** + * Tests {@link Collection#add(Object)}. + */ + @Test(expected = UnsupportedOperationException.class) + public void testAdd() { + coll.add(null); + } + + @Test(expected = UnsupportedOperationException.class) + public void testAddAll() { + coll.addAll(null); + } + + @Test(expected = UnsupportedOperationException.class) + public void testClear() { + coll.clear(); + } + + /** + * Tests {@link Collection#contains(Object)}. + */ + @Test + public void testContainsValue() { + assertFalse(map.containsValue(1)); + + Enumeration keys = createMock(Enumeration.class); + Enumeration values1 = createMock(Enumeration.class); + Enumeration values2 = createMock(Enumeration.class); + + expect(extractor.getKeys()).andReturn(keys); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("one"); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("two"); + + expect(extractor.getValues("one")).andReturn(values1); + expect(values1.hasMoreElements()).andReturn(true); + expect(values1.nextElement()).andReturn("value1"); + expect(values1.hasMoreElements()).andReturn(false); + + expect(extractor.getValues("two")).andReturn(values2); + expect(values2.hasMoreElements()).andReturn(true); + expect(values2.nextElement()).andReturn("value2"); + expect(values2.hasMoreElements()).andReturn(true); + expect(values2.nextElement()).andReturn("value3"); + expect(values2.hasMoreElements()).andReturn(false); + + replay(extractor, keys, values1, values2); + assertTrue(coll.contains(new String[]{"value2", "value3"})); + verify(extractor, keys, values1, values2); + } + + /** + * Tests {@link Collection#contains(Object)}. + */ + @Test + public void testContainsValueFalse() { + Enumeration keys = createMock(Enumeration.class); + Enumeration values1 = createMock(Enumeration.class); + Enumeration values2 = createMock(Enumeration.class); + + expect(extractor.getKeys()).andReturn(keys); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("one"); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("two"); + expect(keys.hasMoreElements()).andReturn(false); + + expect(extractor.getValues("one")).andReturn(values1); + expect(values1.hasMoreElements()).andReturn(true); + expect(values1.nextElement()).andReturn("value1"); + expect(values1.hasMoreElements()).andReturn(false); + + expect(extractor.getValues("two")).andReturn(values2); + expect(values2.hasMoreElements()).andReturn(true); + expect(values2.nextElement()).andReturn("value2"); + expect(values2.hasMoreElements()).andReturn(true); + expect(values2.nextElement()).andReturn("value3"); + expect(values2.hasMoreElements()).andReturn(false); + + replay(extractor, keys, values1, values2); + assertFalse(coll.contains(new String[]{"value2", "value4"})); + verify(extractor, keys, values1, values2); + } + + @Test + public void testContainsAll() { + Enumeration keys = createMock(Enumeration.class); + Enumeration values1 = createMock(Enumeration.class); + Enumeration values2 = createMock(Enumeration.class); + + expect(extractor.getKeys()).andReturn(keys).times(2); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("one"); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("one"); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("two"); + + expect(extractor.getValues("one")).andReturn(values1).times(2); + expect(values1.hasMoreElements()).andReturn(true); + expect(values1.nextElement()).andReturn("value1"); + expect(values1.hasMoreElements()).andReturn(false); + expect(values1.hasMoreElements()).andReturn(true); + expect(values1.nextElement()).andReturn("value1"); + expect(values1.hasMoreElements()).andReturn(false); + + expect(extractor.getValues("two")).andReturn(values2); + expect(values2.hasMoreElements()).andReturn(true); + expect(values2.nextElement()).andReturn("value2"); + expect(values2.hasMoreElements()).andReturn(true); + expect(values2.nextElement()).andReturn("value3"); + expect(values2.hasMoreElements()).andReturn(false); + + replay(extractor, keys, values1, values2); + List coll = new ArrayList<>(); + coll.add(new String[]{"value1"}); + coll.add(new String[]{"value2", "value3"}); + assertTrue(this.coll.containsAll(coll)); + verify(extractor, keys, values1, values2); + } + + @Test + public void testContainsAllFalse() { + Enumeration keys = createMock(Enumeration.class); + Enumeration values1 = createMock(Enumeration.class); + Enumeration values2 = createMock(Enumeration.class); + + expect(extractor.getKeys()).andReturn(keys); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("one"); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("two"); + expect(keys.hasMoreElements()).andReturn(false); + + expect(extractor.getValues("one")).andReturn(values1); + expect(values1.hasMoreElements()).andReturn(true); + expect(values1.nextElement()).andReturn("value1"); + expect(values1.hasMoreElements()).andReturn(false); + + expect(extractor.getValues("two")).andReturn(values2); + expect(values2.hasMoreElements()).andReturn(true); + expect(values2.nextElement()).andReturn("value2"); + expect(values2.hasMoreElements()).andReturn(true); + + replay(extractor, keys, values1, values2); + List coll = new ArrayList<>(); + coll.add(new String[]{"value4"}); + assertFalse(this.coll.containsAll(coll)); + verify(extractor, keys, values1, values2); + } + + /** + * Test method for {@link Collection#isEmpty()}. + */ + @Test + public void testIsEmpty() { + Enumeration keys = createMock(Enumeration.class); + + expect(extractor.getKeys()).andReturn(keys); + expect(keys.hasMoreElements()).andReturn(true); + + replay(extractor, keys); + assertFalse(coll.isEmpty()); + verify(extractor, keys); + } + + /** + * Test method for {@link Collection#iterator()}. + */ + @Test + public void testIterator() { + Enumeration keys = createMock(Enumeration.class); + Enumeration values2 = createMock(Enumeration.class); + + expect(extractor.getKeys()).andReturn(keys); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("two"); + expect(extractor.getValues("two")).andReturn(values2); + + expect(values2.hasMoreElements()).andReturn(true); + expect(values2.nextElement()).andReturn("value2"); + expect(values2.hasMoreElements()).andReturn(true); + expect(values2.nextElement()).andReturn("value3"); + expect(values2.hasMoreElements()).andReturn(false); + + replay(extractor, keys, values2); + Iterator entryIt = coll.iterator(); + assertTrue(entryIt.hasNext()); + assertArrayEquals(new String[]{"value2", "value3"}, entryIt.next()); + verify(extractor, keys, values2); + } + + /** + * Test method for {@link Collection#iterator()}. + */ + @Test(expected = UnsupportedOperationException.class) + public void testIteratorRemove() { + Enumeration keys = createMock(Enumeration.class); + + expect(extractor.getKeys()).andReturn(keys); + + try { + replay(extractor, keys); + coll.iterator().remove(); + } finally { + verify(extractor, keys); + } + } + + /** + * Tests {@link Collection#remove(Object)}. + */ + @Test(expected = UnsupportedOperationException.class) + public void testRemove() { + coll.remove(null); + } + + /** + * Tests {@link Collection#removeAll(Collection)}. + */ + @Test(expected = UnsupportedOperationException.class) + public void testRemoveAll() { + coll.removeAll(null); + } + + /** + * Tests {@link Collection#retainAll(Collection)}. + */ + @Test(expected = UnsupportedOperationException.class) + public void testRetainAll() { + coll.retainAll(null); + } + + /** + * Test method for {@link HeaderValuesMap#size()}. + */ + @Test + public void testSize() { + Enumeration keys = createMock(Enumeration.class); + + expect(extractor.getKeys()).andReturn(keys); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("one"); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("two"); + expect(keys.hasMoreElements()).andReturn(false); + + replay(extractor, keys); + assertEquals(2, coll.size()); + verify(extractor, keys); + } + + /** + * Test method for {@link Collection#toArray()}. + */ + @Test + public void testToArray() { + Enumeration keys = createMock(Enumeration.class); + Enumeration values1 = createMock(Enumeration.class); + Enumeration values2 = createMock(Enumeration.class); + + expect(extractor.getKeys()).andReturn(keys); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("one"); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("two"); + expect(keys.hasMoreElements()).andReturn(false); + + expect(extractor.getValues("one")).andReturn(values1); + expect(values1.hasMoreElements()).andReturn(true); + expect(values1.nextElement()).andReturn("value1"); + expect(values1.hasMoreElements()).andReturn(false); + + expect(extractor.getValues("two")).andReturn(values2); + expect(values2.hasMoreElements()).andReturn(true); + expect(values2.nextElement()).andReturn("value2"); + expect(values2.hasMoreElements()).andReturn(true); + expect(values2.nextElement()).andReturn("value3"); + expect(values2.hasMoreElements()).andReturn(false); + + String[][] entryArray = new String[2][]; + entryArray[0] = new String[]{"value1"}; + entryArray[1] = new String[]{"value2", "value3"}; + + replay(extractor, keys, values1, values2); + assertArrayEquals(entryArray, coll.toArray()); + verify(extractor, keys, values1, values2); + } + + /** + * Test method for {@link Collection#toArray(Object[])}. + */ + @Test + public void testToArrayTArray() { + Enumeration keys = createMock(Enumeration.class); + Enumeration values1 = createMock(Enumeration.class); + Enumeration values2 = createMock(Enumeration.class); + + expect(extractor.getKeys()).andReturn(keys); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("one"); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("two"); + expect(keys.hasMoreElements()).andReturn(false); + + expect(extractor.getValues("one")).andReturn(values1); + expect(values1.hasMoreElements()).andReturn(true); + expect(values1.nextElement()).andReturn("value1"); + expect(values1.hasMoreElements()).andReturn(false); + + expect(extractor.getValues("two")).andReturn(values2); + expect(values2.hasMoreElements()).andReturn(true); + expect(values2.nextElement()).andReturn("value2"); + expect(values2.hasMoreElements()).andReturn(true); + expect(values2.nextElement()).andReturn("value3"); + expect(values2.hasMoreElements()).andReturn(false); + + String[][] entryArray = new String[2][]; + entryArray[0] = new String[]{"value1"}; + entryArray[1] = new String[]{"value2", "value3"}; + String[][] realArray = new String[2][]; + + replay(extractor, keys, values1, values2); + assertArrayEquals(entryArray, coll.toArray(realArray)); + verify(extractor, keys, values1, values2); + } +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/request/collection/HeaderValuesMapEntrySetTest.java b/plugins/tiles/src/test/java/org/apache/tiles/request/collection/HeaderValuesMapEntrySetTest.java new file mode 100644 index 000000000..77218414d --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/request/collection/HeaderValuesMapEntrySetTest.java @@ -0,0 +1,337 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.request.collection; + +import org.apache.tiles.request.attribute.EnumeratedValuesExtractor; +import org.junit.Before; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +/** + * Tests {@link HeaderValuesMap entry set}. + */ +public class HeaderValuesMapEntrySetTest { + + /** + * The extractor to use. + */ + private EnumeratedValuesExtractor extractor; + + /** + * The set to test. + */ + private Set> entrySet; + + /** + * Sets up the test. + */ + @Before + public void setUp() { + extractor = createMock(EnumeratedValuesExtractor.class); + HeaderValuesMap map = new HeaderValuesMap(extractor); + entrySet = map.entrySet(); + } + + /** + * Tests {@link Set#add(Object)}. + */ + @Test(expected = UnsupportedOperationException.class) + public void testAdd() { + entrySet.add(null); + } + + @Test(expected = UnsupportedOperationException.class) + public void testAddAll() { + entrySet.addAll(null); + } + + @Test(expected = UnsupportedOperationException.class) + public void testClear() { + entrySet.clear(); + } + + /** + * Tests {@link Set#contains(Object)}. + */ + @Test + public void testContains() { + Map.Entry entry = createMock(Map.Entry.class); + Enumeration values2 = createMock(Enumeration.class); + + expect(entry.getKey()).andReturn("two"); + expect(entry.getValue()).andReturn(new String[]{"value2", "value3"}); + + expect(extractor.getValues("two")).andReturn(values2); + expect(values2.hasMoreElements()).andReturn(true); + expect(values2.nextElement()).andReturn("value2"); + expect(values2.hasMoreElements()).andReturn(true); + expect(values2.nextElement()).andReturn("value3"); + expect(values2.hasMoreElements()).andReturn(false); + + replay(extractor, entry, values2); + assertTrue(entrySet.contains(entry)); + verify(extractor, entry, values2); + } + + @Test + public void testContainsAll() { + Enumeration values1 = createMock(Enumeration.class); + Enumeration values2 = createMock(Enumeration.class); + Map.Entry entry1 = createMock(Map.Entry.class); + Map.Entry entry2 = createMock(Map.Entry.class); + + expect(entry1.getKey()).andReturn("one"); + expect(entry1.getValue()).andReturn(new String[]{"value1"}); + expect(entry2.getKey()).andReturn("two"); + expect(entry2.getValue()).andReturn(new String[]{"value2", "value3"}); + + expect(extractor.getValues("one")).andReturn(values1); + expect(values1.hasMoreElements()).andReturn(true); + expect(values1.nextElement()).andReturn("value1"); + expect(values1.hasMoreElements()).andReturn(false); + + expect(extractor.getValues("two")).andReturn(values2); + expect(values2.hasMoreElements()).andReturn(true); + expect(values2.nextElement()).andReturn("value2"); + expect(values2.hasMoreElements()).andReturn(true); + expect(values2.nextElement()).andReturn("value3"); + expect(values2.hasMoreElements()).andReturn(false); + + replay(extractor, values1, values2, entry1, entry2); + List> coll = new ArrayList<>(); + coll.add(entry1); + coll.add(entry2); + assertTrue(entrySet.containsAll(coll)); + verify(extractor, values1, values2, entry1, entry2); + } + + @Test + public void testContainsAllFalse() { + Enumeration values1 = createMock(Enumeration.class); + Map.Entry entry1 = createMock(Map.Entry.class); + + expect(entry1.getKey()).andReturn("one"); + expect(entry1.getValue()).andReturn(new String[]{"value4"}); + + expect(extractor.getValues("one")).andReturn(values1); + expect(values1.hasMoreElements()).andReturn(true); + expect(values1.nextElement()).andReturn("value1"); + + replay(extractor, values1, entry1); + List> coll = new ArrayList<>(); + coll.add(entry1); + assertFalse(entrySet.containsAll(coll)); + verify(extractor, values1, entry1); + } + + /** + * Test method for {@link Set#isEmpty()}. + */ + @Test + public void testIsEmpty() { + Enumeration keys = createMock(Enumeration.class); + + expect(extractor.getKeys()).andReturn(keys); + expect(keys.hasMoreElements()).andReturn(true); + + replay(extractor, keys); + assertFalse(entrySet.isEmpty()); + verify(extractor, keys); + } + + /** + * Test method for {@link Set#iterator()}. + */ + @Test + public void testIterator() { + Enumeration keys = createMock(Enumeration.class); + Enumeration values2 = createMock(Enumeration.class); + + expect(extractor.getKeys()).andReturn(keys); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("two"); + + expect(extractor.getValues("two")).andReturn(values2); + expect(values2.hasMoreElements()).andReturn(true); + expect(values2.nextElement()).andReturn("value2"); + expect(values2.hasMoreElements()).andReturn(true); + expect(values2.nextElement()).andReturn("value3"); + expect(values2.hasMoreElements()).andReturn(false); + + replay(extractor, keys, values2); + Iterator> entryIt = entrySet.iterator(); + assertTrue(entryIt.hasNext()); + MapEntryArrayValues entry = new MapEntryArrayValues<>("two", new String[]{"value2", "value3"}, false); + assertEquals(entry, entryIt.next()); + verify(extractor, keys, values2); + } + + /** + * Test method for {@link Set#iterator()}. + */ + @Test(expected = UnsupportedOperationException.class) + public void testIteratorRemove() { + Enumeration keys = createMock(Enumeration.class); + + expect(extractor.getKeys()).andReturn(keys); + + try { + replay(extractor, keys); + entrySet.iterator().remove(); + } finally { + verify(extractor, keys); + } + } + + /** + * Tests {@link Set#remove(Object)}. + */ + @Test(expected = UnsupportedOperationException.class) + public void testRemove() { + entrySet.remove(null); + } + + /** + * Tests {@link Set#removeAll(java.util.Collection)}. + */ + @Test(expected = UnsupportedOperationException.class) + public void testRemoveAll() { + entrySet.removeAll(null); + } + + /** + * Tests {@link Set#retainAll(java.util.Collection)}. + */ + @Test(expected = UnsupportedOperationException.class) + public void testRetainAll() { + entrySet.retainAll(null); + } + + /** + * Test method for {@link HeaderValuesMap#size()}. + */ + @Test + public void testSize() { + Enumeration keys = createMock(Enumeration.class); + + expect(extractor.getKeys()).andReturn(keys); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("one"); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("two"); + expect(keys.hasMoreElements()).andReturn(false); + + replay(extractor, keys); + assertEquals(2, entrySet.size()); + verify(extractor, keys); + } + + /** + * Test method for {@link Set#toArray()}. + */ + @SuppressWarnings("unchecked") + @Test + public void testToArray() { + Enumeration keys = createMock(Enumeration.class); + Enumeration values1 = createMock(Enumeration.class); + Enumeration values2 = createMock(Enumeration.class); + + expect(extractor.getKeys()).andReturn(keys); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("one"); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("two"); + expect(keys.hasMoreElements()).andReturn(false); + + expect(extractor.getValues("one")).andReturn(values1); + expect(values1.hasMoreElements()).andReturn(true); + expect(values1.nextElement()).andReturn("value1"); + expect(values1.hasMoreElements()).andReturn(false); + + expect(extractor.getValues("two")).andReturn(values2); + expect(values2.hasMoreElements()).andReturn(true); + expect(values2.nextElement()).andReturn("value2"); + expect(values2.hasMoreElements()).andReturn(true); + expect(values2.nextElement()).andReturn("value3"); + expect(values2.hasMoreElements()).andReturn(false); + + MapEntryArrayValues[] entryArray = new MapEntryArrayValues[2]; + entryArray[0] = new MapEntryArrayValues<>("one", new String[]{"value1"}, false); + entryArray[1] = new MapEntryArrayValues<>("two", new String[]{"value2", "value3"}, false); + + replay(extractor, keys, values1, values2); + assertArrayEquals(entryArray, entrySet.toArray()); + verify(extractor, keys, values1, values2); + } + + /** + * Test method for {@link Set#toArray(Object[])}. + */ + @Test + @SuppressWarnings("unchecked") + public void testToArrayTArray() { + Enumeration keys = createMock(Enumeration.class); + Enumeration values1 = createMock(Enumeration.class); + Enumeration values2 = createMock(Enumeration.class); + + expect(extractor.getKeys()).andReturn(keys); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("one"); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("two"); + expect(keys.hasMoreElements()).andReturn(false); + + expect(extractor.getValues("one")).andReturn(values1); + expect(values1.hasMoreElements()).andReturn(true); + expect(values1.nextElement()).andReturn("value1"); + expect(values1.hasMoreElements()).andReturn(false); + + expect(extractor.getValues("two")).andReturn(values2); + expect(values2.hasMoreElements()).andReturn(true); + expect(values2.nextElement()).andReturn("value2"); + expect(values2.hasMoreElements()).andReturn(true); + expect(values2.nextElement()).andReturn("value3"); + expect(values2.hasMoreElements()).andReturn(false); + + MapEntryArrayValues[] entryArray = new MapEntryArrayValues[2]; + entryArray[0] = new MapEntryArrayValues<>("one", new String[]{"value1"}, false); + entryArray[1] = new MapEntryArrayValues<>("two", new String[]{"value2", "value3"}, false); + MapEntryArrayValues[] realArray = new MapEntryArrayValues[2]; + + replay(extractor, keys, values1, values2); + assertArrayEquals(entryArray, entrySet.toArray(realArray)); + verify(extractor, keys, values1, values2); + } +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/request/collection/HeaderValuesMapTest.java b/plugins/tiles/src/test/java/org/apache/tiles/request/collection/HeaderValuesMapTest.java new file mode 100644 index 000000000..aaf0ef602 --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/request/collection/HeaderValuesMapTest.java @@ -0,0 +1,337 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.request.collection; + +import org.apache.tiles.request.attribute.EnumeratedValuesExtractor; +import org.junit.Before; +import org.junit.Test; + +import java.util.Enumeration; +import java.util.HashMap; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +/** + * Tests {@link HeaderValuesMap}. + */ +public class HeaderValuesMapTest { + + /** + * The extractor to use. + */ + private EnumeratedValuesExtractor extractor; + + /** + * The map to test. + */ + private HeaderValuesMap map; + + /** + * Sets up the test. + */ + @Before + public void setUp() { + extractor = createMock(EnumeratedValuesExtractor.class); + map = new HeaderValuesMap(extractor); + } + + /** + * Test method for {@link HeaderValuesMap#hashCode()}. + */ + @Test + public void testHashCode() { + Enumeration keys = createMock(Enumeration.class); + Enumeration values1 = createMock(Enumeration.class); + Enumeration values2 = createMock(Enumeration.class); + + expect(extractor.getKeys()).andReturn(keys); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("one"); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("two"); + expect(keys.hasMoreElements()).andReturn(false); + + expect(extractor.getValues("one")).andReturn(values1); + expect(values1.hasMoreElements()).andReturn(true); + expect(values1.nextElement()).andReturn("value1"); + expect(values1.hasMoreElements()).andReturn(false); + + expect(extractor.getValues("two")).andReturn(values2); + expect(values2.hasMoreElements()).andReturn(true); + expect(values2.nextElement()).andReturn("value2"); + expect(values2.hasMoreElements()).andReturn(true); + expect(values2.nextElement()).andReturn("value3"); + expect(values2.hasMoreElements()).andReturn(false); + + replay(extractor, keys, values1, values2); + assertEquals( + ("one".hashCode() ^ "value1".hashCode()) + + ("two".hashCode() ^ ("value2".hashCode() + "value3" + .hashCode())), + map.hashCode()); + verify(extractor, keys, values1, values2); + } + + /** + * Test method for {@link HeaderValuesMap#clear()}. + */ + @Test(expected = UnsupportedOperationException.class) + public void testClear() { + map.clear(); + } + + /** + * Test method for {@link HeaderValuesMap#containsKey(Object)}. + */ + @Test + public void testContainsKey() { + expect(extractor.getValue("one")).andReturn("value1"); + expect(extractor.getValue("two")).andReturn(null); + + replay(extractor); + assertTrue(map.containsKey("one")); + assertFalse(map.containsKey("two")); + verify(extractor); + } + + /** + * Test method for {@link HeaderValuesMap#containsValue(Object)}. + */ + @Test + public void testContainsValue() { + assertFalse(map.containsValue(1)); + + Enumeration keys = createMock(Enumeration.class); + Enumeration values1 = createMock(Enumeration.class); + Enumeration values2 = createMock(Enumeration.class); + + expect(extractor.getKeys()).andReturn(keys); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("one"); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("two"); + + expect(extractor.getValues("one")).andReturn(values1); + expect(values1.hasMoreElements()).andReturn(true); + expect(values1.nextElement()).andReturn("value1"); + expect(values1.hasMoreElements()).andReturn(false); + + expect(extractor.getValues("two")).andReturn(values2); + expect(values2.hasMoreElements()).andReturn(true); + expect(values2.nextElement()).andReturn("value2"); + expect(values2.hasMoreElements()).andReturn(true); + expect(values2.nextElement()).andReturn("value3"); + expect(values2.hasMoreElements()).andReturn(false); + + replay(extractor, keys, values1, values2); + assertTrue(map.containsValue(new String[]{"value2", "value3"})); + verify(extractor, keys, values1, values2); + } + + /** + * Test method for {@link HeaderValuesMap#containsValue(Object)}. + */ + @Test + public void testContainsValueFalse() { + Enumeration keys = createMock(Enumeration.class); + Enumeration values1 = createMock(Enumeration.class); + Enumeration values2 = createMock(Enumeration.class); + + expect(extractor.getKeys()).andReturn(keys); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("one"); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("two"); + expect(keys.hasMoreElements()).andReturn(false); + + expect(extractor.getValues("one")).andReturn(values1); + expect(values1.hasMoreElements()).andReturn(true); + expect(values1.nextElement()).andReturn("value1"); + expect(values1.hasMoreElements()).andReturn(false); + + expect(extractor.getValues("two")).andReturn(values2); + expect(values2.hasMoreElements()).andReturn(true); + expect(values2.nextElement()).andReturn("value2"); + expect(values2.hasMoreElements()).andReturn(true); + expect(values2.nextElement()).andReturn("value3"); + expect(values2.hasMoreElements()).andReturn(false); + + replay(extractor, keys, values1, values2); + assertFalse(map.containsValue(new String[]{"value2", "value4"})); + verify(extractor, keys, values1, values2); + } + + /** + * Test method for {@link HeaderValuesMap#equals(Object)}. + */ + @Test + public void testEqualsObject() { + Enumeration keys = createMock(Enumeration.class); + Enumeration values1 = createMock(Enumeration.class); + Enumeration values2 = createMock(Enumeration.class); + EnumeratedValuesExtractor otherExtractor = createMock(EnumeratedValuesExtractor.class); + Enumeration otherValues1 = createMock(Enumeration.class); + Enumeration otherValues2 = createMock(Enumeration.class); + + expect(extractor.getKeys()).andReturn(keys); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("one"); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("two"); + expect(keys.hasMoreElements()).andReturn(false); + + expect(extractor.getValues("one")).andReturn(values1); + expect(values1.hasMoreElements()).andReturn(true); + expect(values1.nextElement()).andReturn("value1"); + expect(values1.hasMoreElements()).andReturn(false); + + expect(extractor.getValues("two")).andReturn(values2); + expect(values2.hasMoreElements()).andReturn(true); + expect(values2.nextElement()).andReturn("value2"); + expect(values2.hasMoreElements()).andReturn(true); + expect(values2.nextElement()).andReturn("value3"); + expect(values2.hasMoreElements()).andReturn(false); + + expect(otherExtractor.getValues("one")).andReturn(otherValues1); + expect(otherValues1.hasMoreElements()).andReturn(true); + expect(otherValues1.nextElement()).andReturn("value1"); + expect(otherValues1.hasMoreElements()).andReturn(false); + + expect(otherExtractor.getValues("two")).andReturn(otherValues2); + expect(otherValues2.hasMoreElements()).andReturn(true); + expect(otherValues2.nextElement()).andReturn("value2"); + expect(otherValues2.hasMoreElements()).andReturn(true); + expect(otherValues2.nextElement()).andReturn("value3"); + expect(otherValues2.hasMoreElements()).andReturn(false); + + replay(extractor, otherExtractor, keys, values1, values2, otherValues1, otherValues2); + HeaderValuesMap otherMap = new HeaderValuesMap(otherExtractor); + assertTrue(map.equals(otherMap)); + verify(extractor, otherExtractor, keys, values1, values2, otherValues1, otherValues2); + } + + /** + * Test method for {@link HeaderValuesMap#get(Object)}. + */ + @Test + public void testGet() { + Enumeration values2 = createMock(Enumeration.class); + + expect(extractor.getValues("two")).andReturn(values2); + expect(values2.hasMoreElements()).andReturn(true); + expect(values2.nextElement()).andReturn("value2"); + expect(values2.hasMoreElements()).andReturn(true); + expect(values2.nextElement()).andReturn("value3"); + expect(values2.hasMoreElements()).andReturn(false); + + replay(extractor, values2); + assertArrayEquals(new String[]{"value2", "value3"}, map.get("two")); + verify(extractor, values2); + } + + /** + * Test method for {@link HeaderValuesMap#isEmpty()}. + */ + @Test + public void testIsEmpty() { + Enumeration keys = createMock(Enumeration.class); + + expect(extractor.getKeys()).andReturn(keys); + expect(keys.hasMoreElements()).andReturn(true); + + replay(extractor, keys); + assertFalse(map.isEmpty()); + verify(extractor, keys); + } + + /** + * Test method for {@link HeaderValuesMap#isEmpty()}. + */ + @Test + public void testIsEmptyTrue() { + Enumeration keys = createMock(Enumeration.class); + + expect(extractor.getKeys()).andReturn(keys); + expect(keys.hasMoreElements()).andReturn(false); + + replay(extractor, keys); + assertTrue(map.isEmpty()); + verify(extractor, keys); + } + + /** + * Test method for {@link HeaderValuesMap#keySet()}. + */ + @Test + public void testKeySet() { + replay(extractor); + assertTrue(map.keySet() instanceof KeySet); + verify(extractor); + } + + /** + * Test method for {@link HeaderValuesMap#put(String, String[])}. + */ + @Test(expected = UnsupportedOperationException.class) + public void testPut() { + map.put("one", new String[]{"value1", "value2"}); + } + + /** + * Test method for {@link HeaderValuesMap#putAll(java.util.Map)}. + */ + @Test(expected = UnsupportedOperationException.class) + public void testPutAll() { + map.putAll(new HashMap<>()); + } + + /** + * Test method for {@link HeaderValuesMap#remove(Object)}. + */ + @Test(expected = UnsupportedOperationException.class) + public void testRemove() { + map.remove("one"); + } + + /** + * Test method for {@link HeaderValuesMap#size()}. + */ + @Test + public void testSize() { + Enumeration keys = createMock(Enumeration.class); + + expect(extractor.getKeys()).andReturn(keys); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("one"); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("two"); + expect(keys.hasMoreElements()).andReturn(false); + + replay(extractor, keys); + assertEquals(2, map.size()); + verify(extractor, keys); + } +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/request/collection/KeySetTest.java b/plugins/tiles/src/test/java/org/apache/tiles/request/collection/KeySetTest.java new file mode 100644 index 000000000..452bb5123 --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/request/collection/KeySetTest.java @@ -0,0 +1,283 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.request.collection; + +import org.apache.tiles.request.attribute.HasKeys; +import org.junit.Before; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.Iterator; +import java.util.List; +import java.util.Set; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +/** + * Tests {@link KeySet}. + */ +public class KeySetTest { + + /** + * The extractor to use. + */ + private HasKeys extractor; + + /** + * The key set. + */ + private Set entrySet; + + /** + * Sets up the test. + */ + @Before + public void setUp() { + extractor = createMock(HasKeys.class); + entrySet = new KeySet(extractor); + } + + /** + * Tests {@link Set#add(Object)}. + */ + @Test(expected = UnsupportedOperationException.class) + public void testAdd() { + entrySet.add(null); + } + + @Test(expected = UnsupportedOperationException.class) + public void testAddAll() { + entrySet.addAll(null); + } + + @Test(expected = UnsupportedOperationException.class) + public void testClear() { + entrySet.clear(); + } + + /** + * Tests {@link Set#contains(Object)}. + */ + @Test + public void testContains() { + expect(extractor.getValue("one")).andReturn(1); + + replay(extractor); + assertTrue(entrySet.contains("one")); + verify(extractor); + } + + /** + * Tests {@link Set#contains(Object)}. + */ + @Test + public void testContainsFalse() { + expect(extractor.getValue("one")).andReturn(null); + + replay(extractor); + assertFalse(entrySet.contains("one")); + verify(extractor); + } + + @Test + public void testContainsAll() { + expect(extractor.getValue("one")).andReturn(1); + expect(extractor.getValue("two")).andReturn(1); + + replay(extractor); + List coll = new ArrayList(); + coll.add("one"); + coll.add("two"); + assertTrue(entrySet.containsAll(coll)); + verify(extractor); + } + + @Test + public void testContainsAllFalse() { + expect(extractor.getValue("one")).andReturn(1); + expect(extractor.getValue("two")).andReturn(null); + + replay(extractor); + List coll = new ArrayList<>(); + coll.add("one"); + coll.add("two"); + assertFalse(entrySet.containsAll(coll)); + verify(extractor); + } + + /** + * Test method for {@link Set#isEmpty()}. + */ + @Test + public void testIsEmpty() { + Enumeration keys = createMock(Enumeration.class); + + expect(extractor.getKeys()).andReturn(keys); + expect(keys.hasMoreElements()).andReturn(true); + + replay(extractor, keys); + assertFalse(entrySet.isEmpty()); + verify(extractor, keys); + } + + /** + * Test method for {@link Set#isEmpty()}. + */ + @Test + public void testIsEmptyTrue() { + Enumeration keys = createMock(Enumeration.class); + + expect(extractor.getKeys()).andReturn(keys); + expect(keys.hasMoreElements()).andReturn(false); + + replay(extractor, keys); + assertTrue(entrySet.isEmpty()); + verify(extractor, keys); + } + + /** + * Test method for {@link Set#iterator()}. + */ + @Test + public void testIterator() { + Enumeration keys = createMock(Enumeration.class); + Enumeration values2 = createMock(Enumeration.class); + + expect(extractor.getKeys()).andReturn(keys); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("two"); + + replay(extractor, keys, values2); + Iterator entryIt = entrySet.iterator(); + assertTrue(entryIt.hasNext()); + assertEquals("two", entryIt.next()); + verify(extractor, keys, values2); + } + + /** + * Test method for {@link Set#iterator()}. + */ + @Test(expected = UnsupportedOperationException.class) + public void testIteratorRemove() { + Enumeration keys = createMock(Enumeration.class); + + expect(extractor.getKeys()).andReturn(keys); + + try { + replay(extractor, keys); + entrySet.iterator().remove(); + } finally { + verify(extractor, keys); + } + } + + /** + * Tests {@link Set#remove(Object)}. + */ + @Test(expected = UnsupportedOperationException.class) + public void testRemove() { + entrySet.remove(null); + } + + /** + * Tests {@link Set#removeAll(java.util.Collection)}. + */ + @Test(expected = UnsupportedOperationException.class) + public void testRemoveAll() { + entrySet.removeAll(null); + } + + /** + * Tests {@link Set#retainAll(java.util.Collection)}. + */ + @Test(expected = UnsupportedOperationException.class) + public void testRetainAll() { + entrySet.retainAll(null); + } + + /** + * Test method for {@link HeaderValuesMap#size()}. + */ + @Test + public void testSize() { + Enumeration keys = createMock(Enumeration.class); + + expect(extractor.getKeys()).andReturn(keys); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("one"); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("two"); + expect(keys.hasMoreElements()).andReturn(false); + + replay(extractor, keys); + assertEquals(2, entrySet.size()); + verify(extractor, keys); + } + + /** + * Test method for {@link Set#toArray()}. + */ + @Test + public void testToArray() { + Enumeration keys = createMock(Enumeration.class); + Enumeration values1 = createMock(Enumeration.class); + Enumeration values2 = createMock(Enumeration.class); + + expect(extractor.getKeys()).andReturn(keys); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("one"); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("two"); + expect(keys.hasMoreElements()).andReturn(false); + replay(extractor, keys, values1, values2); + assertArrayEquals(new String[]{"one", "two"}, entrySet.toArray()); + verify(extractor, keys, values1, values2); + } + + /** + * Test method for {@link Set#toArray(Object[])}. + */ + @Test + public void testToArrayTArray() { + Enumeration keys = createMock(Enumeration.class); + Enumeration values1 = createMock(Enumeration.class); + Enumeration values2 = createMock(Enumeration.class); + + expect(extractor.getKeys()).andReturn(keys); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("one"); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("two"); + expect(keys.hasMoreElements()).andReturn(false); + + replay(extractor, keys, values1, values2); + String[] realArray = new String[2]; + assertArrayEquals(new String[]{"one", "two"}, entrySet.toArray(realArray)); + verify(extractor, keys, values1, values2); + } +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/request/collection/MapEntryArrayValuesTest.java b/plugins/tiles/src/test/java/org/apache/tiles/request/collection/MapEntryArrayValuesTest.java new file mode 100644 index 000000000..97045cd10 --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/request/collection/MapEntryArrayValuesTest.java @@ -0,0 +1,76 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.request.collection; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; + +/** + * Tests {@link MapEntryArrayValues}. + */ +public class MapEntryArrayValuesTest { + + /** + * Test method for {@link MapEntryArrayValues#hashCode()}. + */ + @Test + public void testHashCode() { + MapEntryArrayValues entry = new MapEntryArrayValues<>("key", new String[]{"value1", "value2"}, false); + assertEquals("key".hashCode() ^ ("value1".hashCode() + "value2".hashCode()), entry.hashCode()); + entry = new MapEntryArrayValues<>(null, new String[]{"value1", "value2"}, false); + assertEquals(("value1".hashCode() + "value2".hashCode()), entry.hashCode()); + entry = new MapEntryArrayValues<>("key", null, false); + assertEquals("key".hashCode(), entry.hashCode()); + entry = new MapEntryArrayValues<>(null, null, false); + assertEquals(0, entry.hashCode()); + } + + /** + * Test method for {@link MapEntryArrayValues#equals(Object)}. + */ + @Test + public void testEqualsObject() { + MapEntryArrayValues entry = new MapEntryArrayValues<>("key", new String[]{"value1", "value2"}, false); + assertNotEquals(null, entry); + MapEntryArrayValues entry2 = new MapEntryArrayValues<>("key", new String[]{"value1", "value2"}, false); + assertEquals(entry, entry2); + entry2 = new MapEntryArrayValues<>("key", null, false); + assertNotEquals(entry, entry2); + entry2 = new MapEntryArrayValues<>("key2", new String[]{"value1", "value2"}, false); + assertNotEquals(entry, entry2); + entry2 = new MapEntryArrayValues<>("key", new String[]{"value1", "value3"}, false); + assertNotEquals(entry, entry2); + entry = new MapEntryArrayValues<>(null, new String[]{"value1", "value2"}, false); + entry2 = new MapEntryArrayValues<>(null, new String[]{"value1", "value2"}, false); + assertEquals(entry, entry2); + entry = new MapEntryArrayValues<>("key", null, false); + entry2 = new MapEntryArrayValues<>("key", null, false); + assertEquals(entry, entry2); + entry2 = new MapEntryArrayValues<>("key", new String[]{"value1", "value2"}, false); + assertNotEquals(entry, entry2); + entry = new MapEntryArrayValues<>(null, new String[]{null, "value2"}, false); + entry2 = new MapEntryArrayValues<>(null, new String[]{null, "value2"}, false); + assertEquals(entry, entry2); + entry2 = new MapEntryArrayValues<>(null, new String[]{"value1", "value2"}, false); + assertNotEquals(entry, entry2); + } + +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/request/collection/MapEntryTest.java b/plugins/tiles/src/test/java/org/apache/tiles/request/collection/MapEntryTest.java new file mode 100644 index 000000000..31406b057 --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/request/collection/MapEntryTest.java @@ -0,0 +1,106 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.request.collection; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; + +/** + * Tests {@link MapEntry}. + */ +public class MapEntryTest { + + /** + * Test method for {@link MapEntry#hashCode()}. + */ + @Test + public void testHashCode() { + MapEntry entry = new MapEntry<>("key", "value", false); + assertEquals("key".hashCode() ^ "value".hashCode(), entry.hashCode()); + entry = new MapEntry<>(null, "value", false); + assertEquals("value".hashCode(), entry.hashCode()); + entry = new MapEntry<>("key", null, false); + assertEquals("key".hashCode(), entry.hashCode()); + entry = new MapEntry<>(null, null, false); + assertEquals(0, entry.hashCode()); + } + + /** + * Test method for {@link MapEntry#getKey()}. + */ + @Test + public void testGetKey() { + MapEntry entry = new MapEntry<>("key", "value", false); + assertEquals("key", entry.getKey()); + } + + /** + * Test method for {@link MapEntry#getValue()}. + */ + @Test + public void testGetValue() { + MapEntry entry = new MapEntry<>("key", "value", false); + assertEquals("value", entry.getValue()); + } + + /** + * Test method for {@link MapEntry#setValue(Object)}. + */ + @Test + public void testSetValue() { + MapEntry entry = new MapEntry<>("key", "value", true); + assertEquals("value", entry.getValue()); + entry.setValue("value2"); + assertEquals("value2", entry.getValue()); + } + + /** + * Test method for {@link MapEntry#setValue(Object)}. + */ + @Test(expected = UnsupportedOperationException.class) + public void testSetValueException() { + MapEntry entry = new MapEntry<>("key", "value", false); + assertEquals("value", entry.getValue()); + entry.setValue("value2"); + } + + /** + * Test method for {@link MapEntry#equals(Object)}. + */ + @Test + public void testEqualsObject() { + MapEntry entry = new MapEntry<>("key", "value", false); + assertNotEquals(null, entry); + MapEntry entry2 = new MapEntry<>("key", "value", false); + assertEquals(entry, entry2); + entry2 = new MapEntry<>("key2", "value", false); + assertNotEquals(entry, entry2); + entry2 = new MapEntry<>("key", "value2", false); + assertNotEquals(entry, entry2); + entry = new MapEntry<>(null, "value", false); + entry2 = new MapEntry<>(null, "value", false); + assertEquals(entry, entry2); + entry = new MapEntry<>("key", null, false); + entry2 = new MapEntry<>("key", null, false); + assertEquals(entry, entry2); + } + +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/request/collection/ReadOnlyEnumerationMapEntrySetTest.java b/plugins/tiles/src/test/java/org/apache/tiles/request/collection/ReadOnlyEnumerationMapEntrySetTest.java new file mode 100644 index 000000000..ad44d0379 --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/request/collection/ReadOnlyEnumerationMapEntrySetTest.java @@ -0,0 +1,294 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.request.collection; + +import org.apache.tiles.request.attribute.HasKeys; +import org.junit.Before; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +/** + * Tests {@link ReadOnlyEnumerationMap#entrySet()}. + */ +public class ReadOnlyEnumerationMapEntrySetTest { + + /** + * The extractor to use. + */ + private HasKeys extractor; + + /** + * The set to test. + */ + private Set> entrySet; + + /** + * Sets up the test. + */ + @Before + public void setUp() { + extractor = createMock(HasKeys.class); + ReadOnlyEnumerationMap map = new ReadOnlyEnumerationMap<>(extractor); + entrySet = map.entrySet(); + } + + /** + * Tests {@link Set#add(Object)}. + */ + @Test(expected = UnsupportedOperationException.class) + public void testAdd() { + entrySet.add(null); + } + + @Test(expected = UnsupportedOperationException.class) + public void testAddAll() { + entrySet.addAll(null); + } + + @Test(expected = UnsupportedOperationException.class) + public void testClear() { + entrySet.clear(); + } + + /** + * Tests {@link Set#contains(Object)}. + */ + @Test + public void testContains() { + Map.Entry entry = createMock(Map.Entry.class); + Enumeration values2 = createMock(Enumeration.class); + + expect(entry.getKey()).andReturn("two"); + expect(entry.getValue()).andReturn(2); + + expect(extractor.getValue("two")).andReturn(2); + + replay(extractor, entry, values2); + assertTrue(entrySet.contains(entry)); + verify(extractor, entry, values2); + } + + @Test + public void testContainsAll() { + Map.Entry entry1 = createMock(Map.Entry.class); + Map.Entry entry2 = createMock(Map.Entry.class); + + expect(entry1.getKey()).andReturn("one"); + expect(entry1.getValue()).andReturn(1); + expect(entry2.getKey()).andReturn("two"); + expect(entry2.getValue()).andReturn(2); + + expect(extractor.getValue("one")).andReturn(1); + expect(extractor.getValue("two")).andReturn(2); + + replay(extractor, entry1, entry2); + List> coll = new ArrayList<>(); + coll.add(entry1); + coll.add(entry2); + assertTrue(entrySet.containsAll(coll)); + verify(extractor, entry1, entry2); + } + + @Test + public void testContainsAllFalse() { + Map.Entry entry1 = createMock(Map.Entry.class); + + expect(entry1.getKey()).andReturn("one"); + expect(entry1.getValue()).andReturn("value4"); + + expect(extractor.getValue("one")).andReturn(1); + + replay(extractor, entry1); + List> coll = new ArrayList<>(); + coll.add(entry1); + assertFalse(entrySet.containsAll(coll)); + verify(extractor, entry1); + } + + /** + * Test method for {@link Set#isEmpty()}. + */ + @Test + public void testIsEmpty() { + Enumeration keys = createMock(Enumeration.class); + + expect(extractor.getKeys()).andReturn(keys); + expect(keys.hasMoreElements()).andReturn(true); + + replay(extractor, keys); + assertFalse(entrySet.isEmpty()); + verify(extractor, keys); + } + + /** + * Test method for {@link Set#iterator()}. + */ + @Test + public void testIterator() { + Enumeration keys = createMock(Enumeration.class); + + expect(extractor.getKeys()).andReturn(keys); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("two"); + + expect(extractor.getValue("two")).andReturn(2); + + replay(extractor, keys); + Iterator> entryIt = entrySet.iterator(); + assertTrue(entryIt.hasNext()); + MapEntry entry = new MapEntry<>("two", 2, false); + assertEquals(entry, entryIt.next()); + verify(extractor, keys); + } + + /** + * Test method for {@link Set#iterator()}. + */ + @Test(expected = UnsupportedOperationException.class) + public void testIteratorRemove() { + Enumeration keys = createMock(Enumeration.class); + + expect(extractor.getKeys()).andReturn(keys); + + try { + replay(extractor, keys); + entrySet.iterator().remove(); + } finally { + verify(extractor, keys); + } + } + + /** + * Tests {@link Set#remove(Object)}. + */ + @Test(expected = UnsupportedOperationException.class) + public void testRemove() { + entrySet.remove(null); + } + + /** + * Tests {@link Set#removeAll(java.util.Collection)}. + */ + @Test(expected = UnsupportedOperationException.class) + public void testRemoveAll() { + entrySet.removeAll(null); + } + + /** + * Tests {@link Set#retainAll(java.util.Collection)}. + */ + @Test(expected = UnsupportedOperationException.class) + public void testRetainAll() { + entrySet.retainAll(null); + } + + /** + * Test method for {@link HeaderValuesMap#size()}. + */ + @Test + public void testSize() { + Enumeration keys = createMock(Enumeration.class); + + expect(extractor.getKeys()).andReturn(keys); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("one"); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("two"); + expect(keys.hasMoreElements()).andReturn(false); + + replay(extractor, keys); + assertEquals(2, entrySet.size()); + verify(extractor, keys); + } + + /** + * Test method for {@link Set#toArray()}. + */ + @SuppressWarnings("unchecked") + @Test + public void testToArray() { + Enumeration keys = createMock(Enumeration.class); + Enumeration values1 = createMock(Enumeration.class); + Enumeration values2 = createMock(Enumeration.class); + + expect(extractor.getKeys()).andReturn(keys); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("one"); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("two"); + expect(keys.hasMoreElements()).andReturn(false); + + expect(extractor.getValue("one")).andReturn(1); + expect(extractor.getValue("two")).andReturn(2); + + MapEntry[] entryArray = new MapEntry[2]; + entryArray[0] = new MapEntry<>("one", 1, false); + entryArray[1] = new MapEntry<>("two", 2, false); + + replay(extractor, keys, values1, values2); + assertArrayEquals(entryArray, entrySet.toArray()); + verify(extractor, keys, values1, values2); + } + + /** + * Test method for {@link Set#toArray(Object[])}. + */ + @SuppressWarnings("unchecked") + @Test + public void testToArrayTArray() { + Enumeration keys = createMock(Enumeration.class); + Enumeration values1 = createMock(Enumeration.class); + Enumeration values2 = createMock(Enumeration.class); + + expect(extractor.getKeys()).andReturn(keys); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("one"); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("two"); + expect(keys.hasMoreElements()).andReturn(false); + + expect(extractor.getValue("one")).andReturn(1); + expect(extractor.getValue("two")).andReturn(2); + + MapEntry[] entryArray = new MapEntry[2]; + entryArray[0] = new MapEntry<>("one", 1, false); + entryArray[1] = new MapEntry<>("two", 2, false); + + replay(extractor, keys, values1, values2); + MapEntry[] realArray = new MapEntry[2]; + assertArrayEquals(entryArray, entrySet.toArray(realArray)); + verify(extractor, keys, values1, values2); + } +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/request/collection/ReadOnlyEnumerationMapTest.java b/plugins/tiles/src/test/java/org/apache/tiles/request/collection/ReadOnlyEnumerationMapTest.java new file mode 100644 index 000000000..be3245691 --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/request/collection/ReadOnlyEnumerationMapTest.java @@ -0,0 +1,306 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.request.collection; + +import org.apache.tiles.request.attribute.HasKeys; +import org.junit.Before; +import org.junit.Test; + +import java.util.Enumeration; +import java.util.HashMap; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.createMockBuilder; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertTrue; + +/** + * Tests {@link ReadOnlyEnumerationMap}. + */ +public class ReadOnlyEnumerationMapTest { + + /** + * The extractor to use. + */ + private HasKeys extractor; + + /** + * The map to test. + */ + private ReadOnlyEnumerationMap map; + + /** + * Sets up the test. + */ + @Before + public void setUp() { + extractor = createMock(HasKeys.class); + map = new ReadOnlyEnumerationMap<>(extractor); + } + + /** + * Test method for {@link ReadOnlyEnumerationMap#clear()}. + */ + @Test(expected = UnsupportedOperationException.class) + public void testClear() { + map.clear(); + } + + /** + * Test method for {@link ReadOnlyEnumerationMap#containsKey(Object)}. + */ + @Test + public void testContainsKey() { + expect(extractor.getValue("one")).andReturn(1); + expect(extractor.getValue("two")).andReturn(null); + + replay(extractor); + assertTrue(map.containsKey("one")); + assertFalse(map.containsKey("two")); + verify(extractor); + } + + /** + * Test method for {@link ReadOnlyEnumerationMap#containsValue(Object)}. + */ + @Test + public void testContainsValue() { + Enumeration keys = createMock(Enumeration.class); + + expect(extractor.getKeys()).andReturn(keys); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("one"); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("two"); + + expect(extractor.getValue("one")).andReturn(1); + expect(extractor.getValue("two")).andReturn(2); + + replay(extractor, keys); + assertTrue(map.containsValue(2)); + verify(extractor, keys); + } + + /** + * Test method for {@link ReadOnlyEnumerationMap#containsValue(Object)}. + */ + @Test + public void testContainsValueFalse() { + Enumeration keys = createMock(Enumeration.class); + + expect(extractor.getKeys()).andReturn(keys); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("one"); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("two"); + expect(keys.hasMoreElements()).andReturn(false); + + expect(extractor.getValue("one")).andReturn(1); + expect(extractor.getValue("two")).andReturn(1); + + replay(extractor, keys); + assertFalse(map.containsValue(3)); + verify(extractor, keys); + } + + /** + * Test method for {@link ReadOnlyEnumerationMap#get(Object)}. + */ + @Test + public void testGet() { + expect(extractor.getValue("two")).andReturn(2); + + replay(extractor); + assertEquals(new Integer(2), map.get("two")); + verify(extractor); + } + + /** + * Test method for {@link ReadOnlyEnumerationMap#isEmpty()}. + */ + @Test + public void testIsEmpty() { + Enumeration keys = createMock(Enumeration.class); + + expect(extractor.getKeys()).andReturn(keys); + expect(keys.hasMoreElements()).andReturn(true); + + replay(extractor, keys); + assertFalse(map.isEmpty()); + verify(extractor, keys); + } + + /** + * Test method for {@link ReadOnlyEnumerationMap#isEmpty()}. + */ + @Test + public void testIsEmptyTrue() { + Enumeration keys = createMock(Enumeration.class); + + expect(extractor.getKeys()).andReturn(keys); + expect(keys.hasMoreElements()).andReturn(false); + + replay(extractor, keys); + assertTrue(map.isEmpty()); + verify(extractor, keys); + } + + /** + * Test method for {@link ReadOnlyEnumerationMap#keySet()}. + */ + @Test + public void testKeySet() { + replay(extractor); + assertTrue(map.keySet() instanceof KeySet); + verify(extractor); + } + + @Test(expected = UnsupportedOperationException.class) + public void testPut() { + map.put("one", 1); + } + + /** + * Test method for {@link ReadOnlyEnumerationMap#putAll(java.util.Map)}. + */ + @Test(expected = UnsupportedOperationException.class) + public void testPutAll() { + map.putAll(new HashMap<>()); + } + + /** + * Test method for {@link ReadOnlyEnumerationMap#remove(Object)}. + */ + @Test(expected = UnsupportedOperationException.class) + public void testRemove() { + map.remove("one"); + } + + /** + * Test method for {@link ReadOnlyEnumerationMap#size()}. + */ + @Test + public void testSize() { + Enumeration keys = createMock(Enumeration.class); + + expect(extractor.getKeys()).andReturn(keys); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("one"); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("two"); + expect(keys.hasMoreElements()).andReturn(false); + + replay(extractor, keys); + assertEquals(2, map.size()); + verify(extractor, keys); + } + + @Test + public void testHashCode() { + Enumeration keys = createMock(Enumeration.class); + + expect(extractor.getKeys()).andReturn(keys); + + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("first"); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("second"); + expect(keys.hasMoreElements()).andReturn(false); + + Integer value1 = 1; + + expect(extractor.getValue("first")).andReturn(value1); + expect(extractor.getValue("second")).andReturn(null); + + replay(extractor, keys); + assertEquals(("first".hashCode() ^ value1.hashCode()) + ("second".hashCode()), map.hashCode()); + verify(extractor, keys); + } + + @Test + public void testEqualsObject() { + HasKeys otherRequest = createMock(HasKeys.class); + ReadOnlyEnumerationMap otherMap = createMockBuilder(ReadOnlyEnumerationMap.class).withConstructor(otherRequest).createMock(); + Enumeration keys = createMock(Enumeration.class); + Enumeration otherKeys = createMock(Enumeration.class); + + expect(extractor.getKeys()).andReturn(keys); + expect(otherRequest.getKeys()).andReturn(otherKeys); + + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("first"); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("second"); + expect(keys.hasMoreElements()).andReturn(false); + + expect(extractor.getValue("first")).andReturn(1); + expect(extractor.getValue("second")).andReturn(2); + + expect(otherKeys.hasMoreElements()).andReturn(true); + expect(otherKeys.nextElement()).andReturn("first"); + expect(otherKeys.hasMoreElements()).andReturn(true); + expect(otherKeys.nextElement()).andReturn("second"); + expect(otherKeys.hasMoreElements()).andReturn(false); + + expect(otherRequest.getValue("first")).andReturn(1); + expect(otherRequest.getValue("second")).andReturn(2); + + replay(extractor, otherRequest, otherMap, keys, otherKeys); + assertEquals(map, otherMap); + verify(extractor, otherRequest, otherMap, keys, otherKeys); + } + + @Test + public void testEqualsObjectFalse() { + HasKeys otherRequest = createMock(HasKeys.class); + ReadOnlyEnumerationMap otherMap = createMockBuilder(ReadOnlyEnumerationMap.class).withConstructor(otherRequest).createMock(); + Enumeration keys = createMock(Enumeration.class); + Enumeration otherKeys = createMock(Enumeration.class); + + expect(extractor.getKeys()).andReturn(keys); + expect(otherRequest.getKeys()).andReturn(otherKeys); + + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("first"); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("second"); + expect(keys.hasMoreElements()).andReturn(false); + + expect(extractor.getValue("first")).andReturn(1); + expect(extractor.getValue("second")).andReturn(2); + + expect(otherKeys.hasMoreElements()).andReturn(true); + expect(otherKeys.nextElement()).andReturn("first"); + expect(otherKeys.hasMoreElements()).andReturn(true); + expect(otherKeys.nextElement()).andReturn("second"); + expect(otherKeys.hasMoreElements()).andReturn(false); + + expect(otherRequest.getValue("first")).andReturn(1); + expect(otherRequest.getValue("second")).andReturn(3); + + replay(extractor, otherRequest, otherMap, keys, otherKeys); + assertNotEquals(map, otherMap); + verify(extractor, otherRequest, otherMap, keys, otherKeys); + } +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/request/collection/ReadOnlyEnumerationMapValuesCollectionTest.java b/plugins/tiles/src/test/java/org/apache/tiles/request/collection/ReadOnlyEnumerationMapValuesCollectionTest.java new file mode 100644 index 000000000..b37dbdc03 --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/request/collection/ReadOnlyEnumerationMapValuesCollectionTest.java @@ -0,0 +1,312 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.request.collection; + +import org.apache.tiles.request.attribute.HasKeys; +import org.junit.Before; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Enumeration; +import java.util.Iterator; +import java.util.List; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +/** + * Tests {@link ReadOnlyEnumerationMap#values()}. + */ +public class ReadOnlyEnumerationMapValuesCollectionTest { + + /** + * The extractor to use. + */ + private HasKeys extractor; + + /** + * The collection to test. + */ + private Collection coll; + + /** + * Sets up the test. + */ + @Before + public void setUp() { + extractor = createMock(HasKeys.class); + ReadOnlyEnumerationMap map = new ReadOnlyEnumerationMap<>(extractor); + coll = map.values(); + } + + /** + * Tests {@link Collection#add(Object)}. + */ + @Test(expected = UnsupportedOperationException.class) + public void testAdd() { + coll.add(null); + } + + @Test(expected = UnsupportedOperationException.class) + public void testAddAll() { + coll.addAll(null); + } + + @Test(expected = UnsupportedOperationException.class) + public void testClear() { + coll.clear(); + } + + /** + * Tests {@link Collection#contains(Object)}. + */ + @Test + public void testContainsValue() { + Enumeration keys = createMock(Enumeration.class); + + expect(extractor.getKeys()).andReturn(keys); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("one"); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("two"); + + expect(extractor.getValue("one")).andReturn(1); + expect(extractor.getValue("two")).andReturn(2); + + replay(extractor, keys); + assertTrue(coll.contains(2)); + verify(extractor, keys); + } + + /** + * Tests {@link Collection#contains(Object)}. + */ + @Test + public void testContainsValueFalse() { + Enumeration keys = createMock(Enumeration.class); + + expect(extractor.getKeys()).andReturn(keys); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("one"); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("two"); + expect(keys.hasMoreElements()).andReturn(false); + + expect(extractor.getValue("one")).andReturn(1); + expect(extractor.getValue("two")).andReturn(2); + + replay(extractor, keys); + assertFalse(coll.contains(3)); + verify(extractor, keys); + } + + @Test + public void testContainsAll() { + Enumeration keys = createMock(Enumeration.class); + + expect(extractor.getKeys()).andReturn(keys); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("one"); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("two"); + + expect(extractor.getValue("one")).andReturn(1); + expect(extractor.getValue("two")).andReturn(2); + + replay(extractor, keys); + List coll = new ArrayList<>(); + coll.add(1); + coll.add(2); + assertTrue(this.coll.containsAll(coll)); + verify(extractor, keys); + } + + @Test + public void testContainsAllFalse() { + Enumeration keys = createMock(Enumeration.class); + + expect(extractor.getKeys()).andReturn(keys); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("one"); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("two"); + expect(keys.hasMoreElements()).andReturn(false); + + expect(extractor.getValue("one")).andReturn(1); + expect(extractor.getValue("two")).andReturn(2); + + replay(extractor, keys); + List coll = new ArrayList<>(); + coll.add(3); + assertFalse(this.coll.containsAll(coll)); + verify(extractor, keys); + } + + /** + * Test method for {@link Collection#isEmpty()}. + */ + @Test + public void testIsEmpty() { + Enumeration keys = createMock(Enumeration.class); + + expect(extractor.getKeys()).andReturn(keys); + expect(keys.hasMoreElements()).andReturn(true); + + replay(extractor, keys); + assertFalse(coll.isEmpty()); + verify(extractor, keys); + } + + /** + * Test method for {@link Collection#iterator()}. + */ + @Test + public void testIterator() { + Enumeration keys = createMock(Enumeration.class); + + expect(extractor.getKeys()).andReturn(keys); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("two"); + + expect(extractor.getValue("two")).andReturn(2); + + replay(extractor, keys); + Iterator entryIt = coll.iterator(); + assertTrue(entryIt.hasNext()); + assertEquals(new Integer(2), entryIt.next()); + verify(extractor, keys); + } + + /** + * Test method for {@link Collection#iterator()}. + */ + @Test(expected = UnsupportedOperationException.class) + public void testIteratorRemove() { + Enumeration keys = createMock(Enumeration.class); + + expect(extractor.getKeys()).andReturn(keys); + + try { + replay(extractor, keys); + coll.iterator().remove(); + } finally { + verify(extractor, keys); + } + } + + /** + * Tests {@link Collection#remove(Object)}. + */ + @Test(expected = UnsupportedOperationException.class) + public void testRemove() { + coll.remove(null); + } + + /** + * Tests {@link Collection#removeAll(Collection)}. + */ + @Test(expected = UnsupportedOperationException.class) + public void testRemoveAll() { + coll.removeAll(null); + } + + /** + * Tests {@link Collection#retainAll(Collection)}. + */ + @Test(expected = UnsupportedOperationException.class) + public void testRetainAll() { + coll.retainAll(null); + } + + /** + * Test method for {@link HeaderValuesMap#size()}. + */ + @Test + public void testSize() { + Enumeration keys = createMock(Enumeration.class); + + expect(extractor.getKeys()).andReturn(keys); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("one"); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("two"); + expect(keys.hasMoreElements()).andReturn(false); + + replay(extractor, keys); + assertEquals(2, coll.size()); + verify(extractor, keys); + } + + /** + * Test method for {@link Collection#toArray()}. + */ + @Test + public void testToArray() { + Enumeration keys = createMock(Enumeration.class); + + expect(extractor.getKeys()).andReturn(keys); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("one"); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("two"); + expect(keys.hasMoreElements()).andReturn(false); + + expect(extractor.getValue("one")).andReturn(1); + expect(extractor.getValue("two")).andReturn(2); + + Integer[] entryArray = new Integer[]{1, 2}; + + replay(extractor, keys); + assertArrayEquals(entryArray, coll.toArray()); + verify(extractor, keys); + } + + /** + * Test method for {@link Collection#toArray(Object[])}. + */ + @Test + public void testToArrayTArray() { + Enumeration keys = createMock(Enumeration.class); + + expect(extractor.getKeys()).andReturn(keys); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("one"); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("two"); + expect(keys.hasMoreElements()).andReturn(false); + + expect(extractor.getValue("one")).andReturn(1); + expect(extractor.getValue("two")).andReturn(2); + + Integer[] entryArray = new Integer[]{1, 2}; + + replay(extractor, keys); + Integer[] realArray = new Integer[2]; + assertArrayEquals(entryArray, coll.toArray(realArray)); + verify(extractor, keys); + } +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/request/collection/RemovableKeySetTest.java b/plugins/tiles/src/test/java/org/apache/tiles/request/collection/RemovableKeySetTest.java new file mode 100644 index 000000000..e60b02ed6 --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/request/collection/RemovableKeySetTest.java @@ -0,0 +1,129 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.request.collection; + +import org.apache.tiles.request.attribute.HasRemovableKeys; +import org.junit.Before; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.List; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +/** + * Tests {@link RemovableKeySet}. + */ +public class RemovableKeySetTest { + + /** + * The extractor to use. + */ + private HasRemovableKeys extractor; + + /** + * The key set to test. + */ + private RemovableKeySet entrySet; + + /** + * Sets up the test. + */ + @Before + public void setUp() { + extractor = createMock(HasRemovableKeys.class); + entrySet = new RemovableKeySet(extractor); + } + + /** + * Test method for {@link RemovableKeySet#remove(Object)}. + */ + @Test + public void testRemove() { + expect(extractor.getValue("one")).andReturn(1); + extractor.removeValue("one"); + + replay(extractor); + assertTrue(entrySet.remove("one")); + verify(extractor); + } + + /** + * Test method for {@link RemovableKeySet#remove(Object)}. + */ + @Test + public void testRemoveNoEffect() { + expect(extractor.getValue("one")).andReturn(null); + + replay(extractor); + assertFalse(entrySet.remove("one")); + verify(extractor); + } + + /** + * Test method for {@link RemovableKeySet#removeAll(java.util.Collection)}. + */ + @Test + public void testRemoveAll() { + expect(extractor.getValue("one")).andReturn(1); + expect(extractor.getValue("two")).andReturn(2); + extractor.removeValue("one"); + extractor.removeValue("two"); + + replay(extractor); + List coll = new ArrayList<>(); + coll.add("one"); + coll.add("two"); + assertTrue(entrySet.removeAll(coll)); + verify(extractor); + } + + /** + * Test method for {@link RemovableKeySet#retainAll(java.util.Collection)}. + */ + @Test + public void testRetainAll() { + Enumeration keys = createMock(Enumeration.class); + + expect(extractor.getKeys()).andReturn(keys); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("one"); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("two"); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("three"); + expect(keys.hasMoreElements()).andReturn(false); + + extractor.removeValue("three"); + + replay(extractor, keys); + List coll = new ArrayList<>(); + coll.add("one"); + coll.add("two"); + assertTrue(entrySet.retainAll(coll)); + verify(extractor, keys); + } + +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/request/collection/ScopeMapEntrySetTest.java b/plugins/tiles/src/test/java/org/apache/tiles/request/collection/ScopeMapEntrySetTest.java new file mode 100644 index 000000000..c8ceea437 --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/request/collection/ScopeMapEntrySetTest.java @@ -0,0 +1,234 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.request.collection; + +import org.apache.tiles.request.attribute.AttributeExtractor; +import org.junit.Before; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +/** + * Tests {@link ScopeMap#entrySet()}. + */ +public class ScopeMapEntrySetTest { + + /** + * The extractor to use. + */ + private AttributeExtractor extractor; + + /** + * The entry set to test. + */ + private Set> entrySet; + + /** + * Sets up the test. + */ + @Before + public void setUp() { + extractor = createMock(AttributeExtractor.class); + ScopeMap map = new ScopeMap(extractor); + entrySet = map.entrySet(); + } + + /** + * Tests {@link Set#add(Object)}. + */ + @Test + public void testAdd() { + Map.Entry entry = createMock(Map.Entry.class); + + expect(entry.getKey()).andReturn("one"); + expect(entry.getValue()).andReturn(1); + expect(extractor.getValue("one")).andReturn(null); + + extractor.setValue("one", 1); + + replay(extractor, entry); + assertTrue(entrySet.add(entry)); + verify(extractor, entry); + } + + /** + * Tests {@link Set#add(Object)}. + */ + @Test + public void testAddNoEffect() { + Map.Entry entry = createMock(Map.Entry.class); + + expect(entry.getKey()).andReturn("one"); + expect(entry.getValue()).andReturn(1); + expect(extractor.getValue("one")).andReturn(1); + + replay(extractor, entry); + assertFalse(entrySet.add(entry)); + verify(extractor, entry); + } + + /** + * Tests {@link Set#addAll(java.util.Collection)}. + */ + @Test + public void testAddAll() { + Map.Entry entry1 = createMock(Map.Entry.class); + Map.Entry entry2 = createMock(Map.Entry.class); + + expect(entry1.getKey()).andReturn("one"); + expect(entry1.getValue()).andReturn(1); + expect(entry2.getKey()).andReturn("two"); + expect(entry2.getValue()).andReturn(2); + expect(extractor.getValue("one")).andReturn(null); + expect(extractor.getValue("two")).andReturn(null); + + extractor.setValue("one", 1); + extractor.setValue("two", 2); + + replay(extractor, entry1, entry2); + List> coll = new ArrayList<>(); + coll.add(entry1); + coll.add(entry2); + assertTrue(entrySet.addAll(coll)); + verify(extractor, entry1, entry2); + } + + /** + * Test method for {@link ScopeMap#clear()}. + */ + @Test + public void testClear() { + Enumeration keys = createMock(Enumeration.class); + + expect(extractor.getKeys()).andReturn(keys); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("one"); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("two"); + expect(keys.hasMoreElements()).andReturn(false); + + extractor.removeValue("one"); + extractor.removeValue("two"); + + replay(extractor, keys); + entrySet.clear(); + verify(extractor, keys); + } + + /** + * Tests {@link Set#remove(Object)}. + */ + @Test + public void testRemove() { + Map.Entry entry = createMock(Map.Entry.class); + + expect(entry.getKey()).andReturn("one"); + expect(entry.getValue()).andReturn(1); + expect(extractor.getValue("one")).andReturn(1); + extractor.removeValue("one"); + + replay(extractor, entry); + assertTrue(entrySet.remove(entry)); + verify(extractor, entry); + } + + /** + * Tests {@link Set#remove(Object)}. + */ + @Test + public void testRemoveNoEffect() { + Map.Entry entry = createMock(Map.Entry.class); + + expect(entry.getKey()).andReturn("one"); + expect(extractor.getValue("one")).andReturn(null); + + replay(extractor, entry); + assertFalse(entrySet.remove(entry)); + verify(extractor, entry); + } + + /** + * Tests {@link Set#addAll(java.util.Collection)}. + */ + @Test + public void testRemoveAll() { + Map.Entry entry1 = createMock(Map.Entry.class); + Map.Entry entry2 = createMock(Map.Entry.class); + + expect(entry1.getKey()).andReturn("one"); + expect(entry1.getValue()).andReturn(1); + expect(entry2.getKey()).andReturn("two"); + expect(entry2.getValue()).andReturn(2); + expect(extractor.getValue("one")).andReturn(1); + expect(extractor.getValue("two")).andReturn(2); + extractor.removeValue("one"); + extractor.removeValue("two"); + + replay(extractor, entry1, entry2); + List> coll = new ArrayList<>(); + coll.add(entry1); + coll.add(entry2); + assertTrue(entrySet.removeAll(coll)); + verify(extractor, entry1, entry2); + } + + /** + * Tests {@link Set#addAll(java.util.Collection)}. + */ + @Test + public void testRetainAll() { + Enumeration keys = createMock(Enumeration.class); + + expect(extractor.getKeys()).andReturn(keys); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("one"); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("two"); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("three"); + expect(keys.hasMoreElements()).andReturn(false); + + Map.Entry entry1 = new MapEntry<>("one", 1, false); + Map.Entry entry2 = new MapEntry<>("two", 2, false); + + expect(extractor.getValue("one")).andReturn(1); + expect(extractor.getValue("two")).andReturn(3); + expect(extractor.getValue("three")).andReturn(4); + extractor.removeValue("two"); + extractor.removeValue("three"); + + replay(extractor, keys); + List> coll = new ArrayList<>(); + coll.add(entry1); + coll.add(entry2); + assertTrue(entrySet.retainAll(coll)); + verify(extractor, keys); + } +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/request/collection/ScopeMapTest.java b/plugins/tiles/src/test/java/org/apache/tiles/request/collection/ScopeMapTest.java new file mode 100644 index 000000000..09853bcae --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/request/collection/ScopeMapTest.java @@ -0,0 +1,135 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.request.collection; + +import org.apache.tiles.request.attribute.AttributeExtractor; +import org.junit.Before; +import org.junit.Test; + +import java.util.Enumeration; +import java.util.LinkedHashMap; +import java.util.Map; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + +/** + * Tests {@link ScopeMap}. + */ +public class ScopeMapTest { + + /** + * The map tot est. + */ + private ScopeMap map; + + /** + * The extractor to use. + */ + private AttributeExtractor extractor; + + /** + * Sets up the test. + */ + @Before + public void setUp() { + extractor = createMock(AttributeExtractor.class); + map = new ScopeMap(extractor); + } + + /** + * Test method for {@link ScopeMap#clear()}. + */ + @Test + public void testClear() { + Enumeration keys = createMock(Enumeration.class); + + expect(extractor.getKeys()).andReturn(keys); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("one"); + expect(keys.hasMoreElements()).andReturn(true); + expect(keys.nextElement()).andReturn("two"); + expect(keys.hasMoreElements()).andReturn(false); + + extractor.removeValue("one"); + extractor.removeValue("two"); + + replay(extractor, keys); + map.clear(); + verify(extractor, keys); + } + + /** + * Test method for {@link ScopeMap#keySet()}. + */ + @Test + public void testKeySet() { + replay(extractor); + assertTrue(map.keySet() instanceof RemovableKeySet); + verify(extractor); + } + + /** + * Test method for {@link ScopeMap#put(String, Object)}. + */ + @Test + public void testPutStringObject() { + expect(extractor.getValue("one")).andReturn(null); + extractor.setValue("one", 1); + + replay(extractor); + assertNull(map.put("one", 1)); + verify(extractor); + } + + /** + * Test method for {@link ScopeMap#putAll(Map)}. + */ + @Test + public void testPutAllMapOfQextendsStringQextendsObject() { + Map items = new LinkedHashMap<>(); + items.put("one", 1); + items.put("two", 2); + + extractor.setValue("one", 1); + extractor.setValue("two", 2); + + replay(extractor); + map.putAll(items); + verify(extractor); + } + + /** + * Test method for {@link ScopeMap#remove(Object)}. + */ + @Test + public void testRemoveObject() { + expect(extractor.getValue("one")).andReturn(1); + extractor.removeValue("one"); + + replay(extractor); + assertEquals(1, map.remove("one")); + verify(extractor); + } +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/request/locale/LocaleUtilTest.java b/plugins/tiles/src/test/java/org/apache/tiles/request/locale/LocaleUtilTest.java new file mode 100644 index 000000000..202a68c48 --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/request/locale/LocaleUtilTest.java @@ -0,0 +1,42 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tiles.request.locale; + +import junit.framework.TestCase; + +import java.util.Locale; + +/** + * Tests {@link LocaleUtil}. + */ +public class LocaleUtilTest extends TestCase { + + /** + * Test method for {@link LocaleUtil#getParentLocale(Locale)}. + */ + public void testGetParentLocale() { + assertNull("The parent locale of NULL_LOCALE is not correct", LocaleUtil.getParentLocale(Locale.ROOT)); + assertEquals("The parent locale of 'en' is not correct", Locale.ROOT, LocaleUtil.getParentLocale(Locale.ENGLISH)); + assertEquals("The parent locale of 'en_US' is not correct", Locale.ENGLISH, LocaleUtil.getParentLocale(Locale.US)); + Locale locale = new Locale("es", "ES", "Traditional_WIN"); + Locale parentLocale = new Locale("es", "ES"); + assertEquals("The parent locale of 'es_ES_Traditional_WIN' is not correct", parentLocale, LocaleUtil.getParentLocale(locale)); + } +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/request/locale/PostfixedApplicationResourceTest.java b/plugins/tiles/src/test/java/org/apache/tiles/request/locale/PostfixedApplicationResourceTest.java new file mode 100644 index 000000000..48bd0a21b --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/request/locale/PostfixedApplicationResourceTest.java @@ -0,0 +1,131 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.request.locale; + +import org.junit.Test; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Locale; + +import static org.junit.Assert.assertEquals; + +/** + * Tests PostfixedApplicationResource. + */ +public class PostfixedApplicationResourceTest { + + private static class TestApplicationResource extends PostfixedApplicationResource { + public TestApplicationResource(String path, Locale locale) { + super(path, locale); + } + + public TestApplicationResource(String localePath) { + super(localePath); + } + + @Override + public InputStream getInputStream() throws IOException { + return null; + } + + @Override + public long getLastModified() throws IOException { + return 0; + } + + } + + /** + * Test getLocalePath(String path, Locale locale). + */ + @Test + public void testGetLocalePath() { + TestApplicationResource resource = new TestApplicationResource("/my test/path_fr.html"); + assertEquals("/my test/path.html", resource.getLocalePath(null)); + assertEquals("/my test/path.html", resource.getLocalePath(Locale.ROOT)); + assertEquals("/my test/path_it.html", resource.getLocalePath(Locale.ITALIAN)); + assertEquals("/my test/path_it_IT.html", resource.getLocalePath(Locale.ITALY)); + assertEquals("/my test/path_en_GB_scotland.html", resource.getLocalePath(new Locale("en", "GB", "scotland"))); + } + + @Test + public void testBuildFromString() { + TestApplicationResource resource = new TestApplicationResource("/my test/path_en_GB_scotland.html"); + assertEquals("/my test/path_en_GB_scotland.html", resource.getLocalePath()); + assertEquals("/my test/path.html", resource.getPath()); + assertEquals(new Locale("en", "GB", "scotland"), resource.getLocale()); + resource = new TestApplicationResource("/my test/path_it_IT.html"); + assertEquals("/my test/path_it_IT.html", resource.getLocalePath()); + assertEquals("/my test/path.html", resource.getPath()); + assertEquals(Locale.ITALY, resource.getLocale()); + resource = new TestApplicationResource("/my test/path_it.html"); + assertEquals("/my test/path_it.html", resource.getLocalePath()); + assertEquals("/my test/path.html", resource.getPath()); + assertEquals(Locale.ITALIAN, resource.getLocale()); + resource = new TestApplicationResource("/my test/path.html"); + assertEquals("/my test/path.html", resource.getLocalePath()); + assertEquals("/my test/path.html", resource.getPath()); + assertEquals(Locale.ROOT, resource.getLocale()); + resource = new TestApplicationResource("/my test/path_zz.html"); + assertEquals("/my test/path_zz.html", resource.getLocalePath()); + assertEquals("/my test/path_zz.html", resource.getPath()); + assertEquals(Locale.ROOT, resource.getLocale()); + resource = new TestApplicationResource("/my test/path_en_ZZ.html"); + assertEquals("/my test/path_en.html", resource.getLocalePath()); + assertEquals("/my test/path.html", resource.getPath()); + assertEquals(new Locale("en"), resource.getLocale()); + resource = new TestApplicationResource("/my test/path_tiles.html"); + assertEquals("/my test/path_tiles.html", resource.getLocalePath()); + assertEquals("/my test/path_tiles.html", resource.getPath()); + assertEquals(Locale.ROOT, resource.getLocale()); + resource = new TestApplicationResource("/my test/path_longwordthatbreaksISO639.html"); + assertEquals("/my test/path_longwordthatbreaksISO639.html", resource.getLocalePath()); + assertEquals("/my test/path_longwordthatbreaksISO639.html", resource.getPath()); + assertEquals(Locale.ROOT, resource.getLocale()); + resource = new TestApplicationResource("/my test/path_en_tiles.html"); + assertEquals("/my test/path_en.html", resource.getLocalePath()); + assertEquals("/my test/path.html", resource.getPath()); + assertEquals(new Locale("en"), resource.getLocale()); + resource = new TestApplicationResource("/my test/path_en_longwordthatbreaksISO3166.html"); + assertEquals("/my test/path_en.html", resource.getLocalePath()); + assertEquals("/my test/path.html", resource.getPath()); + assertEquals(new Locale("en"), resource.getLocale()); + } + + @Test + public void testBuildFromStringAndLocale() { + TestApplicationResource resource = new TestApplicationResource("/my test/path.html", new Locale("en", "GB", "scotland")); + assertEquals("/my test/path_en_GB_scotland.html", resource.getLocalePath()); + assertEquals("/my test/path.html", resource.getPath()); + assertEquals(new Locale("en", "GB", "scotland"), resource.getLocale()); + resource = new TestApplicationResource("/my test/path.html", Locale.ITALY); + assertEquals("/my test/path_it_IT.html", resource.getLocalePath()); + assertEquals("/my test/path.html", resource.getPath()); + assertEquals(Locale.ITALY, resource.getLocale()); + resource = new TestApplicationResource("/my test/path.html", Locale.ITALIAN); + assertEquals("/my test/path_it.html", resource.getLocalePath()); + assertEquals("/my test/path.html", resource.getPath()); + assertEquals(Locale.ITALIAN, resource.getLocale()); + resource = new TestApplicationResource("/my test/path.html", Locale.ROOT); + assertEquals("/my test/path.html", resource.getLocalePath()); + assertEquals("/my test/path.html", resource.getPath()); + assertEquals(Locale.ROOT, resource.getLocale()); + } +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/request/locale/URLApplicationResourceTest.java b/plugins/tiles/src/test/java/org/apache/tiles/request/locale/URLApplicationResourceTest.java new file mode 100644 index 000000000..964ca1b73 --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/request/locale/URLApplicationResourceTest.java @@ -0,0 +1,201 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.request.locale; + +import org.junit.After; +import org.junit.BeforeClass; +import org.junit.Test; + +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.lang.reflect.Field; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLConnection; +import java.net.URLStreamHandler; +import java.net.URLStreamHandlerFactory; +import java.util.Locale; + +import static java.lang.System.setProperty; +import static java.lang.reflect.Modifier.FINAL; +import static org.apache.tiles.request.locale.URLApplicationResource.REMOTE_PROTOCOLS_PROPERTY; +import static org.apache.tiles.request.locale.URLApplicationResource.initRemoteProtocols; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +/** + * Tests URLApplicationResource. + */ +public class URLApplicationResourceTest { + + private static final String EXPECTED_MESSAGE = "aMessage"; + + private static class TestUrlStreamHandler extends URLStreamHandler { + + @Override + protected URLConnection openConnection(final URL u) throws IOException { + throw new IOException(EXPECTED_MESSAGE); + } + } + + private static class TestURLStreamHandlerFactory implements URLStreamHandlerFactory { + + @Override + public URLStreamHandler createURLStreamHandler(final String protocol) { + if ("test1".equals(protocol) || "test2".equals(protocol)) { + return new TestUrlStreamHandler(); + } + return null; + } + } + + @BeforeClass + public static void setURLStreamHandlerFactory() { + URL.setURLStreamHandlerFactory(new TestURLStreamHandlerFactory()); + } + + @After + public void tearDown() { + setProperty(REMOTE_PROTOCOLS_PROPERTY, ""); + } + + /** + * Test getLocalePath(String path, Locale locale). + */ + @Test + public void testGetLocalePath() throws MalformedURLException { + URLApplicationResource resource = new URLApplicationResource("/my test/path_fr.html", new URL("file:///")); + assertEquals("/my test/path.html", resource.getLocalePath(null)); + assertEquals("/my test/path.html", resource.getLocalePath(Locale.ROOT)); + assertEquals("/my test/path_it.html", resource.getLocalePath(Locale.ITALIAN)); + assertEquals("/my test/path_it_IT.html", resource.getLocalePath(Locale.ITALY)); + assertEquals("/my test/path_en_GB_scotland.html", resource.getLocalePath(new Locale("en", "GB", "scotland"))); + } + + @Test + public void testBuildFromString() throws MalformedURLException { + URLApplicationResource resource = new URLApplicationResource("/my test/path_en_GB_scotland.html", new URL("file:///")); + assertEquals("/my test/path_en_GB_scotland.html", resource.getLocalePath()); + assertEquals("/my test/path.html", resource.getPath()); + assertEquals(new Locale("en", "GB", "scotland"), resource.getLocale()); + resource = new URLApplicationResource("/my test/path_it_IT.html", new URL("file:///")); + assertEquals("/my test/path_it_IT.html", resource.getLocalePath()); + assertEquals("/my test/path.html", resource.getPath()); + assertEquals(Locale.ITALY, resource.getLocale()); + resource = new URLApplicationResource("/my test/path_it.html", new URL("file:///")); + assertEquals("/my test/path_it.html", resource.getLocalePath()); + assertEquals("/my test/path.html", resource.getPath()); + assertEquals(Locale.ITALIAN, resource.getLocale()); + resource = new URLApplicationResource("/my test/path.html", new URL("file:///")); + assertEquals("/my test/path.html", resource.getLocalePath()); + assertEquals("/my test/path.html", resource.getPath()); + assertEquals(Locale.ROOT, resource.getLocale()); + resource = new URLApplicationResource("/my test/path_zz.html", new URL("file:///")); + assertEquals("/my test/path_zz.html", resource.getLocalePath()); + assertEquals("/my test/path_zz.html", resource.getPath()); + assertEquals(Locale.ROOT, resource.getLocale()); + resource = new URLApplicationResource("/my test/path_en_ZZ.html", new URL("file:///")); + assertEquals("/my test/path_en.html", resource.getLocalePath()); + assertEquals("/my test/path.html", resource.getPath()); + assertEquals(new Locale("en"), resource.getLocale()); + resource = new URLApplicationResource("/my test/path_tiles.html", new URL("file:///")); + assertEquals("/my test/path_tiles.html", resource.getLocalePath()); + assertEquals("/my test/path_tiles.html", resource.getPath()); + assertEquals(Locale.ROOT, resource.getLocale()); + resource = new URLApplicationResource("/my test/path_longwordthatbreaksISO639.html", new URL("file:///")); + assertEquals("/my test/path_longwordthatbreaksISO639.html", resource.getLocalePath()); + assertEquals("/my test/path_longwordthatbreaksISO639.html", resource.getPath()); + assertEquals(Locale.ROOT, resource.getLocale()); + resource = new URLApplicationResource("/my test/path_en_tiles.html", new URL("file:///")); + assertEquals("/my test/path_en.html", resource.getLocalePath()); + assertEquals("/my test/path.html", resource.getPath()); + assertEquals(new Locale("en"), resource.getLocale()); + resource = new URLApplicationResource("/my test/path_en_longwordthatbreaksISO3166.html", new URL("file:///")); + assertEquals("/my test/path_en.html", resource.getLocalePath()); + assertEquals("/my test/path.html", resource.getPath()); + assertEquals(new Locale("en"), resource.getLocale()); + } + + @Test + public void testBuildFromStringAndLocale() throws MalformedURLException { + URLApplicationResource resource = new URLApplicationResource("/my test/path.html", new Locale("en", "GB", "scotland"), new URL("file:///")); + assertEquals("/my test/path_en_GB_scotland.html", resource.getLocalePath()); + assertEquals("/my test/path.html", resource.getPath()); + assertEquals(new Locale("en", "GB", "scotland"), resource.getLocale()); + resource = new URLApplicationResource("/my test/path.html", Locale.ITALY, new URL("file:///")); + assertEquals("/my test/path_it_IT.html", resource.getLocalePath()); + assertEquals("/my test/path.html", resource.getPath()); + assertEquals(Locale.ITALY, resource.getLocale()); + resource = new URLApplicationResource("/my test/path.html", Locale.ITALIAN, new URL("file:///")); + assertEquals("/my test/path_it.html", resource.getLocalePath()); + assertEquals("/my test/path.html", resource.getPath()); + assertEquals(Locale.ITALIAN, resource.getLocale()); + resource = new URLApplicationResource("/my test/path.html", Locale.ROOT, new URL("file:///")); + assertEquals("/my test/path.html", resource.getLocalePath()); + assertEquals("/my test/path.html", resource.getPath()); + assertEquals(Locale.ROOT, resource.getLocale()); + } + + @Test + public void testGetLastModified() throws IOException { + URL url = getClass().getClassLoader().getResource("org/apache/tiles/request/locale/resource.txt"); + assertNotNull(url); + URLApplicationResource resource = new URLApplicationResource("org/apache/tiles/request/locale/resource.txt", url); + assertTrue(resource.getLastModified() > 0); + } + + @Test + public void testGetLastModifiedWithSpace() throws IOException { + URL url = getClass().getClassLoader().getResource("org/apache/tiles/request/locale/resource with space.txt"); + assertNotNull(url); + URLApplicationResource resource = new URLApplicationResource("org/apache/tiles/request/locale/resource with space.txt", url); + assertTrue(resource.getLastModified() > 0); + } + + @Test + public void testGetInputStream() throws IOException { + URL url = getClass().getClassLoader().getResource("org/apache/tiles/request/locale/resource.txt"); + assertNotNull(url); + URLApplicationResource resource = new URLApplicationResource("org/apache/tiles/request/locale/resource.txt", url); + InputStream is = resource.getInputStream(); + assertNotNull(is); + is.close(); + } + + @Test + public void testGetInputStreamWithSpace() throws IOException { + URL url = getClass().getClassLoader().getResource("org/apache/tiles/request/locale/resource with space.txt"); + assertNotNull(url); + URLApplicationResource resource = new URLApplicationResource("org/apache/tiles/request/locale/resource with space.txt", url); + InputStream is = resource.getInputStream(); + assertNotNull(is); + is.close(); + } + + @Test(expected = FileNotFoundException.class) + public void testLocalProtocol() throws IOException { + URL url = new URL("file://foo/bar.txt"); + URLApplicationResource resource = new URLApplicationResource("org/apache/tiles/request/locale/resource.txt", url); + resource.getInputStream(); + } + +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/request/reflect/CannotInstantiateObjectExceptionTest.java b/plugins/tiles/src/test/java/org/apache/tiles/request/reflect/CannotInstantiateObjectExceptionTest.java new file mode 100644 index 000000000..b170ca4e7 --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/request/reflect/CannotInstantiateObjectExceptionTest.java @@ -0,0 +1,41 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.request.reflect; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +/** + * Tests {@link CannotInstantiateObjectException}. + */ +public class CannotInstantiateObjectExceptionTest { + + /** + * Test method for {@link CannotInstantiateObjectException#CannotInstantiateObjectException(String, Throwable)}. + */ + @Test + public void testCannotInstantiateObjectExceptionStringThrowable() { + Throwable cause = new Throwable(); + CannotInstantiateObjectException exception = new CannotInstantiateObjectException("my message", cause); + assertEquals("my message", exception.getMessage()); + assertEquals(cause, exception.getCause()); + } + +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/request/reflect/ClassUtilTest.java b/plugins/tiles/src/test/java/org/apache/tiles/request/reflect/ClassUtilTest.java new file mode 100644 index 000000000..db01a2414 --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/request/reflect/ClassUtilTest.java @@ -0,0 +1,175 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tiles.request.reflect; + +import org.junit.Test; + +import java.beans.PropertyDescriptor; +import java.util.HashMap; +import java.util.Map; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; + +/** + * Tests {@link ClassUtil}. + */ +public class ClassUtilTest { + + /** + * The size of descriptor map. + */ + private static final int MAP_SIZE = 3; + + /** + * Test method for {@link ClassUtil#collectBeanInfo(Class, Map)}. + */ + @Test + public void testCollectBeanInfo() { + Map name2descriptor = new HashMap<>(); + ClassUtil.collectBeanInfo(TestInterface.class, name2descriptor); + assertEquals(MAP_SIZE, name2descriptor.size()); + PropertyDescriptor descriptor = name2descriptor.get("value"); + assertEquals("value", descriptor.getName()); + assertEquals(int.class, descriptor.getPropertyType()); + assertNotNull(descriptor.getReadMethod()); + assertNotNull(descriptor.getWriteMethod()); + descriptor = name2descriptor.get("value2"); + assertEquals("value2", descriptor.getName()); + assertEquals(long.class, descriptor.getPropertyType()); + assertNotNull(descriptor.getReadMethod()); + assertNull(descriptor.getWriteMethod()); + descriptor = name2descriptor.get("value3"); + assertEquals("value3", descriptor.getName()); + assertEquals(String.class, descriptor.getPropertyType()); + assertNull(descriptor.getReadMethod()); + assertNotNull(descriptor.getWriteMethod()); + } + + /** + * Test method for {@link ClassUtil#getClass(String, Class)}. + * @throws ClassNotFoundException If something goes wrong. + */ + @Test + public void testGetClass() throws ClassNotFoundException { + assertEquals(TestInterface.class, ClassUtil.getClass( + TestInterface.class.getName(), Object.class)); + } + + /** + * Test method for {@link ClassUtil#getClass(String, Class)}. + * @throws ClassNotFoundException If something goes wrong. + */ + @Test(expected = ClassNotFoundException.class) + public void testGetClassException() throws ClassNotFoundException { + ClassUtil.getClass("this.class.does.not.Exist", Object.class); + } + + /** + * Test method for {@link ClassUtil#instantiate(String, boolean)}. + */ + @Test + public void testInstantiate() { + assertNotNull(ClassUtil.instantiate(TestClass.class.getName(), true)); + assertNull(ClassUtil.instantiate("this.class.does.not.Exist", true)); + } + + /** + * Test method for {@link ClassUtil#instantiate(String, boolean)}. + */ + @Test + public void testInstantiateOneParameter() { + assertNotNull(ClassUtil.instantiate(TestClass.class.getName())); + } + + /** + * Test method for {@link ClassUtil#instantiate(String)}. + */ + @Test(expected = CannotInstantiateObjectException.class) + public void testInstantiateOneParameterException() { + assertNotNull(ClassUtil.instantiate("this.class.does.not.Exist")); + } + + /** + * Test method for {@link ClassUtil#instantiate(String)}. + */ + @Test(expected = CannotInstantiateObjectException.class) + public void testInstantiateInstantiationException() { + ClassUtil.instantiate(TestInterface.class.getName()); + } + + /** + * Test method for {@link ClassUtil#instantiate(String)}. + */ + @Test(expected = CannotInstantiateObjectException.class) + public void testInstantiateIllegalAccessException() { + ClassUtil.instantiate(TestPrivateClass.class.getName()); + } + + /** + * Interface to be used as test. + * + * @version $Rev$ $Date$ + */ + public interface TestInterface { + + /** + * The value. + * + * @return The value. + */ + int getValue(); + + /** + * The value. + * + * @param value The value. + */ + void setValue(int value); + + /** + * The value. + * + * @return The value. + */ + long getValue2(); + + /** + * The value. + * + * @param value3 The value. + */ + @SuppressWarnings("unused") + void setValue3(String value3); + } + + /** + * A test static class. + */ + public static class TestClass { + } + + /** + * A test static private class. + */ + private static class TestPrivateClass { + } +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/request/render/BasicRendererFactoryTest.java b/plugins/tiles/src/test/java/org/apache/tiles/request/render/BasicRendererFactoryTest.java new file mode 100644 index 000000000..c133b4cb2 --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/request/render/BasicRendererFactoryTest.java @@ -0,0 +1,100 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.request.render; + +import org.apache.tiles.request.ApplicationContext; +import org.junit.Before; +import org.junit.Test; + +import static org.easymock.EasyMock.*; +import static org.junit.Assert.assertSame; + +/** + * Basic renderer factory implementation. + */ +public class BasicRendererFactoryTest { + + /** + * The renderer factory. + */ + private BasicRendererFactory rendererFactory; + + /** + * Sets up the test. + */ + @Before + public void setUp() { + rendererFactory = new BasicRendererFactory(); + ApplicationContext applicationContext = createMock(ApplicationContext.class); + replay(applicationContext); + } + + /** + * Tests execution and + * {@link BasicRendererFactory#getRenderer(String)}. + */ + @Test + public void testInitAndGetRenderer() { + Renderer renderer1 = createMock(Renderer.class); + Renderer renderer2 = createMock(Renderer.class); + Renderer renderer3 = createMock(Renderer.class); + Renderer renderer4 = createMock(Renderer.class); + ApplicationContext applicationContext = createMock(ApplicationContext.class); + + replay(renderer1, renderer2, renderer3, renderer4, applicationContext); + rendererFactory.registerRenderer("string", renderer1); + rendererFactory.registerRenderer("test", renderer2); + rendererFactory.registerRenderer("test2", renderer3); + rendererFactory.setDefaultRenderer(renderer4); + Renderer renderer = rendererFactory.getRenderer("string"); + assertSame(renderer1, renderer); + renderer = rendererFactory.getRenderer("test"); + assertSame(renderer2, renderer); + renderer = rendererFactory.getRenderer("test2"); + assertSame(renderer3, renderer); + renderer = rendererFactory.getRenderer(null); + assertSame(renderer4, renderer); + verify(renderer1, renderer2, renderer3, renderer4, applicationContext); + } + + /** + * Tests execution and + * {@link BasicRendererFactory#getRenderer(String)}. + */ + @Test(expected = NoSuchRendererException.class) + public void testGetRendererException() { + Renderer renderer1 = createMock(Renderer.class); + Renderer renderer2 = createMock(Renderer.class); + Renderer renderer3 = createMock(Renderer.class); + Renderer renderer4 = createMock(Renderer.class); + ApplicationContext applicationContext = createMock(ApplicationContext.class); + + replay(renderer1, renderer2, renderer3, renderer4, applicationContext); + rendererFactory.registerRenderer("string", renderer1); + rendererFactory.registerRenderer("test", renderer2); + rendererFactory.registerRenderer("test2", renderer3); + rendererFactory.setDefaultRenderer(renderer4); + try { + rendererFactory.getRenderer("nothing"); + } finally { + verify(renderer1, renderer2, renderer3, renderer4, applicationContext); + } + } + +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/request/render/ChainedDelegateRendererTest.java b/plugins/tiles/src/test/java/org/apache/tiles/request/render/ChainedDelegateRendererTest.java new file mode 100644 index 000000000..31daf7fe1 --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/request/render/ChainedDelegateRendererTest.java @@ -0,0 +1,178 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.request.render; + +import org.apache.tiles.request.Request; +import org.easymock.EasyMock; +import org.junit.Before; +import org.junit.Test; + +import java.io.IOException; +import java.io.StringWriter; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; + +/** + * Tests {@link ChainedDelegateRenderer}. + */ +public class ChainedDelegateRendererTest { + + /** + * The renderer. + */ + private ChainedDelegateRenderer renderer; + + /** + * A mock string attribute renderer. + */ + private Renderer stringRenderer; + + /** + * A mock template attribute renderer. + */ + private Renderer templateRenderer; + + /** + * A mock definition attribute renderer. + */ + private Renderer definitionRenderer; + + /** + * Sets up the test. + */ + @Before + public void setUp() { + stringRenderer = createMock(Renderer.class); + templateRenderer = createMock(Renderer.class); + definitionRenderer = createMock(Renderer.class); + renderer = new ChainedDelegateRenderer(); + renderer.addAttributeRenderer(definitionRenderer); + renderer.addAttributeRenderer(templateRenderer); + renderer.addAttributeRenderer(stringRenderer); + } + + /** + * Tests + * {@link ChainedDelegateRenderer#render(String, Request)} + * writing a definition. + * + * @throws IOException If something goes wrong during rendition. + */ + @Test + public void testWriteDefinition() throws IOException { + Request requestContext = EasyMock.createMock(Request.class); + + expect(definitionRenderer.isRenderable("my.definition", requestContext)).andReturn(Boolean.TRUE); + definitionRenderer.render("my.definition", requestContext); + + replay(requestContext, stringRenderer, templateRenderer, definitionRenderer); + renderer.render("my.definition", requestContext); + verify(requestContext, stringRenderer, templateRenderer, definitionRenderer); + } + + /** + * Tests + * {@link ChainedDelegateRenderer#render(String, Request)} + * writing a definition. + * + * @throws IOException If something goes wrong during rendition. + */ + @Test(expected = NullPointerException.class) + public void testWriteNull() throws IOException { + StringWriter writer = new StringWriter(); + Request requestContext = EasyMock.createMock(Request.class); + + replay(requestContext, stringRenderer, templateRenderer, definitionRenderer); + try { + renderer.render(null, requestContext); + } finally { + writer.close(); + verify(requestContext, stringRenderer, templateRenderer, definitionRenderer); + } + } + + /** + * Tests + * {@link ChainedDelegateRenderer#render(String, Request)} + * writing a definition. + * + * @throws IOException If something goes wrong during rendition. + */ + @Test(expected = CannotRenderException.class) + public void testWriteNotRenderable() throws IOException { + StringWriter writer = new StringWriter(); + Request requestContext = EasyMock.createMock(Request.class); + + expect(definitionRenderer.isRenderable("Result", requestContext)).andReturn(Boolean.FALSE); + expect(templateRenderer.isRenderable("Result", requestContext)).andReturn(Boolean.FALSE); + expect(stringRenderer.isRenderable("Result", requestContext)).andReturn(Boolean.FALSE); + + replay(requestContext, stringRenderer, templateRenderer, definitionRenderer); + try { + renderer.render("Result", requestContext); + } finally { + writer.close(); + verify(requestContext, stringRenderer, templateRenderer, definitionRenderer); + } + } + + /** + * Tests + * {@link ChainedDelegateRenderer#render(String, Request)} + * writing a string. + * + * @throws IOException If something goes wrong during rendition. + */ + @Test + public void testWriteString() throws IOException { + Request requestContext = EasyMock.createMock(Request.class); + expect(definitionRenderer.isRenderable("Result", requestContext)).andReturn(Boolean.FALSE); + expect(templateRenderer.isRenderable("Result", requestContext)).andReturn(Boolean.FALSE); + expect(stringRenderer.isRenderable("Result", requestContext)).andReturn(Boolean.TRUE); + stringRenderer.render("Result", requestContext); + + replay(requestContext, stringRenderer, templateRenderer, definitionRenderer); + renderer.render("Result", requestContext); + verify(requestContext, stringRenderer, templateRenderer, definitionRenderer); + } + + /** + * Tests + * {@link ChainedDelegateRenderer#render(String, Request)} + * writing a template. + * + * @throws IOException If something goes wrong during rendition. + */ + @Test + public void testWriteTemplate() throws IOException { + StringWriter writer = new StringWriter(); + Request requestContext = EasyMock.createMock(Request.class); + templateRenderer.render("/myTemplate.jsp", requestContext); + expect(definitionRenderer.isRenderable("/myTemplate.jsp", requestContext)).andReturn(Boolean.FALSE); + expect(templateRenderer.isRenderable("/myTemplate.jsp", requestContext)).andReturn(Boolean.TRUE); + + replay(requestContext, stringRenderer, templateRenderer, definitionRenderer); + renderer.render("/myTemplate.jsp", requestContext); + writer.close(); + verify(requestContext, stringRenderer, templateRenderer, definitionRenderer); + } +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/request/render/DispatchRendererTest.java b/plugins/tiles/src/test/java/org/apache/tiles/request/render/DispatchRendererTest.java new file mode 100644 index 000000000..7f158ce69 --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/request/render/DispatchRendererTest.java @@ -0,0 +1,74 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.request.render; + +import org.apache.tiles.request.DispatchRequest; +import org.apache.tiles.request.Request; +import org.junit.Before; +import org.junit.Test; + +import java.io.IOException; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +/** + * Tests {@link DispatchRenderer}. + */ +public class DispatchRendererTest { + + /** + * The renderer. + */ + private DispatchRenderer renderer; + + @Before + public void setUp() { + renderer = new DispatchRenderer(); + } + + @Test + public void testWrite() throws IOException { + DispatchRequest requestContext = createMock(DispatchRequest.class); + requestContext.dispatch("/myTemplate.jsp"); + replay(requestContext); + renderer.render("/myTemplate.jsp", requestContext); + verify(requestContext); + } + + @Test(expected = CannotRenderException.class) + public void testWriteNull() throws IOException { + DispatchRequest requestContext = createMock(DispatchRequest.class); + replay(requestContext); + renderer.render(null, requestContext); + verify(requestContext); + } + + @Test + public void testIsRenderable() { + Request requestContext = createMock(DispatchRequest.class); + replay(requestContext); + assertTrue(renderer.isRenderable("/myTemplate.jsp", requestContext)); + assertFalse(renderer.isRenderable(null, requestContext)); + verify(requestContext); + } +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/request/render/NoSuchRendererExceptionTest.java b/plugins/tiles/src/test/java/org/apache/tiles/request/render/NoSuchRendererExceptionTest.java new file mode 100644 index 000000000..5c51a730c --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/request/render/NoSuchRendererExceptionTest.java @@ -0,0 +1,42 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tiles.request.render; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; + +/** + * Tests {@link NoSuchRendererException}. + */ +public class NoSuchRendererExceptionTest { + + /** + * Test method for {@link NoSuchRendererException#NoSuchRendererException(String)}. + */ + @Test + public void testNoSuchRendererExceptionString() { + NoSuchRendererException exception = new NoSuchRendererException("my message"); + assertEquals("my message", exception.getMessage()); + assertNull(exception.getCause()); + } + +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/request/render/StringRendererTest.java b/plugins/tiles/src/test/java/org/apache/tiles/request/render/StringRendererTest.java new file mode 100644 index 000000000..cce4710af --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/request/render/StringRendererTest.java @@ -0,0 +1,79 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.request.render; + +import org.apache.tiles.request.Request; +import org.junit.Before; +import org.junit.Test; + +import java.io.IOException; +import java.io.StringWriter; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +/** + * Tests {@link StringRenderer}. + */ +public class StringRendererTest { + + /** + * The renderer. + */ + private StringRenderer renderer; + + @Before + public void setUp() { + renderer = new StringRenderer(); + } + + /** + * Tests + * {@link StringRenderer#render(String, Request)}. + * + * @throws IOException If something goes wrong during rendition. + */ + @Test + public void testWrite() throws IOException { + StringWriter writer = new StringWriter(); + Request requestContext = createMock(Request.class); + expect(requestContext.getWriter()).andReturn(writer); + replay(requestContext); + renderer.render("Result", requestContext); + writer.close(); + assertEquals("Not written 'Result'", "Result", writer.toString()); + verify(requestContext); + } + + /** + * Tests + * {@link StringRenderer#isRenderable(String, Request)}. + */ + @Test + public void testIsRenderable() { + Request requestContext = createMock(Request.class); + replay(requestContext); + assertTrue(renderer.isRenderable("Result", requestContext)); + verify(requestContext); + } +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/template/AddAttributeModelTest.java b/plugins/tiles/src/test/java/org/apache/tiles/template/AddAttributeModelTest.java new file mode 100644 index 000000000..86da99995 --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/template/AddAttributeModelTest.java @@ -0,0 +1,111 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.template; + +import org.apache.tiles.api.Attribute; +import org.apache.tiles.api.ListAttribute; +import org.apache.tiles.autotag.core.runtime.ModelBody; +import org.apache.tiles.request.Request; +import org.junit.Before; +import org.junit.Test; + +import java.io.IOException; +import java.util.ArrayDeque; +import java.util.Deque; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import static org.junit.Assert.assertEquals; + +/** + * Tests {@link AddAttributeModel}. + */ +public class AddAttributeModelTest { + + /** + * The model to test. + */ + private AddAttributeModel model; + + /** + * Sets up the test. + */ + @Before + public void setUp() { + model = new AddAttributeModel(); + } + + /** + * Test method for {@link AddAttributeModel + * #execute(java.lang.Object, java.lang.String, java.lang.String, java.lang.String, + * Request, ModelBody)}. + * + * @throws IOException If something goes wrong. + */ + @Test + public void testExecute() throws IOException { + Request request = createMock(Request.class); + ModelBody modelBody = createMock(ModelBody.class); + Deque composeStack = new ArrayDeque<>(); + ListAttribute listAttribute = new ListAttribute(); + Attribute attribute; + composeStack.push(listAttribute); + Map requestScope = new HashMap<>(); + requestScope.put(ComposeStackUtil.COMPOSE_STACK_ATTRIBUTE_NAME, composeStack); + + expect(request.getContext("request")).andReturn(requestScope).times(2); + expect(modelBody.evaluateAsString()).andReturn(null); + expect(modelBody.evaluateAsString()).andReturn("myBody"); + + replay(request, modelBody); + model.execute("myValue", "myExpression", "myRole", "myType", + request, modelBody); + List attributes = listAttribute.getValue(); + assertEquals(1, attributes.size()); + attribute = attributes.iterator().next(); + assertEquals("myValue", attribute.getValue()); + assertEquals("myExpression", attribute.getExpressionObject().getExpression()); + assertEquals("myRole", attribute.getRole()); + assertEquals("myType", attribute.getRenderer()); + + composeStack.clear(); + listAttribute = new ListAttribute(); + attribute = new Attribute(); + composeStack.push(listAttribute); + composeStack.push(attribute); + + model.execute(null, "myExpression", "myRole", "myType", request, + modelBody); + attributes = listAttribute.getValue(); + assertEquals(1, attributes.size()); + attribute = attributes.iterator().next(); + assertEquals("myBody", attribute.getValue()); + assertEquals("myExpression", attribute.getExpressionObject() + .getExpression()); + assertEquals("myRole", attribute.getRole()); + assertEquals("myType", attribute.getRenderer()); + verify(request, modelBody); + } + +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/template/AddListAttributeModelTest.java b/plugins/tiles/src/test/java/org/apache/tiles/template/AddListAttributeModelTest.java new file mode 100644 index 000000000..3bdf11f5f --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/template/AddListAttributeModelTest.java @@ -0,0 +1,86 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.template; + +import org.apache.tiles.api.ListAttribute; +import org.apache.tiles.autotag.core.runtime.ModelBody; +import org.apache.tiles.request.Request; +import org.junit.Before; +import org.junit.Test; + +import java.io.IOException; +import java.util.ArrayDeque; +import java.util.Deque; +import java.util.HashMap; +import java.util.Map; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import static org.junit.Assert.assertEquals; + +/** + * Tests {@link AddListAttributeModel}. + */ +public class AddListAttributeModelTest { + + /** + * The model to test. + */ + private AddListAttributeModel model; + + /** + * Sets up the test. + */ + @Before + public void setUp() { + model = new AddListAttributeModel(); + } + + /** + * Test method for + * {@link AddListAttributeModel#execute(String, Request, ModelBody)} + * . + * + * @throws IOException If something goes wrong. + */ + @Test + public void testExecute() throws IOException { + Deque composeStack = new ArrayDeque<>(); + Request request = createMock(Request.class); + Map requestScope = new HashMap<>(); + ModelBody modelBody = createMock(ModelBody.class); + + modelBody.evaluateWithoutWriting(); + requestScope.put(ComposeStackUtil.COMPOSE_STACK_ATTRIBUTE_NAME, composeStack); + expect(request.getContext("request")).andReturn(requestScope); + + replay(request, modelBody); + ListAttribute parent = new ListAttribute(); + composeStack.push(parent); + model.execute("myRole", request, modelBody); + assertEquals(1, composeStack.size()); + assertEquals(parent, composeStack.pop()); + assertEquals(1, parent.getValue().size()); + ListAttribute listAttribute = (ListAttribute) parent.getValue().get(0); + assertEquals("myRole", listAttribute.getRole()); + verify(request, modelBody); + } +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/template/ComposeStackUtilTest.java b/plugins/tiles/src/test/java/org/apache/tiles/template/ComposeStackUtilTest.java new file mode 100644 index 000000000..cdfbab26e --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/template/ComposeStackUtilTest.java @@ -0,0 +1,123 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.template; + +import org.apache.tiles.request.Request; +import org.junit.Test; + +import java.util.ArrayDeque; +import java.util.Date; +import java.util.Deque; +import java.util.HashMap; +import java.util.Map; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertSame; + +/** + * Tests {@link ComposeStackUtil}. + */ +public class ComposeStackUtilTest { + + /** + * An integer value. + */ + private static final int INT_VALUE = 3; + + /** + * A long value. + */ + private static final long LONG_VALUE = 2L; + + /** + * Test method for {@link ComposeStackUtil + * #findAncestorWithClass(java.util.Stack, java.lang.Class)}. + */ + @Test + public void testFindAncestorWithClass() { + Deque composeStack = new ArrayDeque<>(); + Integer integerValue = 1; + Long longValue = LONG_VALUE; + String stringValue = "my value"; + Integer integerValue2 = INT_VALUE; + composeStack.push(integerValue); + composeStack.push(longValue); + composeStack.push(stringValue); + composeStack.push(integerValue2); + assertEquals(integerValue2, ComposeStackUtil.findAncestorWithClass(composeStack, Integer.class)); + assertEquals(longValue, ComposeStackUtil.findAncestorWithClass(composeStack, Long.class)); + assertEquals(stringValue, ComposeStackUtil.findAncestorWithClass(composeStack, String.class)); + assertEquals(integerValue2, ComposeStackUtil.findAncestorWithClass(composeStack, Object.class)); + assertNull(ComposeStackUtil.findAncestorWithClass(composeStack, Date.class)); + } + + /** + * Tests {@link ComposeStackUtil#getComposeStack(Request)}. + */ + @Test + public void testGetComposeStackNull() { + Request request = createMock(Request.class); + + Map requestScope = new HashMap<>(); + expect(request.getContext("request")).andReturn(requestScope); + + replay(request); + assertSame(ComposeStackUtil.getComposeStack(request), + requestScope.get(ComposeStackUtil.COMPOSE_STACK_ATTRIBUTE_NAME)); + verify(request); + } + + /** + * Tests {@link ComposeStackUtil#getComposeStack(Request)}. + */ + @Test + public void testGetComposeStackNotNull() { + Request request = createMock(Request.class); + Deque composeStack = createMock(Deque.class); + + Map requestScope = new HashMap<>(); + requestScope.put(ComposeStackUtil.COMPOSE_STACK_ATTRIBUTE_NAME, composeStack); + expect(request.getContext("request")).andReturn(requestScope); + + replay(request, composeStack); + assertSame(composeStack, ComposeStackUtil.getComposeStack(request)); + verify(request, composeStack); + } + + /** + * Tests {@link ComposeStackUtil#getComposeStack(Request)}. + */ + @Test + public void testGetComposeStackNoNull() { + Request request = createMock(Request.class); + + Map requestScope = new HashMap<>(); + expect(request.getContext("request")).andReturn(requestScope); + + replay(request); + assertSame(ComposeStackUtil.getComposeStack(request), + requestScope.get(ComposeStackUtil.COMPOSE_STACK_ATTRIBUTE_NAME)); + verify(request); + } +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/template/DefaultAttributeResolverTest.java b/plugins/tiles/src/test/java/org/apache/tiles/template/DefaultAttributeResolverTest.java new file mode 100644 index 000000000..ad51c1f70 --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/template/DefaultAttributeResolverTest.java @@ -0,0 +1,155 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tiles.template; + +import org.apache.tiles.api.Attribute; +import org.apache.tiles.api.AttributeContext; +import org.apache.tiles.api.Expression; +import org.apache.tiles.api.TilesContainer; +import org.apache.tiles.request.Request; +import org.junit.Before; +import org.junit.Test; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; + +/** + * Tests {@link DefaultAttributeResolver}. + */ +public class DefaultAttributeResolverTest { + + /** + * The resolver to test. + */ + private DefaultAttributeResolver resolver; + + /** + * Sets up the test. + */ + @Before + public void setUp() { + resolver = new DefaultAttributeResolver(); + } + + /** + * Test method for {@link DefaultAttributeResolver + * #computeAttribute(org.apache.tiles.TilesContainer, org.apache.tiles.Attribute, + * java.lang.String, java.lang.String, boolean, java.lang.Object, java.lang.String, + * java.lang.String, Request)}. + */ + @Test + public void testComputeAttributeInContext() { + TilesContainer container = createMock(TilesContainer.class); + AttributeContext attributeContext = createMock(AttributeContext.class); + Request request = createMock(Request.class); + Attribute attribute = new Attribute("myValue", Expression.createExpression("myExpression", null), "myRole", "myRenderer"); + + expect(container.getAttributeContext(request)).andReturn(attributeContext); + expect(attributeContext.getAttribute("myName")).andReturn(attribute); + + replay(container, attributeContext, request); + assertEquals(attribute, resolver.computeAttribute(container, null, "myName", null, false, null, null, null, request)); + verify(container, attributeContext, request); + } + + /** + * Test method for {@link DefaultAttributeResolver + * #computeAttribute(org.apache.tiles.TilesContainer, org.apache.tiles.Attribute, + * java.lang.String, java.lang.String, boolean, java.lang.Object, java.lang.String, + * java.lang.String, Request)}. + */ + @Test + public void testComputeAttributeInCall() { + TilesContainer container = createMock(TilesContainer.class); + Request request = createMock(Request.class); + Attribute attribute = new Attribute("myValue", Expression.createExpression("myExpression", null), "myRole", "myRenderer"); + + replay(container, request); + assertEquals(attribute, resolver.computeAttribute(container, attribute, null, null, false, null, null, null, request)); + verify(container, request); + } + + /** + * Test method for {@link DefaultAttributeResolver + * #computeAttribute(org.apache.tiles.TilesContainer, org.apache.tiles.Attribute, + * java.lang.String, java.lang.String, boolean, java.lang.Object, java.lang.String, + * java.lang.String, Request)}. + */ + @Test + public void testComputeAttributeDefault() { + TilesContainer container = createMock(TilesContainer.class); + Request request = createMock(Request.class); + AttributeContext attributeContext = createMock(AttributeContext.class); + + expect(container.getAttributeContext(request)).andReturn(attributeContext); + expect(attributeContext.getAttribute("myName")).andReturn(null); + + replay(container, attributeContext, request); + Attribute attribute = resolver.computeAttribute(container, null, "myName", null, false, "defaultValue", "defaultRole", "defaultType", request); + assertEquals("defaultValue", attribute.getValue()); + assertEquals("defaultRole", attribute.getRole()); + assertEquals("defaultType", attribute.getRenderer()); + verify(container, attributeContext, request); + } + + /** + * Test method for {@link DefaultAttributeResolver + * #computeAttribute(org.apache.tiles.TilesContainer, org.apache.tiles.Attribute, + * java.lang.String, java.lang.String, boolean, java.lang.Object, java.lang.String, + * java.lang.String, Request)}. + */ + @Test(expected = NoSuchAttributeException.class) + public void testComputeAttributeException() { + TilesContainer container = createMock(TilesContainer.class); + AttributeContext attributeContext = createMock(AttributeContext.class); + Request request = createMock(Request.class); + + expect(container.getAttributeContext(request)).andReturn(attributeContext); + expect(attributeContext.getAttribute("myName")).andReturn(null); + + replay(container, attributeContext, request); + resolver.computeAttribute(container, null, "myName", null, false, null, "defaultRole", "defaultType", request); + verify(container, attributeContext, request); + } + + /** + * Test method for {@link DefaultAttributeResolver + * #computeAttribute(org.apache.tiles.TilesContainer, org.apache.tiles.Attribute, + * java.lang.String, java.lang.String, boolean, java.lang.Object, java.lang.String, + * java.lang.String, Request)}. + */ + @Test + public void testComputeAttributeIgnore() { + TilesContainer container = createMock(TilesContainer.class); + AttributeContext attributeContext = createMock(AttributeContext.class); + Request request = createMock(Request.class); + + expect(container.getAttributeContext(request)).andReturn(attributeContext); + expect(attributeContext.getAttribute("myName")).andReturn(null); + + replay(container, attributeContext, request); + assertNull(resolver.computeAttribute(container, null, "myName", null, true, null, "defaultRole", "defaultType", request)); + verify(container, attributeContext, request); + } +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/template/DefinitionModelTest.java b/plugins/tiles/src/test/java/org/apache/tiles/template/DefinitionModelTest.java new file mode 100644 index 000000000..44511452f --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/template/DefinitionModelTest.java @@ -0,0 +1,98 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.template; + +import org.apache.tiles.api.Attribute; +import org.apache.tiles.api.access.TilesAccess; +import org.apache.tiles.api.mgmt.MutableTilesContainer; +import org.apache.tiles.autotag.core.runtime.ModelBody; +import org.apache.tiles.request.ApplicationContext; +import org.apache.tiles.request.Request; +import org.junit.Before; +import org.junit.Test; + +import java.io.IOException; +import java.util.ArrayDeque; +import java.util.Deque; +import java.util.HashMap; +import java.util.Map; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.eq; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.notNull; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +/** + * Tests {@link DefinitionModel}. + */ +public class DefinitionModelTest { + + /** + * The model to test. + */ + private DefinitionModel model; + + /** + * Sets up the test. + */ + @Before + public void setUp() { + model = new DefinitionModel(); + } + + /** + * Test method for {@link DefinitionModel + * #execute(java.lang.String, java.lang.String, + * java.lang.String, java.lang.String, java.lang.String, Request, ModelBody)}. + * + * @throws IOException If something goes wrong. + */ + @Test + public void testExecute() throws IOException { + MutableTilesContainer container = createMock(MutableTilesContainer.class); + Request request = createMock(Request.class); + Deque composeStack = new ArrayDeque<>(); + Attribute attribute = new Attribute(); + composeStack.push(attribute); + Map requestScope = new HashMap<>(); + requestScope.put(ComposeStackUtil.COMPOSE_STACK_ATTRIBUTE_NAME, composeStack); + requestScope.put(TilesAccess.CURRENT_CONTAINER_ATTRIBUTE_NAME, container); + ApplicationContext applicationContext = createMock(ApplicationContext.class); + ModelBody modelBody = createMock(ModelBody.class); + + modelBody.evaluateWithoutWriting(); + expect(request.getApplicationContext()).andReturn(applicationContext); + expect(request.getContext("request")).andReturn(requestScope).anyTimes(); + container.register(notNull(), eq(request)); + + replay(container, request, modelBody, applicationContext); + model.execute("myName", "myTemplate", "myRole", "myExtends", + "myPreparer", request, modelBody); + assertEquals(1, composeStack.size()); + attribute = (Attribute) composeStack.peek(); + assertNotNull(attribute); + assertEquals("definition", attribute.getRenderer()); + verify(container, request, modelBody, applicationContext); + } + +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/template/GetAsStringModelTest.java b/plugins/tiles/src/test/java/org/apache/tiles/template/GetAsStringModelTest.java new file mode 100644 index 000000000..8a8bbeee1 --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/template/GetAsStringModelTest.java @@ -0,0 +1,140 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.template; + +import org.apache.tiles.api.Attribute; +import org.apache.tiles.api.AttributeContext; +import org.apache.tiles.api.TilesContainer; +import org.apache.tiles.api.access.TilesAccess; +import org.apache.tiles.autotag.core.runtime.ModelBody; +import org.apache.tiles.request.ApplicationContext; +import org.apache.tiles.request.Request; +import org.junit.Before; +import org.junit.Test; + +import java.io.IOException; +import java.io.Writer; +import java.util.ArrayDeque; +import java.util.Deque; +import java.util.HashMap; +import java.util.Map; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; + +/** + * Tests {@link GetAsStringModel}. + */ +public class GetAsStringModelTest { + + /** + * The mock resolver. + */ + private AttributeResolver resolver; + + /** + * The model to test. + */ + private GetAsStringModel model; + + /** + * Sets up the test. + */ + @Before + public void setUp() { + resolver = createMock(AttributeResolver.class); + model = new GetAsStringModel(resolver); + } + + /** + * Test method for {@link GetAsStringModel + * #execute(boolean, java.lang.String, java.lang.String, + * java.lang.Object, java.lang.String, java.lang.String, java.lang.String, + * org.apache.tiles.Attribute, Request, ModelBody)}. + * + * @throws IOException If something goes wrong. + */ + @Test + public void testExecute() throws IOException { + TilesContainer container = createMock(TilesContainer.class); + Attribute attribute = createMock(Attribute.class); + AttributeContext attributeContext = createMock(AttributeContext.class); + Request request = createMock(Request.class); + Writer writer = createMock(Writer.class); + Map requestScope = new HashMap<>(); + Deque composeStack = new ArrayDeque<>(); + requestScope.put(ComposeStackUtil.COMPOSE_STACK_ATTRIBUTE_NAME, composeStack); + requestScope.put(TilesAccess.CURRENT_CONTAINER_ATTRIBUTE_NAME, container); + ApplicationContext applicationContext = createMock(ApplicationContext.class); + ModelBody modelBody = createMock(ModelBody.class); + + modelBody.evaluateWithoutWriting(); + expect(request.getApplicationContext()).andReturn(applicationContext).times(2); + expect(request.getContext("request")).andReturn(requestScope).anyTimes(); + expect(request.getWriter()).andReturn(writer); + container.prepare("myPreparer", request); + expect(resolver.computeAttribute(container, attribute, "myName", "myRole", false, "myDefaultValue", "myDefaultValueRole", "myDefaultValueType", request)).andReturn(attribute); + expect(container.startContext(request)).andReturn(attributeContext); + expect(container.evaluate(attribute, request)).andReturn("myValue"); + writer.write("myValue"); + container.endContext(request); + + replay(resolver, container, writer, request, applicationContext, modelBody); + model.execute(false, "myPreparer", "myRole", "myDefaultValue", "myDefaultValueRole", "myDefaultValueType", "myName", attribute, request, modelBody); + verify(resolver, container, writer, request, applicationContext, modelBody); + } + + /** + * Test method for {@link GetAsStringModel + * #execute(boolean, java.lang.String, java.lang.String, + * java.lang.Object, java.lang.String, java.lang.String, java.lang.String, + * org.apache.tiles.Attribute, Request, ModelBody)} when ignore flag is set. + * + * @throws IOException If something goes wrong. + */ + @Test + public void testExecuteIgnore() throws IOException { + TilesContainer container = createMock(TilesContainer.class); + AttributeContext attributeContext = createMock(AttributeContext.class); + Request request = createMock(Request.class); + Writer writer = createMock(Writer.class); + Map requestScope = new HashMap<>(); + Deque composeStack = new ArrayDeque<>(); + requestScope.put(ComposeStackUtil.COMPOSE_STACK_ATTRIBUTE_NAME, composeStack); + requestScope.put(TilesAccess.CURRENT_CONTAINER_ATTRIBUTE_NAME, container); + ApplicationContext applicationContext = createMock(ApplicationContext.class); + ModelBody modelBody = createMock(ModelBody.class); + + modelBody.evaluateWithoutWriting(); + expect(request.getApplicationContext()).andReturn(applicationContext).times(2); + expect(request.getContext("request")).andReturn(requestScope).anyTimes(); + expect(request.getWriter()).andReturn(writer); + container.prepare("myPreparer", request); + expect(resolver.computeAttribute(container, null, "myName", "myRole", true, "myDefaultValue", "myDefaultValueRole", "myDefaultValueType", request)).andReturn(null); + expect(container.startContext(request)).andReturn(attributeContext); + container.endContext(request); + + replay(resolver, container, writer, request, applicationContext, modelBody); + model.execute(true, "myPreparer", "myRole", "myDefaultValue", "myDefaultValueRole", "myDefaultValueType", "myName", null, request, modelBody); + verify(resolver, container, writer, request, applicationContext, modelBody); + } + +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/template/ImportAttributeModelTest.java b/plugins/tiles/src/test/java/org/apache/tiles/template/ImportAttributeModelTest.java new file mode 100644 index 000000000..73a10121e --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/template/ImportAttributeModelTest.java @@ -0,0 +1,316 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tiles.template; + +import org.apache.tiles.api.Attribute; +import org.apache.tiles.api.AttributeContext; +import org.apache.tiles.api.TilesContainer; +import org.apache.tiles.api.access.TilesAccess; +import org.apache.tiles.request.ApplicationContext; +import org.apache.tiles.request.Request; +import org.junit.Before; +import org.junit.Test; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import static org.junit.Assert.assertEquals; + +/** + * Tests {@link ImportAttributeModel}. + */ +public class ImportAttributeModelTest { + + /** + * The size of the attributes collection. + */ + private static final int ATTRIBUTES_SIZE = 4; + + /** + * The model to test. + */ + private ImportAttributeModel model; + + /** + * Sets up the test. + */ + @Before + public void setUp() { + model = new ImportAttributeModel(); + } + + /** + * Test method for {@link ImportAttributeModel + * #execute(String, String, String, boolean, Request). + */ + @Test + public void testExecuteSingle() { + TilesContainer container = createMock(TilesContainer.class); + AttributeContext attributeContext = createMock(AttributeContext.class); + Attribute attribute = new Attribute(); + Request request = createMock(Request.class); + ApplicationContext applicationContext = createMock(ApplicationContext.class); + Map requestScope = new HashMap<>(); + requestScope.put(TilesAccess.CURRENT_CONTAINER_ATTRIBUTE_NAME, container); + + expect(request.getApplicationContext()).andReturn(applicationContext); + expect(request.getContext("request")).andReturn(requestScope).anyTimes(); + expect(container.getAttributeContext(request)).andReturn(attributeContext); + expect(attributeContext.getAttribute("myName")).andReturn(attribute); + expect(container.evaluate(attribute, request)).andReturn("myEvaluatedValue"); + + replay(container, attributeContext, request, applicationContext); + model.execute("myName", "request", null, false, request); + assertEquals(2, requestScope.size()); + assertEquals("myEvaluatedValue", requestScope.get("myName")); + verify(container, attributeContext, request, applicationContext); + } + + /** + * Test method for {@link ImportAttributeModel + * #execute(String, String, String, boolean, Request). + */ + @Test + public void testExecuteSingleToName() { + TilesContainer container = createMock(TilesContainer.class); + Request request = createMock(Request.class); + AttributeContext attributeContext = createMock(AttributeContext.class); + Attribute attribute = new Attribute(); + ApplicationContext applicationContext = createMock(ApplicationContext.class); + Map requestScope = new HashMap<>(); + requestScope.put(TilesAccess.CURRENT_CONTAINER_ATTRIBUTE_NAME, container); + + expect(request.getApplicationContext()).andReturn(applicationContext); + expect(request.getContext("request")).andReturn(requestScope).anyTimes(); + expect(container.getAttributeContext(request)).andReturn(attributeContext); + expect(attributeContext.getAttribute("myName")).andReturn(attribute); + expect(container.evaluate(attribute, request)).andReturn("myEvaluatedValue"); + + replay(container, attributeContext, request, applicationContext); + model.execute("myName", "request", "myToName", false, request); + assertEquals(2, requestScope.size()); + assertEquals("myEvaluatedValue", requestScope.get("myToName")); + verify(container, attributeContext, request, applicationContext); + } + + /** + * Test method for {@link ImportAttributeModel + * #execute(String, String, String, boolean, Request). + */ + @Test + public void testExecuteAll() { + TilesContainer container = createMock(TilesContainer.class); + Request request = createMock(Request.class); + AttributeContext attributeContext = createMock(AttributeContext.class); + Attribute attribute1 = new Attribute("myValue1"); + Attribute attribute2 = new Attribute("myValue2"); + Attribute attribute3 = new Attribute("myValue3"); + Set cascadedNames = new HashSet<>(); + cascadedNames.add("myName1"); + cascadedNames.add("myName2"); + Set localNames = new HashSet<>(); + localNames.add("myName1"); + localNames.add("myName3"); + ApplicationContext applicationContext = createMock(ApplicationContext.class); + Map requestScope = new HashMap<>(); + requestScope.put(TilesAccess.CURRENT_CONTAINER_ATTRIBUTE_NAME, container); + + expect(request.getApplicationContext()).andReturn(applicationContext); + expect(request.getContext("request")).andReturn(requestScope).anyTimes(); + expect(container.getAttributeContext(request)).andReturn(attributeContext); + expect(attributeContext.getCascadedAttributeNames()).andReturn(cascadedNames); + expect(attributeContext.getLocalAttributeNames()).andReturn(localNames); + expect(attributeContext.getAttribute("myName1")).andReturn(attribute1).times(2); + expect(attributeContext.getAttribute("myName2")).andReturn(attribute2); + expect(attributeContext.getAttribute("myName3")).andReturn(attribute3); + expect(container.evaluate(attribute1, request)).andReturn("myEvaluatedValue1").times(2); + expect(container.evaluate(attribute2, request)).andReturn("myEvaluatedValue2"); + expect(container.evaluate(attribute3, request)).andReturn("myEvaluatedValue3"); + + replay(container, attributeContext, request, applicationContext); + model.execute(null, "request", null, false, request); + assertEquals(ATTRIBUTES_SIZE, requestScope.size()); + assertEquals("myEvaluatedValue1", requestScope.get("myName1")); + assertEquals("myEvaluatedValue2", requestScope.get("myName2")); + assertEquals("myEvaluatedValue3", requestScope.get("myName3")); + verify(container, attributeContext, request, applicationContext); + } + + /** + * Test method for {@link ImportAttributeModel + * #execute(String, String, String, boolean, Request). + */ + @Test(expected = NoSuchAttributeException.class) + public void testExecuteSingleNullAttributeException() { + TilesContainer container = createMock(TilesContainer.class); + Request request = createMock(Request.class); + AttributeContext attributeContext = createMock(AttributeContext.class); + ApplicationContext applicationContext = createMock(ApplicationContext.class); + Map requestScope = new HashMap<>(); + requestScope.put(TilesAccess.CURRENT_CONTAINER_ATTRIBUTE_NAME, container); + + expect(request.getApplicationContext()).andReturn(applicationContext); + expect(request.getContext("request")).andReturn(requestScope).anyTimes(); + expect(container.getAttributeContext(request)).andReturn(attributeContext); + expect(attributeContext.getAttribute("myName")).andReturn(null); + + replay(container, attributeContext, request, applicationContext); + try { + model.execute("myName", "request", null, false, request); + } finally { + verify(container, attributeContext, request, applicationContext); + } + } + + /** + * Test method for {@link ImportAttributeModel + * #execute(String, String, String, boolean, Request). + */ + @Test(expected = NoSuchAttributeException.class) + public void testExecuteSingleNullAttributeValueException() { + TilesContainer container = createMock(TilesContainer.class); + Request request = createMock(Request.class); + AttributeContext attributeContext = createMock(AttributeContext.class); + Attribute attribute = new Attribute(); + ApplicationContext applicationContext = createMock(ApplicationContext.class); + Map requestScope = new HashMap<>(); + requestScope.put(TilesAccess.CURRENT_CONTAINER_ATTRIBUTE_NAME, container); + + expect(request.getApplicationContext()).andReturn(applicationContext); + expect(request.getContext("request")).andReturn(requestScope).anyTimes(); + expect(container.getAttributeContext(request)).andReturn(attributeContext); + expect(attributeContext.getAttribute("myName")).andReturn(attribute); + expect(container.evaluate(attribute, request)).andReturn(null); + + replay(container, attributeContext, request, applicationContext); + try { + model.execute("myName", "request", null, false, request); + } finally { + verify(container, attributeContext, request, applicationContext); + } + } + + /** + * Test method for {@link ImportAttributeModel + * #execute(String, String, String, boolean, Request). + */ + @Test(expected = RuntimeException.class) + public void testExecuteSingleRuntimeException() { + TilesContainer container = createMock(TilesContainer.class); + Request request = createMock(Request.class); + AttributeContext attributeContext = createMock(AttributeContext.class); + Attribute attribute = new Attribute(); + ApplicationContext applicationContext = createMock(ApplicationContext.class); + Map requestScope = new HashMap<>(); + requestScope.put(TilesAccess.CURRENT_CONTAINER_ATTRIBUTE_NAME, container); + + expect(request.getApplicationContext()).andReturn(applicationContext); + expect(request.getContext("request")).andReturn(requestScope).anyTimes(); + expect(container.getAttributeContext(request)).andReturn(attributeContext); + expect(attributeContext.getAttribute("myName")).andReturn(attribute); + expect(container.evaluate(attribute, request)).andThrow(new RuntimeException()); + + replay(container, attributeContext, request, applicationContext); + try { + model.execute("myName", "request", null, false, request); + } finally { + verify(container, attributeContext, request, applicationContext); + } + } + + /** + * Test method for {@link ImportAttributeModel + * #execute(String, String, String, boolean, Request). + */ + @Test + public void testExecuteSingleNullAttributeIgnore() { + TilesContainer container = createMock(TilesContainer.class); + Request request = createMock(Request.class); + AttributeContext attributeContext = createMock(AttributeContext.class); + ApplicationContext applicationContext = createMock(ApplicationContext.class); + Map requestScope = new HashMap<>(); + requestScope.put(TilesAccess.CURRENT_CONTAINER_ATTRIBUTE_NAME, container); + + expect(request.getApplicationContext()).andReturn(applicationContext); + expect(request.getContext("request")).andReturn(requestScope).anyTimes(); + expect(container.getAttributeContext(request)).andReturn(attributeContext); + expect(attributeContext.getAttribute("myName")).andReturn(null); + + replay(container, attributeContext, request, applicationContext); + model.execute("myName", "request", null, true, request); + verify(container, attributeContext, request, applicationContext); + } + + /** + * Test method for {@link ImportAttributeModel + * #execute(String, String, String, boolean, Request). + */ + @Test + public void testExecuteSingleNullAttributeValueIgnore() { + TilesContainer container = createMock(TilesContainer.class); + Request request = createMock(Request.class); + AttributeContext attributeContext = createMock(AttributeContext.class); + Attribute attribute = new Attribute(); + ApplicationContext applicationContext = createMock(ApplicationContext.class); + Map requestScope = new HashMap<>(); + requestScope.put(TilesAccess.CURRENT_CONTAINER_ATTRIBUTE_NAME, container); + + expect(request.getApplicationContext()).andReturn(applicationContext); + expect(request.getContext("request")).andReturn(requestScope).anyTimes(); + expect(container.getAttributeContext(request)).andReturn(attributeContext); + expect(attributeContext.getAttribute("myName")).andReturn(attribute); + expect(container.evaluate(attribute, request)).andReturn(null); + + replay(container, attributeContext, request, applicationContext); + model.execute("myName", "request", null, true, request); + verify(container, attributeContext, request, applicationContext); + } + + /** + * Test method for {@link ImportAttributeModel + * #execute(String, String, String, boolean, Request). + */ + @Test + public void testExecuteSingleRuntimeIgnore() { + TilesContainer container = createMock(TilesContainer.class); + Request request = createMock(Request.class); + AttributeContext attributeContext = createMock(AttributeContext.class); + Attribute attribute = new Attribute(); + ApplicationContext applicationContext = createMock(ApplicationContext.class); + Map requestScope = new HashMap<>(); + requestScope.put(TilesAccess.CURRENT_CONTAINER_ATTRIBUTE_NAME, container); + + expect(request.getApplicationContext()).andReturn(applicationContext); + expect(request.getContext("request")).andReturn(requestScope).anyTimes(); + expect(container.getAttributeContext(request)).andReturn(attributeContext); + expect(attributeContext.getAttribute("myName")).andReturn(attribute); + expect(container.evaluate(attribute, request)).andThrow(new RuntimeException()); + + replay(container, attributeContext, request, applicationContext); + model.execute("myName", "request", null, true, request); + verify(container, attributeContext, request, applicationContext); + } +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/template/InsertAttributeModelTest.java b/plugins/tiles/src/test/java/org/apache/tiles/template/InsertAttributeModelTest.java new file mode 100644 index 000000000..e8a997ac0 --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/template/InsertAttributeModelTest.java @@ -0,0 +1,131 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.template; + +import org.apache.tiles.api.Attribute; +import org.apache.tiles.api.AttributeContext; +import org.apache.tiles.api.TilesContainer; +import org.apache.tiles.api.access.TilesAccess; +import org.apache.tiles.autotag.core.runtime.ModelBody; +import org.apache.tiles.request.ApplicationContext; +import org.apache.tiles.request.Request; +import org.junit.Before; +import org.junit.Test; + +import java.io.IOException; +import java.util.ArrayDeque; +import java.util.Deque; +import java.util.HashMap; +import java.util.Map; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; + +/** + * Tests {@link InsertAttributeModel}. + */ +public class InsertAttributeModelTest { + + /** + * The mock resolver. + */ + private AttributeResolver resolver; + + /** + * The model to test. + */ + private InsertAttributeModel model; + + /** + * Sets up the test. + */ + @Before + public void setUp() { + resolver = createMock(AttributeResolver.class); + model = new InsertAttributeModel(resolver); + } + + /** + * Test method for {@link InsertAttributeModel + * #execute(boolean, String, String, Object, String, String, String, + * Attribute, boolean, Request, ModelBody)}. + * + * @throws IOException If something goes wrong. + */ + @Test + public void testExecute() throws IOException { + TilesContainer container = createMock(TilesContainer.class); + Request request = createMock(Request.class); + Attribute attribute = new Attribute("myValue"); + AttributeContext attributeContext = createMock(AttributeContext.class); + Map requestScope = new HashMap<>(); + requestScope.put(TilesAccess.CURRENT_CONTAINER_ATTRIBUTE_NAME, container); + ApplicationContext applicationContext = createMock(ApplicationContext.class); + ModelBody modelBody = createMock(ModelBody.class); + + modelBody.evaluateWithoutWriting(); + expect(request.getApplicationContext()).andReturn(applicationContext).times(2); + expect(request.getContext("request")).andReturn(requestScope).anyTimes(); + + container.prepare("myPreparer", request); + expect(resolver.computeAttribute(container, attribute, "myName", "myRole", false, "myDefaultValue", "myDefaultValueRole", "myDefaultValueType", request)).andReturn(attribute); + expect(container.startContext(request)).andReturn(attributeContext); + container.endContext(request); + container.render(attribute, request); + + replay(resolver, container, request, applicationContext, modelBody); + model.execute(false, "myPreparer", "myRole", "myDefaultValue", "myDefaultValueRole", "myDefaultValueType", "myName", attribute, false, request, modelBody); + verify(resolver, container, request, applicationContext, modelBody); + } + + /** + * Test method for {@link InsertAttributeModel + * #execute(boolean, String, String, Object, String, String, String, + * Attribute, boolean, Request, ModelBody)} when ignore flag is set. + * + * @throws IOException If something goes wrong. + */ + @Test + public void testExecuteIgnore() throws IOException { + TilesContainer container = createMock(TilesContainer.class); + Request request = createMock(Request.class); + AttributeContext attributeContext = createMock(AttributeContext.class); + Map requestScope = new HashMap<>(); + Deque composeStack = new ArrayDeque<>(); + requestScope.put(ComposeStackUtil.COMPOSE_STACK_ATTRIBUTE_NAME, composeStack); + requestScope.put(TilesAccess.CURRENT_CONTAINER_ATTRIBUTE_NAME, container); + ApplicationContext applicationContext = createMock(ApplicationContext.class); + ModelBody modelBody = createMock(ModelBody.class); + + modelBody.evaluateWithoutWriting(); + expect(request.getApplicationContext()).andReturn(applicationContext).times(2); + expect(request.getContext("request")).andReturn(requestScope).anyTimes(); + + container.prepare("myPreparer", request); + expect(resolver.computeAttribute(container, null, "myName", "myRole", true, "myDefaultValue", "myDefaultValueRole", "myDefaultValueType", request)).andReturn(null); + expect(container.startContext(request)).andReturn(attributeContext); + container.endContext(request); + + replay(resolver, container, request, applicationContext, modelBody); + model.execute(true, "myPreparer", "myRole", "myDefaultValue", "myDefaultValueRole", "myDefaultValueType", "myName", null, false, request, modelBody); + verify(resolver, container, request, applicationContext, modelBody); + } +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/template/InsertDefinitionModelTest.java b/plugins/tiles/src/test/java/org/apache/tiles/template/InsertDefinitionModelTest.java new file mode 100644 index 000000000..48d3fb492 --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/template/InsertDefinitionModelTest.java @@ -0,0 +1,90 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.template; + +import org.apache.tiles.api.AttributeContext; +import org.apache.tiles.api.TilesContainer; +import org.apache.tiles.api.access.TilesAccess; +import org.apache.tiles.autotag.core.runtime.ModelBody; +import org.apache.tiles.request.ApplicationContext; +import org.apache.tiles.request.Request; +import org.junit.Before; +import org.junit.Test; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.notNull; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; + +/** + * Tests {@link InsertDefinitionModel}. + */ +public class InsertDefinitionModelTest { + + /** + * The model to test. + */ + private InsertDefinitionModel model; + + /** + * Sets up the test. + */ + @Before + public void setUp() { + model = new InsertDefinitionModel(); + } + + /** + * Test method for {@link InsertDefinitionModel + * #execute(java.lang.String, java.lang.String, String, + * String, java.lang.String, java.lang.String, boolean, Request, ModelBody)}. + * + * @throws IOException If something goes wrong. + */ + @Test + public void testExecute() throws IOException { + TilesContainer container = createMock(TilesContainer.class); + Request request = createMock(Request.class); + AttributeContext attributeContext = createMock(AttributeContext.class); + Map requestScope = new HashMap<>(); + requestScope.put(TilesAccess.CURRENT_CONTAINER_ATTRIBUTE_NAME, container); + ApplicationContext applicationContext = createMock(ApplicationContext.class); + ModelBody modelBody = createMock(ModelBody.class); + + modelBody.evaluateWithoutWriting(); + expect(request.getApplicationContext()).andReturn(applicationContext).times(2); + expect(request.getContext("request")).andReturn(requestScope).anyTimes(); + expect(container.startContext(request)).andReturn(attributeContext); + expect(container.getAttributeContext(request)).andReturn(attributeContext); + container.endContext(request); + attributeContext.setPreparer("myPreparer"); + attributeContext.setTemplateAttribute(notNull()); + container.render("myDefinitionName", request); + + replay(container, attributeContext, request, applicationContext, modelBody); + model.execute("myDefinitionName", "myTemplate", "myTemplateType", "myTemplateExpression", "myRole", "myPreparer", false, request, modelBody); + verify(container, attributeContext, request, applicationContext, modelBody); + } + +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/template/InsertTemplateModelTest.java b/plugins/tiles/src/test/java/org/apache/tiles/template/InsertTemplateModelTest.java new file mode 100644 index 000000000..840593d7e --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/template/InsertTemplateModelTest.java @@ -0,0 +1,89 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.template; + +import org.apache.tiles.api.AttributeContext; +import org.apache.tiles.api.TilesContainer; +import org.apache.tiles.api.access.TilesAccess; +import org.apache.tiles.autotag.core.runtime.ModelBody; +import org.apache.tiles.request.ApplicationContext; +import org.apache.tiles.request.Request; +import org.junit.Before; +import org.junit.Test; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.notNull; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; + +/** + * Tests {@link InsertTemplateModel}. + */ +public class InsertTemplateModelTest { + + /** + * The model to test. + */ + private InsertTemplateModel model; + + /** + * Sets up the test. + */ + @Before + public void setUp() { + model = new InsertTemplateModel(); + } + + /** + * Test method for {@link InsertTemplateModel + * #execute(String, String, String, String, String, boolean, Request, ModelBody)}. + * + * @throws IOException If something goes wrong. + */ + @Test + public void testExecute() throws IOException { + TilesContainer container = createMock(TilesContainer.class); + Request request = createMock(Request.class); + AttributeContext attributeContext = createMock(AttributeContext.class); + Map requestScope = new HashMap<>(); + requestScope.put(TilesAccess.CURRENT_CONTAINER_ATTRIBUTE_NAME, container); + ApplicationContext applicationContext = createMock(ApplicationContext.class); + ModelBody modelBody = createMock(ModelBody.class); + + modelBody.evaluateWithoutWriting(); + expect(request.getApplicationContext()).andReturn(applicationContext).times(2); + expect(request.getContext("request")).andReturn(requestScope).anyTimes(); + expect(container.startContext(request)).andReturn(attributeContext); + expect(container.getAttributeContext(request)).andReturn(attributeContext); + container.endContext(request); + attributeContext.setPreparer("myPreparer"); + attributeContext.setTemplateAttribute(notNull()); + container.renderContext(request); + + replay(container, attributeContext, request, applicationContext, modelBody); + model.execute("myTemplate", "myTemplateType", "myTemplateExpression", "myRole", "myPreparer", false, request, modelBody); + verify(container, attributeContext, request, applicationContext, modelBody); + } + +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/template/PutAttributeModelTest.java b/plugins/tiles/src/test/java/org/apache/tiles/template/PutAttributeModelTest.java new file mode 100644 index 000000000..572dcad59 --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/template/PutAttributeModelTest.java @@ -0,0 +1,93 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.template; + +import org.apache.tiles.api.AttributeContext; +import org.apache.tiles.api.ListAttribute; +import org.apache.tiles.api.TilesContainer; +import org.apache.tiles.api.access.TilesAccess; +import org.apache.tiles.autotag.core.runtime.ModelBody; +import org.apache.tiles.request.ApplicationContext; +import org.apache.tiles.request.Request; +import org.junit.Before; +import org.junit.Test; + +import java.io.IOException; +import java.util.ArrayDeque; +import java.util.Deque; +import java.util.HashMap; +import java.util.Map; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.eq; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.notNull; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; + +/** + * Tests {@link PutAttributeModel}. + */ +public class PutAttributeModelTest { + + /** + * The model to test. + */ + private PutAttributeModel model; + + /** + * Sets up the test. + */ + @Before + public void setUp() { + model = new PutAttributeModel(); + } + + /** + * Test method for {@link PutAttributeModel + * #execute(String, Object, String, String, String, + * boolean, Request, ModelBody)}. + * + * @throws IOException If something goes wrong. + */ + @Test + public void testExecuteListAttribute() throws IOException { + TilesContainer container = createMock(TilesContainer.class); + Request request = createMock(Request.class); + ModelBody modelBody = createMock(ModelBody.class); + AttributeContext attributeContext = createMock(AttributeContext.class); + Deque composeStack = new ArrayDeque<>(); + ListAttribute listAttribute = new ListAttribute(); + composeStack.push(listAttribute); + Map requestScope = new HashMap<>(); + requestScope.put(ComposeStackUtil.COMPOSE_STACK_ATTRIBUTE_NAME, composeStack); + requestScope.put(TilesAccess.CURRENT_CONTAINER_ATTRIBUTE_NAME, container); + ApplicationContext applicationContext = createMock(ApplicationContext.class); + + expect(request.getApplicationContext()).andReturn(applicationContext); + expect(request.getContext("request")).andReturn(requestScope).anyTimes(); + expect(container.getAttributeContext(request)).andReturn(attributeContext); + attributeContext.putAttribute(eq("myName"), notNull(), eq(false)); + expect(modelBody.evaluateAsString()).andReturn(null); + + replay(container, attributeContext, request, applicationContext, modelBody); + model.execute("myName", "myValue", "myExpression", "myRole", "myType", false, request, modelBody); + verify(container, attributeContext, request, applicationContext, modelBody); + } +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/template/PutListAttributeModelTest.java b/plugins/tiles/src/test/java/org/apache/tiles/template/PutListAttributeModelTest.java new file mode 100644 index 000000000..cd4708afc --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/template/PutListAttributeModelTest.java @@ -0,0 +1,93 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.template; + +import org.apache.tiles.api.AttributeContext; +import org.apache.tiles.api.ListAttribute; +import org.apache.tiles.api.TilesContainer; +import org.apache.tiles.api.access.TilesAccess; +import org.apache.tiles.autotag.core.runtime.ModelBody; +import org.apache.tiles.request.ApplicationContext; +import org.apache.tiles.request.Request; +import org.junit.Before; +import org.junit.Test; + +import java.io.IOException; +import java.util.ArrayDeque; +import java.util.Deque; +import java.util.HashMap; +import java.util.Map; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.eq; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.isA; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import static org.junit.Assert.assertEquals; + +/** + * Tests {@link PutListAttributeModel}. + */ +public class PutListAttributeModelTest { + + /** + * The model to test. + */ + private PutListAttributeModel model; + + /** + * Sets up the test. + */ + @Before + public void setUp() { + model = new PutListAttributeModel(); + } + + /** + * Test method for {@link PutListAttributeModel + * #execute(String, String, boolean, boolean, Request, ModelBody)}. + * + * @throws IOException If something goes wrong. + */ + @Test + public void testExecute() throws IOException { + TilesContainer container = createMock(TilesContainer.class); + AttributeContext attributeContext = createMock(AttributeContext.class); + Request request = createMock(Request.class); + Deque composeStack = new ArrayDeque<>(); + Map requestScope = new HashMap<>(); + requestScope.put(ComposeStackUtil.COMPOSE_STACK_ATTRIBUTE_NAME, composeStack); + requestScope.put(TilesAccess.CURRENT_CONTAINER_ATTRIBUTE_NAME, container); + ApplicationContext applicationContext = createMock(ApplicationContext.class); + ModelBody modelBody = createMock(ModelBody.class); + + modelBody.evaluateWithoutWriting(); + expect(request.getApplicationContext()).andReturn(applicationContext); + expect(request.getContext("request")).andReturn(requestScope).anyTimes(); + expect(container.getAttributeContext(request)).andReturn(attributeContext); + attributeContext.putAttribute(eq("myName"), isA(ListAttribute.class), eq(false)); + + replay(container, attributeContext, request, modelBody); + model.execute("myName", "myRole", false, false, request, modelBody); + assertEquals(0, composeStack.size()); + verify(container, attributeContext, request, modelBody); + } + +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/template/SetCurrentContainerModelTest.java b/plugins/tiles/src/test/java/org/apache/tiles/template/SetCurrentContainerModelTest.java new file mode 100644 index 000000000..2ecda504f --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/template/SetCurrentContainerModelTest.java @@ -0,0 +1,84 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.template; + +import org.apache.tiles.api.NoSuchContainerException; +import org.apache.tiles.api.TilesContainer; +import org.apache.tiles.api.access.TilesAccess; +import org.apache.tiles.request.ApplicationContext; +import org.apache.tiles.request.Request; +import org.junit.Test; + +import java.util.HashMap; +import java.util.Map; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import static org.junit.Assert.assertEquals; + +/** + * Tests {@link SetCurrentContainerModel}. + */ +public class SetCurrentContainerModelTest { + + /** + * Test method for {@link SetCurrentContainerModel#execute(String, Request)}. + */ + @Test + public void testSetCurrentContainer() { + Request request = createMock(Request.class); + ApplicationContext context = createMock(ApplicationContext.class); + TilesContainer container = createMock(TilesContainer.class); + Map attribs = new HashMap<>(); + attribs.put("myKey", container); + Map requestScope = new HashMap<>(); + + expect(context.getApplicationScope()).andReturn(attribs).anyTimes(); + expect(request.getContext("request")).andReturn(requestScope); + expect(request.getApplicationContext()).andReturn(context); + replay(request, context, container); + SetCurrentContainerModel model = new SetCurrentContainerModel(); + model.execute("myKey", request); + assertEquals(container, requestScope.get(TilesAccess.CURRENT_CONTAINER_ATTRIBUTE_NAME)); + verify(request, context, container); + } + + /** + * Test method for {@link SetCurrentContainerModel#execute(String, Request)}. + */ + @Test(expected = NoSuchContainerException.class) + public void testSetCurrentContainerException() { + Request request = createMock(Request.class); + ApplicationContext context = createMock(ApplicationContext.class); + Map attribs = new HashMap<>(); + + expect(request.getApplicationContext()).andReturn(context); + expect(context.getApplicationScope()).andReturn(attribs).anyTimes(); + replay(request, context); + try { + SetCurrentContainerModel model = new SetCurrentContainerModel(); + model.execute("myKey", request); + } finally { + verify(request, context); + } + } + +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/web/jsp/taglib/UseAttributeTagTest.java b/plugins/tiles/src/test/java/org/apache/tiles/web/jsp/taglib/UseAttributeTagTest.java new file mode 100644 index 000000000..48486746f --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/web/jsp/taglib/UseAttributeTagTest.java @@ -0,0 +1,220 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.web.jsp.taglib; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.isA; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.io.IOException; +import java.util.Map; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.jsp.JspException; +import javax.servlet.jsp.PageContext; +import javax.servlet.jsp.tagext.JspFragment; +import javax.servlet.jsp.tagext.JspTag; +import javax.servlet.jsp.tagext.TagData; +import javax.servlet.jsp.tagext.VariableInfo; + +import org.apache.tiles.api.Attribute; +import org.apache.tiles.api.AttributeContext; +import org.apache.tiles.api.TilesContainer; +import org.apache.tiles.api.access.TilesAccess; +import org.apache.tiles.request.ApplicationAccess; +import org.apache.tiles.request.ApplicationContext; +import org.apache.tiles.request.jsp.JspRequest; +import org.apache.tiles.web.jsp.taglib.UseAttributeTag; +import org.junit.Before; +import org.junit.Test; + +/** + * Tests UseAttributeTag. + */ +public class UseAttributeTagTest { + + /** + * The tag to test. + */ + private UseAttributeTag tag; + + /** + * Sets up the test. + */ + @Before + public void setUp() { + tag = new UseAttributeTag(); + } + + /** + * Test method for + * {@link org/apache/tiles/web/jsp/taglib.UseAttributeTag#execute(org.apache.tiles.request.Request)}. + * + * @throws IOException + * @throws JspException + */ + @Test + public void testExecute() throws JspException, IOException { + JspFragment jspBody = createMock(JspFragment.class); + PageContext pageContext = createMock(PageContext.class); + JspTag parent = createMock(JspTag.class); + ApplicationContext applicationContext = createMock(ApplicationContext.class); + HttpServletRequest httpServletRequest = createMock(HttpServletRequest.class); + HttpServletResponse httpServletResponse = createMock(HttpServletResponse.class); + Map applicationScope = createMock(Map.class); + TilesContainer container = createMock(TilesContainer.class); + AttributeContext attributeContext = createMock(AttributeContext.class); + Attribute attribute = createMock(Attribute.class); + expect(pageContext.getAttribute(ApplicationAccess.APPLICATION_CONTEXT_ATTRIBUTE, PageContext.APPLICATION_SCOPE)) + .andReturn(applicationContext); + expect(applicationContext.getApplicationScope()).andReturn(applicationScope).anyTimes(); + expect(pageContext.getRequest()).andReturn(httpServletRequest); + expect(pageContext.getResponse()).andReturn(httpServletResponse); + expect(pageContext.getAttribute(TilesAccess.CURRENT_CONTAINER_ATTRIBUTE_NAME, PageContext.REQUEST_SCOPE)) + .andReturn(container); + expect(container.getAttributeContext(isA(JspRequest.class))).andReturn(attributeContext); + expect(attributeContext.getAttribute("name")).andReturn(attribute); + expect(container.evaluate(isA(Attribute.class), isA(JspRequest.class))).andReturn(new Integer(1)); + pageContext.setAttribute("id", new Integer(1), PageContext.PAGE_SCOPE); + replay(jspBody, pageContext, parent, applicationContext, httpServletRequest, httpServletResponse, + applicationScope, container, attributeContext, attribute); + tag.setName("name"); + tag.setScope("page"); + tag.setId("id"); + tag.setIgnore(false); + tag.setJspContext(pageContext); + tag.setJspBody(jspBody); + tag.setParent(parent); + tag.doTag(); + verify(jspBody, pageContext, parent, applicationContext, httpServletRequest, httpServletResponse, container, + attributeContext, attribute); + } + + /** + * Test method for + * {@link org/apache/tiles/web/jsp/taglib.UseAttributeTag#setId(java.lang.String)}. + */ + @Test + public void testSetId() { + tag.setId("id"); + assertEquals("id", tag.getId()); + } + + /** + * Test method for + * {@link org/apache/tiles/web/jsp/taglib.UseAttributeTag#getScope()}. + */ + @Test + public void testGetScope() { + tag.setScope("scope"); + assertEquals("scope", tag.getScope()); + } + + /** + * Test method for + * {@link org/apache/tiles/web/jsp/taglib.UseAttributeTag#setName(java.lang.String)}. + */ + @Test + public void testSetName() { + tag.setName("name"); + assertEquals("name", tag.getName()); + } + + /** + * Test method for + * {@link org/apache/tiles/web/jsp/taglib.UseAttributeTag#setIgnore(boolean)}. + */ + @Test + public void testSetIgnore() { + tag.setIgnore(true); + assertTrue(tag.isIgnore()); + } + + /** + * Test method for + * {@link org/apache/tiles/web/jsp/taglib.UseAttributeTag#setClassname(java.lang.String)}. + */ + @Test + public void testSetClassname() { + tag.setClassname("classname"); + assertEquals("classname", tag.getClassname()); + } + + /** + * Test method for + * {@link org/apache/tiles/web/jsp/taglib.UseAttributeTag#getScriptingVariable()}. + */ + @Test + public void testGetScriptingVariable() { + tag.setName("name"); + assertEquals("name", tag.getScriptingVariable()); + tag.setId("id"); + assertEquals("id", tag.getScriptingVariable()); + } + + /** + * Tests {@link UseAttributeTag.Tei}. + */ + @Test + public void testTei() { + TagData tagData = createMock(TagData.class); + + expect(tagData.getAttributeString("classname")).andReturn("my.Clazz"); + expect(tagData.getAttributeString("id")).andReturn("id"); + + replay(tagData); + UseAttributeTag.Tei tei = new UseAttributeTag.Tei(); + VariableInfo[] infos = tei.getVariableInfo(tagData); + assertEquals(1, infos.length); + VariableInfo info = infos[0]; + assertEquals("id", info.getVarName()); + assertEquals("my.Clazz", info.getClassName()); + assertTrue(info.getDeclare()); + assertEquals(VariableInfo.AT_END, info.getScope()); + verify(tagData); + } + + /** + * Tests {@link UseAttributeTag.Tei}. + */ + @Test + public void testTeiDefaults() { + TagData tagData = createMock(TagData.class); + + expect(tagData.getAttributeString("classname")).andReturn(null); + expect(tagData.getAttributeString("id")).andReturn(null); + expect(tagData.getAttributeString("name")).andReturn("name"); + + replay(tagData); + UseAttributeTag.Tei tei = new UseAttributeTag.Tei(); + VariableInfo[] infos = tei.getVariableInfo(tagData); + assertEquals(1, infos.length); + VariableInfo info = infos[0]; + assertEquals("name", info.getVarName()); + assertEquals("java.lang.Object", info.getClassName()); + assertTrue(info.getDeclare()); + assertEquals(VariableInfo.AT_END, info.getScope()); + verify(tagData); + } +} diff --git a/plugins/tiles/src/test/java/org/apache/tiles/web/startup/AbstractTilesListenerTest.java b/plugins/tiles/src/test/java/org/apache/tiles/web/startup/AbstractTilesListenerTest.java new file mode 100644 index 000000000..dbf6f3ec2 --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/tiles/web/startup/AbstractTilesListenerTest.java @@ -0,0 +1,61 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tiles.web.startup; + +import org.apache.tiles.core.startup.TilesInitializer; +import org.apache.tiles.request.servlet.ServletApplicationContext; +import org.junit.Test; + +import javax.servlet.ServletContext; +import javax.servlet.ServletContextEvent; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.createMockBuilder; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.isA; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; + +/** + * Tests {@link AbstractTilesListener}. + */ +public class AbstractTilesListenerTest { + + /** + * Test method for {@link AbstractTilesListener#contextInitialized(ServletContextEvent)}. + */ + @Test + public void testContextInitialized() { + AbstractTilesListener listener = createMockBuilder(AbstractTilesListener.class).createMock(); + ServletContextEvent event = createMock(ServletContextEvent.class); + ServletContext servletContext = createMock(ServletContext.class); + TilesInitializer initializer = createMock(TilesInitializer.class); + + expect(event.getServletContext()).andReturn(servletContext); + expect(listener.createTilesInitializer()).andReturn(initializer); + initializer.initialize(isA(ServletApplicationContext.class)); + initializer.destroy(); + + replay(listener, event, servletContext, initializer); + listener.contextInitialized(event); + listener.contextDestroyed(event); + verify(listener, event, servletContext, initializer); + } + +} diff --git a/plugins/tiles/src/test/resources/org/apache/tiles/autotag/freemarker/test/DoStuffFMModel.javat b/plugins/tiles/src/test/resources/org/apache/tiles/autotag/freemarker/test/DoStuffFMModel.javat new file mode 100644 index 000000000..14e3fafc9 --- /dev/null +++ b/plugins/tiles/src/test/resources/org/apache/tiles/autotag/freemarker/test/DoStuffFMModel.javat @@ -0,0 +1,72 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +/* + * This file was automatically generated by Autotag. Please do not edit it manually. + */ +package org.apache.tiles.autotag.freemarker.test; + +import java.io.IOException; +import java.util.Map; + +import org.apache.tiles.autotag.core.runtime.ModelBody; +import org.apache.tiles.autotag.core.runtime.AutotagRuntime; + +import freemarker.core.Environment; +import freemarker.template.TemplateDirectiveBody; +import freemarker.template.TemplateDirectiveModel; +import freemarker.template.TemplateException; +import freemarker.template.TemplateModel; + +/** + * Documentation of the DoStuff class. + */ +public class DoStuffFMModel implements TemplateDirectiveModel { + + /** + * The template model. + */ + private org.apache.tiles.autotag.template.DoStuffTemplate model; + + /** + * Constructor. + * + * @param model + * The template model. + */ + public DoStuffFMModel(org.apache.tiles.autotag.template.DoStuffTemplate model) { + this.model = model; + } + + @Override + public void execute(Environment env, @SuppressWarnings("rawtypes") Map params, TemplateModel[] loopVars, + TemplateDirectiveBody body) throws TemplateException, IOException { + AutotagRuntime runtime = new org.apache.tiles.autotag.freemarker.test.Runtime(); + if (runtime instanceof TemplateDirectiveModel) { + ((TemplateDirectiveModel) runtime).execute(env, params, loopVars, body); + } + org.apache.tiles.autotag.freemarker.test.Request request = runtime.createRequest(); + ModelBody modelBody = runtime.createModelBody(); + model.execute( + runtime.getParameter("one", java.lang.String.class, null), + runtime.getParameter("two", java.lang.Integer.class, 0), + runtime.getParameter("three", java.lang.Boolean.class, false), + request, modelBody + ); + } +} diff --git a/plugins/tiles/src/test/resources/org/apache/tiles/autotag/freemarker/test/DoStuffNoBodyFMModel.javat b/plugins/tiles/src/test/resources/org/apache/tiles/autotag/freemarker/test/DoStuffNoBodyFMModel.javat new file mode 100644 index 000000000..8841206d5 --- /dev/null +++ b/plugins/tiles/src/test/resources/org/apache/tiles/autotag/freemarker/test/DoStuffNoBodyFMModel.javat @@ -0,0 +1,70 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +/* + * This file was automatically generated by Autotag. Please do not edit it manually. + */ +package org.apache.tiles.autotag.freemarker.test; + +import java.io.IOException; +import java.util.Map; + +import org.apache.tiles.autotag.core.runtime.AutotagRuntime; + +import freemarker.core.Environment; +import freemarker.template.TemplateDirectiveBody; +import freemarker.template.TemplateDirectiveModel; +import freemarker.template.TemplateException; +import freemarker.template.TemplateModel; + +/** + * Documentation of the DoStuffNoBody class. + */ +public class DoStuffNoBodyFMModel implements TemplateDirectiveModel { + + /** + * The template model. + */ + private org.apache.tiles.autotag.template.DoStuffNoBodyTemplate model; + + /** + * Constructor. + * + * @param model + * The template model. + */ + public DoStuffNoBodyFMModel(org.apache.tiles.autotag.template.DoStuffNoBodyTemplate model) { + this.model = model; + } + + @Override + public void execute(Environment env, @SuppressWarnings("rawtypes") Map params, TemplateModel[] loopVars, + TemplateDirectiveBody body) throws TemplateException, IOException { + AutotagRuntime runtime = new org.apache.tiles.autotag.freemarker.test.Runtime(); + if (runtime instanceof TemplateDirectiveModel) { + ((TemplateDirectiveModel) runtime).execute(env, params, loopVars, body); + } + org.apache.tiles.autotag.freemarker.test.Request request = runtime.createRequest(); + model.execute( + runtime.getParameter("one", java.lang.Double.class, null), + runtime.getParameter("two", java.lang.Float.class, 0.0f), + runtime.getParameter("three", java.util.Date.class, null), + request + ); + } +} diff --git a/plugins/tiles/src/test/resources/org/apache/tiles/autotag/freemarker/test/TldtestFMModelRepository.javat b/plugins/tiles/src/test/resources/org/apache/tiles/autotag/freemarker/test/TldtestFMModelRepository.javat new file mode 100644 index 000000000..0aaa347f3 --- /dev/null +++ b/plugins/tiles/src/test/resources/org/apache/tiles/autotag/freemarker/test/TldtestFMModelRepository.javat @@ -0,0 +1,64 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +/* + * This file was automatically generated by Autotag. Please do not edit it manually. + */ +package org.apache.tiles.autotag.freemarker.test; + +/** + * Test for TLD docs. + */ +public class TldtestFMModelRepository { + + /** + * The "doStuff" directive. + */ + private DoStuffFMModel doStuff; + + /** + * The "doStuffNoBody" directive. + */ + private DoStuffNoBodyFMModel doStuffNoBody; + + /** + * Constructor. + */ + public TilesFMModelRepository() { + doStuff = new DoStuffFMModel(new org.apache.tiles.autotag.template.DoStuffTemplate()); + doStuffNoBody = new DoStuffNoBodyFMModel(new org.apache.tiles.autotag.template.DoStuffNoBodyTemplate()); + } + + /** + * Returns the "doStuff" directive. + * + * @return The "doStuff" directive. + */ + public DoStuffFMModel getDoStuff() { + return doStuff; + } + + /** + * Returns the "doStuffNoBody" directive. + * + * @return The "doStuffNoBody" directive. + */ + public DoStuffNoBodyFMModel getDoStuffNoBody() { + return doStuffNoBody; + } +} diff --git a/plugins/tiles/src/test/resources/org/apache/tiles/autotag/jsp/test/DoStuffNoBodyTag.java b/plugins/tiles/src/test/resources/org/apache/tiles/autotag/jsp/test/DoStuffNoBodyTag.java new file mode 100644 index 000000000..85433d581 --- /dev/null +++ b/plugins/tiles/src/test/resources/org/apache/tiles/autotag/jsp/test/DoStuffNoBodyTag.java @@ -0,0 +1,134 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + /* + * This file was automatically generated by Autotag. Please do not edit it manually. + */ +package org.apache.tiles.autotag.jsp.test; + +import java.io.IOException; + +import javax.servlet.jsp.JspException; +import javax.servlet.jsp.tagext.SimpleTagSupport; + +import org.apache.tiles.autotag.core.runtime.AutotagRuntime; + +/** + * Documentation of the DoStuffNoBody class. + */ +public class DoStuffNoBodyTag extends SimpleTagSupport { + + /** + * The template model. + */ + private org.apache.tiles.autotag.template.DoStuffNoBodyTemplate model = new org.apache.tiles.autotag.template.DoStuffNoBodyTemplate(); + + /** + * Parameter one. + */ + private java.lang.Double one; + + /** + * Parameter two. + */ + private float two; + + /** + * Parameter three. + */ + private java.util.Date three; + + /** + * Getter for one property. + * + * @return + * Parameter one. + */ + public java.lang.Double getOne() { + return one; + } + + /** + * Setter for one property. + * + * @param one + * Parameter one. + */ + public void setOne(java.lang.Double one) { + this.one = one; + } + + /** + * Getter for two property. + * + * @return + * Parameter two. + */ + public float getTwo() { + return two; + } + + /** + * Setter for two property. + * + * @param two + * Parameter two. + */ + public void setTwo(float two) { + this.two = two; + } + + /** + * Getter for three property. + * + * @return + * Parameter three. + */ + public java.util.Date getThree() { + return three; + } + + /** + * Setter for three property. + * + * @param three + * Parameter three. + */ + public void setThree(java.util.Date three) { + this.three = three; + } + + @Override + public void doTag() throws JspException, IOException { + AutotagRuntime runtime = new org.apache.tiles.autotag.jsp.test.Runtime(); + if (runtime instanceof SimpleTagSupport) { + SimpleTagSupport tag = (SimpleTagSupport) runtime; + tag.setJspContext(getJspContext()); + tag.setJspBody(getJspBody()); + tag.setParent(getParent()); + tag.doTag(); + } + org.apache.tiles.autotag.jsp.test.Request request = runtime.createRequest(); + model.execute( + one, + two, + three, + request + ); + } +} diff --git a/plugins/tiles/src/test/resources/org/apache/tiles/autotag/jsp/test/DoStuffTag.java b/plugins/tiles/src/test/resources/org/apache/tiles/autotag/jsp/test/DoStuffTag.java new file mode 100644 index 000000000..6ad8b1e6f --- /dev/null +++ b/plugins/tiles/src/test/resources/org/apache/tiles/autotag/jsp/test/DoStuffTag.java @@ -0,0 +1,136 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + /* + * This file was automatically generated by Autotag. Please do not edit it manually. + */ +package org.apache.tiles.autotag.jsp.test; + +import java.io.IOException; + +import javax.servlet.jsp.JspException; +import javax.servlet.jsp.tagext.SimpleTagSupport; + +import org.apache.tiles.autotag.core.runtime.ModelBody; +import org.apache.tiles.autotag.core.runtime.AutotagRuntime; + +/** + * Documentation of the DoStuff class. + */ +public class DoStuffTag extends SimpleTagSupport { + + /** + * The template model. + */ + private org.apache.tiles.autotag.template.DoStuffTemplate model = new org.apache.tiles.autotag.template.DoStuffTemplate(); + + /** + * Parameter one. + */ + private java.lang.String one; + + /** + * Parameter two. + */ + private int two; + + /** + * Parameter three. + */ + private boolean three; + + /** + * Getter for one property. + * + * @return + * Parameter one. + */ + public java.lang.String getOne() { + return one; + } + + /** + * Setter for one property. + * + * @param one + * Parameter one. + */ + public void setOne(java.lang.String one) { + this.one = one; + } + + /** + * Getter for two property. + * + * @return + * Parameter two. + */ + public int getTwo() { + return two; + } + + /** + * Setter for two property. + * + * @param two + * Parameter two. + */ + public void setTwo(int two) { + this.two = two; + } + + /** + * Getter for three property. + * + * @return + * Parameter three. + */ + public boolean isThree() { + return three; + } + + /** + * Setter for three property. + * + * @param three + * Parameter three. + */ + public void setThree(boolean three) { + this.three = three; + } + + @Override + public void doTag() throws JspException, IOException { + AutotagRuntime runtime = new org.apache.tiles.autotag.jsp.test.Runtime(); + if (runtime instanceof SimpleTagSupport) { + SimpleTagSupport tag = (SimpleTagSupport) runtime; + tag.setJspContext(getJspContext()); + tag.setJspBody(getJspBody()); + tag.setParent(getParent()); + tag.doTag(); + } + org.apache.tiles.autotag.jsp.test.Request request = runtime.createRequest(); + ModelBody modelBody = runtime.createModelBody(); + model.execute( + one, + two, + three, + request, modelBody + ); + } +} diff --git a/plugins/tiles/src/test/resources/org/apache/tiles/autotag/velocity/test/DoStuffDirective.javat b/plugins/tiles/src/test/resources/org/apache/tiles/autotag/velocity/test/DoStuffDirective.javat new file mode 100644 index 000000000..8ae29b34a --- /dev/null +++ b/plugins/tiles/src/test/resources/org/apache/tiles/autotag/velocity/test/DoStuffDirective.javat @@ -0,0 +1,70 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + /* + * This file was automatically generated by Autotag. Please do not edit it manually. + */ +package org.apache.tiles.autotag.velocity.test; + +import java.io.IOException; +import java.io.Writer; + +import org.apache.tiles.autotag.core.runtime.ModelBody; +import org.apache.tiles.autotag.core.runtime.AutotagRuntime; +import org.apache.velocity.context.InternalContextAdapter; +import org.apache.velocity.runtime.directive.Directive; +import org.apache.velocity.runtime.parser.node.Node; + +/** + * Documentation of the DoStuff class. + */ +public class DoStuffDirective extends Directive { + + /** + * The template model. + */ + private org.apache.tiles.autotag.template.DoStuffTemplate model = new org.apache.tiles.autotag.template.DoStuffTemplate(); + + @Override + public String getName() { + return "tldtest_doStuff"; + } + + @Override + public int getType() { + return BLOCK; + } + + @Override + public boolean render(InternalContextAdapter context, Writer writer, Node node) + throws IOException { + AutotagRuntime runtime = new org.apache.tiles.autotag.velocity.test.Runtime(); + if (runtime instanceof Directive) { + ((Directive) runtime).render(context, writer, node); + } + org.apache.tiles.autotag.velocity.Request request = runtime.createRequest(); + ModelBody modelBody = runtime.createModelBody(); + model.execute( + runtime.getParameter("one", java.lang.String.class, null), + runtime.getParameter("two", java.lang.Integer.class, 0), + runtime.getParameter("three", java.lang.Boolean.class, false), + request, modelBody + ); + return true; + } +} diff --git a/plugins/tiles/src/test/resources/org/apache/tiles/autotag/velocity/test/DoStuffNoBodyDirective.javat b/plugins/tiles/src/test/resources/org/apache/tiles/autotag/velocity/test/DoStuffNoBodyDirective.javat new file mode 100644 index 000000000..6ed645a66 --- /dev/null +++ b/plugins/tiles/src/test/resources/org/apache/tiles/autotag/velocity/test/DoStuffNoBodyDirective.javat @@ -0,0 +1,68 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + /* + * This file was automatically generated by Autotag. Please do not edit it manually. + */ +package org.apache.tiles.autotag.velocity.test; + +import java.io.IOException; +import java.io.Writer; + +import org.apache.tiles.autotag.core.runtime.AutotagRuntime; +import org.apache.velocity.context.InternalContextAdapter; +import org.apache.velocity.runtime.directive.Directive; +import org.apache.velocity.runtime.parser.node.Node; + +/** + * Documentation of the DoStuffNoBody class. + */ +public class DoStuffNoBodyDirective extends Directive { + + /** + * The template model. + */ + private org.apache.tiles.autotag.template.DoStuffNoBodyTemplate model = new org.apache.tiles.autotag.template.DoStuffNoBodyTemplate(); + + @Override + public String getName() { + return "tldtest_doStuffNoBody"; + } + + @Override + public int getType() { + return LINE; + } + + @Override + public boolean render(InternalContextAdapter context, Writer writer, Node node) + throws IOException { + AutotagRuntime runtime = new org.apache.tiles.autotag.velocity.test.Runtime(); + if (runtime instanceof Directive) { + ((Directive) runtime).render(context, writer, node); + } + org.apache.tiles.autotag.velocity.Request request = runtime.createRequest(); + model.execute( + runtime.getParameter("one", java.lang.Double.class, null), + runtime.getParameter("two", java.lang.Float.class, 0.0f), + runtime.getParameter("three", java.util.Date.class, null), + request + ); + return true; + } +} diff --git a/plugins/tiles/src/test/resources/org/apache/tiles/core/config/defs-tiles-513.xml b/plugins/tiles/src/test/resources/org/apache/tiles/core/config/defs-tiles-513.xml new file mode 100644 index 000000000..3b6c6a377 --- /dev/null +++ b/plugins/tiles/src/test/resources/org/apache/tiles/core/config/defs-tiles-513.xml @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/tiles/src/test/resources/org/apache/tiles/core/config/defs-wildcard.xml b/plugins/tiles/src/test/resources/org/apache/tiles/core/config/defs-wildcard.xml new file mode 100644 index 000000000..9312f9d60 --- /dev/null +++ b/plugins/tiles/src/test/resources/org/apache/tiles/core/config/defs-wildcard.xml @@ -0,0 +1,62 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/tiles/src/test/resources/org/apache/tiles/core/config/defs1.xml b/plugins/tiles/src/test/resources/org/apache/tiles/core/config/defs1.xml new file mode 100644 index 000000000..621d7cef9 --- /dev/null +++ b/plugins/tiles/src/test/resources/org/apache/tiles/core/config/defs1.xml @@ -0,0 +1,75 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/tiles/src/test/resources/org/apache/tiles/core/config/defs1_en_US.xml b/plugins/tiles/src/test/resources/org/apache/tiles/core/config/defs1_en_US.xml new file mode 100644 index 000000000..1a89b229c --- /dev/null +++ b/plugins/tiles/src/test/resources/org/apache/tiles/core/config/defs1_en_US.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/tiles/src/test/resources/org/apache/tiles/core/config/defs1_fr.xml b/plugins/tiles/src/test/resources/org/apache/tiles/core/config/defs1_fr.xml new file mode 100644 index 000000000..62ed68170 --- /dev/null +++ b/plugins/tiles/src/test/resources/org/apache/tiles/core/config/defs1_fr.xml @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/tiles/src/test/resources/org/apache/tiles/core/config/defs1_fr_CA.xml b/plugins/tiles/src/test/resources/org/apache/tiles/core/config/defs1_fr_CA.xml new file mode 100644 index 000000000..b35d0d83e --- /dev/null +++ b/plugins/tiles/src/test/resources/org/apache/tiles/core/config/defs1_fr_CA.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/tiles/src/test/resources/org/apache/tiles/core/config/defs2.xml b/plugins/tiles/src/test/resources/org/apache/tiles/core/config/defs2.xml new file mode 100644 index 000000000..f24f1c5d7 --- /dev/null +++ b/plugins/tiles/src/test/resources/org/apache/tiles/core/config/defs2.xml @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/tiles/src/test/resources/org/apache/tiles/core/config/defs3.xml b/plugins/tiles/src/test/resources/org/apache/tiles/core/config/defs3.xml new file mode 100644 index 000000000..77d7bed2d --- /dev/null +++ b/plugins/tiles/src/test/resources/org/apache/tiles/core/config/defs3.xml @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/tiles/src/test/resources/org/apache/tiles/core/config/defs_regression_TILES-352.xml b/plugins/tiles/src/test/resources/org/apache/tiles/core/config/defs_regression_TILES-352.xml new file mode 100644 index 000000000..a28ec49ca --- /dev/null +++ b/plugins/tiles/src/test/resources/org/apache/tiles/core/config/defs_regression_TILES-352.xml @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + diff --git a/plugins/tiles/src/test/resources/org/apache/tiles/core/config/invalid-defs.xml b/plugins/tiles/src/test/resources/org/apache/tiles/core/config/invalid-defs.xml new file mode 100644 index 000000000..3973a749a --- /dev/null +++ b/plugins/tiles/src/test/resources/org/apache/tiles/core/config/invalid-defs.xml @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/tiles/src/test/resources/org/apache/tiles/core/config/malformed-defs.xml b/plugins/tiles/src/test/resources/org/apache/tiles/core/config/malformed-defs.xml new file mode 100644 index 000000000..b82f95de7 --- /dev/null +++ b/plugins/tiles/src/test/resources/org/apache/tiles/core/config/malformed-defs.xml @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/tiles/src/test/resources/org/apache/tiles/core/config/temp-defs.xml b/plugins/tiles/src/test/resources/org/apache/tiles/core/config/temp-defs.xml new file mode 100644 index 000000000..d5334eab4 --- /dev/null +++ b/plugins/tiles/src/test/resources/org/apache/tiles/core/config/temp-defs.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/tiles/src/test/resources/org/apache/tiles/core/config/tiles-defs-2.1.xml b/plugins/tiles/src/test/resources/org/apache/tiles/core/config/tiles-defs-2.1.xml new file mode 100644 index 000000000..f8b651ce2 --- /dev/null +++ b/plugins/tiles/src/test/resources/org/apache/tiles/core/config/tiles-defs-2.1.xml @@ -0,0 +1,88 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/tiles/src/test/resources/org/apache/tiles/core/config/tiles-defs-2.1_it.xml b/plugins/tiles/src/test/resources/org/apache/tiles/core/config/tiles-defs-2.1_it.xml new file mode 100644 index 000000000..4c7c0834f --- /dev/null +++ b/plugins/tiles/src/test/resources/org/apache/tiles/core/config/tiles-defs-2.1_it.xml @@ -0,0 +1,33 @@ + + + + + + + + + + + + diff --git a/plugins/tiles/src/test/resources/org/apache/tiles/core/config/tiles-defs.xml b/plugins/tiles/src/test/resources/org/apache/tiles/core/config/tiles-defs.xml new file mode 100644 index 000000000..590e0c7cf --- /dev/null +++ b/plugins/tiles/src/test/resources/org/apache/tiles/core/config/tiles-defs.xml @@ -0,0 +1,143 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/tiles/src/test/resources/org/apache/tiles/core/factory/test-defs-key-one.xml b/plugins/tiles/src/test/resources/org/apache/tiles/core/factory/test-defs-key-one.xml new file mode 100644 index 000000000..180fb0a8c --- /dev/null +++ b/plugins/tiles/src/test/resources/org/apache/tiles/core/factory/test-defs-key-one.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + diff --git a/plugins/tiles/src/test/resources/org/apache/tiles/core/factory/test-defs-key-two.xml b/plugins/tiles/src/test/resources/org/apache/tiles/core/factory/test-defs-key-two.xml new file mode 100644 index 000000000..d0639d696 --- /dev/null +++ b/plugins/tiles/src/test/resources/org/apache/tiles/core/factory/test-defs-key-two.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + diff --git a/plugins/tiles/src/test/resources/org/apache/tiles/core/factory/test-defs.xml b/plugins/tiles/src/test/resources/org/apache/tiles/core/factory/test-defs.xml new file mode 100644 index 000000000..2d124a2be --- /dev/null +++ b/plugins/tiles/src/test/resources/org/apache/tiles/core/factory/test-defs.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + diff --git a/plugins/tiles/src/test/resources/org/apache/tiles/request/locale/resource with space.txt b/plugins/tiles/src/test/resources/org/apache/tiles/request/locale/resource with space.txt new file mode 100644 index 000000000..82cb4afe8 --- /dev/null +++ b/plugins/tiles/src/test/resources/org/apache/tiles/request/locale/resource with space.txt @@ -0,0 +1,17 @@ + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. +test diff --git a/plugins/tiles/src/test/resources/org/apache/tiles/request/locale/resource.txt b/plugins/tiles/src/test/resources/org/apache/tiles/request/locale/resource.txt new file mode 100644 index 000000000..82cb4afe8 --- /dev/null +++ b/plugins/tiles/src/test/resources/org/apache/tiles/request/locale/resource.txt @@ -0,0 +1,17 @@ + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. +test diff --git a/plugins/tiles/src/test/resources/tldtest-jsp.tld b/plugins/tiles/src/test/resources/tldtest-jsp.tld new file mode 100644 index 000000000..b2cbb8eb7 --- /dev/null +++ b/plugins/tiles/src/test/resources/tldtest-jsp.tld @@ -0,0 +1,121 @@ + + + + + + + + 1.2 + tldtest + http://www.initrode.net/tags/test + + + + + doStuff + org.apache.tiles.autotag.jsp.test.DoStuffTag + scriptless + + + + + one + true + true + java.lang.String + + + + + + two + false + true + int + + + + + + three + false + true + long + + + + + + + doStuffNoBody + org.apache.tiles.autotag.jsp.test.DoStuffNoBodyTag + empty + + + + + one + true + true + java.lang.Double + + + + + + two + false + true + float + + + + + + three + false + true + java.util.Date + + + diff --git a/plugins/tiles/src/test/resources/velocity.properties.test b/plugins/tiles/src/test/resources/velocity.properties.test new file mode 100644 index 000000000..3ee9deeb8 --- /dev/null +++ b/plugins/tiles/src/test/resources/velocity.properties.test @@ -0,0 +1,21 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# +# This file was automatically generated by Autotag. Please do not edit it manually. + +userdirective=org.apache.tiles.autotag.velocity.test.DoStuffDirective,\ +org.apache.tiles.autotag.velocity.test.DoStuffNoBodyDirective \ No newline at end of file diff --git a/pom.xml b/pom.xml index c5488b996..13522b003 100644 --- a/pom.xml +++ b/pom.xml @@ -780,7 +780,7 @@ org.easymock easymock - 4.2 + 4.3 test @@ -825,62 +825,6 @@ provided - - org.apache.tiles - tiles-api - ${tiles.version} - - - org.apache.tiles - tiles-core - ${tiles.version} - - - org.apache.tiles - tiles-servlet - ${tiles.version} - - - org.apache.tiles - tiles-request-portlet - ${tiles-request.version} - - - org.apache.tiles - tiles-request-api - ${tiles-request.version} - - - org.apache.tiles - tiles-request-jsp - ${tiles-request.version} - - - org.apache.tiles - tiles-request-servlet - ${tiles-request.version} - - - org.apache.tiles - tiles-jsp - ${tiles.version} - - - org.apache.tiles - tiles-freemarker - ${tiles.version} - - - org.apache.tiles - tiles-ognl - ${tiles.version} - - - org.apache.tiles - tiles-el - ${tiles.version} - - javax.servlet.jsp jsp-api @@ -936,6 +880,12 @@ commons-digester commons-digester 2.1 + + + commons-logging + commons-logging + + commons-el @@ -1086,6 +1036,12 @@ ${log4j2.version} + + org.apache.logging.log4j + log4j-jcl + ${log4j2.version} + + org.testng testng