/** * This file Copyright (c) 2003-2012 Magnolia International * Ltd. (http://www.magnolia-cms.com). All rights reserved. * * * This file is dual-licensed under both the Magnolia * Network Agreement and the GNU General Public License. * You may elect to use one or the other of these licenses. * * This file is distributed in the hope that it will be * useful, but AS-IS and WITHOUT ANY WARRANTY; without even the * implied warranty of MERCHANTABILITY or FITNESS FOR A * PARTICULAR PURPOSE, TITLE, or NONINFRINGEMENT. * Redistribution, except as permitted by whichever of the GPL * or MNA you select, is prohibited. * * 1. For the GPL license (GPL), you can redistribute and/or * modify this file under the terms of the GNU General * Public License, Version 3, as published by the Free Software * Foundation. You should have received a copy of the GNU * General Public License, Version 3 along with this program; * if not, write to the Free Software Foundation, Inc., 51 * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * 2. For the Magnolia Network Agreement (MNA), this file * and the accompanying materials are made available under the * terms of the MNA which accompanies this distribution, and * is available at http://www.magnolia-cms.com/mna.html * * Any modifications to this file must keep this entire header * intact. * */ package info.magnolia.module.model.reader; import info.magnolia.context.MgnlContext; import info.magnolia.module.ModuleManagementException; import info.magnolia.module.model.ComponentDefinition; import info.magnolia.module.model.ComponentsDefinition; import info.magnolia.module.model.ConfigurerDefinition; import info.magnolia.module.model.DependencyDefinition; import info.magnolia.module.model.ModuleDefinition; import info.magnolia.module.model.RepositoryDefinition; import info.magnolia.module.model.ServletDefinition; import info.magnolia.module.model.TypeMappingDefinition; import info.magnolia.module.model.Version; import info.magnolia.module.model.VersionRange; import info.magnolia.module.model.VersionTest; import info.magnolia.test.ComponentsTestUtil; import org.junit.After; import org.junit.Before; import org.junit.Test; import static org.junit.Assert.*; import java.io.StringReader; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import java.util.List; /** * @author gjoseph * @version $Revision: $ ($Author: $) */ public class BetwixtModuleDefinitionReaderTest { @Before public void setUp() throws Exception { // shunt log4j org.apache.log4j.Logger.getRootLogger().setLevel(org.apache.log4j.Level.OFF); // shunt the chatty Digester log explicitely - possibly because of the commons-logging wrapping, shunting the root logger isn't enough org.apache.log4j.Logger.getLogger(org.apache.commons.digester.Digester.class).setLevel(org.apache.log4j.Level.OFF); } @After public void tearDown() throws Exception { ComponentsTestUtil.clear(); MgnlContext.setInstance(null); } @Test public void testDisplayNameCanBeWrittenWithDashEventhoughThisIsDeprecated() throws Exception { String xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + "<module>\n" + " <name>the name</name>\n" + " <display-name>The Display Name</display-name>" + " <class>foo</class>\n" + " <versionHandler>java.lang.String</versionHandler>\n" + " <version>1.0</version>\n" + "</module>"; ModuleDefinition mod = new BetwixtModuleDefinitionReader().read(new StringReader(xml)); assertEquals("The Display Name", mod.getDisplayName()); } @Test public void testDisplayNameShouldBeWrittenWithCapitalN() throws Exception { String xml = "<module>\n" + " <name>the name</name>\n" + " <displayName>The Display Name</displayName>\n" + " <class>foo</class>\n" + " <versionHandler>java.lang.String</versionHandler>\n" + " <version>1.0</version>\n" + "</module>"; ModuleDefinition mod = new BetwixtModuleDefinitionReader().read(new StringReader(xml)); assertEquals("The Display Name", mod.getDisplayName()); } @Test public void testClassIsResolvedToClassNameAsAString() throws Exception { String xml = "<module>\n" + " <name>the name</name>\n" + " <class>java.lang.Integer</class>\n" + " <versionHandler>java.lang.String</versionHandler>\n" + " <version>1.0</version>\n" + "</module>"; ModuleDefinition mod = new BetwixtModuleDefinitionReader().read(new StringReader(xml)); assertEquals("java.lang.Integer", mod.getClassName()); } @Test public void testVersionHandlerIsResolvedToAClass() throws Exception { String xml = "<module>\n" + " <name>the name</name>\n" + " <class>java.lang.Integer</class>\n" + " <versionHandler>java.lang.String</versionHandler>" + " <version>1.0</version>\n" + "</module>"; ModuleDefinition mod = new BetwixtModuleDefinitionReader().read(new StringReader(xml)); assertEquals(String.class, mod.getVersionHandler()); } @Test public void testModuleVersionIsProperlyRead() throws ModuleManagementException { String xml = "<module>\n" + " <name>the name</name>\n" + " <class>foo</class>\n" + " <versionHandler>java.lang.String</versionHandler>\n" + " <version>1.2.3</version>\n" + "</module>"; final ModuleDefinition def = new BetwixtModuleDefinitionReader().read(new StringReader(xml)); final Version version = def.getVersion(); assertNotNull(version); assertEquals("1.2.3", version.toString()); VersionTest.assertVersion(1, 2, 3, null, version); } @Test public void testDependenciesVersionAreProperlyRead() throws ModuleManagementException { //org.apache.log4j.Logger.getLogger("org.apache").setLevel(org.apache.log4j.Level.DEBUG); String xml = "<module>\n" + " <name>myName</name>\n" + " <class>foo</class>\n" + " <versionHandler>java.lang.String</versionHandler>\n" + " <version>1.2.3</version>\n" + " <dependencies>\n" + " <dependency>\n" + " <name>foo</name>\n" + " <version>2.3.4/*</version>\n" + " <optional>true</optional>\n" + " </dependency>\n" + " <dependency>\n" + " <name>bar</name>\n" + " <version>5.6.7/8.9.0</version>\n" + " </dependency>\n" + " </dependencies>\n" + "</module>"; final ModuleDefinition def = new BetwixtModuleDefinitionReader().read(new StringReader(xml)); final Collection deps = def.getDependencies(); assertEquals(2, deps.size()); final Iterator it = deps.iterator(); final DependencyDefinition dep1 = (DependencyDefinition) it.next(); final DependencyDefinition dep2 = (DependencyDefinition) it.next(); assertEquals("foo", dep1.getName()); assertEquals(true, dep1.isOptional()); assertEquals("2.3.4/*", dep1.getVersion()); final VersionRange dep1versionRange = dep1.getVersionRange(); assertNotNull(dep1versionRange); assertEquals("2.3.4/*", dep1versionRange.toString()); VersionTest.assertVersion(2, 3, 4, null, dep1versionRange.getFrom()); assertEquals(Version.UNDEFINED_TO, dep1versionRange.getTo()); assertEquals("bar", dep2.getName()); assertEquals(false, dep2.isOptional()); assertEquals("5.6.7/8.9.0", dep2.getVersion()); final VersionRange dep2versionRange = dep2.getVersionRange(); assertNotNull(dep2versionRange); assertEquals("5.6.7/8.9.0", dep2versionRange.toString()); VersionTest.assertVersion(5, 6, 7, null, dep2versionRange.getFrom()); VersionTest.assertVersion(8, 9, 0, null, dep2versionRange.getTo()); } @Test public void testDependenciesCanBeSpecifiedWithoutVersion() throws ModuleManagementException { String xml = "<module>\n" + " <name>myName</name>\n" + " <version>1.2.3</version>\n" + " <dependencies>\n" + " <dependency>\n" + " <name>foo</name>\n" + " <optional>true</optional>\n" + " </dependency>\n" + " <dependency>\n" + " <name>bar</name>\n" + " </dependency>\n" + " </dependencies>\n" + "</module>"; final ModuleDefinition def = new BetwixtModuleDefinitionReader().read(new StringReader(xml)); final List<DependencyDefinition> deps = new ArrayList<DependencyDefinition>(def.getDependencies()); assertEquals(2, deps.size()); final DependencyDefinition dep1 = deps.get(0); final DependencyDefinition dep2 = deps.get(1); assertEquals("foo", dep1.getName()); assertEquals(true, dep1.isOptional()); assertEquals(null, dep1.getVersion()); final VersionRange dep1versionRange = dep1.getVersionRange(); assertEquals(Version.UNDEFINED_FROM, dep1versionRange.getFrom()); assertEquals(Version.UNDEFINED_TO, dep1versionRange.getTo()); assertEquals("bar", dep2.getName()); assertEquals(false, dep2.isOptional()); assertEquals(null, dep2.getVersion()); final VersionRange dep2versionRange = dep2.getVersionRange(); assertEquals(Version.UNDEFINED_FROM, dep2versionRange.getFrom()); assertEquals(Version.UNDEFINED_TO, dep2versionRange.getTo()); } @Test public void testInvalidXmlIsCheckedAgainstDTD() { String xmlWithVersionElementMisplaced = "<module>\n" + " <version>2.3.4</version>\n" + " <name>the name</name>\n" + "</module>"; try { new BetwixtModuleDefinitionReader().read(new StringReader(xmlWithVersionElementMisplaced)); fail("should have failed"); } catch (ModuleManagementException e) { assertEquals("Invalid module definition file, error at line 6 column 10: The content of element type \"module\" must match \"(name,(displayName|display-name)?,description?,class?,versionHandler?,version,properties?,components*,dependencies?,servlets?,repositories?)\".", e.getMessage()); } } @Test public void testGivenDtdIsIgnoredAndCheckedAgainstOurs() { String xmlWithWrongDtd = "<!DOCTYPE log4j:configuration SYSTEM \"log4j.dtd\">\n" + "<module>\n" + " <version>2.3.4</version>\n" + " <name>the name</name>\n" + "</module>"; try { new BetwixtModuleDefinitionReader().read(new StringReader(xmlWithWrongDtd)); fail("should have failed"); } catch (ModuleManagementException e) { assertEquals("Invalid module definition file, error at line 6 column 10: The content of element type \"module\" must match \"(name,(displayName|display-name)?,description?,class?,versionHandler?,version,properties?,components*,dependencies?,servlets?,repositories?)\".", e.getMessage()); } } @Test public void testReadCompleteDescriptorAndCheckAllPropertiesDamnYouBetwixt() throws Exception { final BetwixtModuleDefinitionReader reader = new BetwixtModuleDefinitionReader(); final ModuleDefinition m = reader.readFromResource("/info/magnolia/module/model/reader/dummy-module.xml"); assertNotNull(m); assertEquals("dummy", m.getName()); assertEquals("dummy module", m.getDisplayName()); assertEquals("a dummy module descriptor for tests", m.getDescription()); // this dummy module descriptor uses random classes that we know are there when running the test assertEquals(BetwixtModuleDefinitionReaderTest.class.getName(), m.getClassName()); assertEquals(DependencyCheckerImplTest.class, m.getVersionHandler()); assertEquals("7.8.9", m.getVersion().toString()); assertNotNull(m.getProperties()); assertEquals(2, m.getProperties().size()); assertEquals("bar", m.getProperty("foo")); assertEquals("lolo", m.getProperty("lala")); assertNotNull(m.getDependencies()); assertEquals(2, m.getDependencies().size()); assertNotNull(m.getServlets()); assertEquals(2, m.getServlets().size()); final ServletDefinition servlet1 = (ServletDefinition) fromList(m.getServlets(), 0); assertNotNull(servlet1); assertEquals("AServlet", servlet1.getName()); assertEquals(DependencyLevelComparatorTest.class.getName(), servlet1.getClassName()); assertEquals("lalala", servlet1.getComment()); assertEquals(2, servlet1.getMappings().size()); assertEquals("/foo/*", fromList(servlet1.getMappings(), 0)); assertEquals("/bar", fromList(servlet1.getMappings(), 1)); final ServletDefinition servlet2 = (ServletDefinition) fromList(m.getServlets(), 1); assertNotNull(servlet2); assertEquals("OtherServlet", servlet2.getName()); assertEquals(info.magnolia.module.model.VersionComparatorTest.class.getName(), servlet2.getClassName()); assertEquals("blahblah", servlet2.getComment()); assertEquals(1, servlet2.getMappings().size()); assertEquals("/blah/*", fromList(servlet2.getMappings(), 0)); assertNotNull(m.getRepositories()); assertEquals(2, m.getRepositories().size()); final RepositoryDefinition repo1 = (RepositoryDefinition) fromList(m.getRepositories(), 0); assertEquals("some-repo", repo1.getName()); assertEquals(2, repo1.getWorkspaces().size()); assertEquals("workspace-a", fromList(repo1.getWorkspaces(), 0)); assertEquals("workspace-b", fromList(repo1.getWorkspaces(), 1)); assertEquals(null, repo1.getNodeTypeFile()); final RepositoryDefinition repo2 = (RepositoryDefinition) fromList(m.getRepositories(), 1); assertEquals("other-repo", repo2.getName()); assertEquals(1, repo2.getWorkspaces().size()); assertEquals("bleh", fromList(repo2.getWorkspaces(), 0)); assertEquals("/chalala/testNodeTypes.xml", repo2.getNodeTypeFile()); } @Test public void testSelf() { // make sure these resources are available - ide might not have compiled them assertNotNull(BetwixtModuleDefinitionReaderTest.class.getResourceAsStream("/info/magnolia/module/model/ModuleDefinition.betwixt")); assertNotNull(BetwixtModuleDefinitionReaderTest.class.getResourceAsStream("/info/magnolia/module/model/ServletDefinition.betwixt")); } @Test public void testReadModuleDescriptorWithComponents() throws ModuleManagementException { final BetwixtModuleDefinitionReader reader = new BetwixtModuleDefinitionReader(); final ModuleDefinition m = reader.readFromResource("/info/magnolia/module/model/reader/dummy-module-with-components.xml"); assertNotNull(m); assertEquals(1, m.getComponents().size()); ComponentsDefinition components = m.getComponents().iterator().next(); assertEquals("platform", components.getId()); assertEquals(2, components.getConfigurers().size()); Iterator<ConfigurerDefinition> iterator = components.getConfigurers().iterator(); ConfigurerDefinition configurer = iterator.next(); assertEquals("com.acme.FirstTestConfigurer", configurer.getClassName()); configurer = iterator.next(); assertEquals("com.acme.SecondTestConfigurer", configurer.getClassName()); assertEquals(1, components.getComponents().size()); ComponentDefinition componentDefinition = components.getComponents().iterator().next(); assertEquals("com.acme.ComponentKey", componentDefinition.getType()); assertEquals("session", componentDefinition.getScope()); assertEquals("impl", componentDefinition.getImplementation()); assertEquals("provider", componentDefinition.getProvider()); assertEquals("true", componentDefinition.getObserved()); assertEquals("config", componentDefinition.getWorkspace()); assertEquals("/modules/acme/foo", componentDefinition.getPath()); assertEquals(1, components.getTypeMappings().size()); TypeMappingDefinition typeMapping = components.getTypeMappings().iterator().next(); assertEquals("t-m-key", typeMapping.getType()); assertEquals("t-m-impl", typeMapping.getImplementation()); } private Object fromList(Collection coll, int index) { return ((List)coll).get(index); } }