From: Mathieu Baudier Date: Sat, 7 Sep 2019 16:59:59 +0000 (+0200) Subject: Make testing more generic. X-Git-Tag: argeo-commons-2.1.79~18 X-Git-Url: https://git.argeo.org/?p=lgpl%2Fargeo-commons.git;a=commitdiff_plain;h=438237c2b8c995d4f9562d53bfe4ea63c4442054 Make testing more generic. --- diff --git a/org.argeo.core/pom.xml b/org.argeo.core/pom.xml index 62de67181..ed0cc927d 100644 --- a/org.argeo.core/pom.xml +++ b/org.argeo.core/pom.xml @@ -1,4 +1,7 @@ - + + 4.0.0 org.argeo.commons @@ -14,6 +17,11 @@ org.argeo.util 2.1.79-SNAPSHOT + + org.argeo.commons + org.argeo.enterprise + 2.1.79-SNAPSHOT + org.argeo.commons org.argeo.jcr diff --git a/org.argeo.core/src/org/argeo/sync/fs/PathSync.java b/org.argeo.core/src/org/argeo/sync/fs/PathSync.java index 99d5de81f..151194da6 100644 --- a/org.argeo.core/src/org/argeo/sync/fs/PathSync.java +++ b/org.argeo.core/src/org/argeo/sync/fs/PathSync.java @@ -6,19 +6,15 @@ import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.spi.FileSystemProvider; -import java.time.ZonedDateTime; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; import org.argeo.jackrabbit.fs.DavexFsProvider; import org.argeo.ssh.Sftp; import org.argeo.sync.SyncException; -import org.argeo.util.LangUtils; +/** Synchronises two paths. */ public class PathSync implements Runnable { - private final static Log log = LogFactory.getLog(PathSync.class); - private final URI sourceUri, targetUri; + private boolean delete = false; public PathSync(URI sourceUri, URI targetUri) { this.sourceUri = sourceUri; @@ -30,11 +26,8 @@ public class PathSync implements Runnable { try { Path sourceBasePath = createPath(sourceUri); Path targetBasePath = createPath(targetUri); - SyncFileVisitor syncFileVisitor = new SyncFileVisitor(sourceBasePath, targetBasePath); - ZonedDateTime begin = ZonedDateTime.now(); + SyncFileVisitor syncFileVisitor = new SyncFileVisitor(sourceBasePath, targetBasePath, delete); Files.walkFileTree(sourceBasePath, syncFileVisitor); - if (log.isDebugEnabled()) - log.debug("Sync from " + sourceBasePath + " to " + targetBasePath + " took " + LangUtils.since(begin)); } catch (Exception e) { e.printStackTrace(); } @@ -57,8 +50,4 @@ public class PathSync implements Runnable { throw new SyncException("URI scheme not supported for " + uri); return path; } - - static enum Arg { - to, from; - } } diff --git a/org.argeo.core/src/org/argeo/sync/fs/SyncFileVisitor.java b/org.argeo.core/src/org/argeo/sync/fs/SyncFileVisitor.java index de8032004..d59a611fc 100644 --- a/org.argeo.core/src/org/argeo/sync/fs/SyncFileVisitor.java +++ b/org.argeo.core/src/org/argeo/sync/fs/SyncFileVisitor.java @@ -1,56 +1,31 @@ package org.argeo.sync.fs; -import java.io.IOException; -import java.nio.file.FileVisitResult; -import java.nio.file.Files; import java.nio.file.Path; -import java.nio.file.SimpleFileVisitor; -import java.nio.file.attribute.BasicFileAttributes; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.argeo.fs.BasicSyncFileVisitor; /** Synchronises two directory structures. */ -public class SyncFileVisitor extends SimpleFileVisitor { +public class SyncFileVisitor extends BasicSyncFileVisitor { private final static Log log = LogFactory.getLog(SyncFileVisitor.class); - private final Path sourceBasePath; - private final Path targetBasePath; - - public SyncFileVisitor(Path sourceBasePath, Path targetBasePath) { - this.sourceBasePath = sourceBasePath; - this.targetBasePath = targetBasePath; + public SyncFileVisitor(Path sourceBasePath, Path targetBasePath, boolean delete) { + super(sourceBasePath, targetBasePath, delete); } @Override - public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException { - Path targetPath = toTargetPath(dir); - Files.createDirectories(targetPath); - return FileVisitResult.CONTINUE; + protected void error(Object obj, Throwable e) { + log.error(obj, e); } @Override - public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { - Path targetPath = toTargetPath(file); - try { - Files.copy(file, targetPath); - if (log.isDebugEnabled()) - log.debug("Copied " + targetPath); - } catch (Exception e) { - log.error("Cannot copy " + file + " to " + targetPath, e); - } - return FileVisitResult.CONTINUE; + protected boolean isDebugEnabled() { + return log.isDebugEnabled(); } @Override - public FileVisitResult visitFileFailed(Path file, IOException exc) throws IOException { - log.error("Cannot sync " + file, exc); - return FileVisitResult.CONTINUE; - } - - private Path toTargetPath(Path sourcePath) { - Path relativePath = sourceBasePath.relativize(sourcePath); - Path targetPath = targetBasePath.resolve(relativePath.toString()); - return targetPath; + protected void debug(Object obj) { + log.debug(obj); } } diff --git a/org.argeo.enterprise/bnd.bnd b/org.argeo.enterprise/bnd.bnd index 4b2eb271a..5f42f7786 100644 --- a/org.argeo.enterprise/bnd.bnd +++ b/org.argeo.enterprise/bnd.bnd @@ -1,2 +1,6 @@ +Bundle-Activator: org.argeo.osgi.internal.EnterpriseActivator +Bundle-ActivationPolicy: lazy + Import-Package: org.osgi.*;version=0.0.0,\ +!org.apache.commons.logging,\ * diff --git a/org.argeo.enterprise/build.properties b/org.argeo.enterprise/build.properties index 6fa156125..cd379dca9 100644 --- a/org.argeo.enterprise/build.properties +++ b/org.argeo.enterprise/build.properties @@ -1,7 +1,4 @@ source.. = src/,\ ext/test/ additional.bundles = org.junit,\ - org.slf4j.commons.logging,\ - org.slf4j.api,\ - org.slf4j.log4j12,\ - org.apache.log4j + org.argeo.util diff --git a/org.argeo.enterprise/ext/test/AllEnterpriseTests.java b/org.argeo.enterprise/ext/test/AllEnterpriseTests.java new file mode 100644 index 000000000..aed01f25f --- /dev/null +++ b/org.argeo.enterprise/ext/test/AllEnterpriseTests.java @@ -0,0 +1,20 @@ +import org.argeo.fs.FsUtilsTest; +import org.argeo.osgi.useradmin.LdifParserTest; +import org.argeo.osgi.useradmin.UserAdminConfTest; +import org.argeo.util.test.Tester; + +class AllEnterpriseTests { + + public static void main(String[] args) throws Exception { + Tester tester = new Tester(); + + // FS + tester.execute(FsUtilsTest.class.getName()); + + // User admin + tester.execute(LdifParserTest.class.getName()); + //tester.execute(LdifUserAdminTest.class.getName()); + tester.execute(UserAdminConfTest.class.getName()); + } + +} diff --git a/org.argeo.enterprise/ext/test/log4j.properties b/org.argeo.enterprise/ext/test/log4j.properties deleted file mode 100644 index ef735668b..000000000 --- a/org.argeo.enterprise/ext/test/log4j.properties +++ /dev/null @@ -1,28 +0,0 @@ -log4j.rootLogger=WARN, console - -## Levels -log4j.logger.org.argeo=TRACE - -log4j.logger.org.hibernate=WARN - -log4j.logger.org.springframework=WARN -#log4j.logger.org.springframework.web=DEBUG -#log4j.logger.org.springframework.jms=WARN -#log4j.logger.org.springframework.security=WARN - -log4j.logger.org.apache.activemq=WARN -log4j.logger.org.apache.activemq.transport=WARN -log4j.logger.org.apache.activemq.ActiveMQMessageConsumer=INFO -log4j.logger.org.apache.activemq.ActiveMQMessageProducer=INFO - -log4j.logger.org.apache.catalina=INFO -log4j.logger.org.apache.coyote=INFO -log4j.logger.org.apache.tomcat=INFO - -## Appenders -# console is set to be a ConsoleAppender. -log4j.appender.console=org.apache.log4j.ConsoleAppender - -# console uses PatternLayout. -log4j.appender.console.layout=org.apache.log4j.PatternLayout -log4j.appender.console.layout.ConversionPattern= %-5p %d{ISO8601} %m - %c%n diff --git a/org.argeo.enterprise/ext/test/org/argeo/fs/FsUtilsTest.java b/org.argeo.enterprise/ext/test/org/argeo/fs/FsUtilsTest.java new file mode 100644 index 000000000..793216b1d --- /dev/null +++ b/org.argeo.enterprise/ext/test/org/argeo/fs/FsUtilsTest.java @@ -0,0 +1,49 @@ +package org.argeo.fs; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; + +/** {@link FsUtils} tests. */ +public class FsUtilsTest { + final static String FILE00 = "file00"; + final static String FILE01 = "file01"; + final static String SUB_DIR = "subDir"; + + public void testDelete() throws IOException { + Path dir = createDir00(); + assert Files.exists(dir); + FsUtils.delete(dir); + assert !Files.exists(dir); + } + + public void testSync() throws IOException { + Path source = createDir00(); + Path target = Files.createTempDirectory(getClass().getName()); + FsUtils.sync(source, target); + assert Files.exists(target.resolve(FILE00)); + assert Files.exists(target.resolve(SUB_DIR)); + assert Files.exists(target.resolve(SUB_DIR + File.separator + FILE01)); + FsUtils.delete(source.resolve(SUB_DIR)); + FsUtils.sync(source, target, true); + assert Files.exists(target.resolve(FILE00)); + assert !Files.exists(target.resolve(SUB_DIR)); + assert !Files.exists(target.resolve(SUB_DIR + File.separator + FILE01)); + + // clean up + FsUtils.delete(source); + FsUtils.delete(target); + + } + + Path createDir00() throws IOException { + Path base = Files.createTempDirectory(getClass().getName()); + base.toFile().deleteOnExit(); + Files.createFile(base.resolve(FILE00)).toFile().deleteOnExit(); + Path subDir = Files.createDirectories(base.resolve(SUB_DIR)); + subDir.toFile().deleteOnExit(); + Files.createFile(subDir.resolve(FILE01)).toFile().deleteOnExit(); + return base; + } +} diff --git a/org.argeo.enterprise/ext/test/org/argeo/osgi/useradmin/LdifParserTest.java b/org.argeo.enterprise/ext/test/org/argeo/osgi/useradmin/LdifParserTest.java index 75bfe11ff..012a50ed1 100644 --- a/org.argeo.enterprise/ext/test/org/argeo/osgi/useradmin/LdifParserTest.java +++ b/org.argeo.enterprise/ext/test/org/argeo/osgi/useradmin/LdifParserTest.java @@ -13,38 +13,32 @@ import javax.naming.ldap.LdapName; import org.argeo.naming.LdapAttrs; import org.argeo.naming.LdifParser; -import junit.framework.TestCase; - -public class LdifParserTest extends TestCase implements BasicTestConstants { +/** {@link LdifParser} tests. */ +public class LdifParserTest implements BasicTestConstants { public void testBasicLdif() throws Exception { LdifParser ldifParser = new LdifParser(); - SortedMap res = ldifParser.read(getClass() - .getResourceAsStream("basic.ldif")); + SortedMap res = ldifParser.read(getClass().getResourceAsStream("basic.ldif")); LdapName rootDn = new LdapName(ROOT_USER_DN); Attributes rootAttributes = res.get(rootDn); - assertNotNull(rootAttributes); - assertEquals("Superuser", - rootAttributes.get(LdapAttrs.description.name()).get()); - byte[] rawPwEntry = (byte[]) rootAttributes.get( - LdapAttrs.userPassword.name()).get(); - assertEquals("{SHA}ieSV55Qc+eQOaYDRSha/AjzNTJE=", - new String(rawPwEntry)); + assert rootAttributes != null; + assert "Superuser".equals(rootAttributes.get(LdapAttrs.description.name()).get()); + byte[] rawPwEntry = (byte[]) rootAttributes.get(LdapAttrs.userPassword.name()).get(); + assert "{SHA}ieSV55Qc+eQOaYDRSha/AjzNTJE=".contentEquals(new String(rawPwEntry)); byte[] hashedPassword = DigestUtils.sha1("demo".getBytes()); - assertEquals("{SHA}" + Base64.getEncoder().encodeToString(hashedPassword), - new String(rawPwEntry)); + assert ("{SHA}" + Base64.getEncoder().encodeToString(hashedPassword)).equals(new String(rawPwEntry)); LdapName adminDn = new LdapName(ADMIN_GROUP_DN); Attributes adminAttributes = res.get(adminDn); - assertNotNull(adminAttributes); + assert adminAttributes != null; Attribute memberAttribute = adminAttributes.get(LdapAttrs.member.name()); - assertNotNull(memberAttribute); + assert memberAttribute != null; NamingEnumeration members = memberAttribute.getAll(); List users = new ArrayList(); while (members.hasMore()) { Object value = members.next(); users.add(value.toString()); } - assertEquals(1, users.size()); - assertEquals(rootDn, new LdapName(users.get(0))); + assert 1 == users.size(); + assert rootDn.equals(new LdapName(users.get(0))); } } diff --git a/org.argeo.enterprise/ext/test/org/argeo/osgi/useradmin/LdifUserAdminTest.java b/org.argeo.enterprise/ext/test/org/argeo/osgi/useradmin/LdifUserAdminTest.java index 748abe835..1d6b0f3a5 100644 --- a/org.argeo.enterprise/ext/test/org/argeo/osgi/useradmin/LdifUserAdminTest.java +++ b/org.argeo.enterprise/ext/test/org/argeo/osgi/useradmin/LdifUserAdminTest.java @@ -27,7 +27,11 @@ import org.osgi.service.useradmin.User; import junit.framework.TestCase; +/** {@link LdifUserAdmin} tests. */ public class LdifUserAdminTest extends TestCase implements BasicTestConstants { + // We have to keep using JUnit because of + // https://issues.apache.org/jira/browse/SUREFIRE-1669 + final static int TM_SIMPLE = 0; final static int TM_BITRONIX = 1; @@ -37,20 +41,52 @@ public class LdifUserAdminTest extends TestCase implements BasicTestConstants { private AbstractUserDirectory userAdmin; private Path tempDir; - // public void testConcurrent() throws Exception { - // } + public void setUp() { + System.out.println("Enter setUp()"); + try { + tempDir = Files.createTempDirectory(getClass().getName()); + tempDir.toFile().deleteOnExit(); + String uriProp = System.getProperty("argeo.userdirectory.uri"); + if (uriProp != null) + uri = new URI(uriProp); + else { + tempDir.toFile().deleteOnExit(); + Path ldifPath = tempDir.resolve(BASE_DN + ".ldif"); + try (InputStream in = getClass().getResource("basic.ldif").openStream()) { + Files.copy(in, ldifPath); + } + uri = ldifPath.toUri(); + } + + // Init transaction manager + if (TM_SIMPLE == tmType) { + tm = new SimpleTransactionManager(); + } +// else if (TM_BITRONIX == tmType) { +// bitronix.tm.Configuration tmConf = TransactionManagerServices.getConfiguration(); +// tmConf.setServerId(UUID.randomUUID().toString()); +// tmConf.setLogPart1Filename(new File(tempDir.toFile(), "btm1.tlog").getAbsolutePath()); +// tmConf.setLogPart2Filename(new File(tempDir.toFile(), "btm2.tlog").getAbsolutePath()); +// tm = TransactionManagerServices.getTransactionManager(); +// } + + userAdmin = initUserAdmin(uri, tm); + } catch (Exception e) { + throw new RuntimeException(e); + } + } public void testEdition() throws Exception { User demoUser = (User) userAdmin.getRole(DEMO_USER_DN); - assertNotNull(demoUser); + assert demoUser != null; tm.begin(); String newName = "demo"; demoUser.getProperties().put("cn", newName); - assertEquals(newName, demoUser.getProperties().get("cn")); + assert newName.equals(demoUser.getProperties().get("cn")); tm.commit(); persistAndRestart(); - assertEquals(newName, demoUser.getProperties().get("cn")); + assert newName.equals(demoUser.getProperties().get("cn")); tm.begin(); userAdmin.removeRole(DEMO_USER_DN); @@ -59,59 +95,59 @@ public class LdifUserAdminTest extends TestCase implements BasicTestConstants { // check data Role[] search = userAdmin.getRoles("(objectclass=inetOrgPerson)"); - assertEquals(1, search.length); + assert 1 == search.length; Group editorGroup = (Group) userAdmin.getRole(EDITORS_GROUP_DN); - assertNotNull(editorGroup); + assert editorGroup != null; Role[] members = editorGroup.getMembers(); - assertEquals(1, members.length); + assert 1 == members.length; } public void testRetrieve() throws Exception { // users User rootUser = (User) userAdmin.getRole(ROOT_USER_DN); - assertNotNull(rootUser); + assert rootUser != null; User demoUser = (User) userAdmin.getRole(DEMO_USER_DN); - assertNotNull(demoUser); + assert demoUser != null; // groups Group adminGroup = (Group) userAdmin.getRole(ADMIN_GROUP_DN); - assertNotNull(adminGroup); + assert adminGroup != null; Role[] members = adminGroup.getMembers(); - assertEquals(1, members.length); - assertEquals(rootUser, members[0]); + assert 1 == members.length; + assert rootUser.equals(members[0]); Group editorGroup = (Group) userAdmin.getRole(EDITORS_GROUP_DN); - assertNotNull(editorGroup); + assert editorGroup != null; members = editorGroup.getMembers(); - assertEquals(2, members.length); - assertEquals(adminGroup, members[0]); - assertEquals(demoUser, members[1]); + assert 2 == members.length; + assert adminGroup.equals(members[0]); + assert demoUser.equals(members[1]); Authorization rootAuth = userAdmin.getAuthorization(rootUser); List rootRoles = Arrays.asList(rootAuth.getRoles()); - assertEquals(3, rootRoles.size()); - assertTrue(rootRoles.contains(ROOT_USER_DN)); - assertTrue(rootRoles.contains(ADMIN_GROUP_DN)); - assertTrue(rootRoles.contains(EDITORS_GROUP_DN)); + assert 3 == rootRoles.size(); + assert rootRoles.contains(ROOT_USER_DN); + assert rootRoles.contains(ADMIN_GROUP_DN); + assert rootRoles.contains(EDITORS_GROUP_DN); // properties - assertEquals("root@localhost", rootUser.getProperties().get("mail")); + assert "root@localhost".equals(rootUser.getProperties().get("mail")); // credentials byte[] hashedPassword = ("{SHA}" + Base64.getEncoder().encodeToString(DigestUtils.sha1("demo".getBytes()))) .getBytes(); - assertTrue(rootUser.hasCredential(LdapAttrs.userPassword.name(), hashedPassword)); - assertTrue(demoUser.hasCredential(LdapAttrs.userPassword.name(), hashedPassword)); + assert rootUser.hasCredential(LdapAttrs.userPassword.name(), hashedPassword); + assert demoUser.hasCredential(LdapAttrs.userPassword.name(), hashedPassword); // search Role[] search = userAdmin.getRoles(null); - assertEquals(4, search.length); + assert 4 == search.length; search = userAdmin.getRoles("(objectClass=groupOfNames)"); - assertEquals(2, search.length); + assert 2 == search.length; search = userAdmin.getRoles("(objectclass=inetOrgPerson)"); - assertEquals(2, search.length); + assert 2 == search.length; search = userAdmin.getRoles("(&(objectclass=inetOrgPerson)(uid=demo))"); - assertEquals(1, search.length); + assert 1 == search.length; } public void testReadWriteRead() throws Exception { @@ -129,43 +165,12 @@ public class LdifUserAdminTest extends TestCase implements BasicTestConstants { ((LdifUserAdmin) userAdmin).load(in); } Role[] search = userAdmin.getRoles(null); - assertEquals(4, search.length); + assert 4 == search.length; } else { // test not relevant for LDAP } } - @Override - protected void setUp() throws Exception { - tempDir = Files.createTempDirectory(getClass().getName()); - tempDir.toFile().deleteOnExit(); - String uriProp = System.getProperty("argeo.userdirectory.uri"); - if (uriProp != null) - uri = new URI(uriProp); - else { - tempDir.toFile().deleteOnExit(); - Path ldifPath = tempDir.resolve(BASE_DN + ".ldif"); - try (InputStream in = getClass().getResource("basic.ldif").openStream()) { - Files.copy(in, ldifPath); - } - uri = ldifPath.toUri(); - } - - // Init transaction manager - if (TM_SIMPLE == tmType) { - tm = new SimpleTransactionManager(); - } -// else if (TM_BITRONIX == tmType) { -// bitronix.tm.Configuration tmConf = TransactionManagerServices.getConfiguration(); -// tmConf.setServerId(UUID.randomUUID().toString()); -// tmConf.setLogPart1Filename(new File(tempDir.toFile(), "btm1.tlog").getAbsolutePath()); -// tmConf.setLogPart2Filename(new File(tempDir.toFile(), "btm2.tlog").getAbsolutePath()); -// tm = TransactionManagerServices.getTransactionManager(); -// } - - userAdmin = initUserAdmin(uri, tm); - } - private AbstractUserDirectory initUserAdmin(URI uri, TransactionManager tm) { Dictionary props = new Hashtable<>(); props.put(UserAdminConf.uri.name(), uri.toString()); @@ -194,8 +199,7 @@ public class LdifUserAdminTest extends TestCase implements BasicTestConstants { userAdmin = initUserAdmin(uri, tm); } - @Override - protected void tearDown() throws Exception { + public void tearDown() throws Exception { // if (TM_BITRONIX == tmType) { // EhCacheXAResourceProducer.unregisterXAResource(UserDirectory.class.getName(), userAdmin.getXaResource()); // ((BitronixTransactionManager) tm).shutdown(); diff --git a/org.argeo.enterprise/ext/test/org/argeo/osgi/useradmin/UserAdminConfTest.java b/org.argeo.enterprise/ext/test/org/argeo/osgi/useradmin/UserAdminConfTest.java index d69cae4c0..77a35f424 100644 --- a/org.argeo.enterprise/ext/test/org/argeo/osgi/useradmin/UserAdminConfTest.java +++ b/org.argeo.enterprise/ext/test/org/argeo/osgi/useradmin/UserAdminConfTest.java @@ -6,48 +6,48 @@ import static org.argeo.osgi.useradmin.UserAdminConf.uriAsProperties; import java.net.URI; import java.util.Dictionary; -import junit.framework.TestCase; - -public class UserAdminConfTest extends TestCase { +/** {@link UserAdminConf} tests. */ +public class UserAdminConfTest { public void testUriFormat() throws Exception { // LDAP URI uriIn = new URI("ldap://" + "uid=admin,ou=system:secret@localhost:10389" + "/dc=example,dc=com" + "?readOnly=false&userObjectClass=person"); Dictionary props = uriAsProperties(uriIn.toString()); System.out.println(props); - assertEquals("dc=example,dc=com", props.get(UserAdminConf.baseDn.name())); - assertEquals("false", props.get(UserAdminConf.readOnly.name())); - assertEquals("person", props.get(UserAdminConf.userObjectClass.name())); + assert "dc=example,dc=com".equals(props.get(UserAdminConf.baseDn.name())); + assert "false".equals(props.get(UserAdminConf.readOnly.name())); + assert "person".equals(props.get(UserAdminConf.userObjectClass.name())); URI uriOut = propertiesAsUri(props); System.out.println(uriOut); - assertEquals("/dc=example,dc=com?userObjectClass=person&readOnly=false", uriOut.toString()); + assert "/dc=example,dc=com?userObjectClass=person&readOnly=false".equals(uriOut.toString()); // File uriIn = new URI("file://some/dir/dc=example,dc=com.ldif"); props = uriAsProperties(uriIn.toString()); System.out.println(props); - assertEquals("dc=example,dc=com", props.get(UserAdminConf.baseDn.name())); + assert "dc=example,dc=com".equals(props.get(UserAdminConf.baseDn.name())); // Base configuration uriIn = new URI("/dc=example,dc=com.ldif?readOnly=true&userBase=ou=CoWorkers,ou=People&groupBase=ou=Roles"); props = uriAsProperties(uriIn.toString()); System.out.println(props); - assertEquals("dc=example,dc=com", props.get(UserAdminConf.baseDn.name())); - assertEquals("true", props.get(UserAdminConf.readOnly.name())); - assertEquals("ou=CoWorkers,ou=People", props.get(UserAdminConf.userBase.name())); - assertEquals("ou=Roles", props.get(UserAdminConf.groupBase.name())); + assert "dc=example,dc=com".equals(props.get(UserAdminConf.baseDn.name())); + assert "true".equals(props.get(UserAdminConf.readOnly.name())); + assert "ou=CoWorkers,ou=People".equals(props.get(UserAdminConf.userBase.name())); + assert "ou=Roles".equals(props.get(UserAdminConf.groupBase.name())); uriOut = propertiesAsUri(props); System.out.println(uriOut); - assertEquals("/dc=example,dc=com?userBase=ou=CoWorkers,ou=People&groupBase=ou=Roles&readOnly=true", uriOut.toString()); + assert "/dc=example,dc=com?userBase=ou=CoWorkers,ou=People&groupBase=ou=Roles&readOnly=true" + .equals(uriOut.toString()); // OS uriIn = new URI("os:///dc=example,dc=com"); props = uriAsProperties(uriIn.toString()); System.out.println(props); - assertEquals("dc=example,dc=com", props.get(UserAdminConf.baseDn.name())); - assertEquals("true", props.get(UserAdminConf.readOnly.name())); + assert "dc=example,dc=com".equals(props.get(UserAdminConf.baseDn.name())); + assert "true".equals(props.get(UserAdminConf.readOnly.name())); uriOut = propertiesAsUri(props); System.out.println(uriOut); - assertEquals("/dc=example,dc=com?readOnly=true", uriOut.toString()); + assert "/dc=example,dc=com?readOnly=true".equals(uriOut.toString()); } } diff --git a/org.argeo.enterprise/pom.xml b/org.argeo.enterprise/pom.xml index a5cc1aa7e..6dc4cc1c5 100644 --- a/org.argeo.enterprise/pom.xml +++ b/org.argeo.enterprise/pom.xml @@ -1,5 +1,7 @@ - + 4.0.0 org.argeo.commons @@ -9,4 +11,12 @@ org.argeo.enterprise Commons Enterprise + + + org.argeo.commons + org.argeo.util + 2.1.79-SNAPSHOT + test + + \ No newline at end of file diff --git a/org.argeo.enterprise/src/org/argeo/fs/BasicSyncFileVisitor.java b/org.argeo.enterprise/src/org/argeo/fs/BasicSyncFileVisitor.java new file mode 100644 index 000000000..6c9f39913 --- /dev/null +++ b/org.argeo.enterprise/src/org/argeo/fs/BasicSyncFileVisitor.java @@ -0,0 +1,139 @@ +package org.argeo.fs; + +import java.io.IOException; +import java.nio.file.FileVisitResult; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.SimpleFileVisitor; +import java.nio.file.StandardCopyOption; +import java.nio.file.attribute.BasicFileAttributes; +import java.nio.file.attribute.FileTime; + +/** Synchronises two directory structures. */ +public class BasicSyncFileVisitor extends SimpleFileVisitor { + // TODO make it configurable + private boolean debug = true; + + private final Path sourceBasePath; + private final Path targetBasePath; + private final boolean delete; + + public BasicSyncFileVisitor(Path sourceBasePath, Path targetBasePath, boolean delete) { + this.sourceBasePath = sourceBasePath; + this.targetBasePath = targetBasePath; + this.delete = delete; + } + + @Override + public FileVisitResult preVisitDirectory(Path sourceDir, BasicFileAttributes attrs) throws IOException { + Path targetDir = toTargetPath(sourceDir); + Files.createDirectories(targetDir); + return FileVisitResult.CONTINUE; + } + + @Override + public FileVisitResult postVisitDirectory(Path sourceDir, IOException exc) throws IOException { + if (delete) { + Path targetDir = toTargetPath(sourceDir); + for (Path targetPath : Files.newDirectoryStream(targetDir)) { + Path sourcePath = sourceDir.resolve(targetPath.getFileName()); + if (!Files.exists(sourcePath)) { + try { + FsUtils.delete(targetPath); + deleted(targetPath); + } catch (Exception e) { + deleteFailed(targetPath, exc); + } + } + } + } + return FileVisitResult.CONTINUE; + } + + @Override + public FileVisitResult visitFile(Path sourceFile, BasicFileAttributes attrs) throws IOException { + Path targetFile = toTargetPath(sourceFile); + try { + if (!Files.exists(targetFile)) { + Files.copy(sourceFile, targetFile); + copied(sourceFile, targetFile); + } else { + if (shouldOverwrite(sourceFile, targetFile)) { + Files.copy(sourceFile, targetFile, StandardCopyOption.REPLACE_EXISTING); + } + } + } catch (Exception e) { + copyFailed(sourceFile, targetFile, e); + } + return FileVisitResult.CONTINUE; + } + + protected boolean shouldOverwrite(Path sourceFile, Path targetFile) throws IOException { + long sourceSize = Files.size(sourceFile); + long targetSize = Files.size(targetFile); + if (sourceSize != targetSize) { + return true; + } + FileTime sourceLastModif = Files.getLastModifiedTime(sourceFile); + FileTime targetLastModif = Files.getLastModifiedTime(targetFile); + if (sourceLastModif.compareTo(targetLastModif) > 0) + return true; + return shouldOverwriteLaterSameSize(sourceFile, targetFile); + } + + protected boolean shouldOverwriteLaterSameSize(Path sourceFile, Path targetFile) { + return false; + } + +// @Override +// public FileVisitResult visitFileFailed(Path sourceFile, IOException exc) throws IOException { +// error("Cannot sync " + sourceFile, exc); +// return FileVisitResult.CONTINUE; +// } + + private Path toTargetPath(Path sourcePath) { + Path relativePath = sourceBasePath.relativize(sourcePath); + Path targetPath = targetBasePath.resolve(relativePath.toString()); + return targetPath; + } + + public Path getSourceBasePath() { + return sourceBasePath; + } + + public Path getTargetBasePath() { + return targetBasePath; + } + + protected void copied(Path sourcePath, Path targetPath) { + if (isDebugEnabled()) + debug("Copied " + sourcePath + " to " + targetPath); + } + + protected void copyFailed(Path sourcePath, Path targetPath, Exception e) { + error("Cannot copy " + sourcePath + " to " + targetPath, e); + } + + protected void deleted(Path targetPath) { + if (isDebugEnabled()) + debug("Deleted " + targetPath); + } + + protected void deleteFailed(Path targetPath, Exception e) { + error("Cannot delete " + targetPath, e); + } + + /** Log error. */ + protected void error(Object obj, Throwable e) { + System.err.println(obj); + e.printStackTrace(); + } + + protected boolean isDebugEnabled() { + return debug; + } + + protected void debug(Object obj) { + System.out.println(obj); + } +} diff --git a/org.argeo.enterprise/src/org/argeo/fs/FsUtils.java b/org.argeo.enterprise/src/org/argeo/fs/FsUtils.java new file mode 100644 index 000000000..6fc7bd25d --- /dev/null +++ b/org.argeo.enterprise/src/org/argeo/fs/FsUtils.java @@ -0,0 +1,58 @@ +package org.argeo.fs; + +import java.io.IOException; +import java.nio.file.FileVisitResult; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.SimpleFileVisitor; +import java.nio.file.attribute.BasicFileAttributes; + +/** Utilities around the standard Java file abstractions. */ +public class FsUtils { + /** Sync a source path with a target path. */ + public static void sync(Path sourceBasePath, Path targetBasePath) { + sync(sourceBasePath, targetBasePath, false); + } + + /** Sync a source path with a target path. */ + public static void sync(Path sourceBasePath, Path targetBasePath, boolean delete) { + sync(new BasicSyncFileVisitor(sourceBasePath, targetBasePath, delete)); + } + + public static void sync(BasicSyncFileVisitor syncFileVisitor) { + try { + Files.walkFileTree(syncFileVisitor.getSourceBasePath(), syncFileVisitor); + } catch (Exception e) { + throw new RuntimeException("Cannot sync " + syncFileVisitor.getSourceBasePath() + " with " + + syncFileVisitor.getTargetBasePath(), e); + } + } + + /** Deletes this path, recursively if needed. */ + public static void delete(Path path) { + try { + Files.walkFileTree(path, new SimpleFileVisitor() { + @Override + public FileVisitResult postVisitDirectory(Path directory, IOException e) throws IOException { + if (e != null) + throw e; + Files.delete(directory); + return FileVisitResult.CONTINUE; + } + + @Override + public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { + Files.delete(file); + return FileVisitResult.CONTINUE; + } + }); + } catch (IOException e) { + throw new RuntimeException("Cannot delete " + path, e); + } + } + + /** Singleton. */ + private FsUtils() { + } + +} diff --git a/org.argeo.enterprise/src/org/argeo/naming/DnsBrowser.java b/org.argeo.enterprise/src/org/argeo/naming/DnsBrowser.java index 7aadd64d8..62667c518 100644 --- a/org.argeo.enterprise/src/org/argeo/naming/DnsBrowser.java +++ b/org.argeo.enterprise/src/org/argeo/naming/DnsBrowser.java @@ -21,12 +21,7 @@ import javax.naming.directory.Attributes; import javax.naming.directory.DirContext; import javax.naming.directory.InitialDirContext; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - public class DnsBrowser implements Closeable { - private final static Log log = LogFactory.getLog(DnsBrowser.class); - private final DirContext initialCtx; public DnsBrowser() throws NamingException { @@ -140,7 +135,7 @@ public class DnsBrowser implements Closeable { try { initialCtx.close(); } catch (NamingException e) { - log.error("Cannot close context", e); + // silent } } diff --git a/org.argeo.enterprise/src/org/argeo/naming/LdifParser.java b/org.argeo.enterprise/src/org/argeo/naming/LdifParser.java index 86392b345..cc1957058 100644 --- a/org.argeo.enterprise/src/org/argeo/naming/LdifParser.java +++ b/org.argeo.enterprise/src/org/argeo/naming/LdifParser.java @@ -22,13 +22,10 @@ import javax.naming.directory.BasicAttributes; import javax.naming.ldap.LdapName; import javax.naming.ldap.Rdn; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; import org.argeo.osgi.useradmin.UserDirectoryException; /** Basic LDIF parser. */ public class LdifParser { - private final static Log log = LogFactory.getLog(LdifParser.class); private final static Charset DEFAULT_CHARSET = StandardCharsets.UTF_8; protected Attributes addAttributes(SortedMap res, int lineNumber, LdapName currentDn, @@ -43,8 +40,6 @@ public class LdifParser { "Attribute " + nameAttr.getID() + "=" + nameAttr.get() + " not consistent with DN " + currentDn + " (shortly before line " + lineNumber + " in LDIF file)"); Attributes previous = res.put(currentDn, currentAttributes); - if (log.isTraceEnabled()) - log.trace("Added " + currentDn); return previous; } catch (NamingException e) { throw new UserDirectoryException("Cannot add " + currentDn, e); @@ -59,8 +54,7 @@ public class LdifParser { try { in.close(); } catch (IOException e) { - if (log.isTraceEnabled()) - log.error("Cannot close stream", e); + // silent } } } @@ -126,8 +120,8 @@ public class LdifParser { // Attributes previous = addAttributes(res, lineNumber, currentDn, currentAttributes); if (previous != null) { - log.warn("There was already an entry with DN " + currentDn - + ", which has been discarded by a subsequent one."); +// log.warn("There was already an entry with DN " + currentDn +// + ", which has been discarded by a subsequent one."); } } @@ -136,7 +130,7 @@ public class LdifParser { currentDn = new LdapName(attributeValue.toString()); currentAttributes = new BasicAttributes(true); } catch (InvalidNameException e) { - log.error(attributeValue + " not a valid DN, skipping the entry."); +// log.error(attributeValue + " not a valid DN, skipping the entry."); currentDn = null; currentAttributes = null; } @@ -159,8 +153,7 @@ public class LdifParser { try { reader.close(); } catch (IOException e) { - if (log.isTraceEnabled()) - log.error("Cannot close stream", e); + // silent } } return res; diff --git a/org.argeo.enterprise/src/org/argeo/osgi/internal/EnterpriseActivator.java b/org.argeo.enterprise/src/org/argeo/osgi/internal/EnterpriseActivator.java new file mode 100644 index 000000000..03054828c --- /dev/null +++ b/org.argeo.enterprise/src/org/argeo/osgi/internal/EnterpriseActivator.java @@ -0,0 +1,21 @@ +package org.argeo.osgi.internal; + +import org.osgi.framework.BundleActivator; +import org.osgi.framework.BundleContext; + +/** + * Called to gather information about the OSGi runtime. Should not activate + * anything else that canonical monitoring services (not creating implicit + * APIs), which is the responsibility of higher levels.. + */ +public class EnterpriseActivator implements BundleActivator { + + @Override + public void start(BundleContext context) throws Exception { + } + + @Override + public void stop(BundleContext context) throws Exception { + } + +} diff --git a/org.argeo.enterprise/src/org/argeo/osgi/useradmin/AbstractUserDirectory.java b/org.argeo.enterprise/src/org/argeo/osgi/useradmin/AbstractUserDirectory.java index 385ea740e..a39743897 100644 --- a/org.argeo.enterprise/src/org/argeo/osgi/useradmin/AbstractUserDirectory.java +++ b/org.argeo.enterprise/src/org/argeo/osgi/useradmin/AbstractUserDirectory.java @@ -31,8 +31,6 @@ import javax.transaction.SystemException; import javax.transaction.Transaction; import javax.transaction.TransactionManager; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; import org.argeo.naming.LdapAttrs; import org.osgi.framework.Filter; import org.osgi.framework.FrameworkUtil; @@ -47,8 +45,6 @@ public abstract class AbstractUserDirectory implements UserAdmin, UserDirectory static final String SHARED_STATE_USERNAME = "javax.security.auth.login.name"; static final String SHARED_STATE_PASSWORD = "javax.security.auth.login.password"; - private final static Log log = LogFactory.getLog(AbstractUserDirectory.class); - private final Hashtable properties; private final LdapName baseDn, userBaseDn, groupBaseDn; private final String userObjectClass, userBase, groupObjectClass, groupBase; @@ -187,8 +183,6 @@ public abstract class AbstractUserDirectory implements UserAdmin, UserDirectory LdapName groupDn = new LdapName(value.toString()); DirectoryUser group = doGetRole(groupDn); allRoles.add(group); - if (log.isTraceEnabled()) - log.trace("Add memberOf " + groupDn); } } catch (Exception e) { throw new UserDirectoryException("Cannot get memberOf groups for " + user, e); @@ -198,8 +192,6 @@ public abstract class AbstractUserDirectory implements UserAdmin, UserDirectory // TODO check for loops DirectoryUser group = doGetRole(groupDn); allRoles.add(group); - if (log.isTraceEnabled()) - log.trace("Add direct group " + groupDn); collectRoles(group, allRoles); } } @@ -262,23 +254,14 @@ public abstract class AbstractUserDirectory implements UserAdmin, UserDirectory doGetUser(key, value, collectedUsers); } else { throw new UserDirectoryException("Key cannot be null"); - // // try dn - // DirectoryUser user = null; - // try { - // user = (DirectoryUser) getRole(value); - // if (user != null) - // collectedUsers.add(user); - // } catch (Exception e) { - // // silent - // } - // // try all indexes - // for (String attr : getIndexedUserProperties()) - // doGetUser(attr, value, collectedUsers); } - if (collectedUsers.size() == 1) + + if (collectedUsers.size() == 1) { return collectedUsers.get(0); - else if (collectedUsers.size() > 1) - log.warn(collectedUsers.size() + " users for " + (key != null ? key + "=" : "") + value); + } else if (collectedUsers.size() > 1) { + // log.warn(collectedUsers.size() + " users for " + (key != null ? key + "=" : + // "") + value); + } return null; } diff --git a/org.argeo.enterprise/src/org/argeo/osgi/useradmin/LdapUserAdmin.java b/org.argeo.enterprise/src/org/argeo/osgi/useradmin/LdapUserAdmin.java index 10a75feb0..58f6eb1fa 100644 --- a/org.argeo.enterprise/src/org/argeo/osgi/useradmin/LdapUserAdmin.java +++ b/org.argeo.enterprise/src/org/argeo/osgi/useradmin/LdapUserAdmin.java @@ -22,8 +22,6 @@ import javax.naming.ldap.InitialLdapContext; import javax.naming.ldap.LdapName; import javax.transaction.TransactionManager; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; import org.argeo.naming.LdapAttrs; import org.osgi.framework.Filter; import org.osgi.service.useradmin.Role; @@ -34,8 +32,6 @@ import org.osgi.service.useradmin.User; * and an open transaction for write access. */ public class LdapUserAdmin extends AbstractUserDirectory { - private final static Log log = LogFactory.getLog(LdapUserAdmin.class); - private InitialLdapContext initialLdapContext = null; public LdapUserAdmin(Dictionary properties) { @@ -74,7 +70,7 @@ public class LdapUserAdmin extends AbstractUserDirectory { // tls.close(); initialLdapContext.close(); } catch (NamingException e) { - log.error("Cannot destroy LDAP user admin", e); + e.printStackTrace(); } } @@ -128,8 +124,6 @@ public class LdapUserAdmin extends AbstractUserDirectory { } catch (NameNotFoundException e) { throw e; } catch (NamingException e) { - if (log.isTraceEnabled()) - log.error("Cannot get role: " + name, e); return null; } } @@ -160,7 +154,7 @@ public class LdapUserAdmin extends AbstractUserDirectory { || objectClassAttr.contains(getUserObjectClass().toLowerCase())) role = new LdifUser(this, dn, attrs); else { - log.warn("Unsupported LDAP type for " + searchResult.getName()); +// log.warn("Unsupported LDAP type for " + searchResult.getName()); continue results; } res.add(role); diff --git a/org.argeo.enterprise/src/org/argeo/osgi/useradmin/UserAdminConf.java b/org.argeo.enterprise/src/org/argeo/osgi/useradmin/UserAdminConf.java index 37d633920..bb7345f0b 100644 --- a/org.argeo.enterprise/src/org/argeo/osgi/useradmin/UserAdminConf.java +++ b/org.argeo.enterprise/src/org/argeo/osgi/useradmin/UserAdminConf.java @@ -15,8 +15,6 @@ import javax.naming.Context; import javax.naming.NamingException; import javax.naming.ldap.LdapName; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; import org.argeo.naming.DnsBrowser; import org.argeo.naming.NamingUtils; import org.osgi.framework.Constants; @@ -51,7 +49,6 @@ public enum UserAdminConf { realm(null); public final static String FACTORY_PID = "org.argeo.osgi.useradmin.config"; - private final static Log log = LogFactory.getLog(UserAdminConf.class); public final static String SCHEME_LDAP = "ldap"; public final static String SCHEME_FILE = "file"; @@ -221,8 +218,6 @@ public enum UserAdminConf { } URI convertedUri = new URI( SCHEME_LDAP + "://" + ldapHostsStr + "/" + IpaUtils.domainToUserDirectoryConfigPath(kerberosRealm)); - if (log.isDebugEnabled()) - log.debug("Converted " + uri + " to " + convertedUri); return convertedUri; } catch (NamingException | IOException | URISyntaxException e) { throw new UserDirectoryException("cannot convert IPA uri " + uri, e); @@ -248,7 +243,6 @@ public enum UserAdminConf { try { hostname = InetAddress.getLocalHost().getHostName(); } catch (UnknownHostException e) { - log.warn("Using localhost as hostname", e); hostname = "localhost.localdomain"; } int dotIdx = hostname.indexOf('.'); diff --git a/org.argeo.enterprise/src/org/argeo/osgi/useradmin/WcXaResource.java b/org.argeo.enterprise/src/org/argeo/osgi/useradmin/WcXaResource.java index a6048fdca..525176d96 100644 --- a/org.argeo.enterprise/src/org/argeo/osgi/useradmin/WcXaResource.java +++ b/org.argeo.enterprise/src/org/argeo/osgi/useradmin/WcXaResource.java @@ -7,13 +7,8 @@ import javax.transaction.xa.XAException; import javax.transaction.xa.XAResource; import javax.transaction.xa.Xid; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - /** {@link XAResource} for a user directory being edited. */ class WcXaResource implements XAResource { - private final static Log log = LogFactory.getLog(WcXaResource.class); - private final AbstractUserDirectory userDirectory; private Map workingCopies = new HashMap(); @@ -28,11 +23,9 @@ class WcXaResource implements XAResource { public synchronized void start(Xid xid, int flags) throws XAException { if (editingXid != null) throw new UserDirectoryException("Already editing " + editingXid); - UserDirectoryWorkingCopy wc = workingCopies.put(xid, - new UserDirectoryWorkingCopy()); + UserDirectoryWorkingCopy wc = workingCopies.put(xid, new UserDirectoryWorkingCopy()); if (wc != null) - throw new UserDirectoryException( - "There is already a working copy for " + xid); + throw new UserDirectoryException("There is already a working copy for " + xid); this.editingXid = xid; } @@ -50,8 +43,7 @@ class WcXaResource implements XAResource { return null; UserDirectoryWorkingCopy wc = workingCopies.get(editingXid); if (wc == null) - throw new UserDirectoryException("No working copy found for " - + editingXid); + throw new UserDirectoryException("No working copy found for " + editingXid); return wc; } @@ -70,7 +62,6 @@ class WcXaResource implements XAResource { try { userDirectory.prepare(wc); } catch (Exception e) { - log.error("Cannot prepare " + xid, e); throw new XAException(XAException.XAER_RMERR); } return XA_OK; @@ -87,7 +78,6 @@ class WcXaResource implements XAResource { userDirectory.prepare(wc); userDirectory.commit(wc); } catch (Exception e) { - log.error("Cannot commit " + xid, e); throw new XAException(XAException.XAER_RMERR); } finally { cleanUp(xid); @@ -100,7 +90,6 @@ class WcXaResource implements XAResource { checkXid(xid); userDirectory.rollback(wc(xid)); } catch (Exception e) { - log.error("Cannot rollback " + xid, e); throw new XAException(XAException.XAER_RMERR); } finally { cleanUp(xid); diff --git a/org.argeo.enterprise/src/org/argeo/transaction/simple/SimpleTransaction.java b/org.argeo.enterprise/src/org/argeo/transaction/simple/SimpleTransaction.java index fbb138668..43d4cd91c 100644 --- a/org.argeo.enterprise/src/org/argeo/transaction/simple/SimpleTransaction.java +++ b/org.argeo.enterprise/src/org/argeo/transaction/simple/SimpleTransaction.java @@ -14,12 +14,8 @@ import javax.transaction.xa.XAException; import javax.transaction.xa.XAResource; import javax.transaction.xa.Xid; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - +/** Simple implementation of an XA {@link Transaction}. */ class SimpleTransaction implements Transaction, Status { - private final static Log log = LogFactory.getLog(SimpleTransaction.class); - private final Xid xid; private int status = Status.STATUS_ACTIVE; private final List xaResources = new ArrayList(); @@ -32,8 +28,7 @@ class SimpleTransaction implements Transaction, Status { } @Override - public synchronized void commit() throws RollbackException, - HeuristicMixedException, HeuristicRollbackException, + public synchronized void commit() throws RollbackException, HeuristicMixedException, HeuristicRollbackException, SecurityException, IllegalStateException, SystemException { status = STATUS_PREPARING; for (XAResource xaRes : xaResources) { @@ -43,7 +38,7 @@ class SimpleTransaction implements Transaction, Status { xaRes.prepare(xid); } catch (XAException e) { status = STATUS_MARKED_ROLLBACK; - log.error("Cannot prepare " + xaRes + " for " + xid, e); + error("Cannot prepare " + xaRes + " for " + xid, e); } } if (status == STATUS_MARKED_ROLLBACK) { @@ -60,7 +55,7 @@ class SimpleTransaction implements Transaction, Status { xaRes.commit(xid, false); } catch (XAException e) { status = STATUS_MARKED_ROLLBACK; - log.error("Cannot prepare " + xaRes + " for " + xid, e); + error("Cannot prepare " + xaRes + " for " + xid, e); } } if (status == STATUS_MARKED_ROLLBACK) { @@ -70,28 +65,23 @@ class SimpleTransaction implements Transaction, Status { // complete status = STATUS_COMMITTED; - if (log.isTraceEnabled()) - log.trace("COMMITTED " + xid); clearResources(XAResource.TMSUCCESS); transactionManager.unregister(xid); } @Override - public synchronized void rollback() throws IllegalStateException, - SystemException { + public synchronized void rollback() throws IllegalStateException, SystemException { status = STATUS_ROLLING_BACK; for (XAResource xaRes : xaResources) { try { xaRes.rollback(xid); } catch (XAException e) { - log.error("Cannot rollback " + xaRes + " for " + xid, e); + error("Cannot rollback " + xaRes + " for " + xid, e); } } // complete status = STATUS_ROLLEDBACK; - if (log.isTraceEnabled()) - log.trace("ROLLEDBACK " + xid); clearResources(XAResource.TMFAIL); transactionManager.unregister(xid); } @@ -104,7 +94,7 @@ class SimpleTransaction implements Transaction, Status { xaRes.start(getXid(), XAResource.TMNOFLAGS); return true; } catch (XAException e) { - log.error("Cannot enlist " + xaRes, e); + error("Cannot enlist " + xaRes, e); return false; } } else @@ -118,7 +108,7 @@ class SimpleTransaction implements Transaction, Status { try { xaRes.end(getXid(), flag); } catch (XAException e) { - log.error("Cannot delist " + xaRes, e); + error("Cannot delist " + xaRes, e); return false; } return true; @@ -131,11 +121,16 @@ class SimpleTransaction implements Transaction, Status { try { xaRes.end(getXid(), flag); } catch (XAException e) { - log.error("Cannot end " + xaRes, e); + error("Cannot end " + xaRes, e); } xaResources.clear(); } + protected void error(Object obj, Exception e) { + System.err.println(obj); + e.printStackTrace(); + } + @Override public synchronized int getStatus() throws SystemException { return status; diff --git a/org.argeo.enterprise/src/org/argeo/transaction/simple/SimpleTransactionException.java b/org.argeo.enterprise/src/org/argeo/transaction/simple/SimpleTransactionException.java deleted file mode 100644 index d00def966..000000000 --- a/org.argeo.enterprise/src/org/argeo/transaction/simple/SimpleTransactionException.java +++ /dev/null @@ -1,14 +0,0 @@ -package org.argeo.transaction.simple; - -public class SimpleTransactionException extends RuntimeException { - private static final long serialVersionUID = -7465792070797750212L; - - public SimpleTransactionException(String message) { - super(message); - } - - public SimpleTransactionException(String message, Throwable cause) { - super(message, cause); - } - -} diff --git a/org.argeo.enterprise/src/org/argeo/transaction/simple/SimpleTransactionManager.java b/org.argeo.enterprise/src/org/argeo/transaction/simple/SimpleTransactionManager.java index fef728146..7dcf7d99a 100644 --- a/org.argeo.enterprise/src/org/argeo/transaction/simple/SimpleTransactionManager.java +++ b/org.argeo.enterprise/src/org/argeo/transaction/simple/SimpleTransactionManager.java @@ -18,12 +18,11 @@ import javax.transaction.TransactionSynchronizationRegistry; import javax.transaction.UserTransaction; import javax.transaction.xa.Xid; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - +/** + * Simple implementation of an XA {@link TransactionManager} and + * {@link UserTransaction}. + */ public class SimpleTransactionManager implements TransactionManager, UserTransaction { - private final static Log log = LogFactory.getLog(SimpleTransactionManager.class); - private ThreadLocal current = new ThreadLocal(); private Map knownTransactions = Collections @@ -37,8 +36,6 @@ public class SimpleTransactionManager implements TransactionManager, UserTransac SimpleTransaction transaction = new SimpleTransaction(this); knownTransactions.put(transaction.getXid(), transaction); current.set(transaction); - if (log.isTraceEnabled()) - log.trace("STARTED " + transaction.getXid()); } @Override @@ -123,7 +120,7 @@ public class SimpleTransactionManager implements TransactionManager, UserTransac return null; return getCurrent().getXid(); } catch (SystemException e) { - throw new SimpleTransactionException("Cannot get transaction key", e); + throw new IllegalStateException("Cannot get transaction key", e); } } @@ -147,7 +144,7 @@ public class SimpleTransactionManager implements TransactionManager, UserTransac try { return getStatus(); } catch (SystemException e) { - throw new SimpleTransactionException("Cannot get status", e); + throw new IllegalStateException("Cannot get status", e); } } @@ -156,7 +153,7 @@ public class SimpleTransactionManager implements TransactionManager, UserTransac try { return getStatus() == Status.STATUS_MARKED_ROLLBACK; } catch (SystemException e) { - throw new SimpleTransactionException("Cannot get status", e); + throw new IllegalStateException("Cannot get status", e); } } @@ -165,7 +162,7 @@ public class SimpleTransactionManager implements TransactionManager, UserTransac try { getCurrent().setRollbackOnly(); } catch (Exception e) { - throw new SimpleTransactionException("Cannot set rollback only", e); + throw new IllegalStateException("Cannot set rollback only", e); } } diff --git a/org.argeo.util/build.properties b/org.argeo.util/build.properties index 9a8006a7c..d34068df7 100644 --- a/org.argeo.util/build.properties +++ b/org.argeo.util/build.properties @@ -1,6 +1,3 @@ source.. = src/,\ ext/test/ output.. = bin/ -additional.bundles = org.junit,\ - org.slf4j.commons.logging,\ - org.apache.log4j diff --git a/org.argeo.util/ext/test/org/argeo/util/CsvParserEncodingTest.java b/org.argeo.util/ext/test/org/argeo/util/CsvParserEncodingTest.java new file mode 100644 index 000000000..72f2932d3 --- /dev/null +++ b/org.argeo.util/ext/test/org/argeo/util/CsvParserEncodingTest.java @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.util; + +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.util.List; + +/** Tests that {@link CsvParser} can deal properly with encodings. */ +public class CsvParserEncodingTest { + + private String iso = "ISO-8859-1"; + private String utf8 = "UTF-8"; + + public void testParse() throws Exception { + + String xml = new String("áéíóúñ,éééé"); + byte[] utfBytes = xml.getBytes(utf8); + byte[] isoBytes = xml.getBytes(iso); + + InputStream inUtf = new ByteArrayInputStream(utfBytes); + InputStream inIso = new ByteArrayInputStream(isoBytes); + + CsvParser csvParser = new CsvParser() { + protected void processLine(Integer lineNumber, List header, List tokens) { + assert header.size() == tokens.size(); + assert 2 == tokens.size(); + assert "áéíóúñ".equals(tokens.get(0)); + assert "éééé".equals(tokens.get(1)); + } + }; + + csvParser.parse(inUtf, utf8); + inUtf.close(); + csvParser.parse(inIso, iso); + inIso.close(); + } +} diff --git a/org.argeo.util/ext/test/org/argeo/util/CsvParserEncodingTestCase.java b/org.argeo.util/ext/test/org/argeo/util/CsvParserEncodingTestCase.java deleted file mode 100644 index 111a8738c..000000000 --- a/org.argeo.util/ext/test/org/argeo/util/CsvParserEncodingTestCase.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.util; - -import java.io.ByteArrayInputStream; -import java.io.InputStream; -import java.util.List; - -import junit.framework.TestCase; - -public class CsvParserEncodingTestCase extends TestCase { - - private String iso = "ISO-8859-1"; - private String utf8 = "UTF-8"; - - public void testParse() throws Exception { - - String xml = new String("áéíóúñ,éééé"); - byte[] utfBytes = xml.getBytes(utf8); - byte[] isoBytes = xml.getBytes(iso); - - InputStream inUtf = new ByteArrayInputStream(utfBytes); - InputStream inIso = new ByteArrayInputStream(isoBytes); - - CsvParser csvParser = new CsvParser() { - protected void processLine(Integer lineNumber, List header, - List tokens) { - assertEquals(header.size(), tokens.size()); - assertEquals(2, tokens.size()); - assertEquals("áéíóúñ", tokens.get(0)); - assertEquals("éééé", tokens.get(1)); - } - }; - - csvParser.parse(inUtf, utf8); - inUtf.close(); - csvParser.parse(inIso, iso); - inIso.close(); - } -} diff --git a/org.argeo.util/ext/test/org/argeo/util/CsvParserParseFileTest.java b/org.argeo.util/ext/test/org/argeo/util/CsvParserParseFileTest.java index a937ee7c7..0ddc26842 100644 --- a/org.argeo.util/ext/test/org/argeo/util/CsvParserParseFileTest.java +++ b/org.argeo.util/ext/test/org/argeo/util/CsvParserParseFileTest.java @@ -19,17 +19,14 @@ import java.io.InputStream; import java.util.HashMap; import java.util.Map; -import junit.framework.TestCase; - -public class CsvParserParseFileTest extends TestCase { +/** Test that {@link CsvParser} can properly parse a CSV file. */ +public class CsvParserParseFileTest { public void testParse() throws Exception { final Map> lines = new HashMap>(); - InputStream in = getClass().getResourceAsStream( - "/org/argeo/util/ReferenceFile.csv"); + InputStream in = getClass().getResourceAsStream("/org/argeo/util/ReferenceFile.csv"); CsvParserWithLinesAsMap parser = new CsvParserWithLinesAsMap() { - protected void processLine(Integer lineNumber, - Map line) { + protected void processLine(Integer lineNumber, Map line) { lines.put(lineNumber, line); } }; @@ -37,7 +34,7 @@ public class CsvParserParseFileTest extends TestCase { parser.parse(in); in.close(); - assertEquals(5, lines.size()); + assert 5 == lines.size(); } } diff --git a/org.argeo.util/ext/test/org/argeo/util/CsvParserTest.java b/org.argeo.util/ext/test/org/argeo/util/CsvParserTest.java new file mode 100644 index 000000000..e1b6877f4 --- /dev/null +++ b/org.argeo.util/ext/test/org/argeo/util/CsvParserTest.java @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.util; + +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.util.List; + +/** {@link CsvParser} tests. */ +public class CsvParserTest { + public void testParse() throws Exception { + String toParse = "Header1,\"Header\n2\",Header3,\"Header4\"\n" + "Col1,\"Col\n2\",Col3,\"\"\"Col4\"\"\"\n" + + "Col1,\"Col\n2\",Col3,\"\"\"Col4\"\"\"\n" + "Col1,\"Col\n2\",Col3,\"\"\"Col4\"\"\"\n"; + + InputStream in = new ByteArrayInputStream(toParse.getBytes()); + + CsvParser csvParser = new CsvParser() { + protected void processLine(Integer lineNumber, List header, List tokens) { + assert header.size() == tokens.size(); + assert 4 == tokens.size(); + assert "Col1".equals(tokens.get(0)); + assert "Col\n2".equals(tokens.get(1)); + assert "Col3".equals(tokens.get(2)); + assert "\"Col4\"".equals(tokens.get(3)); + } + }; + + csvParser.parse(in); + in.close(); + } + +} diff --git a/org.argeo.util/ext/test/org/argeo/util/CsvParserTestCase.java b/org.argeo.util/ext/test/org/argeo/util/CsvParserTestCase.java deleted file mode 100644 index 02e8d1b59..000000000 --- a/org.argeo.util/ext/test/org/argeo/util/CsvParserTestCase.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.util; - -import java.io.ByteArrayInputStream; -import java.io.InputStream; -import java.util.List; - -import junit.framework.TestCase; - -public class CsvParserTestCase extends TestCase { - public void testParse() throws Exception { - String toParse = "Header1,\"Header\n2\",Header3,\"Header4\"\n" - + "Col1,\"Col\n2\",Col3,\"\"\"Col4\"\"\"\n" - + "Col1,\"Col\n2\",Col3,\"\"\"Col4\"\"\"\n" - + "Col1,\"Col\n2\",Col3,\"\"\"Col4\"\"\"\n"; - - InputStream in = new ByteArrayInputStream(toParse.getBytes()); - - CsvParser csvParser = new CsvParser() { - protected void processLine(Integer lineNumber, List header, - List tokens) { - assertEquals(header.size(), tokens.size()); - assertEquals(4, tokens.size()); - assertEquals("Col1", tokens.get(0)); - assertEquals("Col\n2", tokens.get(1)); - assertEquals("Col3", tokens.get(2)); - assertEquals("\"Col4\"", tokens.get(3)); - } - }; - - csvParser.parse(in); - in.close(); - } - -} diff --git a/org.argeo.util/ext/test/org/argeo/util/CsvParserWithQuotedSeparatorTest.java b/org.argeo.util/ext/test/org/argeo/util/CsvParserWithQuotedSeparatorTest.java index d4131a046..f4095bb72 100644 --- a/org.argeo.util/ext/test/org/argeo/util/CsvParserWithQuotedSeparatorTest.java +++ b/org.argeo.util/ext/test/org/argeo/util/CsvParserWithQuotedSeparatorTest.java @@ -21,9 +21,8 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import junit.framework.TestCase; - -public class CsvParserWithQuotedSeparatorTest extends TestCase { +/** Test that {@link CsvParser} deals properly with "" quotes. */ +public class CsvParserWithQuotedSeparatorTest { public void testSimpleParse() throws Exception { String toParse = "Header1,\"Header2\",Header3,\"Header4\"\n" + "\"Col1, Col2\",\"Col\n2\",Col3,\"\"\"Col4\"\"\"\n"; @@ -31,11 +30,10 @@ public class CsvParserWithQuotedSeparatorTest extends TestCase { InputStream in = new ByteArrayInputStream(toParse.getBytes()); CsvParser csvParser = new CsvParser() { - protected void processLine(Integer lineNumber, List header, - List tokens) { - assertEquals(header.size(), tokens.size()); - assertEquals(4, tokens.size()); - assertEquals("Col1, Col2", tokens.get(0)); + protected void processLine(Integer lineNumber, List header, List tokens) { + assert header.size() == tokens.size(); + assert 4 == tokens.size(); + assert "Col1, Col2".equals(tokens.get(0)); } }; // System.out.println(toParse); @@ -47,12 +45,10 @@ public class CsvParserWithQuotedSeparatorTest extends TestCase { public void testParseFile() throws Exception { final Map> lines = new HashMap>(); - InputStream in = getClass().getResourceAsStream( - "/org/argeo/util/ReferenceFile.csv"); + InputStream in = getClass().getResourceAsStream("/org/argeo/util/ReferenceFile.csv"); CsvParserWithLinesAsMap parser = new CsvParserWithLinesAsMap() { - protected void processLine(Integer lineNumber, - Map line) { + protected void processLine(Integer lineNumber, Map line) { // System.out.println("processing line #" + lineNumber); lines.put(lineNumber, line); } @@ -62,17 +58,16 @@ public class CsvParserWithQuotedSeparatorTest extends TestCase { in.close(); Map line = lines.get(2); - assertEquals(",,,,", line.get("Coma testing")); + assert ",,,,".equals(line.get("Coma testing")); line = lines.get(3); - assertEquals(",, ,,", line.get("Coma testing")); + assert ",, ,,".equals(line.get("Coma testing")); line = lines.get(4); - assertEquals("module1, module2", line.get("Coma testing")); + assert "module1, module2".equals(line.get("Coma testing")); line = lines.get(5); - assertEquals("module1,module2", line.get("Coma testing")); + assert "module1,module2".equals(line.get("Coma testing")); line = lines.get(6); - assertEquals(",module1,module2, \nmodule3, module4", - line.get("Coma testing")); - assertEquals(5, lines.size()); + assert ",module1,module2, \nmodule3, module4".equals(line.get("Coma testing")); + assert 5 == lines.size(); } } diff --git a/org.argeo.util/ext/test/org/argeo/util/CsvWriterTest.java b/org.argeo.util/ext/test/org/argeo/util/CsvWriterTest.java new file mode 100644 index 000000000..fcd2d606b --- /dev/null +++ b/org.argeo.util/ext/test/org/argeo/util/CsvWriterTest.java @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.util; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** {@link CsvWriter} tests. */ +public class CsvWriterTest { + public void testWrite() throws Exception { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + final CsvWriter csvWriter = new CsvWriter(out); + + String[] header = { "Header1", "Header 2", "Header,3", "Header\n4", "Header\"5\"" }; + String[] line1 = { "Value1", "Value 2", "Value,3", "Value\n4", "Value\"5\"" }; + csvWriter.writeLine(Arrays.asList(header)); + csvWriter.writeLine(Arrays.asList(line1)); + + String reference = "Header1,Header 2,\"Header,3\",\"Header\n4\",\"Header\"\"5\"\"\"\n" + + "Value1,Value 2,\"Value,3\",\"Value\n4\",\"Value\"\"5\"\"\"\n"; + String written = new String(out.toByteArray()); + assert reference.equals(written); + out.close(); + System.out.println(written); + + final List allTokens = new ArrayList(); + CsvParser csvParser = new CsvParser() { + protected void processLine(Integer lineNumber, List header, List tokens) { + if (lineNumber == 2) + allTokens.addAll(header); + allTokens.addAll(tokens); + } + }; + ByteArrayInputStream in = new ByteArrayInputStream(written.getBytes()); + csvParser.parse(in); + in.close(); + List allTokensRef = new ArrayList(); + allTokensRef.addAll(Arrays.asList(header)); + allTokensRef.addAll(Arrays.asList(line1)); + + assert allTokensRef.size() == allTokens.size(); + for (int i = 0; i < allTokensRef.size(); i++) + assert allTokensRef.get(i).equals(allTokens.get(i)); + } + +} diff --git a/org.argeo.util/ext/test/org/argeo/util/CsvWriterTestCase.java b/org.argeo.util/ext/test/org/argeo/util/CsvWriterTestCase.java deleted file mode 100644 index 26b356def..000000000 --- a/org.argeo.util/ext/test/org/argeo/util/CsvWriterTestCase.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.util; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -import junit.framework.TestCase; - -public class CsvWriterTestCase extends TestCase { - public void testWrite() throws Exception { - ByteArrayOutputStream out = new ByteArrayOutputStream(); - final CsvWriter csvWriter = new CsvWriter(out); - - String[] header = { "Header1", "Header 2", "Header,3", "Header\n4", - "Header\"5\"" }; - String[] line1 = { "Value1", "Value 2", "Value,3", "Value\n4", - "Value\"5\"" }; - csvWriter.writeLine(Arrays.asList(header)); - csvWriter.writeLine(Arrays.asList(line1)); - - String reference = "Header1,Header 2,\"Header,3\",\"Header\n4\",\"Header\"\"5\"\"\"\n" - + "Value1,Value 2,\"Value,3\",\"Value\n4\",\"Value\"\"5\"\"\"\n"; - String written = new String(out.toByteArray()); - assertEquals(reference, written); - out.close(); - System.out.println(written); - - final List allTokens = new ArrayList(); - CsvParser csvParser = new CsvParser() { - protected void processLine(Integer lineNumber, List header, - List tokens) { - if (lineNumber == 2) - allTokens.addAll(header); - allTokens.addAll(tokens); - } - }; - ByteArrayInputStream in = new ByteArrayInputStream(written.getBytes()); - csvParser.parse(in); - in.close(); - List allTokensRef = new ArrayList(); - allTokensRef.addAll(Arrays.asList(header)); - allTokensRef.addAll(Arrays.asList(line1)); - - assertEquals(allTokensRef.size(), allTokens.size()); - for (int i = 0; i < allTokensRef.size(); i++) - assertEquals(allTokensRef.get(i), allTokens.get(i)); - } - -} diff --git a/org.argeo.util/src/org/argeo/util/test/Test.java b/org.argeo.util/src/org/argeo/util/test/Test.java deleted file mode 100644 index 74f165ef2..000000000 --- a/org.argeo.util/src/org/argeo/util/test/Test.java +++ /dev/null @@ -1,93 +0,0 @@ -package org.argeo.util.test; - -import java.lang.reflect.Method; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.TreeMap; - -/** A generic tester based on Java assertions and functional programming. */ -public class Test { - private Map results = Collections.synchronizedSortedMap(new TreeMap<>()); - - protected void execute(String className) throws Throwable { - ClassLoader classLoader = Test.class.getClassLoader(); - Class clss = classLoader.loadClass(className); - boolean assertionsEnabled = clss.desiredAssertionStatus(); - if (!assertionsEnabled) - throw new IllegalStateException("Test runner " + getClass().getName() - + " requires Java assertions to be enabled. Call the JVM with the -ea argument."); - Object obj = clss.getDeclaredConstructor().newInstance(); - List methods = findMethods(clss); - if (methods.size() == 0) - throw new IllegalArgumentException("No test method found in " + clss); - // TODO make order more predictable? - for (Method method : methods) { - String uid = method.getDeclaringClass().getName() + "#" + method.getName(); - TestStatus testStatus = new TestStatus(uid); - try { - method.invoke(obj); - testStatus.setPassed(); - } catch (Exception e) { - testStatus.setFailed(e); - } finally { - results.put(uid, testStatus); - } - } - } - - protected List findMethods(Class clss) { - List methods = new ArrayList(); -// Method call = getMethod(clss, "call"); -// if (call != null) -// methods.add(call); -// - for (Method method : clss.getMethods()) { - if (method.getName().startsWith("test")) { - methods.add(method); - } - } - return methods; - } - - protected Method getMethod(Class clss, String name, Class... parameterTypes) { - try { - return clss.getMethod(name, parameterTypes); - } catch (NoSuchMethodException e) { - return null; - } catch (SecurityException e) { - throw new IllegalStateException(e); - } - } - - public static void main(String[] args) { - // deal with arguments - String className; - if (args.length < 1) { - System.err.println(usage()); - System.exit(1); - throw new IllegalArgumentException(); - } else { - className = args[0]; - } - - Test test = new Test(); - try { - test.execute(className); - } catch (Throwable e) { - e.printStackTrace(); - } - - Map r = test.results; - for (String uid : r.keySet()) { - TestStatus testStatus = r.get(uid); - System.out.println(testStatus); - } - } - - public static String usage() { - return "java " + Test.class.getName() + " [test class name]"; - - } -} diff --git a/org.argeo.util/src/org/argeo/util/test/TestStatus.java b/org.argeo.util/src/org/argeo/util/test/TestStatus.java deleted file mode 100644 index 79cfbcdd3..000000000 --- a/org.argeo.util/src/org/argeo/util/test/TestStatus.java +++ /dev/null @@ -1,98 +0,0 @@ -package org.argeo.util.test; - -import java.io.Serializable; - -/** The status of a test. */ -public class TestStatus implements Serializable { - private static final long serialVersionUID = 6272975746885487000L; - - private Boolean passed = null; - private final String uid; - private Throwable throwable = null; - - public TestStatus(String uid) { - this.uid = uid; - } - - /** For cloning. */ - public TestStatus(String uid, Boolean passed, Throwable throwable) { - this(uid); - this.passed = passed; - this.throwable = throwable; - } - - public synchronized Boolean isRunning() { - return passed == null; - } - - public synchronized Boolean isPassed() { - assert passed != null; - return passed; - } - - public synchronized Boolean isFailed() { - assert passed != null; - return !passed; - } - - public synchronized void setPassed() { - setStatus(true); - } - - public synchronized void setFailed() { - setStatus(false); - } - - public synchronized void setFailed(Throwable throwable) { - setStatus(false); - setThrowable(throwable); - } - - protected void setStatus(Boolean passed) { - if (this.passed != null) - throw new IllegalStateException("Passed status of test " + uid + " is already set (to " + passed + ")"); - this.passed = passed; - } - - protected void setThrowable(Throwable throwable) { - if (this.throwable != null) - throw new IllegalStateException("Throwable of test " + uid + " is already set (to " + passed + ")"); - this.throwable = throwable; - } - - public String getUid() { - return uid; - } - - public Throwable getThrowable() { - return throwable; - } - - @Override - protected Object clone() throws CloneNotSupportedException { - // TODO Auto-generated method stub - return super.clone(); - } - - @Override - public boolean equals(Object o) { - if (o instanceof TestStatus) { - TestStatus other = (TestStatus) o; - // we don't check consistency for performance purposes - // this equals() is supposed to be used in collections or for transfer - return other.uid.equals(uid); - } - return false; - } - - @Override - public int hashCode() { - return uid.hashCode(); - } - - @Override - public String toString() { - return uid + "\t" + (passed ? "passed" : "failed"); - } - -} diff --git a/org.argeo.util/src/org/argeo/util/test/Tester.java b/org.argeo.util/src/org/argeo/util/test/Tester.java new file mode 100644 index 000000000..36e27de72 --- /dev/null +++ b/org.argeo.util/src/org/argeo/util/test/Tester.java @@ -0,0 +1,126 @@ +package org.argeo.util.test; + +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.TreeMap; + +/** A generic tester based on Java assertions and functional programming. */ +public class Tester { + private Map results = Collections.synchronizedSortedMap(new TreeMap<>()); + + private ClassLoader classLoader; + + /** Use {@link Thread#getContextClassLoader()} by default. */ + public Tester() { + this(Thread.currentThread().getContextClassLoader()); + } + + public Tester(ClassLoader classLoader) { + this.classLoader = classLoader; + } + + public void execute(String className) { + Class clss; + try { + clss = classLoader.loadClass(className); + boolean assertionsEnabled = clss.desiredAssertionStatus(); + if (!assertionsEnabled) + throw new IllegalStateException("Test runner " + getClass().getName() + + " requires Java assertions to be enabled. Call the JVM with the -ea argument."); + } catch (Exception e1) { + throw new IllegalArgumentException("Cannot initalise test for " + className, e1); + + } + List methods = findMethods(clss); + if (methods.size() == 0) + throw new IllegalArgumentException("No test method found in " + clss); + // TODO make order more predictable? + for (Method method : methods) { + String uid = method.getDeclaringClass().getName() + "#" + method.getName(); + TesterStatus testStatus = new TesterStatus(uid); + Object obj = null; + try { + beforeTest(uid, method); + obj = clss.getDeclaredConstructor().newInstance(); + method.invoke(obj); + testStatus.setPassed(); + afterTestPassed(uid, method, obj); + } catch (Exception e) { + testStatus.setFailed(e); + afterTestFailed(uid, method, obj, e); + } finally { + results.put(uid, testStatus); + } + } + } + + protected void beforeTest(String uid, Method method) { + // System.out.println(uid + ": STARTING"); + } + + protected void afterTestPassed(String uid, Method method, Object obj) { + System.out.println(uid + ": PASSED"); + } + + protected void afterTestFailed(String uid, Method method, Object obj, Throwable e) { + System.out.println(uid + ": FAILED"); + e.printStackTrace(); + } + + protected List findMethods(Class clss) { + List methods = new ArrayList(); +// Method call = getMethod(clss, "call"); +// if (call != null) +// methods.add(call); +// + for (Method method : clss.getMethods()) { + if (method.getName().startsWith("test")) { + methods.add(method); + } + } + return methods; + } + + protected Method getMethod(Class clss, String name, Class... parameterTypes) { + try { + return clss.getMethod(name, parameterTypes); + } catch (NoSuchMethodException e) { + return null; + } catch (SecurityException e) { + throw new IllegalStateException(e); + } + } + + public static void main(String[] args) { + // deal with arguments + String className; + if (args.length < 1) { + System.err.println(usage()); + System.exit(1); + throw new IllegalArgumentException(); + } else { + className = args[0]; + } + + Tester test = new Tester(); + try { + test.execute(className); + } catch (Throwable e) { + e.printStackTrace(); + } + + Map r = test.results; + for (String uid : r.keySet()) { + TesterStatus testStatus = r.get(uid); + System.out.println(testStatus); + } + } + + public static String usage() { + return "java " + Tester.class.getName() + " [test class name]"; + + } +} diff --git a/org.argeo.util/src/org/argeo/util/test/TesterStatus.java b/org.argeo.util/src/org/argeo/util/test/TesterStatus.java new file mode 100644 index 000000000..d533e9457 --- /dev/null +++ b/org.argeo.util/src/org/argeo/util/test/TesterStatus.java @@ -0,0 +1,98 @@ +package org.argeo.util.test; + +import java.io.Serializable; + +/** The status of a test. */ +public class TesterStatus implements Serializable { + private static final long serialVersionUID = 6272975746885487000L; + + private Boolean passed = null; + private final String uid; + private Throwable throwable = null; + + public TesterStatus(String uid) { + this.uid = uid; + } + + /** For cloning. */ + public TesterStatus(String uid, Boolean passed, Throwable throwable) { + this(uid); + this.passed = passed; + this.throwable = throwable; + } + + public synchronized Boolean isRunning() { + return passed == null; + } + + public synchronized Boolean isPassed() { + assert passed != null; + return passed; + } + + public synchronized Boolean isFailed() { + assert passed != null; + return !passed; + } + + public synchronized void setPassed() { + setStatus(true); + } + + public synchronized void setFailed() { + setStatus(false); + } + + public synchronized void setFailed(Throwable throwable) { + setStatus(false); + setThrowable(throwable); + } + + protected void setStatus(Boolean passed) { + if (this.passed != null) + throw new IllegalStateException("Passed status of test " + uid + " is already set (to " + passed + ")"); + this.passed = passed; + } + + protected void setThrowable(Throwable throwable) { + if (this.throwable != null) + throw new IllegalStateException("Throwable of test " + uid + " is already set (to " + passed + ")"); + this.throwable = throwable; + } + + public String getUid() { + return uid; + } + + public Throwable getThrowable() { + return throwable; + } + + @Override + protected Object clone() throws CloneNotSupportedException { + // TODO Auto-generated method stub + return super.clone(); + } + + @Override + public boolean equals(Object o) { + if (o instanceof TesterStatus) { + TesterStatus other = (TesterStatus) o; + // we don't check consistency for performance purposes + // this equals() is supposed to be used in collections or for transfer + return other.uid.equals(uid); + } + return false; + } + + @Override + public int hashCode() { + return uid.hashCode(); + } + + @Override + public String toString() { + return uid + "\t" + (passed ? "passed" : "failed"); + } + +}